Monorepo for Tangled tangled.org
4

Configure Feed

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

1package validator 2 3import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "io" 8 "log/slog" 9 "net/http" 10 "net/http/httptest" 11 "path/filepath" 12 "strings" 13 "testing" 14 "time" 15 16 "tangled.org/core/api/tangled" 17 "tangled.org/core/appview/db" 18 "tangled.org/core/appview/knotacl" 19 "tangled.org/core/appview/models" 20 "tangled.org/core/consts" 21 "tangled.org/core/rbac" 22) 23 24func unreachableListValidator(t *testing.T) (*Validator, string) { 25 t.Helper() 26 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 27 switch { 28 case strings.HasSuffix(r.URL.Path, tangled.KnotVersionNSID): 29 json.NewEncoder(w).Encode(tangled.KnotVersion_Output{Version: "v1.15.0", Capabilities: []string{string(consts.CapKnotACL)}}) 30 case strings.HasSuffix(r.URL.Path, tangled.RepoListCollaboratorsNSID): 31 http.Error(w, "list down", http.StatusInternalServerError) 32 default: 33 http.NotFound(w, r) 34 } 35 })) 36 t.Cleanup(srv.Close) 37 host := strings.TrimPrefix(srv.URL, "http://") 38 39 dir := t.TempDir() 40 enforcer, err := rbac.NewEnforcer(filepath.Join(dir, "rbac.db")) 41 if err != nil { 42 t.Fatalf("NewEnforcer: %v", err) 43 } 44 d, err := db.Make(context.Background(), filepath.Join(dir, "appview.db")) 45 if err != nil { 46 t.Fatalf("db.Make: %v", err) 47 } 48 svc := knotacl.NewService(enforcer, d, true, slog.New(slog.NewTextHandler(io.Discard, nil))) 49 return &Validator{acl: svc}, host 50} 51 52func TestValidateLabelOp_MalformedRejectedBeforePermCheck(t *testing.T) { 53 v, host := unreachableListValidator(t) 54 def := &models.LabelDefinition{Did: "did:plc:akshay", Rkey: "deadbeef"} 55 repo := &models.Repo{Did: "did:plc:akshay", Knot: host, RepoDid: "did:plc:limpet"} 56 57 op := &models.LabelOp{ 58 Did: "did:plc:scallop", 59 OperandKey: "does-not-match-the-def-aturi", 60 Operation: "garbage", 61 } 62 err := v.ValidateLabelOp(context.Background(), def, repo, op) 63 if errors.Is(err, knotacl.ErrKnotUnreachable) { 64 t.Fatalf("malformed op returned ErrKnotUnreachable; structural validation did not run before the perm check") 65 } 66 if err == nil || !strings.Contains(err.Error(), "operand key") { 67 t.Fatalf("want a structural operand-key error, got %v", err) 68 } 69} 70 71func TestValidateLabelOp_WellFormedFailsOpenWhenKnotUnreachable(t *testing.T) { 72 v, host := unreachableListValidator(t) 73 def := &models.LabelDefinition{Did: "did:plc:akshay", Rkey: "deadbeef"} 74 repo := &models.Repo{Did: "did:plc:akshay", Knot: host, RepoDid: "did:plc:limpet"} 75 76 op := &models.LabelOp{ 77 Did: "did:plc:scallop", 78 OperandKey: def.AtUri().String(), 79 Operation: models.LabelOperationAdd, 80 Subject: "at://did:plc:limpet/sh.tangled.repo.issue/abc123", 81 PerformedAt: time.Now(), 82 } 83 err := v.ValidateLabelOp(context.Background(), def, repo, op) 84 if !errors.Is(err, knotacl.ErrKnotUnreachable) { 85 t.Fatalf("well-formed op against an unreachable knot = %v, want ErrKnotUnreachable so the ingester fails open", err) 86 } 87}