╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───╮ │src/push.zig│ ╰────────────╯ ╭──────────────────────────────────────────────────────╮ │159 .reader = reader, │ │160 .writer = writer, │ │161 .options = options, │ │162 + .author = author, │ │163 .response = &response, │ │164 .repo_root_path = repo_root_path,│ │165 .error_writer = error_writer, │ ╰──────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │318 try evt.commitEvents(.xit, repo_opts, state, ctx.io, ctx.allocator, evt.events_ref, events[0..event_count], null); │ │319 if (!try evt.consumeInTransaction(.fork, .xit, repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, evt.events_ref)) return error.CancelTransaction;│ │320 } │ │301 - try xit.undo.writeMessage(repo_opts, state, .push); │ │321 + try writeUndo(repo_opts, state, ctx.io, ctx.allocator, ctx.author); │ │322 } │ │323 }; │ │324 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/serve_ssh.zig│ ╰─────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │376 const create_if_missing = parsed.service == .receive_pack; │ │377 │ │378 const owner_repo = evt.parseOwnerRepoPath(repo_identity) orelse return writeError(sess, "repo path must be <owner>/<repo>"); │ │379 - switch (try authorizeRepoKey(io, allocator, handler.admin_repo_path, owner_repo.owner, owner_repo.name, parsed.service, &sess.fingerprint)) { │ │380 - .allowed => {}, │ │379 + var author_arena = std.heap.ArenaAllocator.init(allocator); │ │380 + defer author_arena.deinit(); │ │381 + const author = switch (try authorizeRepoKey(io, &author_arena, handler.admin_repo_path, owner_repo.owner, owner_repo.name, parsed.service, &sess.fingerprint)) {│ │382 + .allowed => |user| user, │ │383 .denied => return switch (parsed.service) { │ │384 .upload_pack => writeError(sess, "unauthorized: this SSH key cannot read this repo"), │ │385 .receive_pack => writeError(sess, "unauthorized: this SSH key cannot push to this repo"), │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │386 }, │ │387 .not_found => return writeError(sess, "repo not found"), │ │386 - } │ │388 + }; │ │389 │ │390 const repo_path = switch (try serve_common.resolveRepoPath(io, allocator, handler.repo_root_path, handler.admin_repo_path, repo_identity, create_if_missing)) {│ │391 .ok => |p| p, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │394 }; │ │395 defer allocator.free(repo_path); │ │396 │ │395 - if (try serveIfExists(repo_path, handler.repo_root_path, &reader.interface, &writer.interface, io, allocator, parsed.service, protocol_version, handler.err)) return; │ │397 + if (try serveIfExists(repo_path, handler.repo_root_path, &reader.interface, &writer.interface, io, allocator, parsed.service, protocol_version, author, handler.err)) return;│ │398 │ │399 if (!create_if_missing) return writeError(sess, "repo not found"); │ │400 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │401 // create the on-disk repo for the just-minted event and serve the push │ │402 var repo = try createRepo(any_repo_opts.toRepoOpts(), io, allocator, repo_path); │ │403 defer repo.deinit(io, allocator); │ │402 - try servePack(repo.self_repo_opts, &repo, handler.repo_root_path, &reader.interface, &writer.interface, io, allocator, parsed.service, protocol_version, handler.err); │ │404 + try servePack(repo.self_repo_opts, &repo, handler.repo_root_path, &reader.interface, &writer.interface, io, allocator, parsed.service, protocol_version, author, handler.err);│ │405 } │ │406 │ │407 // serve a patch draft: anyone may fetch it, only its author may push to it │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │474 allocator: std.mem.Allocator, │ │475 service: GitService, │ │476 protocol_version: xit.net_server_common.ProtocolVersion, │ │477 + author: ?evt.CommitAuthor, │ │478 error_writer: *std.Io.Writer, │ │479 ) !bool { │ │480 // a bare open() creates the directory while probing for the repo, so only│ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │488 defer any_repo.deinit(io, allocator); │ │489 │ │490 switch (any_repo) { │ │488 - inline else => |*repo| try servePack(repo.self_repo_opts, repo, repo_root_path, reader, writer, io, allocator, service, protocol_version, error_writer), │ │491 + inline else => |*repo| try servePack(repo.self_repo_opts, repo, repo_root_path, reader, writer, io, allocator, service, protocol_version, author, error_writer),│ │492 } │ │493 return true; │ │494 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────╮ │516 allocator: std.mem.Allocator, │ │517 service: GitService, │ │518 protocol_version: xit.net_server_common.ProtocolVersion,│ │519 + author: ?evt.CommitAuthor, │ │520 error_writer: *std.Io.Writer, │ │521 ) !void { │ │522 switch (service) { │ ╰─────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │523 .upload_pack => try repo.uploadPack(io, allocator, reader, writer, .{ .protocol_version = protocol_version }), │ │520 - .receive_pack => try push.receivePackAndConsume(repo_opts, io, allocator, repo, reader, writer, .{ .protocol_version = protocol_version }, repo_root_path, error_writer), │ │524 + .receive_pack => try push.receivePackAndConsume(repo_opts, io, allocator, repo, reader, writer, .{ .protocol_version = protocol_version }, author, repo_root_path, error_writer),│ │525 } │ │526 } │ │527 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯