forked from tangled.org/core
Monorepo for Tangled

appview: ingest issue records

Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.sh>

authored by anirudh.fi and committed by Tangled f1bdf70b 8aabf0c4

Changed files
+100 -6
appview
+99 -6
appview/ingester.go
··· 5 5 "encoding/json" 6 6 "fmt" 7 7 "log/slog" 8 + "strings" 8 9 "time" 9 10 10 11 "github.com/bluesky-social/indigo/atproto/syntax" ··· 14 15 "tangled.sh/tangled.sh/core/api/tangled" 15 16 "tangled.sh/tangled.sh/core/appview/config" 16 17 "tangled.sh/tangled.sh/core/appview/db" 18 + "tangled.sh/tangled.sh/core/appview/pages/markup" 17 19 "tangled.sh/tangled.sh/core/appview/serververify" 18 20 "tangled.sh/tangled.sh/core/idresolver" 19 21 "tangled.sh/tangled.sh/core/rbac" ··· 61 63 case tangled.ActorProfileNSID: 62 64 err = i.ingestProfile(e) 63 65 case tangled.SpindleMemberNSID: 64 - err = i.ingestSpindleMember(e) 66 + err = i.ingestSpindleMember(ctx, e) 65 67 case tangled.SpindleNSID: 66 - err = i.ingestSpindle(e) 68 + err = i.ingestSpindle(ctx, e) 67 69 case tangled.KnotMemberNSID: 68 70 err = i.ingestKnotMember(e) 69 71 case tangled.KnotNSID: 70 72 err = i.ingestKnot(e) 71 73 case tangled.StringNSID: 72 74 err = i.ingestString(e) 75 + case tangled.RepoIssueNSID: 76 + err = i.ingestIssue(ctx, e) 73 77 } 74 78 l = i.Logger.With("nsid", e.Commit.Collection) 75 79 } ··· 340 344 return nil 341 345 } 342 346 343 - func (i *Ingester) ingestSpindleMember(e *models.Event) error { 347 + func (i *Ingester) ingestSpindleMember(ctx context.Context, e *models.Event) error { 344 348 did := e.Did 345 349 var err error 346 350 ··· 363 367 return fmt.Errorf("failed to enforce permissions: %w", err) 364 368 } 365 369 366 - memberId, err := i.IdResolver.ResolveIdent(context.Background(), record.Subject) 370 + memberId, err := i.IdResolver.ResolveIdent(ctx, record.Subject) 367 371 if err != nil { 368 372 return err 369 373 } ··· 446 450 return nil 447 451 } 448 452 449 - func (i *Ingester) ingestSpindle(e *models.Event) error { 453 + func (i *Ingester) ingestSpindle(ctx context.Context, e *models.Event) error { 450 454 did := e.Did 451 455 var err error 452 456 ··· 479 483 return err 480 484 } 481 485 482 - err = serververify.RunVerification(context.Background(), instance, did, i.Config.Core.Dev) 486 + err = serververify.RunVerification(ctx, instance, did, i.Config.Core.Dev) 483 487 if err != nil { 484 488 l.Error("failed to add spindle to db", "err", err, "instance", instance) 485 489 return err ··· 769 773 770 774 return nil 771 775 } 776 + func (i *Ingester) ingestIssue(ctx context.Context, e *models.Event) error { 777 + did := e.Did 778 + rkey := e.Commit.RKey 779 + 780 + var err error 781 + 782 + l := i.Logger.With("handler", "ingestIssue", "nsid", e.Commit.Collection, "did", did, "rkey", rkey) 783 + l.Info("ingesting record") 784 + 785 + ddb, ok := i.Db.Execer.(*db.DB) 786 + if !ok { 787 + return fmt.Errorf("failed to index issue record, invalid db cast") 788 + } 789 + 790 + switch e.Commit.Operation { 791 + case models.CommitOperationCreate: 792 + raw := json.RawMessage(e.Commit.Record) 793 + record := tangled.RepoIssue{} 794 + err = json.Unmarshal(raw, &record) 795 + if err != nil { 796 + l.Error("invalid record", "err", err) 797 + return err 798 + } 799 + 800 + issue := db.IssueFromRecord(did, rkey, record) 801 + 802 + sanitizer := markup.NewSanitizer() 803 + if st := strings.TrimSpace(sanitizer.SanitizeDescription(issue.Title)); st == "" { 804 + return fmt.Errorf("title is empty after HTML sanitization") 805 + } 806 + if sb := strings.TrimSpace(sanitizer.SanitizeDefault(issue.Body)); sb == "" { 807 + return fmt.Errorf("body is empty after HTML sanitization") 808 + } 809 + 810 + tx, err := ddb.BeginTx(ctx, nil) 811 + if err != nil { 812 + l.Error("failed to begin transaction", "err", err) 813 + return err 814 + } 815 + 816 + err = db.NewIssue(tx, &issue) 817 + if err != nil { 818 + l.Error("failed to create issue", "err", err) 819 + return err 820 + } 821 + 822 + return nil 823 + 824 + case models.CommitOperationUpdate: 825 + raw := json.RawMessage(e.Commit.Record) 826 + record := tangled.RepoIssue{} 827 + err = json.Unmarshal(raw, &record) 828 + if err != nil { 829 + l.Error("invalid record", "err", err) 830 + return err 831 + } 832 + 833 + body := "" 834 + if record.Body != nil { 835 + body = *record.Body 836 + } 837 + 838 + sanitizer := markup.NewSanitizer() 839 + if st := strings.TrimSpace(sanitizer.SanitizeDescription(record.Title)); st == "" { 840 + return fmt.Errorf("title is empty after HTML sanitization") 841 + } 842 + if sb := strings.TrimSpace(sanitizer.SanitizeDefault(body)); sb == "" { 843 + return fmt.Errorf("body is empty after HTML sanitization") 844 + } 845 + 846 + err = db.UpdateIssueByRkey(ddb, did, rkey, record.Title, body) 847 + if err != nil { 848 + l.Error("failed to update issue", "err", err) 849 + return err 850 + } 851 + 852 + return nil 853 + 854 + case models.CommitOperationDelete: 855 + if err := db.DeleteIssueByRkey(ddb, did, rkey); err != nil { 856 + l.Error("failed to delete", "err", err) 857 + return fmt.Errorf("failed to delete issue record: %w", err) 858 + } 859 + 860 + return nil 861 + } 862 + 863 + return fmt.Errorf("unknown operation: %s", e.Commit.Operation) 864 + }
+1
appview/state/state.go
··· 99 99 tangled.SpindleMemberNSID, 100 100 tangled.SpindleNSID, 101 101 tangled.StringNSID, 102 + tangled.RepoIssueNSID, 102 103 }, 103 104 nil, 104 105 slog.Default(),