Monorepo for Tangled tangled.org
8

Configure Feed

Select the types of activity you want to include in your feed.

appview: grant owner rbac for ingested repos

Signed-off-by: onevcat <onevcat@gmail.com>

author
onevcat
committer
Tangled
date (May 18, 2026, 12:57 PM +0300) commit 81ab1c86 parent b56309c3
+42 -1
+21 -1
appview/ingester_repo.go
··· 58 58 return nil 59 59 } 60 60 61 - _, err = db.GetRepo(i.Db, 61 + existing, err := db.GetRepo(i.Db, 62 62 orm.FilterEq("did", e.Did), 63 63 orm.FilterEq("rkey", e.Commit.RKey), 64 64 ) 65 65 if err == nil { 66 66 l.Info("repo row already exists, skipping create", "did", e.Did, "rkey", e.Commit.RKey) 67 + if err := i.ensureRepoOwnerPermissions(e.Did, existing.Knot, existing.RepoIdentifier()); err != nil { 68 + return fmt.Errorf("failed to ensure repo owner permissions: %w", err) 69 + } 67 70 return nil 68 71 } 69 72 if !errors.Is(err, sql.ErrNoRows) { ··· 121 124 l.Warn("failed to fetch repo after rename for notification", "err", err) 122 125 return nil 123 126 } 127 + if err := i.ensureRepoOwnerPermissions(e.Did, newRepo.Knot, newRepo.RepoIdentifier()); err != nil { 128 + return fmt.Errorf("failed to ensure repo owner permissions: %w", err) 129 + } 124 130 i.Notifier.RenameRepo(ctx, syntax.DID(e.Did), &oldRepo, newRepo) 125 131 return nil 126 132 } ··· 158 164 return fmt.Errorf("failed to commit insert tx: %w", err) 159 165 } 160 166 167 + if err := i.ensureRepoOwnerPermissions(e.Did, repo.Knot, repo.RepoIdentifier()); err != nil { 168 + return fmt.Errorf("failed to ensure repo owner permissions: %w", err) 169 + } 170 + 161 171 i.Notifier.NewRepo(ctx, repo) 162 172 return nil 173 + } 174 + 175 + func (i *Ingester) ensureRepoOwnerPermissions(ownerDid, knot, repo string) error { 176 + if i.Enforcer == nil { 177 + return fmt.Errorf("ingester has no RBAC enforcer configured") 178 + } 179 + if err := i.Enforcer.AddRepo(ownerDid, knot, repo); err != nil { 180 + return err 181 + } 182 + return i.Enforcer.E.SavePolicy() 163 183 } 164 184 165 185 func (i *Ingester) ingestRepoUpdate(ctx context.Context, e *jmodels.Event) error {
+21
appview/ingester_repo_test.go
··· 19 19 "tangled.org/core/appview/notify" 20 20 "tangled.org/core/appview/repoverify" 21 21 "tangled.org/core/orm" 22 + "tangled.org/core/rbac" 22 23 ) 23 24 24 25 func mustKnotURL(t *testing.T, raw string) *url.URL { ··· 69 70 t.Fatalf("db.Make: %v", err) 70 71 } 71 72 t.Cleanup(func() { d.Close() }) 73 + enforcer, err := rbac.NewEnforcer(path) 74 + if err != nil { 75 + t.Fatalf("rbac.NewEnforcer: %v", err) 76 + } 72 77 73 78 spy := &spyNotifier{} 74 79 ing := &Ingester{ 75 80 Db: d, 81 + Enforcer: enforcer, 76 82 Logger: slog.New(slog.NewTextHandler(io.Discard, nil)), 77 83 Notifier: spy, 78 84 } ··· 156 162 return r 157 163 } 158 164 165 + func assertRepoOwnerPermissions(t *testing.T, ing *Ingester, owner, knot, repo string) { 166 + t.Helper() 167 + for _, perm := range []string{"repo:settings", "repo:push", "repo:owner"} { 168 + ok, err := ing.Enforcer.E.Enforce(owner, knot, repo, perm) 169 + if err != nil { 170 + t.Fatalf("Enforce(%q): %v", perm, err) 171 + } 172 + if !ok { 173 + t.Fatalf("owner missing %s permission for %s", perm, repo) 174 + } 175 + } 176 + } 177 + 159 178 func TestIngestRepo_CreateInsertsNewRow(t *testing.T) { 160 179 ing, spy := newTestIngester(t) 161 180 ··· 183 202 if spy.creates != 1 { 184 203 t.Errorf("NewRepo called %d times, want 1", spy.creates) 185 204 } 205 + assertRepoOwnerPermissions(t, ing, "did:plc:akshay", "knot.example", "did:plc:repo1") 186 206 } 187 207 188 208 func TestIngestRepo_CreateSkipsIfRowExists(t *testing.T) { ··· 201 221 if spy.creates != 0 { 202 222 t.Errorf("row already exists, NewRepo should not be called but was called %d times", spy.creates) 203 223 } 224 + assertRepoOwnerPermissions(t, ing, "did:plc:akshay", "knot.example", "did:plc:repo1") 204 225 } 205 226 206 227 func TestIngestRepo_CreateCascadesRename(t *testing.T) {