Monorepo for Tangled
at push-pmqotzqwskqq 99 lines 2.5 kB view raw
1package xrpc 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "os" 8 9 securejoin "github.com/cyphar/filepath-securejoin" 10 11 comatproto "github.com/bluesky-social/indigo/api/atproto" 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 "github.com/bluesky-social/indigo/xrpc" 14 "tangled.org/core/api/tangled" 15 "tangled.org/core/rbac" 16 xrpcerr "tangled.org/core/xrpc/errors" 17) 18 19func (x *Xrpc) DeleteRepo(w http.ResponseWriter, r *http.Request) { 20 l := x.Logger.With("handler", "DeleteRepo") 21 fail := func(e xrpcerr.XrpcError) { 22 l.Error("failed", "kind", e.Tag, "error", e.Message) 23 writeError(w, e, http.StatusBadRequest) 24 } 25 26 actorDid, ok := r.Context().Value(ActorDid).(syntax.DID) 27 if !ok { 28 fail(xrpcerr.MissingActorDidError) 29 return 30 } 31 32 var data tangled.RepoDelete_Input 33 if err := json.NewDecoder(r.Body).Decode(&data); err != nil { 34 fail(xrpcerr.GenericError(err)) 35 return 36 } 37 38 did := data.Did 39 name := data.Name 40 rkey := data.Rkey 41 42 if did == "" || name == "" { 43 fail(xrpcerr.GenericError(fmt.Errorf("did and name are required"))) 44 return 45 } 46 47 ident, err := x.Resolver.ResolveIdent(r.Context(), actorDid.String()) 48 if err != nil || ident.Handle.IsInvalidHandle() { 49 fail(xrpcerr.GenericError(err)) 50 return 51 } 52 53 xrpcc := xrpc.Client{ 54 Host: ident.PDSEndpoint(), 55 } 56 57 // ensure that the record does not exists 58 _, err = comatproto.RepoGetRecord(r.Context(), &xrpcc, "", tangled.RepoNSID, actorDid.String(), rkey) 59 if err == nil { 60 fail(xrpcerr.RecordExistsError(rkey)) 61 return 62 } 63 64 repoPath, repoDid, err := x.Db.ResolveRepoOnDisk(x.Config.Repo.ScanPath, did, name) 65 if err != nil { 66 fail(xrpcerr.GenericError(err)) 67 return 68 } 69 70 rbacResource := repoDid 71 if rbacResource == "" { 72 rbacResource, _ = securejoin.SecureJoin(did, name) 73 } 74 isDeleteAllowed, err := x.Enforcer.IsRepoDeleteAllowed(actorDid.String(), rbac.ThisServer, rbacResource) 75 if err != nil { 76 fail(xrpcerr.GenericError(err)) 77 return 78 } 79 if !isDeleteAllowed { 80 fail(xrpcerr.AccessControlError(actorDid.String())) 81 return 82 } 83 84 err = os.RemoveAll(repoPath) 85 if err != nil { 86 l.Error("deleting repo", "error", err.Error()) 87 writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 88 return 89 } 90 91 err = x.Enforcer.RemoveRepo(did, rbac.ThisServer, rbacResource) 92 if err != nil { 93 l.Error("failed to delete repo from enforcer", "error", err.Error()) 94 writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 95 return 96 } 97 98 w.WriteHeader(http.StatusOK) 99}