using InvercargillSql.Orm.Projections; using Invercargill.DataStructures; using Invercargill; using Invercargill.Expressions; namespace Spry.Authentication { /** * Read model over `spry_users` joined with the user's * `spry_user_permissions` rows. {@link permissions} carries the user's * permission patterns; {@link Spry.SpryAuth.login} copies them into the * auth slot's public data. */ public class UserProjection : Object { public string username { get { return _username; } } public ImmutableLot permissions { owned get { return _permissions.to_immutable_buffer(); } } public int64 id { get; set; } public string email { get; set; } public string forename { get; set; } public string surname { get; set; } public string password_hash { get; set; } public DateTime date_of_birth { get; set; } public DateTime created { get; set; } public DateTime modified { get; set; } public bool enabled { get; set; } /** * SA-1/SA-14: held auth frames for this user must have been authored * at or after this instant ({@link Spry.SpryAuth.revalidate} * enforces it). `null` on rows written before M0002 — read it * through {@link effective_sessions_valid_after}. */ public DateTime? sessions_valid_after { get; set; } /** {@link sessions_valid_after} with `null` resolved to the Unix epoch. */ public DateTime effective_sessions_valid_after { get { return sessions_valid_after ?? UserEntity.EPOCH; } } private string _username; /** * Starts empty (not null): a user with no joined permission rows * never triggers {@link permissions}, so without this initialiser the * getter would hand callers a null collection. */ private ImmutableBuffer _permissions = new ImmutableBuffer(new Series()); public static void projection_mapping(ProjectionBuilder cfg) throws Error { cfg.source("u") .select("id", expr("u.id"), (o, v) => o.id = v) .select("username", expr("u.username"), (o, v) => o._username = v) .select("email", expr("u.email"), (o, v) => o.email = v) .select("forename", expr("u.forename"), (o, v) => o.forename = v) .select("surname", expr("u.surname"), (o, v) => o.surname = v) .select("password_hash", expr("u.password_hash"), (o, v) => o.password_hash = v) .select("date_of_birth", expr("u.date_of_birth"), (o, v) => o.date_of_birth = v) .select("created", expr("u.created"), (o, v) => o.created = v) .select("modified", expr("u.modified"), (o, v) => o.modified = v) .select("enabled", expr("u.enabled"), (o, v) => o.enabled = v) .select("sessions_valid_after", expr("u.sessions_valid_after"), (o, v) => o.sessions_valid_after = v) .join("p", expr("p.user_id == u.id")) .select_many("permissions", expr("p.permission"), (o, v) => o._permissions = v.to_immutable_buffer()); } } }