+
{{.}}
{{ end }}
diff --git a/appview/repo/repo.go b/appview/repo/repo.go
index a989858b..414835ec 100644
--- a/appview/repo/repo.go
+++ b/appview/repo/repo.go
@@ -1418,9 +1418,15 @@ func (rp *Repo) ForkRepo(w http.ResponseWriter, r *http.Request) {
user := rp.oauth.GetMultiAccountUser(r)
knots := rp.acl.KnotsForUser(r.Context(), user.Did)
+ spindles, err := rp.enforcer.GetSpindlesForUser(user.Did)
+ if err != nil {
+ l.Error("failed to fetch spindles", "err", err)
+ }
+
rp.pages.ForkRepo(w, pages.ForkRepoParams{
BaseParams: pages.BaseParamsFromContext(r.Context()),
Knots: knots,
+ Spindles: spindles,
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
})
@@ -1439,6 +1445,21 @@ func (rp *Repo) ForkRepo(w http.ResponseWriter, r *http.Request) {
return
}
+ // optional spindle selection; validate the user is a member if provided
+ spindle := r.FormValue("spindle")
+ if spindle != "" {
+ validSpindles, err := rp.enforcer.GetSpindlesForUser(user.Did)
+ if err != nil {
+ l.Error("failed to fetch spindles", "err", err)
+ rp.pages.Notice(w, "repo", "Failed to configure spindle. Try again later.")
+ return
+ }
+ if !slices.Contains(validSpindles, spindle) {
+ rp.pages.Notice(w, "repo", "Invalid spindle selection.")
+ return
+ }
+ }
+
// choose a name for a fork
forkName := strings.ToLower(r.FormValue("repo_name"))
if forkName == "" {
@@ -1530,6 +1551,7 @@ func (rp *Repo) ForkRepo(w http.ResponseWriter, r *http.Request) {
Rkey: rkey,
Source: forkSource,
Description: forkDescription,
+ Spindle: spindle,
Created: time.Now(),
Labels: rp.config.Label.DefaultLabelDefs,
RepoDid: repoDid,
diff --git a/appview/state/state.go b/appview/state/state.go
index 73b662d4..80aadc13 100644
--- a/appview/state/state.go
+++ b/appview/state/state.go
@@ -7,6 +7,7 @@ import (
"fmt"
"log/slog"
"net/http"
+ "slices"
"strings"
"time"
@@ -449,9 +450,15 @@ func (s *State) NewRepo(w http.ResponseWriter, r *http.Request) {
user := s.oauth.GetMultiAccountUser(r)
knots := s.aclService.KnotsForUser(r.Context(), user.Did)
+ spindles, err := s.enforcer.GetSpindlesForUser(user.Did)
+ if err != nil {
+ s.logger.Error("failed to fetch spindles", "err", err)
+ }
+
s.pages.NewRepo(w, pages.NewRepoParams{
BaseParams: pages.BaseParamsFromContext(r.Context()),
Knots: knots,
+ Spindles: spindles,
})
case http.MethodPost:
@@ -494,6 +501,22 @@ func (s *State) NewRepo(w http.ResponseWriter, r *http.Request) {
return
}
+ // optional spindle selection; validate the user is a member if provided
+ spindle := r.FormValue("spindle")
+ if spindle != "" {
+ validSpindles, err := s.enforcer.GetSpindlesForUser(user.Did)
+ if err != nil {
+ l.Error("failed to fetch spindles", "err", err)
+ s.pages.Notice(w, "repo", "Failed to configure spindle. Try again later.")
+ return
+ }
+ if !slices.Contains(validSpindles, spindle) {
+ s.pages.Notice(w, "repo", "Invalid spindle selection.")
+ return
+ }
+ }
+ l = l.With("spindle", spindle)
+
// ACL validation
if !s.aclService.IsRepoCreateAllowed(r.Context(), domain, user.Did) {
l.Info("unauthorized")
@@ -570,6 +593,7 @@ func (s *State) NewRepo(w http.ResponseWriter, r *http.Request) {
Knot: domain,
Rkey: rkey,
Description: description,
+ Spindle: spindle,
Created: time.Now(),
Labels: s.config.Label.DefaultLabelDefs,
RepoDid: repoDid,