╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2097 const user = (try evt.User.readById(evt.AdminDB, evt.admin_repo_opts.hash, moment, arena, &user_id)) orelse return null; │ │2098 return if (user.removed) null else user; │ │2099 } │ │2100 + │ │2101 +// what the typed assignee resolves to │ │2102 +pub const AssigneeLookup = union(enum) { │ │2103 + email: []const u8, │ │2104 + failure: Session.FormFeedback.AssignmentFailure, │ │2105 +}; │ │2106 │ │2107 +// the email `text` assigns: itself when it holds an @, else the email of the │ │2108 +// user it names. a null moment is local mode, which has no users to look up. │ │2109 +pub fn assigneeEmail(moment_maybe: ?evt.AdminDB.HashMap(.read_only), arena: *std.heap.ArenaAllocator, text: []const u8) !AssigneeLookup { │ │2110 + const trimmed = std.mem.trim(u8, text, " \t\r\n"); │ │2111 + if (std.mem.indexOfScalar(u8, trimmed, '@') != null) return .{ .email = trimmed }; │ │2112 + const moment = moment_maybe orelse return .{ .failure = .not_an_email }; │ │2113 + const user_id = (try evt.User.readIdByName(evt.AdminDB, evt.admin_repo_opts.hash, moment, trimmed)) orelse return .{ .failure = .not_found };│ │2114 + const user = (try activeUser(moment, arena, user_id)) orelse return .{ .failure = .not_found }; │ │2115 + return .{ .email = user.event.email }; │ │2116 +} │ │2117 + │ │2118 // whether the user may write to the repo `identity` names with at least │ │2119 // `min_role`, and to the `thread_kind` tab when there is one │ │2120 pub fn authorizeUser( │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │2268 │ │2269 pub const RolesFailure = enum { not_found, already_added }; │ │2270 │ │2271 + pub const AssignmentFailure = enum { not_found, not_an_email, already_assigned };│ │2272 + │ │2273 pub const UserFailure = enum { │ │2274 required_name, │ │2275 invalid_name, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────╮ │2336 failure: RolesFailure, │ │2337 name: []const u8, │ │2338 }, │ │2339 + assignment: struct { │ │2340 + failure: AssignmentFailure,│ │2341 + text: []const u8, │ │2342 + }, │ │2343 issue: struct { │ │2344 failure: ThreadFailure, │ │2345 fields: ?struct { │ ╰─────────────────────────────────────────────╯