+14
-2
appview/db/db.go
+14
-2
appview/db/db.go
···
1
package db
2
3
import (
4
+
"context"
5
"database/sql"
6
7
_ "github.com/mattn/go-sqlite3"
8
)
9
10
type DB struct {
11
+
*sql.DB
12
+
}
13
+
14
+
type Execer interface {
15
+
Query(query string, args ...any) (*sql.Rows, error)
16
+
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
17
+
QueryRow(query string, args ...any) *sql.Row
18
+
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
19
+
Exec(query string, args ...any) (sql.Result, error)
20
+
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
21
+
Prepare(query string) (*sql.Stmt, error)
22
+
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
23
}
24
25
func Make(dbPath string) (*DB, error) {
···
116
if err != nil {
117
return nil, err
118
}
119
+
return &DB{db}, nil
120
}
+12
-12
appview/db/follow.go
+12
-12
appview/db/follow.go
···
12
RKey string
13
}
14
15
-
func (d *DB) AddFollow(userDid, subjectDid, rkey string) error {
16
query := `insert or ignore into follows (user_did, subject_did, rkey) values (?, ?, ?)`
17
-
_, err := d.db.Exec(query, userDid, subjectDid, rkey)
18
return err
19
}
20
21
// Get a follow record
22
-
func (d *DB) GetFollow(userDid, subjectDid string) (*Follow, error) {
23
query := `select user_did, subject_did, followed_at, rkey from follows where user_did = ? and subject_did = ?`
24
-
row := d.db.QueryRow(query, userDid, subjectDid)
25
26
var follow Follow
27
var followedAt string
···
42
}
43
44
// Get a follow record
45
-
func (d *DB) DeleteFollow(userDid, subjectDid string) error {
46
-
_, err := d.db.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid)
47
return err
48
}
49
50
-
func (d *DB) GetFollowerFollowing(did string) (int, int, error) {
51
followers, following := 0, 0
52
-
err := d.db.QueryRow(
53
`SELECT
54
COUNT(CASE WHEN subject_did = ? THEN 1 END) AS followers,
55
COUNT(CASE WHEN user_did = ? THEN 1 END) AS following
···
81
}
82
}
83
84
-
func (d *DB) GetFollowStatus(userDid, subjectDid string) FollowStatus {
85
if userDid == subjectDid {
86
return IsSelf
87
-
} else if _, err := d.GetFollow(userDid, subjectDid); err != nil {
88
return IsNotFollowing
89
} else {
90
return IsFollowing
91
}
92
}
93
94
-
func (d *DB) GetAllFollows() ([]Follow, error) {
95
var follows []Follow
96
97
-
rows, err := d.db.Query(`select user_did, subject_did, followed_at, rkey from follows`)
98
if err != nil {
99
return nil, err
100
}
···
12
RKey string
13
}
14
15
+
func AddFollow(e Execer, userDid, subjectDid, rkey string) error {
16
query := `insert or ignore into follows (user_did, subject_did, rkey) values (?, ?, ?)`
17
+
_, err := e.Exec(query, userDid, subjectDid, rkey)
18
return err
19
}
20
21
// Get a follow record
22
+
func GetFollow(e Execer, userDid, subjectDid string) (*Follow, error) {
23
query := `select user_did, subject_did, followed_at, rkey from follows where user_did = ? and subject_did = ?`
24
+
row := e.QueryRow(query, userDid, subjectDid)
25
26
var follow Follow
27
var followedAt string
···
42
}
43
44
// Get a follow record
45
+
func DeleteFollow(e Execer, userDid, subjectDid string) error {
46
+
_, err := e.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid)
47
return err
48
}
49
50
+
func GetFollowerFollowing(e Execer, did string) (int, int, error) {
51
followers, following := 0, 0
52
+
err := e.QueryRow(
53
`SELECT
54
COUNT(CASE WHEN subject_did = ? THEN 1 END) AS followers,
55
COUNT(CASE WHEN user_did = ? THEN 1 END) AS following
···
81
}
82
}
83
84
+
func GetFollowStatus(e Execer, userDid, subjectDid string) FollowStatus {
85
if userDid == subjectDid {
86
return IsSelf
87
+
} else if _, err := GetFollow(e, userDid, subjectDid); err != nil {
88
return IsNotFollowing
89
} else {
90
return IsFollowing
91
}
92
}
93
94
+
func GetAllFollows(e Execer) ([]Follow, error) {
95
var follows []Follow
96
97
+
rows, err := e.Query(`select user_did, subject_did, followed_at, rkey from follows`)
98
if err != nil {
99
return nil, err
100
}
+25
-29
appview/db/issues.go
+25
-29
appview/db/issues.go
···
26
Created *time.Time
27
}
28
29
-
func (d *DB) NewIssue(issue *Issue) error {
30
-
tx, err := d.db.Begin()
31
-
if err != nil {
32
-
return err
33
-
}
34
defer tx.Rollback()
35
36
-
_, err = tx.Exec(`
37
insert or ignore into repo_issue_seqs (repo_at, next_issue_id)
38
values (?, 1)
39
`, issue.RepoAt)
···
69
return nil
70
}
71
72
-
func (d *DB) SetIssueAt(repoAt string, issueId int, issueAt string) error {
73
-
_, err := d.db.Exec(`update issues set issue_at = ? where repo_at = ? and issue_id = ?`, issueAt, repoAt, issueId)
74
return err
75
}
76
77
-
func (d *DB) GetIssueAt(repoAt string, issueId int) (string, error) {
78
var issueAt string
79
-
err := d.db.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt)
80
return issueAt, err
81
}
82
83
-
func (d *DB) GetIssueId(repoAt string) (int, error) {
84
var issueId int
85
-
err := d.db.QueryRow(`select next_issue_id from repo_issue_seqs where repo_at = ?`, repoAt).Scan(&issueId)
86
return issueId - 1, err
87
}
88
89
-
func (d *DB) GetIssueOwnerDid(repoAt string, issueId int) (string, error) {
90
var ownerDid string
91
-
err := d.db.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid)
92
return ownerDid, err
93
}
94
95
-
func (d *DB) GetIssues(repoAt string) ([]Issue, error) {
96
var issues []Issue
97
98
-
rows, err := d.db.Query(`select owner_did, issue_id, created, title, body, open from issues where repo_at = ? order by created desc`, repoAt)
99
if err != nil {
100
return nil, err
101
}
···
125
return issues, nil
126
}
127
128
-
func (d *DB) GetIssue(repoAt string, issueId int) (*Issue, error) {
129
query := `select owner_did, created, title, body, open from issues where repo_at = ? and issue_id = ?`
130
-
row := d.db.QueryRow(query, repoAt, issueId)
131
132
var issue Issue
133
var createdAt string
···
145
return &issue, nil
146
}
147
148
-
func (d *DB) GetIssueWithComments(repoAt string, issueId int) (*Issue, []Comment, error) {
149
query := `select owner_did, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?`
150
-
row := d.db.QueryRow(query, repoAt, issueId)
151
152
var issue Issue
153
var createdAt string
···
162
}
163
issue.Created = &createdTime
164
165
-
comments, err := d.GetComments(repoAt, issueId)
166
if err != nil {
167
return nil, nil, err
168
}
···
170
return &issue, comments, nil
171
}
172
173
-
func (d *DB) NewComment(comment *Comment) error {
174
query := `insert into comments (owner_did, repo_at, comment_at, issue_id, comment_id, body) values (?, ?, ?, ?, ?, ?)`
175
-
_, err := d.db.Exec(
176
query,
177
comment.OwnerDid,
178
comment.RepoAt,
···
184
return err
185
}
186
187
-
func (d *DB) GetComments(repoAt string, issueId int) ([]Comment, error) {
188
var comments []Comment
189
190
-
rows, err := d.db.Query(`select owner_did, issue_id, comment_id, comment_at, body, created from comments where repo_at = ? and issue_id = ? order by created asc`, repoAt, issueId)
191
if err == sql.ErrNoRows {
192
return []Comment{}, nil
193
}
···
220
return comments, nil
221
}
222
223
-
func (d *DB) CloseIssue(repoAt string, issueId int) error {
224
-
_, err := d.db.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId)
225
return err
226
}
227
228
-
func (d *DB) ReopenIssue(repoAt string, issueId int) error {
229
-
_, err := d.db.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId)
230
return err
231
}
···
26
Created *time.Time
27
}
28
29
+
func NewIssue(tx *sql.Tx, issue *Issue) error {
30
defer tx.Rollback()
31
32
+
_, err := tx.Exec(`
33
insert or ignore into repo_issue_seqs (repo_at, next_issue_id)
34
values (?, 1)
35
`, issue.RepoAt)
···
65
return nil
66
}
67
68
+
func SetIssueAt(e Execer, repoAt string, issueId int, issueAt string) error {
69
+
_, err := e.Exec(`update issues set issue_at = ? where repo_at = ? and issue_id = ?`, issueAt, repoAt, issueId)
70
return err
71
}
72
73
+
func GetIssueAt(e Execer, repoAt string, issueId int) (string, error) {
74
var issueAt string
75
+
err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt)
76
return issueAt, err
77
}
78
79
+
func GetIssueId(e Execer, repoAt string) (int, error) {
80
var issueId int
81
+
err := e.QueryRow(`select next_issue_id from repo_issue_seqs where repo_at = ?`, repoAt).Scan(&issueId)
82
return issueId - 1, err
83
}
84
85
+
func GetIssueOwnerDid(e Execer, repoAt string, issueId int) (string, error) {
86
var ownerDid string
87
+
err := e.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid)
88
return ownerDid, err
89
}
90
91
+
func GetIssues(e Execer, repoAt string) ([]Issue, error) {
92
var issues []Issue
93
94
+
rows, err := e.Query(`select owner_did, issue_id, created, title, body, open from issues where repo_at = ? order by created desc`, repoAt)
95
if err != nil {
96
return nil, err
97
}
···
121
return issues, nil
122
}
123
124
+
func GetIssue(e Execer, repoAt string, issueId int) (*Issue, error) {
125
query := `select owner_did, created, title, body, open from issues where repo_at = ? and issue_id = ?`
126
+
row := e.QueryRow(query, repoAt, issueId)
127
128
var issue Issue
129
var createdAt string
···
141
return &issue, nil
142
}
143
144
+
func GetIssueWithComments(e Execer, repoAt string, issueId int) (*Issue, []Comment, error) {
145
query := `select owner_did, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?`
146
+
row := e.QueryRow(query, repoAt, issueId)
147
148
var issue Issue
149
var createdAt string
···
158
}
159
issue.Created = &createdTime
160
161
+
comments, err := GetComments(e, repoAt, issueId)
162
if err != nil {
163
return nil, nil, err
164
}
···
166
return &issue, comments, nil
167
}
168
169
+
func NewComment(e Execer, comment *Comment) error {
170
query := `insert into comments (owner_did, repo_at, comment_at, issue_id, comment_id, body) values (?, ?, ?, ?, ?, ?)`
171
+
_, err := e.Exec(
172
query,
173
comment.OwnerDid,
174
comment.RepoAt,
···
180
return err
181
}
182
183
+
func GetComments(e Execer, repoAt string, issueId int) ([]Comment, error) {
184
var comments []Comment
185
186
+
rows, err := e.Query(`select owner_did, issue_id, comment_id, comment_at, body, created from comments where repo_at = ? and issue_id = ? order by created asc`, repoAt, issueId)
187
if err == sql.ErrNoRows {
188
return []Comment{}, nil
189
}
···
216
return comments, nil
217
}
218
219
+
func CloseIssue(e Execer, repoAt string, issueId int) error {
220
+
_, err := e.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId)
221
return err
222
}
223
224
+
func ReopenIssue(e Execer, repoAt string, issueId int) error {
225
+
_, err := e.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId)
226
return err
227
}
+10
-6
appview/db/jetstream.go
+10
-6
appview/db/jetstream.go
···
1
package db
2
3
-
func (d *DB) SaveLastTimeUs(lastTimeUs int64) error {
4
-
_, err := d.db.Exec(`insert into _jetstream (last_time_us) values (?)`, lastTimeUs)
5
return err
6
}
7
8
-
func (d *DB) UpdateLastTimeUs(lastTimeUs int64) error {
9
-
_, err := d.db.Exec(`update _jetstream set last_time_us = ? where rowid = 1`, lastTimeUs)
10
if err != nil {
11
return err
12
}
13
return nil
14
}
15
16
-
func (d *DB) GetLastTimeUs() (int64, error) {
17
var lastTimeUs int64
18
-
row := d.db.QueryRow(`select last_time_us from _jetstream`)
19
err := row.Scan(&lastTimeUs)
20
return lastTimeUs, err
21
}
···
1
package db
2
3
+
type DbWrapper struct {
4
+
Execer
5
+
}
6
+
7
+
func (db DbWrapper) SaveLastTimeUs(lastTimeUs int64) error {
8
+
_, err := db.Exec(`insert into _jetstream (last_time_us) values (?)`, lastTimeUs)
9
return err
10
}
11
12
+
func (db DbWrapper) UpdateLastTimeUs(lastTimeUs int64) error {
13
+
_, err := db.Exec(`update _jetstream set last_time_us = ? where rowid = 1`, lastTimeUs)
14
if err != nil {
15
return err
16
}
17
return nil
18
}
19
20
+
func (db DbWrapper) GetLastTimeUs() (int64, error) {
21
var lastTimeUs int64
22
+
row := db.QueryRow(`select last_time_us from _jetstream`)
23
err := row.Scan(&lastTimeUs)
24
return lastTimeUs, err
25
}
+8
-8
appview/db/pubkeys.go
+8
-8
appview/db/pubkeys.go
···
5
"time"
6
)
7
8
-
func (d *DB) AddPublicKey(did, name, key string) error {
9
query := `insert or ignore into public_keys (did, name, key) values (?, ?, ?)`
10
-
_, err := d.db.Exec(query, did, name, key)
11
return err
12
}
13
14
-
func (d *DB) RemovePublicKey(did string) error {
15
query := `delete from public_keys where did = ?`
16
-
_, err := d.db.Exec(query, did)
17
return err
18
}
19
···
35
})
36
}
37
38
-
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
39
var keys []PublicKey
40
41
-
rows, err := d.db.Query(`select key, name, did, created from public_keys`)
42
if err != nil {
43
return nil, err
44
}
···
62
return keys, nil
63
}
64
65
-
func (d *DB) GetPublicKeys(did string) ([]PublicKey, error) {
66
var keys []PublicKey
67
68
-
rows, err := d.db.Query(`select did, key, name, created from public_keys where did = ?`, did)
69
if err != nil {
70
return nil, err
71
}
···
5
"time"
6
)
7
8
+
func AddPublicKey(e Execer, did, name, key string) error {
9
query := `insert or ignore into public_keys (did, name, key) values (?, ?, ?)`
10
+
_, err := e.Exec(query, did, name, key)
11
return err
12
}
13
14
+
func RemovePublicKey(e Execer, did string) error {
15
query := `delete from public_keys where did = ?`
16
+
_, err := e.Exec(query, did)
17
return err
18
}
19
···
35
})
36
}
37
38
+
func GetAllPublicKeys(e Execer) ([]PublicKey, error) {
39
var keys []PublicKey
40
41
+
rows, err := e.Query(`select key, name, did, created from public_keys`)
42
if err != nil {
43
return nil, err
44
}
···
62
return keys, nil
63
}
64
65
+
func GetPublicKeys(e Execer, did string) ([]PublicKey, error) {
66
var keys []PublicKey
67
68
+
rows, err := e.Query(`select did, key, name, created from public_keys where did = ?`, did)
69
if err != nil {
70
return nil, err
71
}
+11
-11
appview/db/registration.go
+11
-11
appview/db/registration.go
···
32
)
33
34
// returns registered status, did of owner, error
35
-
func (d *DB) RegistrationsByDid(did string) ([]Registration, error) {
36
var registrations []Registration
37
38
-
rows, err := d.db.Query(`
39
select domain, did, created, registered from registrations
40
where did = ?
41
`, did)
···
69
}
70
71
// returns registered status, did of owner, error
72
-
func (d *DB) RegistrationByDomain(domain string) (*Registration, error) {
73
var createdAt *string
74
var registeredAt *string
75
var registration Registration
76
77
-
err := d.db.QueryRow(`
78
select domain, did, created, registered from registrations
79
where domain = ?
80
`, domain).Scan(®istration.Domain, ®istration.ByDid, &createdAt, ®isteredAt)
···
106
return hex.EncodeToString(key)
107
}
108
109
-
func (d *DB) GenerateRegistrationKey(domain, did string) (string, error) {
110
// sanity check: does this domain already have a registration?
111
-
reg, err := d.RegistrationByDomain(domain)
112
if err != nil {
113
return "", err
114
}
···
127
128
secret := genSecret()
129
130
-
_, err = d.db.Exec(`
131
insert into registrations (domain, did, secret)
132
values (?, ?, ?)
133
on conflict(domain) do update set did = excluded.did, secret = excluded.secret
···
140
return secret, nil
141
}
142
143
-
func (d *DB) GetRegistrationKey(domain string) (string, error) {
144
-
res := d.db.QueryRow(`select secret from registrations where domain = ?`, domain)
145
146
var secret string
147
err := res.Scan(&secret)
···
152
return secret, nil
153
}
154
155
-
func (d *DB) Register(domain string) error {
156
-
_, err := d.db.Exec(`
157
update registrations
158
set registered = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
159
where domain = ?;
···
32
)
33
34
// returns registered status, did of owner, error
35
+
func RegistrationsByDid(e Execer, did string) ([]Registration, error) {
36
var registrations []Registration
37
38
+
rows, err := e.Query(`
39
select domain, did, created, registered from registrations
40
where did = ?
41
`, did)
···
69
}
70
71
// returns registered status, did of owner, error
72
+
func RegistrationByDomain(e Execer, domain string) (*Registration, error) {
73
var createdAt *string
74
var registeredAt *string
75
var registration Registration
76
77
+
err := e.QueryRow(`
78
select domain, did, created, registered from registrations
79
where domain = ?
80
`, domain).Scan(®istration.Domain, ®istration.ByDid, &createdAt, ®isteredAt)
···
106
return hex.EncodeToString(key)
107
}
108
109
+
func GenerateRegistrationKey(e Execer, domain, did string) (string, error) {
110
// sanity check: does this domain already have a registration?
111
+
reg, err := RegistrationByDomain(e, domain)
112
if err != nil {
113
return "", err
114
}
···
127
128
secret := genSecret()
129
130
+
_, err = e.Exec(`
131
insert into registrations (domain, did, secret)
132
values (?, ?, ?)
133
on conflict(domain) do update set did = excluded.did, secret = excluded.secret
···
140
return secret, nil
141
}
142
143
+
func GetRegistrationKey(e Execer, domain string) (string, error) {
144
+
res := e.QueryRow(`select secret from registrations where domain = ?`, domain)
145
146
var secret string
147
err := res.Scan(&secret)
···
152
return secret, nil
153
}
154
155
+
func Register(e Execer, domain string) error {
156
+
_, err := e.Exec(`
157
update registrations
158
set registered = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
159
where domain = ?;
+14
-14
appview/db/repos.go
+14
-14
appview/db/repos.go
···
14
AtUri string
15
}
16
17
-
func (d *DB) GetAllRepos() ([]Repo, error) {
18
var repos []Repo
19
20
-
rows, err := d.db.Query(`select did, name, knot, rkey, created from repos`)
21
if err != nil {
22
return nil, err
23
}
···
39
return repos, nil
40
}
41
42
-
func (d *DB) GetAllReposByDid(did string) ([]Repo, error) {
43
var repos []Repo
44
45
-
rows, err := d.db.Query(`select did, name, knot, rkey, created from repos where did = ?`, did)
46
if err != nil {
47
return nil, err
48
}
···
64
return repos, nil
65
}
66
67
-
func (d *DB) GetRepo(did, name string) (*Repo, error) {
68
var repo Repo
69
70
-
row := d.db.QueryRow(`select did, name, knot, created, at_uri from repos where did = ? and name = ?`, did, name)
71
72
var createdAt string
73
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri); err != nil {
···
79
return &repo, nil
80
}
81
82
-
func (d *DB) AddRepo(repo *Repo) error {
83
-
_, err := d.db.Exec(`insert into repos (did, name, knot, rkey, at_uri) values (?, ?, ?, ?, ?)`, repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri)
84
return err
85
}
86
87
-
func (d *DB) RemoveRepo(did, name, rkey string) error {
88
-
_, err := d.db.Exec(`delete from repos where did = ? and name = ? and rkey = ?`, did, name, rkey)
89
return err
90
}
91
92
-
func (d *DB) AddCollaborator(collaborator, repoOwnerDid, repoName, repoKnot string) error {
93
-
_, err := d.db.Exec(
94
`insert into collaborators (did, repo)
95
values (?, (select id from repos where did = ? and name = ? and knot = ?));`,
96
collaborator, repoOwnerDid, repoName, repoKnot)
97
return err
98
}
99
100
-
func (d *DB) CollaboratingIn(collaborator string) ([]Repo, error) {
101
var repos []Repo
102
103
-
rows, err := d.db.Query(`select r.did, r.name, r.knot, r.rkey, r.created from repos r join collaborators c on r.id = c.repo where c.did = ?;`, collaborator)
104
if err != nil {
105
return nil, err
106
}
···
14
AtUri string
15
}
16
17
+
func GetAllRepos(e Execer) ([]Repo, error) {
18
var repos []Repo
19
20
+
rows, err := e.Query(`select did, name, knot, rkey, created from repos`)
21
if err != nil {
22
return nil, err
23
}
···
39
return repos, nil
40
}
41
42
+
func GetAllReposByDid(e Execer, did string) ([]Repo, error) {
43
var repos []Repo
44
45
+
rows, err := e.Query(`select did, name, knot, rkey, created from repos where did = ?`, did)
46
if err != nil {
47
return nil, err
48
}
···
64
return repos, nil
65
}
66
67
+
func GetRepo(e Execer, did, name string) (*Repo, error) {
68
var repo Repo
69
70
+
row := e.QueryRow(`select did, name, knot, created, at_uri from repos where did = ? and name = ?`, did, name)
71
72
var createdAt string
73
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri); err != nil {
···
79
return &repo, nil
80
}
81
82
+
func AddRepo(e Execer, repo *Repo) error {
83
+
_, err := e.Exec(`insert into repos (did, name, knot, rkey, at_uri) values (?, ?, ?, ?, ?)`, repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri)
84
return err
85
}
86
87
+
func RemoveRepo(e Execer, did, name, rkey string) error {
88
+
_, err := e.Exec(`delete from repos where did = ? and name = ? and rkey = ?`, did, name, rkey)
89
return err
90
}
91
92
+
func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error {
93
+
_, err := e.Exec(
94
`insert into collaborators (did, repo)
95
values (?, (select id from repos where did = ? and name = ? and knot = ?));`,
96
collaborator, repoOwnerDid, repoName, repoKnot)
97
return err
98
}
99
100
+
func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) {
101
var repos []Repo
102
103
+
rows, err := e.Query(`select r.did, r.name, r.knot, r.rkey, r.created from repos r join collaborators c on r.id = c.repo where c.did = ?;`, collaborator)
104
if err != nil {
105
return nil, err
106
}
+3
-3
appview/db/timeline.go
+3
-3
appview/db/timeline.go
+1
-1
appview/pages/templates/repo/new.html
+1
-1
appview/pages/templates/repo/new.html
+4
-3
appview/state/follow.go
+4
-3
appview/state/follow.go
···
9
comatproto "github.com/bluesky-social/indigo/api/atproto"
10
lexutil "github.com/bluesky-social/indigo/lex/util"
11
tangled "github.com/sotangled/tangled/api/tangled"
12
)
13
14
func (s *State) Follow(w http.ResponseWriter, r *http.Request) {
···
51
return
52
}
53
54
-
err = s.db.AddFollow(currentUser.Did, subjectIdent.DID.String(), rkey)
55
if err != nil {
56
log.Println("failed to follow", err)
57
return
···
73
return
74
case http.MethodDelete:
75
// find the record in the db
76
-
follow, err := s.db.GetFollow(currentUser.Did, subjectIdent.DID.String())
77
if err != nil {
78
log.Println("failed to get follow relationship")
79
return
···
90
return
91
}
92
93
-
err = s.db.DeleteFollow(currentUser.Did, subjectIdent.DID.String())
94
if err != nil {
95
log.Println("failed to delete follow from DB")
96
// this is not an issue, the firehose event might have already done this
···
9
comatproto "github.com/bluesky-social/indigo/api/atproto"
10
lexutil "github.com/bluesky-social/indigo/lex/util"
11
tangled "github.com/sotangled/tangled/api/tangled"
12
+
"github.com/sotangled/tangled/appview/db"
13
)
14
15
func (s *State) Follow(w http.ResponseWriter, r *http.Request) {
···
52
return
53
}
54
55
+
err = db.AddFollow(s.db, currentUser.Did, subjectIdent.DID.String(), rkey)
56
if err != nil {
57
log.Println("failed to follow", err)
58
return
···
74
return
75
case http.MethodDelete:
76
// find the record in the db
77
+
follow, err := db.GetFollow(s.db, currentUser.Did, subjectIdent.DID.String())
78
if err != nil {
79
log.Println("failed to get follow relationship")
80
return
···
91
return
92
}
93
94
+
err = db.DeleteFollow(s.db, currentUser.Did, subjectIdent.DID.String())
95
if err != nil {
96
log.Println("failed to delete follow from DB")
97
// this is not an issue, the firehose event might have already done this
+3
-3
appview/state/jetstream.go
+3
-3
appview/state/jetstream.go
···
13
14
type Ingester func(ctx context.Context, e *models.Event) error
15
16
-
func jetstreamIngester(db *db.DB) Ingester {
17
return func(ctx context.Context, e *models.Event) error {
18
var err error
19
defer func() {
20
eventTime := e.TimeUS
21
lastTimeUs := eventTime + 1
22
-
if err := db.UpdateLastTimeUs(lastTimeUs); err != nil {
23
err = fmt.Errorf("(deferred) failed to save last time us: %w", err)
24
}
25
}()
···
39
log.Println("invalid record")
40
return err
41
}
42
-
err = db.AddFollow(did, record.Subject, e.Commit.RKey)
43
if err != nil {
44
return fmt.Errorf("failed to add follow to db: %w", err)
45
}
···
13
14
type Ingester func(ctx context.Context, e *models.Event) error
15
16
+
func jetstreamIngester(d db.DbWrapper) Ingester {
17
return func(ctx context.Context, e *models.Event) error {
18
var err error
19
defer func() {
20
eventTime := e.TimeUS
21
lastTimeUs := eventTime + 1
22
+
if err := d.UpdateLastTimeUs(lastTimeUs); err != nil {
23
err = fmt.Errorf("(deferred) failed to save last time us: %w", err)
24
}
25
}()
···
39
log.Println("invalid record")
40
return err
41
}
42
+
err = db.AddFollow(d, did, record.Subject, e.Commit.RKey)
43
if err != nil {
44
return fmt.Errorf("failed to add follow to db: %w", err)
45
}
+2
-1
appview/state/middleware.go
+2
-1
appview/state/middleware.go
···
13
"github.com/go-chi/chi/v5"
14
"github.com/sotangled/tangled/appview"
15
"github.com/sotangled/tangled/appview/auth"
16
)
17
18
type Middleware func(http.Handler) http.Handler
···
176
return
177
}
178
179
-
repo, err := s.db.GetRepo(id.DID.String(), repoName)
180
if err != nil {
181
// invalid did or handle
182
log.Println("failed to resolve repo")
···
13
"github.com/go-chi/chi/v5"
14
"github.com/sotangled/tangled/appview"
15
"github.com/sotangled/tangled/appview/auth"
16
+
"github.com/sotangled/tangled/appview/db"
17
)
18
19
type Middleware func(http.Handler) http.Handler
···
177
return
178
}
179
180
+
repo, err := db.GetRepo(s.db, id.DID.String(), repoName)
181
if err != nil {
182
// invalid did or handle
183
log.Println("failed to resolve repo")
+46
-12
appview/state/repo.go
+46
-12
appview/state/repo.go
···
389
390
// TODO: create an atproto record for this
391
392
-
secret, err := s.db.GetRegistrationKey(f.Knot)
393
if err != nil {
394
log.Printf("no key found for domain %s: %s\n", f.Knot, err)
395
return
···
412
return
413
}
414
415
err = s.enforcer.AddCollaborator(collaboratorIdent.DID.String(), f.Knot, f.OwnerSlashRepo())
416
if err != nil {
417
w.Write([]byte(fmt.Sprint("failed to add collaborator: ", err)))
418
return
419
}
420
421
-
err = s.db.AddCollaborator(collaboratorIdent.DID.String(), f.OwnerDid(), f.RepoName, f.Knot)
422
if err != nil {
423
w.Write([]byte(fmt.Sprint("failed to add collaborator: ", err)))
424
return
425
}
426
427
w.Write([]byte(fmt.Sprint("added collaborator: ", collaboratorIdent.Handle.String())))
428
429
}
···
546
return
547
}
548
549
-
issue, comments, err := s.db.GetIssueWithComments(f.RepoAt, issueIdInt)
550
if err != nil {
551
log.Println("failed to get issue and comments", err)
552
s.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
···
605
return
606
}
607
608
-
issue, err := s.db.GetIssue(f.RepoAt, issueIdInt)
609
if err != nil {
610
log.Println("failed to get issue", err)
611
s.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
645
return
646
}
647
648
-
err := s.db.CloseIssue(f.RepoAt, issueIdInt)
649
if err != nil {
650
log.Println("failed to close issue", err)
651
s.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
678
}
679
680
if user.Did == f.OwnerDid() {
681
-
err := s.db.ReopenIssue(f.RepoAt, issueIdInt)
682
if err != nil {
683
log.Println("failed to reopen issue", err)
684
s.pages.Notice(w, "issue-action", "Failed to reopen issue. Try again later.")
···
719
720
commentId := rand.IntN(1000000)
721
722
-
err := s.db.NewComment(&db.Comment{
723
OwnerDid: user.Did,
724
RepoAt: f.RepoAt,
725
Issue: issueIdInt,
···
735
createdAt := time.Now().Format(time.RFC3339)
736
commentIdInt64 := int64(commentId)
737
ownerDid := user.Did
738
-
issueAt, err := s.db.GetIssueAt(f.RepoAt, issueIdInt)
739
if err != nil {
740
log.Println("failed to get issue at", err)
741
s.pages.Notice(w, "issue-comment", "Failed to create comment.")
···
777
return
778
}
779
780
-
issues, err := s.db.GetIssues(f.RepoAt)
781
if err != nil {
782
log.Println("failed to get issues", err)
783
s.pages.Notice(w, "issues", "Failed to load issues. Try again later.")
···
841
return
842
}
843
844
-
err = s.db.NewIssue(&db.Issue{
845
RepoAt: f.RepoAt,
846
Title: title,
847
Body: body,
···
853
return
854
}
855
856
-
issueId, err := s.db.GetIssueId(f.RepoAt)
857
if err != nil {
858
log.Println("failed to get issue id", err)
859
s.pages.Notice(w, "issues", "Failed to create issue.")
···
881
return
882
}
883
884
-
err = s.db.SetIssueAt(f.RepoAt, issueId, resp.Uri)
885
if err != nil {
886
log.Println("failed to set issue at", err)
887
s.pages.Notice(w, "issues", "Failed to create issue.")
···
389
390
// TODO: create an atproto record for this
391
392
+
secret, err := db.GetRegistrationKey(s.db, f.Knot)
393
if err != nil {
394
log.Printf("no key found for domain %s: %s\n", f.Knot, err)
395
return
···
412
return
413
}
414
415
+
tx, err := s.db.BeginTx(r.Context(), nil)
416
+
if err != nil {
417
+
log.Println("failed to start tx")
418
+
w.Write([]byte(fmt.Sprint("failed to add collaborator: ", err)))
419
+
return
420
+
}
421
+
defer func() {
422
+
tx.Rollback()
423
+
err = s.enforcer.E.LoadPolicy()
424
+
if err != nil {
425
+
log.Println("failed to rollback policies")
426
+
}
427
+
}()
428
+
429
err = s.enforcer.AddCollaborator(collaboratorIdent.DID.String(), f.Knot, f.OwnerSlashRepo())
430
if err != nil {
431
w.Write([]byte(fmt.Sprint("failed to add collaborator: ", err)))
432
return
433
}
434
435
+
err = db.AddCollaborator(s.db, collaboratorIdent.DID.String(), f.OwnerDid(), f.RepoName, f.Knot)
436
if err != nil {
437
w.Write([]byte(fmt.Sprint("failed to add collaborator: ", err)))
438
return
439
}
440
441
+
err = tx.Commit()
442
+
if err != nil {
443
+
log.Println("failed to commit changes", err)
444
+
http.Error(w, err.Error(), http.StatusInternalServerError)
445
+
return
446
+
}
447
+
448
+
err = s.enforcer.E.SavePolicy()
449
+
if err != nil {
450
+
log.Println("failed to update ACLs", err)
451
+
http.Error(w, err.Error(), http.StatusInternalServerError)
452
+
return
453
+
}
454
+
455
w.Write([]byte(fmt.Sprint("added collaborator: ", collaboratorIdent.Handle.String())))
456
457
}
···
574
return
575
}
576
577
+
issue, comments, err := db.GetIssueWithComments(s.db, f.RepoAt, issueIdInt)
578
if err != nil {
579
log.Println("failed to get issue and comments", err)
580
s.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
···
633
return
634
}
635
636
+
issue, err := db.GetIssue(s.db, f.RepoAt, issueIdInt)
637
if err != nil {
638
log.Println("failed to get issue", err)
639
s.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
673
return
674
}
675
676
+
err := db.CloseIssue(s.db, f.RepoAt, issueIdInt)
677
if err != nil {
678
log.Println("failed to close issue", err)
679
s.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
706
}
707
708
if user.Did == f.OwnerDid() {
709
+
err := db.ReopenIssue(s.db, f.RepoAt, issueIdInt)
710
if err != nil {
711
log.Println("failed to reopen issue", err)
712
s.pages.Notice(w, "issue-action", "Failed to reopen issue. Try again later.")
···
747
748
commentId := rand.IntN(1000000)
749
750
+
err := db.NewComment(s.db, &db.Comment{
751
OwnerDid: user.Did,
752
RepoAt: f.RepoAt,
753
Issue: issueIdInt,
···
763
createdAt := time.Now().Format(time.RFC3339)
764
commentIdInt64 := int64(commentId)
765
ownerDid := user.Did
766
+
issueAt, err := db.GetIssueAt(s.db, f.RepoAt, issueIdInt)
767
if err != nil {
768
log.Println("failed to get issue at", err)
769
s.pages.Notice(w, "issue-comment", "Failed to create comment.")
···
805
return
806
}
807
808
+
issues, err := db.GetIssues(s.db, f.RepoAt)
809
if err != nil {
810
log.Println("failed to get issues", err)
811
s.pages.Notice(w, "issues", "Failed to load issues. Try again later.")
···
869
return
870
}
871
872
+
tx, err := s.db.BeginTx(r.Context(), nil)
873
+
if err != nil {
874
+
s.pages.Notice(w, "issues", "Failed to create issue, try again later")
875
+
return
876
+
}
877
+
878
+
err = db.NewIssue(tx, &db.Issue{
879
RepoAt: f.RepoAt,
880
Title: title,
881
Body: body,
···
887
return
888
}
889
890
+
issueId, err := db.GetIssueId(s.db, f.RepoAt)
891
if err != nil {
892
log.Println("failed to get issue id", err)
893
s.pages.Notice(w, "issues", "Failed to create issue.")
···
915
return
916
}
917
918
+
err = db.SetIssueAt(s.db, f.RepoAt, issueId, resp.Uri)
919
if err != nil {
920
log.Println("failed to set issue at", err)
921
s.pages.Notice(w, "issues", "Failed to create issue.")
+3
-2
appview/state/settings.go
+3
-2
appview/state/settings.go
···
10
lexutil "github.com/bluesky-social/indigo/lex/util"
11
"github.com/gliderlabs/ssh"
12
"github.com/sotangled/tangled/api/tangled"
13
"github.com/sotangled/tangled/appview/pages"
14
)
15
16
func (s *State) Settings(w http.ResponseWriter, r *http.Request) {
17
// for now, this is just pubkeys
18
user := s.auth.GetUser(r)
19
-
pubKeys, err := s.db.GetPublicKeys(user.Did)
20
if err != nil {
21
log.Println(err)
22
}
···
47
return
48
}
49
50
-
if err := s.db.AddPublicKey(did, name, key); err != nil {
51
log.Printf("adding public key: %s", err)
52
s.pages.Notice(w, "settings-keys", "Failed to add public key.")
53
return
···
10
lexutil "github.com/bluesky-social/indigo/lex/util"
11
"github.com/gliderlabs/ssh"
12
"github.com/sotangled/tangled/api/tangled"
13
+
"github.com/sotangled/tangled/appview/db"
14
"github.com/sotangled/tangled/appview/pages"
15
)
16
17
func (s *State) Settings(w http.ResponseWriter, r *http.Request) {
18
// for now, this is just pubkeys
19
user := s.auth.GetUser(r)
20
+
pubKeys, err := db.GetPublicKeys(s.db, user.Did)
21
if err != nil {
22
log.Println(err)
23
}
···
48
return
49
}
50
51
+
if err := db.AddPublicKey(s.db, did, name, key); err != nil {
52
log.Printf("adding public key: %s", err)
53
s.pages.Notice(w, "settings-keys", "Failed to add public key.")
54
return
+99
-36
appview/state/state.go
+99
-36
appview/state/state.go
···
39
}
40
41
func Make(config *appview.Config) (*State, error) {
42
-
db, err := db.Make(config.DbPath)
43
if err != nil {
44
return nil, err
45
}
···
60
61
resolver := appview.NewResolver()
62
63
-
jc, err := jetstream.NewJetstreamClient("appview", []string{tangled.GraphFollowNSID}, nil, slog.Default(), db, false)
64
if err != nil {
65
return nil, fmt.Errorf("failed to create jetstream client: %w", err)
66
}
67
-
err = jc.StartJetstream(context.Background(), jetstreamIngester(db))
68
if err != nil {
69
return nil, fmt.Errorf("failed to start jetstream watcher: %w", err)
70
}
71
72
state := &State{
73
-
db,
74
auth,
75
enforcer,
76
clock,
···
135
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
136
user := s.auth.GetUser(r)
137
138
-
timeline, err := s.db.MakeTimeline()
139
if err != nil {
140
log.Println(err)
141
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
···
195
return
196
}
197
198
-
key, err := s.db.GenerateRegistrationKey(domain, did)
199
200
if err != nil {
201
log.Println(err)
···
222
return
223
}
224
225
-
pubKeys, err := s.db.GetPublicKeys(id.DID.String())
226
if err != nil {
227
w.WriteHeader(http.StatusNotFound)
228
return
···
250
}
251
log.Println("checking ", domain)
252
253
-
secret, err := s.db.GetRegistrationKey(domain)
254
if err != nil {
255
log.Printf("no key found for domain %s: %s\n", domain, err)
256
return
···
295
return
296
}
297
298
// mark as registered
299
-
err = s.db.Register(domain)
300
if err != nil {
301
log.Println("failed to register domain", err)
302
http.Error(w, err.Error(), http.StatusInternalServerError)
···
304
}
305
306
// set permissions for this did as owner
307
-
reg, err := s.db.RegistrationByDomain(domain)
308
if err != nil {
309
log.Println("failed to register domain", err)
310
http.Error(w, err.Error(), http.StatusInternalServerError)
···
327
return
328
}
329
330
w.Write([]byte("check success"))
331
}
332
···
338
}
339
340
user := s.auth.GetUser(r)
341
-
reg, err := s.db.RegistrationByDomain(domain)
342
if err != nil {
343
w.Write([]byte("failed to pull up registration info"))
344
return
···
370
func (s *State) Knots(w http.ResponseWriter, r *http.Request) {
371
// for now, this is just pubkeys
372
user := s.auth.GetUser(r)
373
-
registrations, err := s.db.RegistrationsByDid(user.Did)
374
if err != nil {
375
log.Println(err)
376
}
···
444
}
445
log.Println("created atproto record: ", resp.Uri)
446
447
-
secret, err := s.db.GetRegistrationKey(domain)
448
if err != nil {
449
log.Printf("no key found for domain %s: %s\n", domain, err)
450
return
···
520
return
521
}
522
523
-
secret, err := s.db.GetRegistrationKey(domain)
524
if err != nil {
525
s.pages.Notice(w, "repo", fmt.Sprintf("No registration key found for knot %s.", domain))
526
return
···
532
return
533
}
534
535
-
resp, err := client.NewRepo(user.Did, repoName, defaultBranch)
536
-
if err != nil {
537
-
s.pages.Notice(w, "repo", "Failed to create repository on knot server.")
538
-
return
539
-
}
540
-
541
-
switch resp.StatusCode {
542
-
case http.StatusConflict:
543
-
s.pages.Notice(w, "repo", "A repository with that name already exists.")
544
-
return
545
-
case http.StatusInternalServerError:
546
-
s.pages.Notice(w, "repo", "Failed to create repository on knot. Try again later.")
547
-
case http.StatusNoContent:
548
-
// continue
549
-
}
550
-
551
rkey := s.TID()
552
repo := &db.Repo{
553
Did: user.Did,
···
578
}
579
log.Println("created repo record: ", atresp.Uri)
580
581
-
repo.AtUri = atresp.Uri
582
583
-
err = s.db.AddRepo(repo)
584
if err != nil {
585
log.Println(err)
586
s.pages.Notice(w, "repo", "Failed to save repository information.")
···
596
return
597
}
598
599
s.pages.HxLocation(w, fmt.Sprintf("/@%s/%s", user.Handle, repoName))
600
return
601
}
···
615
return
616
}
617
618
-
repos, err := s.db.GetAllReposByDid(ident.DID.String())
619
if err != nil {
620
log.Printf("getting repos for %s: %s", ident.DID.String(), err)
621
}
622
623
-
collaboratingRepos, err := s.db.CollaboratingIn(ident.DID.String())
624
if err != nil {
625
log.Printf("getting collaborating repos for %s: %s", ident.DID.String(), err)
626
}
···
638
}
639
}
640
641
-
followers, following, err := s.db.GetFollowerFollowing(ident.DID.String())
642
if err != nil {
643
log.Printf("getting follow stats repos for %s: %s", ident.DID.String(), err)
644
}
···
646
loggedInUser := s.auth.GetUser(r)
647
followStatus := db.IsNotFollowing
648
if loggedInUser != nil {
649
-
followStatus = s.db.GetFollowStatus(loggedInUser.Did, ident.DID.String())
650
}
651
652
profileAvatarUri, err := GetAvatarUri(ident.DID.String())
···
818
819
r.Route("/repo", func(r chi.Router) {
820
r.Route("/new", func(r chi.Router) {
821
r.Get("/", s.AddRepo)
822
r.Post("/", s.AddRepo)
823
})
···
39
}
40
41
func Make(config *appview.Config) (*State, error) {
42
+
d, err := db.Make(config.DbPath)
43
if err != nil {
44
return nil, err
45
}
···
60
61
resolver := appview.NewResolver()
62
63
+
wrapper := db.DbWrapper{d}
64
+
jc, err := jetstream.NewJetstreamClient("appview", []string{tangled.GraphFollowNSID}, nil, slog.Default(), wrapper, false)
65
if err != nil {
66
return nil, fmt.Errorf("failed to create jetstream client: %w", err)
67
}
68
+
err = jc.StartJetstream(context.Background(), jetstreamIngester(wrapper))
69
if err != nil {
70
return nil, fmt.Errorf("failed to start jetstream watcher: %w", err)
71
}
72
73
state := &State{
74
+
d,
75
auth,
76
enforcer,
77
clock,
···
136
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
137
user := s.auth.GetUser(r)
138
139
+
timeline, err := db.MakeTimeline(s.db)
140
if err != nil {
141
log.Println(err)
142
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
···
196
return
197
}
198
199
+
key, err := db.GenerateRegistrationKey(s.db, domain, did)
200
201
if err != nil {
202
log.Println(err)
···
223
return
224
}
225
226
+
pubKeys, err := db.GetPublicKeys(s.db, id.DID.String())
227
if err != nil {
228
w.WriteHeader(http.StatusNotFound)
229
return
···
251
}
252
log.Println("checking ", domain)
253
254
+
secret, err := db.GetRegistrationKey(s.db, domain)
255
if err != nil {
256
log.Printf("no key found for domain %s: %s\n", domain, err)
257
return
···
296
return
297
}
298
299
+
tx, err := s.db.BeginTx(r.Context(), nil)
300
+
if err != nil {
301
+
log.Println("failed to start tx", err)
302
+
http.Error(w, err.Error(), http.StatusInternalServerError)
303
+
return
304
+
}
305
+
defer func() {
306
+
tx.Rollback()
307
+
err = s.enforcer.E.LoadPolicy()
308
+
if err != nil {
309
+
log.Println("failed to rollback policies")
310
+
}
311
+
}()
312
+
313
// mark as registered
314
+
err = db.Register(tx, domain)
315
if err != nil {
316
log.Println("failed to register domain", err)
317
http.Error(w, err.Error(), http.StatusInternalServerError)
···
319
}
320
321
// set permissions for this did as owner
322
+
reg, err := db.RegistrationByDomain(tx, domain)
323
if err != nil {
324
log.Println("failed to register domain", err)
325
http.Error(w, err.Error(), http.StatusInternalServerError)
···
342
return
343
}
344
345
+
err = tx.Commit()
346
+
if err != nil {
347
+
log.Println("failed to commit changes", err)
348
+
http.Error(w, err.Error(), http.StatusInternalServerError)
349
+
return
350
+
}
351
+
352
+
err = s.enforcer.E.SavePolicy()
353
+
if err != nil {
354
+
log.Println("failed to update ACLs", err)
355
+
http.Error(w, err.Error(), http.StatusInternalServerError)
356
+
return
357
+
}
358
+
359
w.Write([]byte("check success"))
360
}
361
···
367
}
368
369
user := s.auth.GetUser(r)
370
+
reg, err := db.RegistrationByDomain(s.db, domain)
371
if err != nil {
372
w.Write([]byte("failed to pull up registration info"))
373
return
···
399
func (s *State) Knots(w http.ResponseWriter, r *http.Request) {
400
// for now, this is just pubkeys
401
user := s.auth.GetUser(r)
402
+
registrations, err := db.RegistrationsByDid(s.db, user.Did)
403
if err != nil {
404
log.Println(err)
405
}
···
473
}
474
log.Println("created atproto record: ", resp.Uri)
475
476
+
secret, err := db.GetRegistrationKey(s.db, domain)
477
if err != nil {
478
log.Printf("no key found for domain %s: %s\n", domain, err)
479
return
···
549
return
550
}
551
552
+
existingRepo, err := db.GetRepo(s.db, user.Did, repoName)
553
+
if err == nil && existingRepo != nil {
554
+
s.pages.Notice(w, "repo", fmt.Sprintf("A repo by this name already exists on %s", existingRepo.Knot))
555
+
return
556
+
}
557
+
558
+
secret, err := db.GetRegistrationKey(s.db, domain)
559
if err != nil {
560
s.pages.Notice(w, "repo", fmt.Sprintf("No registration key found for knot %s.", domain))
561
return
···
567
return
568
}
569
570
rkey := s.TID()
571
repo := &db.Repo{
572
Did: user.Did,
···
597
}
598
log.Println("created repo record: ", atresp.Uri)
599
600
+
tx, err := s.db.BeginTx(r.Context(), nil)
601
+
if err != nil {
602
+
log.Println(err)
603
+
s.pages.Notice(w, "repo", "Failed to save repository information.")
604
+
return
605
+
}
606
+
defer func() {
607
+
tx.Rollback()
608
+
err = s.enforcer.E.LoadPolicy()
609
+
if err != nil {
610
+
log.Println("failed to rollback policies")
611
+
}
612
+
}()
613
614
+
resp, err := client.NewRepo(user.Did, repoName, defaultBranch)
615
+
if err != nil {
616
+
s.pages.Notice(w, "repo", "Failed to create repository on knot server.")
617
+
return
618
+
}
619
+
620
+
switch resp.StatusCode {
621
+
case http.StatusConflict:
622
+
s.pages.Notice(w, "repo", "A repository with that name already exists.")
623
+
return
624
+
case http.StatusInternalServerError:
625
+
s.pages.Notice(w, "repo", "Failed to create repository on knot. Try again later.")
626
+
case http.StatusNoContent:
627
+
// continue
628
+
}
629
+
630
+
repo.AtUri = atresp.Uri
631
+
err = db.AddRepo(tx, repo)
632
if err != nil {
633
log.Println(err)
634
s.pages.Notice(w, "repo", "Failed to save repository information.")
···
644
return
645
}
646
647
+
err = tx.Commit()
648
+
if err != nil {
649
+
log.Println("failed to commit changes", err)
650
+
http.Error(w, err.Error(), http.StatusInternalServerError)
651
+
return
652
+
}
653
+
654
+
err = s.enforcer.E.SavePolicy()
655
+
if err != nil {
656
+
log.Println("failed to update ACLs", err)
657
+
http.Error(w, err.Error(), http.StatusInternalServerError)
658
+
return
659
+
}
660
+
661
s.pages.HxLocation(w, fmt.Sprintf("/@%s/%s", user.Handle, repoName))
662
return
663
}
···
677
return
678
}
679
680
+
repos, err := db.GetAllReposByDid(s.db, ident.DID.String())
681
if err != nil {
682
log.Printf("getting repos for %s: %s", ident.DID.String(), err)
683
}
684
685
+
collaboratingRepos, err := db.CollaboratingIn(s.db, ident.DID.String())
686
if err != nil {
687
log.Printf("getting collaborating repos for %s: %s", ident.DID.String(), err)
688
}
···
700
}
701
}
702
703
+
followers, following, err := db.GetFollowerFollowing(s.db, ident.DID.String())
704
if err != nil {
705
log.Printf("getting follow stats repos for %s: %s", ident.DID.String(), err)
706
}
···
708
loggedInUser := s.auth.GetUser(r)
709
followStatus := db.IsNotFollowing
710
if loggedInUser != nil {
711
+
followStatus = db.GetFollowStatus(s.db, loggedInUser.Did, ident.DID.String())
712
}
713
714
profileAvatarUri, err := GetAvatarUri(ident.DID.String())
···
880
881
r.Route("/repo", func(r chi.Router) {
882
r.Route("/new", func(r chi.Router) {
883
+
r.Use(AuthMiddleware(s))
884
r.Get("/", s.AddRepo)
885
r.Post("/", s.AddRepo)
886
})
+8
-7
rbac/rbac.go
+8
-7
rbac/rbac.go
···
6
"path"
7
"strings"
8
9
-
sqladapter "github.com/Blank-Xu/sql-adapter"
10
"github.com/casbin/casbin/v2"
11
"github.com/casbin/casbin/v2/model"
12
)
···
31
)
32
33
type Enforcer struct {
34
-
E *casbin.SyncedEnforcer
35
}
36
37
func keyMatch2(key1 string, key2 string) bool {
···
50
return nil, err
51
}
52
53
-
a, err := sqladapter.NewAdapter(db, "sqlite3", "acl")
54
if err != nil {
55
return nil, err
56
}
57
58
-
e, err := casbin.NewSyncedEnforcer(m, a)
59
if err != nil {
60
return nil, err
61
}
62
63
-
e.EnableAutoSave(true)
64
e.AddFunction("keyMatch2", keyMatch2Func)
65
66
return &Enforcer{e}, nil
···
82
}
83
84
func (e *Enforcer) GetDomainsForUser(did string) ([]string, error) {
85
-
return e.E.Enforcer.GetDomainsForUser(did)
86
}
87
88
func (e *Enforcer) AddOwner(domain, owner string) error {
···
131
132
// this includes roles too, casbin does not differentiate.
133
// the filtering criteria is to remove strings not starting with `did:`
134
-
members, err := e.E.Enforcer.GetImplicitUsersForRole(role, domain)
135
for _, m := range members {
136
if strings.HasPrefix(m, "did:") {
137
membersWithoutRoles = append(membersWithoutRoles, m)
···
6
"path"
7
"strings"
8
9
+
adapter "github.com/Blank-Xu/sql-adapter"
10
"github.com/casbin/casbin/v2"
11
"github.com/casbin/casbin/v2/model"
12
)
···
31
)
32
33
type Enforcer struct {
34
+
E *casbin.Enforcer
35
}
36
37
func keyMatch2(key1 string, key2 string) bool {
···
50
return nil, err
51
}
52
53
+
a, err := adapter.NewAdapter(db, "sqlite3", "acl")
54
if err != nil {
55
return nil, err
56
}
57
58
+
e, err := casbin.NewEnforcer(m, a)
59
if err != nil {
60
return nil, err
61
}
62
63
+
e.EnableAutoSave(false)
64
+
65
e.AddFunction("keyMatch2", keyMatch2Func)
66
67
return &Enforcer{e}, nil
···
83
}
84
85
func (e *Enforcer) GetDomainsForUser(did string) ([]string, error) {
86
+
return e.E.GetDomainsForUser(did)
87
}
88
89
func (e *Enforcer) AddOwner(domain, owner string) error {
···
132
133
// this includes roles too, casbin does not differentiate.
134
// the filtering criteria is to remove strings not starting with `did:`
135
+
members, err := e.E.GetImplicitUsersForRole(role, domain)
136
for _, m := range members {
137
if strings.HasPrefix(m, "did:") {
138
membersWithoutRoles = append(membersWithoutRoles, m)