clean up collaborators a bit
MODIFIED
appview/db/follow.go
MODIFIED
appview/db/follow.go
@@ -13,7 +13,7 @@ RKey string}func (d *DB) AddFollow(userDid, subjectDid, rkey string) error {- query := `insert into follows (user_did, subject_did, rkey) values (?, ?, ?)`+ query := `insert or ignore into follows (user_did, subject_did, rkey) values (?, ?, ?)`_, err := d.db.Exec(query, userDid, subjectDid, rkey)return err}
MODIFIED
appview/db/pubkeys.go
MODIFIED
appview/db/pubkeys.go
@@ -6,7 +6,7 @@ "time")func (d *DB) AddPublicKey(did, name, key string) error {- query := `insert into public_keys (did, name, key) values (?, ?, ?)`+ query := `insert or ignore into public_keys (did, name, key) values (?, ?, ?)`_, err := d.db.Exec(query, did, name, key)return err}
MODIFIED
appview/pages/pages.go
MODIFIED
appview/pages/pages.go
@@ -326,10 +326,16 @@ params.Active = "overview"return p.executeRepo("repo/blob", w, params)}+type Collaborator struct {+ Did string+ Handle string+ Role string+}+type RepoSettingsParams struct {LoggedInUser *auth.UserRepoInfo RepoInfo- Collaborators [][]string+ Collaborators []CollaboratorActive stringIsCollaboratorInviteAllowed bool}
@@ -1,16 +1,20 @@{{ define "repoContent" }}- <h3>settings</h3>- <em>collaborators</em>- <ol>- {{ range .Collaborators }}- <li>- {{ index . 0 }} -- {{ index . 3 }}- </li>- {{ else }}- <p>no members</p>- {{ end }}- </ol>+ <header class="font-bold text-sm mb-4">COLLABORATORS</header>++ <div id="collaborator-list" class="flex flex-col gap-2 mb-2">+ {{ range .Collaborators }}+ <div id="collaborator" class="mb-2">+ <a href="/{{ didOrHandle .Did .Handle }}" class="no-underline hover:underline text-black">+ {{ didOrHandle .Did .Handle }}+ </a>+ <div>+ <span class="text-sm text-gray-500">+ {{ .Role }}+ </span>+ </div>+ </div>+ {{ end }}+ </div>{{ if .IsCollaboratorInviteAllowed }}<h3>add collaborator</h3>
MODIFIED
appview/state/repo.go
MODIFIED
appview/state/repo.go
@@ -1,6 +1,7 @@package stateimport (+ "context""encoding/json""fmt""io"@@ -407,11 +408,10 @@ switch r.Method {case http.MethodGet:// for now, this is just pubkeysuser := s.auth.GetUser(r)- repoCollaborators, err := s.enforcer.E.GetImplicitUsersForResourceByDomain(f.OwnerSlashRepo(), f.Knot)+ repoCollaborators, err := f.Collaborators(r.Context(), s)if err != nil {log.Println("failed to get collaborators", err)}- log.Println(repoCollaborators)isCollaboratorInviteAllowed := falseif user != nil {@@ -452,6 +452,45 @@func (f *FullyResolvedRepo) OwnerSlashRepo() string {p, _ := securejoin.SecureJoin(f.OwnerDid(), f.RepoName)return p+}++func (f *FullyResolvedRepo) Collaborators(ctx context.Context, s *State) ([]pages.Collaborator, error) {+ repoCollaborators, err := s.enforcer.E.GetImplicitUsersForResourceByDomain(f.OwnerSlashRepo(), f.Knot)+ if err != nil {+ return nil, err+ }++ var collaborators []pages.Collaborator+ for _, item := range repoCollaborators {+ // currently only two roles: owner and member+ var role string+ if item[3] == "repo:owner" {+ role = "owner"+ } else if item[3] == "repo:collaborator" {+ role = "collaborator"+ } else {+ continue+ }++ did := item[0]++ var handle string+ id, err := s.resolver.ResolveIdent(ctx, did)+ if err != nil {+ handle = ""+ } else {+ handle = string(id.Handle)+ }++ c := pages.Collaborator{+ Did: did,+ Handle: handle,+ Role: role,+ }+ collaborators = append(collaborators, c)+ }++ return collaborators, nil}func fullyResolvedRepo(r *http.Request) (*FullyResolvedRepo, error) {
MODIFIED
rbac/rbac.go
MODIFIED
rbac/rbac.go
@@ -119,6 +119,7 @@ return fmt.Errorf("invalid repo: %s", repo)}_, err := e.E.AddPolicies([][]string{+ {collaborator, domain, repo, "repo:collaborator"},{collaborator, domain, repo, "repo:settings"},{collaborator, domain, repo, "repo:push"},})