╭ changed ────╮ │src/serve.zig│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │65 │ │66 // load or generate the SSH host key │ │67 const host_key = try serve_ssh_protocol.HostKey.loadOrGenerate(io, allocator, data_dir_path);│ │68 + │ │69 + // disk-backed store for web login sessions │ │70 + const session_store = try web.SessionStore.init(io, data_dir); │ │71 + defer session_store.deinit(); │ │72 │ │73 // create wui listener │ │74 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │101 try err.print("serving web UI on http://{s}/\n", .{options.wui_listen}); │ │102 try err.flush(); │ │103 │ │100 - web.run(io, allocator, &wui_server, &tasks, admin_repo_path, err); │ │104 + web.run(io, allocator, &wui_server, &tasks, admin_repo_path, session_store, err);│ │105 │ │106 if (@TypeOf(runnable) != void) { │ │107 try runnable.run(); │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │ 9 const Focus = xitui.focus.Focus; │ │10 const Grid = xitui.grid.Grid; │ │11 │ │12 -const cookie_name = "haxy_user"; │ │12 +const cookie_name = "haxy_session"; │ │13 // flash cookie for surfacing the outcome of the most recent /login POST.│ │14 // set on the failure redirect, read and immediately expired on the next │ │15 // GET / so refreshing the page doesn't keep showing the error. │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────╮ │34 net_server: *std.Io.net.Server,│ │35 tasks: *std.Io.Group, │ │36 admin_repo_path: []const u8, │ │37 + session_store: SessionStore, │ │38 err: *std.Io.Writer, │ │39 ) void { │ │40 const Listener = struct { │ ╰───────────────────────────────────────╯ ╭───────────────────────────────────────────╮ │43 net_server: *std.Io.net.Server,│ │44 tasks: *std.Io.Group, │ │45 admin_repo_path: []const u8, │ │46 + session_store: SessionStore, │ │47 err: *std.Io.Writer, │ │48 │ │49 fn run(ctx: @This()) void { │ ╰───────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────╮ │59 allocator: std.mem.Allocator,│ │60 stream: std.Io.net.Stream, │ │61 admin_repo_path: []const u8, │ │62 + session_store: SessionStore, │ │63 err: *std.Io.Writer, │ │64 │ │65 fn run(conn: @This()) void { │ ╰─────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │66 defer conn.stream.close(conn.io); │ │64 - handleConnection(conn.io, conn.allocator, conn.stream, conn.admin_repo_path, conn.err) catch |request_err| { │ │67 + handleConnection(conn.io, conn.allocator, conn.stream, conn.admin_repo_path, conn.session_store, conn.err) catch |request_err| {│ │68 logError(conn.err, "web ui request failed: {s}\n", .{@errorName(request_err)}); │ │69 }; │ │70 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────╮ │75 .allocator = ctx.allocator, │ │76 .stream = stream, │ │77 .admin_repo_path = ctx.admin_repo_path,│ │78 + .session_store = ctx.session_store, │ │79 .err = ctx.err, │ │80 }}); │ │81 } │ ╰───────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────╮ │88 .net_server = net_server, │ │89 .tasks = tasks, │ │90 .admin_repo_path = admin_repo_path,│ │91 + .session_store = session_store, │ │92 .err = err, │ │93 }}); │ │94 } │ ╰───────────────────────────────────────────────╯ ╭────────────────────────────────────────────╮ │ 98 allocator: std.mem.Allocator, │ │ 99 stream: std.Io.net.Stream, │ │100 admin_repo_path: []const u8, │ │101 + session_store: SessionStore, │ │102 err: *std.Io.Writer, │ │103 ) !void { │ │104 var send_buffer = [_]u8{0} ** 4096;│ ╰────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯