╭ changed ────────╮ │src/serve_ssh.zig│ ╰─────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │487 if (service == .receive_pack and !isKeyInAuthorizedKeys(user.event.ssh_keys, &sess.fingerprint)) │ │488 return writeError(sess, "unauthorized: this SSH key is not registered to the patch author"); │ │489 │ │490 + const target = (try evt.readRepoById(io, allocator, &admin_arena, handler.users_dir, fork_record.event.repo_user_id[0..evt.event_id_size], fork_record.event.repo_id[0..evt.event_id_size], forker_id)) orelse│ │491 + return writeError(sess, "repo not found"); │ │492 + // patches that are off take their drafts with them │ │493 + const patch_role = target.repo.event.patch_role orelse return writeError(sess, "patch draft not found"); │ │494 + if (service == .receive_pack) { │ │495 + const role = target.role orelse return writeError(sess, "repo not found"); │ │496 + if (!role.atLeast(patch_role)) return writeError(sess, "unauthorized: your role in this repo may not write patches"); │ │497 + } │ │498 + │ │499 const draft_path = try fork.forkPath(allocator, handler.users_dir, &forker_id, &fork_id); │ │500 defer allocator.free(draft_path); │ │501 var draft = rp.AnyRepo(.xit, any_repo_opts).open(io, allocator, .{ .path = draft_path }) catch │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │507 inline else => |*repo| try repo.uploadPack(io, allocator, reader, writer, .{ .protocol_version = protocol_version }, &sideband), │ │508 } │ │509 } else { │ │501 - const target = (try evt.readRepoById(io, allocator, &admin_arena, handler.users_dir, fork_record.event.repo_user_id[0..evt.event_id_size], fork_record.event.repo_id[0..evt.event_id_size], null)) orelse│ │502 - return writeError(sess, "repo not found"); │ │510 if (!std.mem.eql(u8, target.repo.event.name, forker_repo.name)) return writeError(sess, "patch draft belongs to another repo"); │ │511 const target_path = try evt.repoPath(allocator, handler.users_dir, fork_record.event.repo_user_id, fork_record.event.repo_id); │ │512 defer allocator.free(target_path); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯