╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │677 }; │ │678 var arena = std.heap.ArenaAllocator.init(allocator); │ │679 defer arena.deinit(); │ │678 - const actor = (try authorizeWrite(io, allocator, &arena, request, host, repo_base, .owner)) orelse return; │ │680 + const actor = (try authorizeWrite(io, allocator, &arena, request, host, repo_base, .owner, null)) orelse return;│ │681 │ │682 const body = try readFormBody(request, allocator); │ │683 defer allocator.free(body); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │688 const access_value = (try parseFormField(allocator, body, "access")) orelse try allocator.dupe(u8, ""); │ │689 defer allocator.free(access_value); │ │690 const access = std.meta.stringToEnum(evt.Repo.Access, access_value) orelse return request.respond("invalid access", .{ .status = .bad_request, .extra_headers = &.{.{ .name = "content-type", .value = "text/plain" }} });│ │691 + var roles: [3]?evt.Repo.Role = undefined; │ │692 + for (&roles, [_][]const u8{ "discuss_role", "issue_role", "patch_role" }) |*role, field| { │ │693 + const role_value = (try parseFormField(allocator, body, field)) orelse try allocator.dupe(u8, ""); │ │694 + defer allocator.free(role_value); │ │695 + role.* = ui.Repo.Settings.labelRole(role_value) catch return request.respond("invalid role", .{ .status = .bad_request, .extra_headers = &.{.{ .name = "content-type", .value = "text/plain" }} }); │ │696 + } │ │697 + const discuss_role, const issue_role, const patch_role = roles; │ │698 │ │699 // authorizeWrite refused any other base │ │700 const identity = repoBaseIdentity(repo_base) orelse unreachable; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │692 - const route = ui.Repo.Settings.update(io, allocator, server.users_dir, actor, identity, name, description, access) catch |err| switch (err) { │ │701 + const route = ui.Repo.Settings.update(io, allocator, server.users_dir, actor, identity, name, description, access, discuss_role, issue_role, patch_role) catch |err| switch (err) {│ │702 error.NotFound => return respondRepoNotFound(request), │ │703 else => { │ │704 const failure = ui.Session.FormFeedback.RepoFailure.fromError(err) orelse return err; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────╮ │706 .name = name, │ │707 .description = description, │ │708 .access = access, │ │709 + .discuss_role = discuss_role,│ │710 + .issue_role = issue_role, │ │711 + .patch_role = patch_role, │ │712 } } }); │ │713 }, │ │714 }; │ ╰──────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │783 ) !void { │ │784 var author_arena = std.heap.ArenaAllocator.init(allocator); │ │785 defer author_arena.deinit(); │ │774 - const actor = (try authorizeWrite(io, allocator, &author_arena, request, host, base, .read)) orelse return; │ │786 + const actor = (try authorizeWrite(io, allocator, &author_arena, request, host, base, .read, kind)) orelse return;│ │787 const author = actor.author; │ │788 const body = try readFormBody(request, allocator); │ │789 defer allocator.free(body); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │950 var author_arena = std.heap.ArenaAllocator.init(allocator); │ │951 defer author_arena.deinit(); │ │952 // only the draft's author may publish it, which publish checks │ │941 - const actor = (try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .read)) orelse return; │ │953 + const actor = (try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .read, .patch)) orelse return;│ │954 const user_id = actor.user_id orelse return respondLoginRequired(request); │ │955 const author = actor.author; │ │956 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │993 }; │ │994 var author_arena = std.heap.ArenaAllocator.init(allocator); │ │995 defer author_arena.deinit(); │ │984 - const author = ((try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .write)) orelse return).author; │ │996 + const author = ((try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .write, .patch)) orelse return).author;│ │997 │ │998 const request_repo = (try requestRepoSource(io, allocator, host, parts.repo_base)) orelse return respondRemoveNotFound(request); │ │999 defer request_repo.deinit(allocator); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1047 │ │1048 var author_arena = std.heap.ArenaAllocator.init(allocator); │ │1049 defer author_arena.deinit(); │ │1038 - const author = ((try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .read)) orelse return).author; │ │1050 + const author = ((try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .read, parts.thread_kind)) orelse return).author;│ │1051 │ │1052 const form_body = try readFormBody(request, allocator); │ │1053 defer allocator.free(form_body); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1084 var any_repo = try rp.AnyRepo(repo_kind, .{}).open(io, allocator, source.localInitOpts()); │ │1085 defer any_repo.deinit(io, allocator); │ │1086 switch (any_repo) { │ │1075 - inline else => |*repo| event_id_hex = try evt.Comment.create(host.event(), repo_kind, repo.self_repo_opts, io, allocator, repo, &thread_id_hex, &parent_id_hex, body, author), │ │1087 + inline else => |*repo| event_id_hex = evt.Comment.create(host.event(), repo_kind, repo.self_repo_opts, io, allocator, repo, parts.thread_kind, &thread_id_hex, &parent_id_hex, body, author) catch |err| switch (err) {│ │1088 + // the url's thread or parent comment isn't what it claims │ │1089 + error.NotFound => return request.respond(not_found, .{ │ │1090 + .status = .not_found, │ │1091 + .extra_headers = &.{.{ .name = "content-type", .value = "text/plain" }}, │ │1092 + }), │ │1093 + else => |e| return e, │ │1094 + }, │ │1095 } │ │1096 }, │ │1097 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1262 │ │1263 var author_arena = std.heap.ArenaAllocator.init(allocator); │ │1264 defer author_arena.deinit(); │ │1246 - const actor = (try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .read)) orelse return; │ │1265 + const actor = (try authorizeWrite(io, allocator, &author_arena, request, host, parts.repo_base, .read, parts.kind)) orelse return; │ │1266 const author = actor.author; │ │1267 // an attachment changes the event it hangs off │ │1268 const request_repo = (try requestRepoSource(io, allocator, host, parts.repo_base)) orelse return respondAttachmentParentNotFound(request);│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯