╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │156 switch (host) { │ │157 .server => |server| { │ │158 // "repo/new" and "user/new" come before "new", which would claim them │ │159 - const PostRoute = enum { login, logout, @"repo/new", @"user/new", repo, new, edit, remove, open, close, resolve, publish, merge, squash, attach, undo, clear }; │ │159 + const PostRoute = enum { login, logout, @"repo/new", @"user/new", user, repo, new, edit, remove, open, close, resolve, publish, merge, squash, attach, undo, clear };│ │160 inline for (@typeInfo(PostRoute).@"enum".field_names) |name| { │ │161 const suffix = "/" ++ name; │ │162 if (std.mem.endsWith(u8, path, suffix)) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │166 .logout => handleLogout(request, base, server.session_store), │ │167 .@"repo/new" => handleRepoNew(io, request, allocator, path, server.admin_repo_path, server.users_dir, server.session_store),│ │168 .@"user/new" => handleUserNew(io, request, allocator, path, server.admin_repo_path, server.users_dir, server.session_store),│ │169 + .user => handleUserSettings(io, request, allocator, path, server.admin_repo_path, server.users_dir, server.session_store), │ │170 .repo => handleRepoSettings(io, request, allocator, path, base, host), │ │171 .new => handleNew(io, request, allocator, base, host), │ │172 .edit => handleEdit(io, request, allocator, base, host), │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │773 }); │ │774 } │ │775 │ │776 +// change the logged-in user's settings, then return to the page that posted │ │777 +// the form, which a failure also goes back to. │ │778 +fn handleUserSettings( │ │779 + io: std.Io, │ │780 + request: *std.http.Server.Request, │ │781 + allocator: std.mem.Allocator, │ │782 + form_location: []const u8, │ │783 + admin_repo_path: []const u8, │ │784 + users_dir: []const u8, │ │785 + session_store: SessionStore, │ │786 +) !void { │ │787 + const user_id = requestUserId(request, session_store) orelse return respondLoginRequired(request); │ │788 + │ │789 + const body = try readFormBody(request, allocator); │ │790 + defer allocator.free(body); │ │791 + const email = (try parseFormField(allocator, body, "email")) orelse try allocator.dupe(u8, ""); │ │792 + defer allocator.free(email); │ │793 + const current_password = (try parseFormField(allocator, body, "current_password")) orelse try allocator.dupe(u8, ""); │ │794 + defer allocator.free(current_password); │ │795 + const new_password = (try parseFormField(allocator, body, "new_password")) orelse try allocator.dupe(u8, ""); │ │796 + defer allocator.free(new_password); │ │797 + const new_password_again = (try parseFormField(allocator, body, "new_password_again")) orelse try allocator.dupe(u8, ""); │ │798 + defer allocator.free(new_password_again); │ │799 + │ │800 + { │ │801 + var admin_repo = try rp.Repo(.xit, evt.admin_repo_opts).open(io, allocator, .{ .path = admin_repo_path }); │ │802 + defer admin_repo.deinit(io, allocator); │ │803 + evt.updateUser(io, allocator, users_dir, &admin_repo, &user_id, email, current_password, new_password, new_password_again) catch |err| switch (err) { │ │804 + error.NotFound => return respondLoginRequired(request), │ │805 + else => { │ │806 + const failure = ui.Session.FormFeedback.UserFailure.fromError(err) orelse return err; │ │807 + return respondFormFailure(request, allocator, session_store, form_location, .{ .user_settings = .{ .failure = failure, .fields = .{ .email = email } } });│ │808 + }, │ │809 + }; │ │810 + } │ │811 + │ │812 + try request.respond("", .{ │ │813 + .status = .see_other, │ │814 + .extra_headers = &.{.{ .name = "location", .value = form_location }}, │ │815 + }); │ │816 +} │ │817 + │ │818 // create a thread in the repo the form's page names and redirect to it. │ │819 fn handleThreadNew( │ │820 io: std.Io, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯