Monorepo for Tangled tangled.org

appview: rework collaborators table, emit record

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 647c6108 b8713839

verified
Changed files
+170 -37
appview
+76
appview/db/collaborators.go
··· 1 + package db 2 + 3 + import ( 4 + "fmt" 5 + "strings" 6 + "time" 7 + 8 + "github.com/bluesky-social/indigo/atproto/syntax" 9 + ) 10 + 11 + type Collaborator struct { 12 + // identifiers for the record 13 + Id int64 14 + Did syntax.DID 15 + Rkey string 16 + 17 + // content 18 + SubjectDid syntax.DID 19 + RepoAt syntax.ATURI 20 + 21 + // meta 22 + Created time.Time 23 + } 24 + 25 + func AddCollaborator(e Execer, c Collaborator) error { 26 + _, err := e.Exec( 27 + `insert into collaborators (did, rkey, subject_did, repo_at) values (?, ?, ?, ?);`, 28 + c.Did, c.Rkey, c.SubjectDid, c.RepoAt, 29 + ) 30 + return err 31 + } 32 + 33 + func DeleteCollaborator(e Execer, filters ...filter) error { 34 + var conditions []string 35 + var args []any 36 + for _, filter := range filters { 37 + conditions = append(conditions, filter.Condition()) 38 + args = append(args, filter.Arg()...) 39 + } 40 + 41 + whereClause := "" 42 + if conditions != nil { 43 + whereClause = " where " + strings.Join(conditions, " and ") 44 + } 45 + 46 + query := fmt.Sprintf(`delete from collaborators %s`, whereClause) 47 + 48 + _, err := e.Exec(query, args...) 49 + return err 50 + } 51 + 52 + func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) { 53 + rows, err := e.Query(`select repo_at from collaborators where did = ?`, collaborator) 54 + if err != nil { 55 + return nil, err 56 + } 57 + defer rows.Close() 58 + 59 + var repoAts []string 60 + for rows.Next() { 61 + var aturi string 62 + err := rows.Scan(&aturi) 63 + if err != nil { 64 + return nil, err 65 + } 66 + repoAts = append(repoAts, aturi) 67 + } 68 + if err := rows.Err(); err != nil { 69 + return nil, err 70 + } 71 + if repoAts == nil { 72 + return nil, nil 73 + } 74 + 75 + return GetRepos(e, 0, FilterIn("at_uri", repoAts)) 76 + }
+55
appview/db/db.go
··· 578 578 return nil 579 579 }) 580 580 581 + // recreate and add rkey + created columns with default constraint 582 + runMigration(db, "rework-collaborators-table", func(tx *sql.Tx) error { 583 + // create new table 584 + // - repo_at instead of repo integer 585 + // - rkey field 586 + // - created field 587 + _, err := tx.Exec(` 588 + create table collaborators_new ( 589 + -- identifiers for the record 590 + id integer primary key autoincrement, 591 + did text not null, 592 + rkey text, 593 + 594 + -- content 595 + subject_did text not null, 596 + repo_at text not null, 597 + 598 + -- meta 599 + created text default (strftime('%y-%m-%dt%h:%m:%sz', 'now')), 600 + 601 + -- constraints 602 + foreign key (repo_at) references repos(at_uri) on delete cascade 603 + ) 604 + `) 605 + if err != nil { 606 + return err 607 + } 608 + 609 + // copy data 610 + _, err = tx.Exec(` 611 + insert into collaborators_new (id, did, rkey, subject_did, repo_at) 612 + select 613 + c.id, 614 + r.did, 615 + '', 616 + c.did, 617 + r.at_uri 618 + from collaborators c 619 + join repos r on c.repo = r.id 620 + `) 621 + if err != nil { 622 + return err 623 + } 624 + 625 + // drop old table 626 + _, err = tx.Exec(`drop table collaborators`) 627 + if err != nil { 628 + return err 629 + } 630 + 631 + // rename new table 632 + _, err = tx.Exec(`alter table collaborators_new rename to collaborators`) 633 + return err 634 + }) 635 + 581 636 return &DB{db}, nil 582 637 } 583 638
-34
appview/db/repos.go
··· 550 550 return &repo, nil 551 551 } 552 552 553 - func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error { 554 - _, err := e.Exec( 555 - `insert into collaborators (did, repo) 556 - values (?, (select id from repos where did = ? and name = ? and knot = ?));`, 557 - collaborator, repoOwnerDid, repoName, repoKnot) 558 - return err 559 - } 560 - 561 553 func UpdateDescription(e Execer, repoAt, newDescription string) error { 562 554 _, err := e.Exec( 563 555 `update repos set description = ? where at_uri = ?`, newDescription, repoAt) ··· 568 560 _, err := e.Exec( 569 561 `update repos set spindle = ? where at_uri = ?`, spindle, repoAt) 570 562 return err 571 - } 572 - 573 - func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) { 574 - rows, err := e.Query(`select repo from collaborators where did = ?`, collaborator) 575 - if err != nil { 576 - return nil, err 577 - } 578 - defer rows.Close() 579 - 580 - var repoIds []int 581 - for rows.Next() { 582 - var id int 583 - err := rows.Scan(&id) 584 - if err != nil { 585 - return nil, err 586 - } 587 - repoIds = append(repoIds, id) 588 - } 589 - if err := rows.Err(); err != nil { 590 - return nil, err 591 - } 592 - if repoIds == nil { 593 - return nil, nil 594 - } 595 - 596 - return GetRepos(e, 0, FilterIn("id", repoIds)) 597 563 } 598 564 599 565 type RepoStats struct {
+39 -3
appview/repo/repo.go
··· 39 39 "github.com/go-git/go-git/v5/plumbing" 40 40 41 41 comatproto "github.com/bluesky-social/indigo/api/atproto" 42 + "github.com/bluesky-social/indigo/atproto/syntax" 42 43 lexutil "github.com/bluesky-social/indigo/lex/util" 43 44 ) 44 45 ··· 751 752 fail("You seem to be adding yourself as a collaborator.", nil) 752 753 return 753 754 } 754 - 755 755 l = l.With("collaborator", collaboratorIdent.Handle) 756 756 l = l.With("knot", f.Knot) 757 - l.Info("adding to knot") 757 + 758 + // announce this relation into the firehose, store into owners' pds 759 + client, err := rp.oauth.AuthorizedClient(r) 760 + if err != nil { 761 + fail("Failed to write to PDS.", err) 762 + return 763 + } 764 + 765 + // emit a record 766 + currentUser := rp.oauth.GetUser(r) 767 + rkey := tid.TID() 768 + createdAt := time.Now() 769 + resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{ 770 + Collection: tangled.RepoCollaboratorNSID, 771 + Repo: currentUser.Did, 772 + Rkey: rkey, 773 + Record: &lexutil.LexiconTypeDecoder{ 774 + Val: &tangled.RepoCollaborator{ 775 + Subject: collaboratorIdent.DID.String(), 776 + Repo: string(f.RepoAt), 777 + CreatedAt: createdAt.Format(time.RFC3339), 778 + }}, 779 + }) 780 + // invalid record 781 + if err != nil { 782 + fail("Failed to write record to PDS.", err) 783 + return 784 + } 785 + l = l.With("at-uri", resp.Uri) 786 + l.Info("wrote record to PDS") 758 787 788 + l.Info("adding to knot") 759 789 secret, err := db.GetRegistrationKey(rp.db, f.Knot) 760 790 if err != nil { 761 791 fail("Failed to add to knot.", err) ··· 798 828 return 799 829 } 800 830 801 - err = db.AddCollaborator(rp.db, collaboratorIdent.DID.String(), f.OwnerDid(), f.RepoName, f.Knot) 831 + err = db.AddCollaborator(rp.db, db.Collaborator{ 832 + Did: syntax.DID(currentUser.Did), 833 + Rkey: rkey, 834 + SubjectDid: collaboratorIdent.DID, 835 + RepoAt: f.RepoAt, 836 + Created: createdAt, 837 + }) 802 838 if err != nil { 803 839 fail("Failed to add collaborator.", err) 804 840 return