User.vala 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using Invercargill;
  2. using Invercargill.DataStructures;
  3. using Json;
  4. namespace Spry.Users {
  5. public class User : GLib.Object {
  6. // Identity
  7. public string id { get; set; }
  8. public string username { get; set; }
  9. public string email { get; set; }
  10. public string password_hash { get; set; }
  11. // Metadata
  12. public DateTime created_at { get; set; }
  13. public DateTime? updated_at { get; set; }
  14. // Permissions - stored as JSON array of strings
  15. public Vector<string> permissions { get; set; default = new Vector<string>(); }
  16. // Application-specific data - stored as JSON object
  17. public Dictionary<string, string> app_data { get; set; default = new Dictionary<string, string>(); }
  18. public User() {
  19. id = "";
  20. username = "";
  21. email = "";
  22. password_hash = "";
  23. created_at = new DateTime.now_utc();
  24. }
  25. public static User from_json(Json.Object obj) {
  26. var user = new User();
  27. // Required string fields - use has_member and null coalescing for safety
  28. user.id = obj.has_member("id") ? (obj.get_string_member("id") ?? "") : "";
  29. user.username = obj.has_member("username") ? (obj.get_string_member("username") ?? "") : "";
  30. user.email = obj.has_member("email") ? (obj.get_string_member("email") ?? "") : "";
  31. user.password_hash = obj.has_member("password_hash") ? (obj.get_string_member("password_hash") ?? "") : "";
  32. // created_at - check member exists and value is not null/empty
  33. if (obj.has_member("created_at")) {
  34. var created_str = obj.get_string_member("created_at");
  35. if (created_str != null && created_str.length > 0) {
  36. user.created_at = new DateTime.from_iso8601(created_str, new TimeZone.utc());
  37. }
  38. }
  39. // updated_at (optional) - check member exists, is not null, and has value
  40. if (obj.has_member("updated_at")) {
  41. var member = obj.get_member("updated_at");
  42. if (member != null && member.get_node_type() == Json.NodeType.VALUE) {
  43. var updated_str = obj.get_string_member("updated_at");
  44. if (updated_str != null && updated_str.length > 0) {
  45. user.updated_at = new DateTime.from_iso8601(updated_str, new TimeZone.utc());
  46. }
  47. }
  48. }
  49. // permissions (array of strings) - check member exists and is array
  50. if (obj.has_member("permissions")) {
  51. var member = obj.get_member("permissions");
  52. if (member != null && member.get_node_type() == Json.NodeType.ARRAY) {
  53. var perms_array = obj.get_array_member("permissions");
  54. if (perms_array != null) {
  55. foreach (var perm in perms_array.get_elements()) {
  56. var perm_str = perm.get_string();
  57. if (perm_str != null) {
  58. user.permissions.add(perm_str);
  59. }
  60. }
  61. }
  62. }
  63. }
  64. // app_data (object with string values) - check member exists and is object
  65. if (obj.has_member("app_data")) {
  66. var member = obj.get_member("app_data");
  67. if (member != null && member.get_node_type() == Json.NodeType.OBJECT) {
  68. var app_data_obj = obj.get_object_member("app_data");
  69. if (app_data_obj != null) {
  70. foreach (var key in app_data_obj.get_members()) {
  71. var value = app_data_obj.get_string_member(key);
  72. user.app_data.set(key, value ?? "");
  73. }
  74. }
  75. }
  76. }
  77. return user;
  78. }
  79. public Json.Object to_json() {
  80. var obj = new Json.Object();
  81. // Use null coalescing to ensure we never pass null to set_string_member
  82. obj.set_string_member("id", id ?? "");
  83. obj.set_string_member("username", username ?? "");
  84. obj.set_string_member("email", email ?? "");
  85. obj.set_string_member("password_hash", password_hash ?? "");
  86. obj.set_string_member("created_at", created_at != null ? created_at.format_iso8601() : new DateTime.now_utc().format_iso8601());
  87. // updated_at (optional)
  88. if (updated_at != null) {
  89. obj.set_string_member("updated_at", ((!)updated_at).format_iso8601());
  90. } else {
  91. obj.set_null_member("updated_at");
  92. }
  93. // permissions array - always create array even if empty
  94. var perms_array = new Json.Array();
  95. if (permissions != null) {
  96. foreach (var perm in permissions) {
  97. if (perm != null) {
  98. perms_array.add_string_element(perm);
  99. }
  100. }
  101. }
  102. obj.set_array_member("permissions", perms_array);
  103. // app_data object - always create object even if empty
  104. var app_data_obj = new Json.Object();
  105. if (app_data != null) {
  106. var iter = app_data.iterator();
  107. while (iter.next()) {
  108. var pair = iter.get();
  109. app_data_obj.set_string_member(pair.key ?? "", pair.value ?? "");
  110. }
  111. }
  112. obj.set_object_member("app_data", app_data_obj);
  113. return obj;
  114. }
  115. }
  116. }