forked from tangled.org/core
this repo has no description
at knot-xrpc 2.3 kB view raw
1package xrpc 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "path/filepath" 8 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 securejoin "github.com/cyphar/filepath-securejoin" 11 "tangled.sh/tangled.sh/core/api/tangled" 12 "tangled.sh/tangled.sh/core/hook" 13 "tangled.sh/tangled.sh/core/knotserver/git" 14 "tangled.sh/tangled.sh/core/rbac" 15 xrpcerr "tangled.sh/tangled.sh/core/xrpc/errors" 16) 17 18func (x *Xrpc) ForkRepo(w http.ResponseWriter, r *http.Request) { 19 l := x.Logger.With("handler", "ForkRepo") 20 fail := func(e xrpcerr.XrpcError) { 21 l.Error("failed", "kind", e.Tag, "error", e.Message) 22 writeError(w, e, http.StatusBadRequest) 23 } 24 25 actorDid, ok := r.Context().Value(ActorDid).(syntax.DID) 26 if !ok { 27 fail(xrpcerr.MissingActorDidError) 28 return 29 } 30 31 isMember, err := x.Enforcer.IsKnotMember(actorDid.String(), rbac.ThisServer) 32 if err != nil { 33 fail(xrpcerr.GenericError(err)) 34 return 35 } 36 if !isMember { 37 fail(xrpcerr.AccessControlError(actorDid.String())) 38 return 39 } 40 41 var data tangled.RepoFork_Input 42 if err := json.NewDecoder(r.Body).Decode(&data); err != nil { 43 fail(xrpcerr.GenericError(err)) 44 return 45 } 46 47 did := data.Did 48 source := data.Source 49 50 if did == "" || source == "" { 51 fail(xrpcerr.GenericError(fmt.Errorf("did and source are required"))) 52 return 53 } 54 55 var name string 56 if data.Name != nil && *data.Name != "" { 57 name = *data.Name 58 } else { 59 name = filepath.Base(source) 60 } 61 62 relativeRepoPath := filepath.Join(did, name) 63 repoPath, err := securejoin.SecureJoin(x.Config.Repo.ScanPath, relativeRepoPath) 64 if err != nil { 65 fail(xrpcerr.GenericError(err)) 66 return 67 } 68 69 err = git.Fork(repoPath, source) 70 if err != nil { 71 l.Error("forking repo", "error", err.Error()) 72 writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 73 return 74 } 75 76 // add perms for this user to access the repo 77 err = x.Enforcer.AddRepo(did, rbac.ThisServer, relativeRepoPath) 78 if err != nil { 79 l.Error("adding repo permissions", "error", err.Error()) 80 writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 81 return 82 } 83 84 hook.SetupRepo( 85 hook.Config( 86 hook.WithScanPath(x.Config.Repo.ScanPath), 87 hook.WithInternalApi(x.Config.Server.InternalListenAddr), 88 ), 89 repoPath, 90 ) 91 92 w.WriteHeader(http.StatusOK) 93}