╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ User.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
99 const user_key = hash.hashInt(hash_kind, &user_id); 100 const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->user")) orelse return .unknown_user; 101 const event_id_to_user = try DB.HashMap(.read_only).init(event_id_to_user_cursor); 102 103 const user_cursor = try event_id_to_user.getCursor(user_key) orelse return .unknown_user; 104 const user_map = try DB.HashMap(.read_only).init(user_cursor); 105 const user_event = try evt.read(@This(), DB, hash_kind, arena, user_map); 106 107 bcrypt.strVerify(user_event.password_hash, password, .{ .silently_truncate_password = false }) catch { 108 return .wrong_password; 109 }; 110 111 return .{ .success = user_id }; 112 } 113 114 // read a user by event id via the event-id->user index, or null if the id 115 // isn't a known user. field byte slices are allocated in `arena`. 116 pub fn readById( 117 comptime DB: type, 118 comptime hash_kind: hash.HashKind, 119 haxy_moment: DB.HashMap(.read_only), 120 arena: *std.heap.ArenaAllocator, 121 user_id: []const u8, 122 ) !?@This() { 123 const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->user")) orelse return null; 124 const event_id_to_user = try DB.HashMap(.read_only).init(event_id_to_user_cursor); 125 const user_cursor = try event_id_to_user.getCursor(hash.hashInt(hash_kind, user_id)) orelse return null; 126 const user_map = try DB.HashMap(.read_only).init(user_cursor); 127 return try evt.read(@This(), DB, hash_kind, arena, user_map); 128 } 129 130 // flip a user's ANSI-art preference by re-emitting their User event with 131 // enable_ansi negated. a no-op for an unknown user. `repo` must be writable. 132 pub fn toggleAnsi( 133 comptime repo_opts: rp.RepoOpts(.xit), 134 io: std.Io, 135 allocator: std.mem.Allocator, 136 repo: *rp.Repo(.xit, repo_opts), 137 user_id: []const u8, 138 ) !void { 139 const DB = rp.Repo(.xit, repo_opts).DB; 140 var arena = std.heap.ArenaAllocator.init(allocator); 141 defer arena.deinit(); 142 143 const moment = try evt.currentMoment(repo_opts, repo); 144 const user = (try readById(DB, repo_opts.hash, moment, &arena, user_id)) orelse return; 145 146 var updated = user; 147 updated.enable_ansi = !user.enable_ansi; 148 try evt.commitAndConsume(repo_opts, io, allocator, repo, evt.events_ref, &[_]evt.EventWithId{.{ 149 .id = std.fmt.bytesToHex(user_id[0..evt.event_id_size].*, .lower), 150 .event = .{ .user = updated }, 151 }}); 152 } 153