UserProjection.vala 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using InvercargillSql.Orm.Projections;
  2. using Invercargill.DataStructures;
  3. using Invercargill;
  4. using Invercargill.Expressions;
  5. namespace Spry.Authentication {
  6. /**
  7. * Read model over `spry_users` joined with the user's
  8. * `spry_user_permissions` rows. {@link permissions} carries the user's
  9. * permission patterns; {@link Spry.SpryAuth.login} copies them into the
  10. * auth slot's public data.
  11. */
  12. public class UserProjection : Object {
  13. public string username { get { return _username; } }
  14. public ImmutableLot<string> permissions { owned get { return _permissions.to_immutable_buffer(); } }
  15. public int64 id { get; set; }
  16. public string email { get; set; }
  17. public string forename { get; set; }
  18. public string surname { get; set; }
  19. public string password_hash { get; set; }
  20. public DateTime date_of_birth { get; set; }
  21. public DateTime created { get; set; }
  22. public DateTime modified { get; set; }
  23. public bool enabled { get; set; }
  24. /**
  25. * SA-1/SA-14: held auth frames for this user must have been authored
  26. * at or after this instant ({@link Spry.SpryAuth.revalidate}
  27. * enforces it). `null` on rows written before M0002 — read it
  28. * through {@link effective_sessions_valid_after}.
  29. */
  30. public DateTime? sessions_valid_after { get; set; }
  31. /** {@link sessions_valid_after} with `null` resolved to the Unix epoch. */
  32. public DateTime effective_sessions_valid_after {
  33. get { return sessions_valid_after ?? UserEntity.EPOCH; }
  34. }
  35. private string _username;
  36. /**
  37. * Starts empty (not null): a user with no joined permission rows
  38. * never triggers {@link permissions}, so without this initialiser the
  39. * getter would hand callers a null collection.
  40. */
  41. private ImmutableBuffer<string> _permissions = new ImmutableBuffer<string>(new Series<string>());
  42. public static void projection_mapping(ProjectionBuilder<UserProjection> cfg) throws Error {
  43. cfg.source<UserEntity>("u")
  44. .select<int64?>("id", expr("u.id"), (o, v) => o.id = v)
  45. .select<string>("username", expr("u.username"), (o, v) => o._username = v)
  46. .select<string>("email", expr("u.email"), (o, v) => o.email = v)
  47. .select<string>("forename", expr("u.forename"), (o, v) => o.forename = v)
  48. .select<string>("surname", expr("u.surname"), (o, v) => o.surname = v)
  49. .select<string>("password_hash", expr("u.password_hash"), (o, v) => o.password_hash = v)
  50. .select<DateTime>("date_of_birth", expr("u.date_of_birth"), (o, v) => o.date_of_birth = v)
  51. .select<DateTime>("created", expr("u.created"), (o, v) => o.created = v)
  52. .select<DateTime>("modified", expr("u.modified"), (o, v) => o.modified = v)
  53. .select<bool>("enabled", expr("u.enabled"), (o, v) => o.enabled = v)
  54. .select<DateTime?>("sessions_valid_after", expr("u.sessions_valid_after"), (o, v) => o.sessions_valid_after = v)
  55. .join<UserPermissionEntity>("p", expr("p.user_id == u.id"))
  56. .select_many<string>("permissions", expr("p.permission"), (o, v) => o._permissions = v.to_immutable_buffer());
  57. }
  58. }
  59. }