Skip to content

Commit 837c48f

Browse files
committed
PR(MAIN): Gate & Test - Schema Patch
1 parent bba3d26 commit 837c48f

5 files changed

Lines changed: 94 additions & 2 deletions

File tree

acp/types/types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const (
8989
AdminAACRelationAddPerm
9090
AdminAACRelationDeletePerm
9191
AdminSchemaAddPerm
92+
AdminSchemaPatchPerm
9293
)
9394

9495
// List of all valid resource interface permissions for admin access control, the order of
@@ -110,6 +111,7 @@ var RequiredResourcePermissionsForAdmin = []string{
110111
"aac-relation-add",
111112
"aac-relation-delete",
112113
"schema-add",
114+
"schema-patch",
113115
}
114116

115117
const InternalAdminACPObjectToGate = "NodeObject"
@@ -156,6 +158,8 @@ resources:
156158
expr: owner + admin
157159
schema-add:
158160
expr: owner + admin
161+
schema-patch:
162+
expr: owner + admin
159163
160164
relations:
161165
owner:

internal/db/store.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ func (db *DB) PatchSchema(
185185
ctx, span := tracer.Start(ctx)
186186
defer span.End()
187187

188+
err := db.checkAdminAccess(ctx, acpTypes.AdminSchemaPatchPerm)
189+
if err != nil {
190+
return err
191+
}
192+
188193
ctx, txn, err := ensureContextTxn(ctx, db, false)
189194
if err != nil {
190195
return err
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2025 Democratized Data Foundation
2+
//
3+
// Use of this software is governed by the Business Source License
4+
// included in the file licenses/BSL.txt.
5+
//
6+
// As of the Change Date specified in that file, in accordance with
7+
// the Business Source License, use of this software will be governed
8+
// by the Apache License, Version 2.0, included in the file
9+
// licenses/APL.txt.
10+
11+
package test_acp_aac
12+
13+
import (
14+
"testing"
15+
16+
testUtils "github.com/sourcenetwork/defradb/tests/integration"
17+
"github.com/sourcenetwork/immutable"
18+
)
19+
20+
func TestAAC_GatesSchemaPatch_AllowIfAuthorizedElseError(t *testing.T) {
21+
test := testUtils.TestCase{
22+
Description: "admin acp correctly gates schema patch operation, allow if authorized, otherwise error",
23+
Actions: []any{
24+
// Setup that we can do before aac is enabled.
25+
testUtils.SchemaUpdate{
26+
Schema: `
27+
type Users {}
28+
`,
29+
},
30+
31+
// Starting with ACC, so only authorized user(s) can perform operations.
32+
testUtils.Close{},
33+
testUtils.Start{
34+
Identity: testUtils.ClientIdentity(1),
35+
EnableAAC: true,
36+
},
37+
38+
// We haven't authorized non-identities. So, this should error.
39+
testUtils.SchemaPatch{
40+
Patch: `
41+
[
42+
{ "op": "add", "path": "/Users/Fields/-", "value": {"Name": "name", "Kind": "String"} }
43+
]
44+
`,
45+
SetAsDefaultVersion: immutable.Some(false),
46+
ExpectedError: "not authorized to perform operation",
47+
},
48+
49+
// Wrong user/identity will also not be authorized.
50+
testUtils.SchemaPatch{
51+
Identity: testUtils.ClientIdentity(2),
52+
Patch: `
53+
[
54+
{ "op": "add", "path": "/Users/Fields/-", "value": {"Name": "name", "Kind": "String"} }
55+
]
56+
`,
57+
SetAsDefaultVersion: immutable.Some(false),
58+
ExpectedError: "not authorized to perform operation",
59+
},
60+
61+
// This should work as the identity is authorized.
62+
testUtils.SchemaPatch{
63+
Identity: testUtils.ClientIdentity(1),
64+
Patch: `
65+
[
66+
{ "op": "add", "path": "/Users/Fields/-", "value": {"Name": "name", "Kind": "String"} }
67+
]
68+
`,
69+
SetAsDefaultVersion: immutable.Some(false),
70+
},
71+
},
72+
}
73+
74+
testUtils.ExecuteTestCase(t, test)
75+
}

tests/integration/test_case.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ type SchemaPatch struct {
234234
// If a value is not provided the patch will be applied to all nodes.
235235
NodeID immutable.Option[int]
236236

237+
// The identity of this request. Optional.
238+
//
239+
// If admin acp is enabled, identity will be used to check if this operation can be performed.
240+
Identity immutable.Option[Identity]
241+
237242
Patch string
238243

239244
// If SetAsDefaultVersion has a value, and that value is false then the schema version

tests/integration/utils.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,16 +1110,19 @@ func patchSchema(
11101110
s *state,
11111111
action SchemaPatch,
11121112
) {
1113-
_, nodes := getNodesWithIDs(action.NodeID, s.nodes)
1114-
for _, node := range nodes {
1113+
nodeIDs, nodes := getNodesWithIDs(action.NodeID, s.nodes)
1114+
for index, node := range nodes {
1115+
nodeID := nodeIDs[index]
11151116
var setAsDefaultVersion bool
11161117
if action.SetAsDefaultVersion.HasValue() {
11171118
setAsDefaultVersion = action.SetAsDefaultVersion.Value()
11181119
} else {
11191120
setAsDefaultVersion = true
11201121
}
11211122

1123+
s.ctx = getContextWithIdentity(s.ctx, s, action.Identity, nodeID)
11221124
err := node.PatchSchema(s.ctx, action.Patch, action.Lens, setAsDefaultVersion)
1125+
resetStateContext(s)
11231126
expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError)
11241127

11251128
assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised)

0 commit comments

Comments
 (0)