+1
-1
appview/db/follow.go
+1
-1
appview/db/follow.go
···
13
13
}
14
14
15
15
func (d *DB) AddFollow(userDid, subjectDid, rkey string) error {
16
-
query := `insert into follows (user_did, subject_did, rkey) values (?, ?, ?)`
16
+
query := `insert or ignore into follows (user_did, subject_did, rkey) values (?, ?, ?)`
17
17
_, err := d.db.Exec(query, userDid, subjectDid, rkey)
18
18
return err
19
19
}
+1
-1
appview/db/pubkeys.go
+1
-1
appview/db/pubkeys.go
···
6
6
)
7
7
8
8
func (d *DB) AddPublicKey(did, name, key string) error {
9
-
query := `insert into public_keys (did, name, key) values (?, ?, ?)`
9
+
query := `insert or ignore into public_keys (did, name, key) values (?, ?, ?)`
10
10
_, err := d.db.Exec(query, did, name, key)
11
11
return err
12
12
}
+7
-1
appview/pages/pages.go
+7
-1
appview/pages/pages.go
···
326
326
return p.executeRepo("repo/blob", w, params)
327
327
}
328
328
329
+
type Collaborator struct {
330
+
Did string
331
+
Handle string
332
+
Role string
333
+
}
334
+
329
335
type RepoSettingsParams struct {
330
336
LoggedInUser *auth.User
331
337
RepoInfo RepoInfo
332
-
Collaborators [][]string
338
+
Collaborators []Collaborator
333
339
Active string
334
340
IsCollaboratorInviteAllowed bool
335
341
}
+16
-12
appview/pages/templates/repo/settings.html
+16
-12
appview/pages/templates/repo/settings.html
···
1
1
{{ define "repoContent" }}
2
-
<h3>settings</h3>
3
-
<em>collaborators</em>
4
-
<ol>
5
-
{{ range .Collaborators }}
6
-
<li>
7
-
{{ index . 0 }} -
8
-
{{ index . 3 }}
9
-
</li>
10
-
{{ else }}
11
-
<p>no members</p>
12
-
{{ end }}
13
-
</ol>
2
+
<header class="font-bold text-sm mb-4">COLLABORATORS</header>
3
+
4
+
<div id="collaborator-list" class="flex flex-col gap-2 mb-2">
5
+
{{ range .Collaborators }}
6
+
<div id="collaborator" class="mb-2">
7
+
<a href="/{{ didOrHandle .Did .Handle }}" class="no-underline hover:underline text-black">
8
+
{{ didOrHandle .Did .Handle }}
9
+
</a>
10
+
<div>
11
+
<span class="text-sm text-gray-500">
12
+
{{ .Role }}
13
+
</span>
14
+
</div>
15
+
</div>
16
+
{{ end }}
17
+
</div>
14
18
15
19
{{ if .IsCollaboratorInviteAllowed }}
16
20
<h3>add collaborator</h3>
+41
-2
appview/state/repo.go
+41
-2
appview/state/repo.go
···
1
1
package state
2
2
3
3
import (
4
+
"context"
4
5
"encoding/json"
5
6
"fmt"
6
7
"io"
···
407
408
case http.MethodGet:
408
409
// for now, this is just pubkeys
409
410
user := s.auth.GetUser(r)
410
-
repoCollaborators, err := s.enforcer.E.GetImplicitUsersForResourceByDomain(f.OwnerSlashRepo(), f.Knot)
411
+
repoCollaborators, err := f.Collaborators(r.Context(), s)
411
412
if err != nil {
412
413
log.Println("failed to get collaborators", err)
413
414
}
414
-
log.Println(repoCollaborators)
415
415
416
416
isCollaboratorInviteAllowed := false
417
417
if user != nil {
···
452
452
func (f *FullyResolvedRepo) OwnerSlashRepo() string {
453
453
p, _ := securejoin.SecureJoin(f.OwnerDid(), f.RepoName)
454
454
return p
455
+
}
456
+
457
+
func (f *FullyResolvedRepo) Collaborators(ctx context.Context, s *State) ([]pages.Collaborator, error) {
458
+
repoCollaborators, err := s.enforcer.E.GetImplicitUsersForResourceByDomain(f.OwnerSlashRepo(), f.Knot)
459
+
if err != nil {
460
+
return nil, err
461
+
}
462
+
463
+
var collaborators []pages.Collaborator
464
+
for _, item := range repoCollaborators {
465
+
// currently only two roles: owner and member
466
+
var role string
467
+
if item[3] == "repo:owner" {
468
+
role = "owner"
469
+
} else if item[3] == "repo:collaborator" {
470
+
role = "collaborator"
471
+
} else {
472
+
continue
473
+
}
474
+
475
+
did := item[0]
476
+
477
+
var handle string
478
+
id, err := s.resolver.ResolveIdent(ctx, did)
479
+
if err != nil {
480
+
handle = ""
481
+
} else {
482
+
handle = string(id.Handle)
483
+
}
484
+
485
+
c := pages.Collaborator{
486
+
Did: did,
487
+
Handle: handle,
488
+
Role: role,
489
+
}
490
+
collaborators = append(collaborators, c)
491
+
}
492
+
493
+
return collaborators, nil
455
494
}
456
495
457
496
func fullyResolvedRepo(r *http.Request) (*FullyResolvedRepo, error) {