1package server
2
3import (
4 "github.com/haileyok/cocoon/internal/helpers"
5 "github.com/haileyok/cocoon/models"
6 "github.com/labstack/echo/v4"
7)
8
9type ComAtprotoRepoApplyWritesInput struct {
10 Repo string `json:"repo" validate:"required,atproto-did"`
11 Validate *bool `json:"bool,omitempty"`
12 Writes []ComAtprotoRepoApplyWritesItem `json:"writes"`
13 SwapCommit *string `json:"swapCommit"`
14}
15
16type ComAtprotoRepoApplyWritesItem struct {
17 Type string `json:"$type"`
18 Collection string `json:"collection"`
19 Rkey string `json:"rkey"`
20 Value *MarshalableMap `json:"value,omitempty"`
21}
22
23type ComAtprotoRepoApplyWritesOutput struct {
24 Commit RepoCommit `json:"commit"`
25 Results []ApplyWriteResult `json:"results"`
26}
27
28func (s *Server) handleApplyWrites(e echo.Context) error {
29 ctx := e.Request().Context()
30 logger := s.logger.With("name", "handleRepoApplyWrites")
31
32 var req ComAtprotoRepoApplyWritesInput
33 if err := e.Bind(&req); err != nil {
34 logger.Error("error binding", "error", err)
35 return helpers.ServerError(e, nil)
36 }
37
38 if err := e.Validate(req); err != nil {
39 logger.Error("error validating", "error", err)
40 return helpers.InputError(e, nil)
41 }
42
43 repo := e.Get("repo").(*models.RepoActor)
44
45 if repo.Repo.Did != req.Repo {
46 logger.Warn("mismatched repo/auth")
47 return helpers.InputError(e, nil)
48 }
49
50 ops := make([]Op, 0, len(req.Writes))
51 for _, item := range req.Writes {
52 ops = append(ops, Op{
53 Type: OpType(item.Type),
54 Collection: item.Collection,
55 Rkey: &item.Rkey,
56 Record: item.Value,
57 })
58 }
59
60 results, err := s.repoman.applyWrites(ctx, repo.Repo, ops, req.SwapCommit)
61 if err != nil {
62 logger.Error("error applying writes", "error", err)
63 return helpers.ServerError(e, nil)
64 }
65
66 commit := *results[0].Commit
67
68 for i := range results {
69 results[i].Commit = nil
70 }
71
72 return e.JSON(200, ComAtprotoRepoApplyWritesOutput{
73 Commit: commit,
74 Results: results,
75 })
76}