1package xrpc
2
3import (
4 "encoding/json"
5 "fmt"
6 "net/http"
7 "os"
8 "path/filepath"
9
10 "github.com/bluesky-social/indigo/atproto/syntax"
11 securejoin "github.com/cyphar/filepath-securejoin"
12 "tangled.sh/tangled.sh/core/api/tangled"
13 "tangled.sh/tangled.sh/core/rbac"
14 xrpcerr "tangled.sh/tangled.sh/core/xrpc/errors"
15)
16
17func (x *Xrpc) DeleteRepo(w http.ResponseWriter, r *http.Request) {
18 l := x.Logger.With("handler", "DeleteRepo")
19 fail := func(e xrpcerr.XrpcError) {
20 l.Error("failed", "kind", e.Tag, "error", e.Message)
21 writeError(w, e, http.StatusBadRequest)
22 }
23
24 actorDid, ok := r.Context().Value(ActorDid).(syntax.DID)
25 if !ok {
26 fail(xrpcerr.MissingActorDidError)
27 return
28 }
29
30 isMember, err := x.Enforcer.IsKnotMember(actorDid.String(), rbac.ThisServer)
31 if err != nil {
32 fail(xrpcerr.GenericError(err))
33 return
34 }
35 if !isMember {
36 fail(xrpcerr.AccessControlError(actorDid.String()))
37 return
38 }
39
40 var data tangled.RepoDelete_Input
41 if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
42 fail(xrpcerr.GenericError(err))
43 return
44 }
45
46 did := data.Did
47 name := data.Name
48
49 if did == "" || name == "" {
50 fail(xrpcerr.GenericError(fmt.Errorf("did and name are required")))
51 return
52 }
53
54 relativeRepoPath := filepath.Join(did, name)
55 if ok, err := x.Enforcer.IsSettingsAllowed(actorDid.String(), rbac.ThisServer, relativeRepoPath); !ok || err != nil {
56 l.Error("insufficient permissions", "did", actorDid.String(), "repo", relativeRepoPath)
57 writeError(w, xrpcerr.AccessControlError(actorDid.String()), http.StatusUnauthorized)
58 return
59 }
60
61 repoPath, err := securejoin.SecureJoin(x.Config.Repo.ScanPath, relativeRepoPath)
62 if err != nil {
63 fail(xrpcerr.GenericError(err))
64 return
65 }
66
67 err = os.RemoveAll(repoPath)
68 if err != nil {
69 l.Error("deleting repo", "error", err.Error())
70 writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError)
71 return
72 }
73
74 err = x.Enforcer.RemoveRepo(did, rbac.ThisServer, relativeRepoPath)
75 if err != nil {
76 l.Error("failed to delete repo from enforcer", "error", err.Error())
77 writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError)
78 return
79 }
80
81 w.WriteHeader(http.StatusOK)
82}