spindle: fetch and add existing collaborators when ingesting repos #399

merged
opened by oppi.li targeting master from push-vuzywsvmkwqn
Changed files
+48 -28
appview
pages
templates
repo
settings
repo
knotserver
spindle
+27 -22
appview/pages/templates/repo/settings/pipelines.html
··· 20 <div class="col-span-1 md:col-span-2"> 21 <h2 class="text-sm pb-2 uppercase font-bold">Spindle</h2> 22 <p class="text-gray-500 dark:text-gray-400"> 23 - Choose a spindle to execute your workflows on. Spindles can be 24 - selfhosted, 25 <a class="text-gray-500 dark:text-gray-400 underline" href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md"> 26 click to learn more. 27 </a> 28 </p> 29 </div> 30 - <form hx-post="/{{ $.RepoInfo.FullName }}/settings/spindle" class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch"> 31 - <select 32 - id="spindle" 33 - name="spindle" 34 - required 35 - class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700" 36 - {{ if not $.RepoInfo.Roles.IsOwner }}disabled{{ end }}> 37 - <option value="" disabled selected > 38 - Choose a spindle 39 - </option> 40 - {{ range $.Spindles }} 41 - <option value="{{ . }}" class="py-1" {{ if eq . $.CurrentSpindle }}selected{{ end }}> 42 - {{ . }} 43 </option> 44 - {{ end }} 45 - </select> 46 - <button class="btn flex gap-2 items-center" type="submit" {{ if not $.RepoInfo.Roles.IsOwner }}disabled{{ end }}> 47 - {{ i "check" "size-4" }} 48 - {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 49 - </button> 50 - </form> 51 </div> 52 {{ end }} 53
··· 20 <div class="col-span-1 md:col-span-2"> 21 <h2 class="text-sm pb-2 uppercase font-bold">Spindle</h2> 22 <p class="text-gray-500 dark:text-gray-400"> 23 + Choose a spindle to execute your workflows on. Only repository owners 24 + can configure spindles. Spindles can be selfhosted, 25 <a class="text-gray-500 dark:text-gray-400 underline" href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md"> 26 click to learn more. 27 </a> 28 </p> 29 </div> 30 + {{ if not $.RepoInfo.Roles.IsOwner }} 31 + <div class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch"> 32 + {{ or $.CurrentSpindle "No spindle configured" }} 33 + </div> 34 + {{ else }} 35 + <form hx-post="/{{ $.RepoInfo.FullName }}/settings/spindle" class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch"> 36 + <select 37 + id="spindle" 38 + name="spindle" 39 + required 40 + class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"> 41 + <option value="" disabled> 42 + Choose a spindle 43 </option> 44 + {{ range $.Spindles }} 45 + <option value="{{ . }}" class="py-1" {{ if eq . $.CurrentSpindle }}selected{{ end }}> 46 + {{ . }} 47 + </option> 48 + {{ end }} 49 + </select> 50 + <button class="btn flex gap-2 items-center" type="submit" {{ if not $.RepoInfo.Roles.IsOwner }}disabled{{ end }}> 51 + {{ i "check" "size-4" }} 52 + {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 53 + </button> 54 + </form> 55 + {{ end }} 56 </div> 57 {{ end }} 58
+2 -2
appview/repo/repo.go
··· 1225 f, err := rp.repoResolver.Resolve(r) 1226 user := rp.oauth.GetUser(r) 1227 1228 - // all spindles that this user is a member of 1229 - spindles, err := rp.enforcer.GetSpindlesForUser(user.Did) 1230 if err != nil { 1231 log.Println("failed to fetch spindles", err) 1232 return
··· 1225 f, err := rp.repoResolver.Resolve(r) 1226 user := rp.oauth.GetUser(r) 1227 1228 + // all spindles that the repo owner is a member of 1229 + spindles, err := rp.enforcer.GetSpindlesForUser(f.OwnerDid()) 1230 if err != nil { 1231 log.Println("failed to fetch spindles", err) 1232 return
-1
knotserver/ingester.go
··· 316 defer func() { 317 eventTime := event.TimeUS 318 lastTimeUs := eventTime + 1 319 - fmt.Println("lastTimeUs", lastTimeUs) 320 if err := h.db.SaveLastTimeUs(lastTimeUs); err != nil { 321 err = fmt.Errorf("(deferred) failed to save last time us: %w", err) 322 }
··· 316 defer func() { 317 eventTime := event.TimeUS 318 lastTimeUs := eventTime + 1 319 if err := h.db.SaveLastTimeUs(lastTimeUs); err != nil { 320 err = fmt.Errorf("(deferred) failed to save last time us: %w", err) 321 }
+19 -3
spindle/ingester.go
··· 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 - "path/filepath" 8 9 "tangled.sh/tangled.sh/core/api/tangled" 10 "tangled.sh/tangled.sh/core/eventconsumer" ··· 100 return nil 101 } 102 103 - func (s *Spindle) ingestRepo(_ context.Context, e *models.Event) error { 104 var err error 105 106 l := s.l.With("component", "ingester", "record", tangled.RepoNSID) 107 ··· 137 return fmt.Errorf("failed to add repo: %w", err) 138 } 139 140 // add repo to rbac 141 - if err := s.e.AddRepo(record.Owner, rbac.ThisServer, filepath.Join(record.Owner, record.Name)); err != nil { 142 l.Error("failed to add repo to enforcer", "error", err) 143 return fmt.Errorf("failed to add repo: %w", err) 144 } 145 146 // add this knot to the event consumer 147 src := eventconsumer.NewKnotSource(record.Knot) 148 s.ks.AddSource(context.Background(), src)
··· 3 import ( 4 "context" 5 "encoding/json" 6 + "errors" 7 "fmt" 8 9 "tangled.sh/tangled.sh/core/api/tangled" 10 "tangled.sh/tangled.sh/core/eventconsumer" ··· 100 return nil 101 } 102 103 + func (s *Spindle) ingestRepo(ctx context.Context, e *models.Event) error { 104 var err error 105 + did := e.Did 106 + resolver := idresolver.DefaultResolver() 107 108 l := s.l.With("component", "ingester", "record", tangled.RepoNSID) 109 ··· 139 return fmt.Errorf("failed to add repo: %w", err) 140 } 141 142 + didSlashRepo, err := securejoin.SecureJoin(record.Owner, record.Name) 143 + if err != nil { 144 + return err 145 + } 146 + 147 // add repo to rbac 148 + if err := s.e.AddRepo(record.Owner, rbac.ThisServer, didSlashRepo); err != nil { 149 l.Error("failed to add repo to enforcer", "error", err) 150 return fmt.Errorf("failed to add repo: %w", err) 151 } 152 153 + // add collaborators to rbac 154 + owner, err := resolver.ResolveIdent(ctx, did) 155 + if err != nil || owner.Handle.IsInvalidHandle() { 156 + return err 157 + } 158 + if err := s.fetchAndAddCollaborators(ctx, owner, didSlashRepo); err != nil { 159 + return err 160 + } 161 + 162 // add this knot to the event consumer 163 src := eventconsumer.NewKnotSource(record.Knot) 164 s.ks.AddSource(context.Background(), src)