···4949 created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
5050 unique(did, name, knot)
5151 );
5252+ create table if not exists collaborators (
5353+ id integer primary key autoincrement,
5454+ did text not null,
5555+ repo integer not null,
5656+ foreign key (repo) references repos(id) on delete cascade
5757+ );
5258 create table if not exists follows (
5359 user_did text not null,
5460 subject_did text not null,
+57-7
appview/db/repos.go
···11package db
2233-import "time"
33+import (
44+ "database/sql"
55+ "time"
66+)
4758type Repo struct {
69 Did string
···1922 defer rows.Close()
20232124 for rows.Next() {
2222- var repo Repo
2323- var createdAt string
2424- if err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt); err != nil {
2525+ repo, err := scanRepo(rows)
2626+ if err != nil {
2527 return nil, err
2628 }
2727- createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
2828- repo.Created = &createdAtTime
2929- repos = append(repos, repo)
2929+ repos = append(repos, *repo)
3030 }
31313232 if err := rows.Err(); err != nil {
···6060 _, err := d.db.Exec(`delete from repos where did = ? and name = ? and knot = ?`, did, name, knot)
6161 return err
6262}
6363+6464+func (d *DB) AddCollaborator(collaborator, repoOwnerDid, repoName, repoKnot string) error {
6565+ _, err := d.db.Exec(
6666+ `insert into collaborators (did, repo)
6767+ values (?, (select id from repos where did = ? and name = ? and knot = ?));`,
6868+ collaborator, repoOwnerDid, repoName, repoKnot)
6969+ return err
7070+}
7171+7272+func (d *DB) CollaboratingIn(collaborator string) ([]Repo, error) {
7373+ var repos []Repo
7474+7575+ rows, err := d.db.Query(`select r.* from repos r join collaborators c on r.id = c.repo where c.did = ?;`, collaborator)
7676+ if err != nil {
7777+ return nil, err
7878+ }
7979+ defer rows.Close()
8080+8181+ for rows.Next() {
8282+ repo, err := scanRepo(rows)
8383+ if err != nil {
8484+ return nil, err
8585+ }
8686+ repos = append(repos, *repo)
8787+ }
8888+8989+ if err := rows.Err(); err != nil {
9090+ return nil, err
9191+ }
9292+9393+ return repos, nil
9494+}
9595+9696+func scanRepo(rows *sql.Rows) (*Repo, error) {
9797+ var repo Repo
9898+ var createdAt string
9999+ if err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt); err != nil {
100100+ return nil, err
101101+ }
102102+103103+ createdAtTime, err := time.Parse(time.RFC3339, createdAt)
104104+ if err != nil {
105105+ now := time.Now()
106106+ repo.Created = &now
107107+ }
108108+109109+ repo.Created = &createdAtTime
110110+111111+ return &repo, nil
112112+}