Skip to content

Commit 4d2835d

Browse files
committed
PR(MAIN): Gate & Test - Index Operations
1 parent 1cf06dd commit 4d2835d

11 files changed

Lines changed: 466 additions & 1 deletion

File tree

acp/types/types.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ const (
9494
NodeSchemaAddPerm
9595
NodeSchemaPatchPerm
9696
NodePatchCollectionPerm
97+
NodeIndexListPerm
98+
NodeIndexCreatePerm
99+
NodeIndexDropPerm
97100
NodeGetIdentityPerm
98101
NodeVerifySignaturePerm
99102
)
@@ -122,6 +125,9 @@ var RequiredResourcePermissionsForNode = []string{
122125
"schema-add",
123126
"schema-patch",
124127
"patch-collection",
128+
"index-list",
129+
"index-create",
130+
"index-drop",
125131
"node-get-identity",
126132
"verify-signature",
127133
}
@@ -180,6 +186,12 @@ resources:
180186
expr: owner + admin
181187
patch-collection:
182188
expr: owner + admin
189+
index-list:
190+
expr: owner + admin
191+
index-create:
192+
expr: owner + admin
193+
index-drop:
194+
expr: owner + admin
183195
node-get-identity:
184196
expr: owner + admin
185197
verify-signature:

internal/db/collection_index.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"slices"
2121

2222
"github.com/sourcenetwork/defradb/acp/identity"
23+
acpTypes "github.com/sourcenetwork/defradb/acp/types"
2324
"github.com/sourcenetwork/defradb/client"
2425
"github.com/sourcenetwork/defradb/client/request"
2526
"github.com/sourcenetwork/defradb/errors"
@@ -161,6 +162,10 @@ func (c *collection) CreateIndex(
161162
ctx, span := tracer.Start(ctx)
162163
defer span.End()
163164

165+
if err := c.db.checkNodeAccess(ctx, acpTypes.NodeIndexCreatePerm); err != nil {
166+
return client.IndexDescription{}, err
167+
}
168+
164169
ctx, txn, err := ensureContextTxn(ctx, c.db, false)
165170
if err != nil {
166171
return client.IndexDescription{}, err
@@ -342,6 +347,10 @@ func (c *collection) DropIndex(ctx context.Context, indexName string) error {
342347
ctx, span := tracer.Start(ctx)
343348
defer span.End()
344349

350+
if err := c.db.checkNodeAccess(ctx, acpTypes.NodeIndexDropPerm); err != nil {
351+
return err
352+
}
353+
345354
ctx, txn, err := ensureContextTxn(ctx, c.db, false)
346355
if err != nil {
347356
return err
@@ -391,7 +400,11 @@ func (c *collection) dropIndex(ctx context.Context, indexName string) error {
391400
}
392401

393402
// GetIndexes returns all indexes for the collection.
394-
func (c *collection) GetIndexes(context.Context) ([]client.IndexDescription, error) {
403+
func (c *collection) GetIndexes(ctx context.Context) ([]client.IndexDescription, error) {
404+
if err := c.db.checkNodeAccess(ctx, acpTypes.NodeIndexListPerm); err != nil {
405+
return nil, err
406+
}
407+
395408
return c.Version().Indexes, nil
396409
}
397410

internal/db/store.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ func (db *DB) GetAllIndexes(
133133
ctx, span := tracer.Start(ctx)
134134
defer span.End()
135135

136+
if err := db.checkNodeAccess(ctx, acpTypes.NodeIndexListPerm); err != nil {
137+
return nil, err
138+
}
139+
136140
ctx, txn, err := ensureContextTxn(ctx, db, true)
137141
if err != nil {
138142
return nil, err
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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+
)
18+
19+
func TestAAC_GatesIndexCreate_AllowIfAuthorizedElseError(t *testing.T) {
20+
test := testUtils.TestCase{
21+
Description: "admin acp correctly gates index create operation, allow if authorized, otherwise error",
22+
Actions: []any{
23+
// Starting with ACC, so only authorized user(s) can perform operations from here on out.
24+
testUtils.Close{},
25+
testUtils.Start{
26+
Identity: testUtils.ClientIdentity(1),
27+
EnableNAC: true,
28+
},
29+
// Note: Doing setup steps after starting with aac enabled, otherwise the in-memory tests
30+
// will loose setup state when the restart happens (i.e. the restart that started aac).
31+
testUtils.SchemaUpdate{
32+
Identity: testUtils.ClientIdentity(1),
33+
Schema: `
34+
type User {
35+
name: String
36+
}
37+
`,
38+
},
39+
// Note: Setup is now done, the test code that follows is what we want to assert.
40+
41+
// We haven't authorized non-identities. So, this should error.
42+
testUtils.CreateIndex{
43+
Identity: testUtils.NoIdentity(),
44+
CollectionID: 0,
45+
FieldName: "name",
46+
ExpectedError: "not authorized to perform operation",
47+
},
48+
49+
// Wrong user/identity will also not be authorized.
50+
testUtils.CreateIndex{
51+
Identity: testUtils.ClientIdentity(2),
52+
CollectionID: 0,
53+
FieldName: "name",
54+
ExpectedError: "not authorized to perform operation",
55+
},
56+
57+
// This should work as the identity is authorized.
58+
testUtils.CreateIndex{
59+
Identity: testUtils.ClientIdentity(1),
60+
CollectionID: 0,
61+
FieldName: "name",
62+
},
63+
},
64+
}
65+
66+
testUtils.ExecuteTestCase(t, test)
67+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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+
)
18+
19+
func TestAAC_GatesIndexDrop_AllowIfAuthorizedElseError(t *testing.T) {
20+
test := testUtils.TestCase{
21+
Description: "admin acp correctly gates index drop operation, allow if authorized, otherwise error",
22+
Actions: []any{
23+
// Starting with ACC, so only authorized user(s) can perform operations from here on out.
24+
testUtils.Close{},
25+
testUtils.Start{
26+
Identity: testUtils.ClientIdentity(1),
27+
EnableNAC: true,
28+
},
29+
// Note: Doing setup steps after starting with aac enabled, otherwise the in-memory tests
30+
// will loose setup state when the restart happens (i.e. the restart that started aac).
31+
testUtils.SchemaUpdate{
32+
Identity: testUtils.ClientIdentity(1),
33+
Schema: `
34+
type User {
35+
name: String @index
36+
}
37+
`,
38+
},
39+
// Note: Setup is now done, the test code that follows is what we want to assert.
40+
41+
// We haven't authorized non-identities. So, this should error.
42+
testUtils.DropIndex{
43+
Identity: testUtils.NoIdentity(),
44+
IndexName: "User_name_ASC",
45+
ExpectedError: "not authorized to perform operation",
46+
},
47+
48+
// Wrong user/identity will also not be authorized.
49+
testUtils.DropIndex{
50+
Identity: testUtils.ClientIdentity(2),
51+
IndexName: "User_name_ASC",
52+
ExpectedError: "not authorized to perform operation",
53+
},
54+
55+
// This should work as the identity is authorized.
56+
testUtils.DropIndex{
57+
Identity: testUtils.ClientIdentity(1),
58+
IndexName: "User_name_ASC",
59+
},
60+
},
61+
}
62+
63+
testUtils.ExecuteTestCase(t, test)
64+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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+
"github.com/sourcenetwork/defradb/client"
17+
testUtils "github.com/sourcenetwork/defradb/tests/integration"
18+
)
19+
20+
func TestAAC_GatesIndexList_AllowIfAuthorizedElseError(t *testing.T) {
21+
test := testUtils.TestCase{
22+
Description: "node acp correctly gates index list operation, allow if authorized, otherwise error",
23+
Actions: []any{
24+
// Starting with ACC, so only authorized user(s) can perform operations from here on out.
25+
testUtils.Close{},
26+
testUtils.Start{
27+
Identity: testUtils.ClientIdentity(1),
28+
EnableNAC: true,
29+
},
30+
// Note: Doing setup steps after starting with aac enabled, otherwise the in-memory tests
31+
// will loose setup state when the restart happens (i.e. the restart that started aac).
32+
testUtils.SchemaUpdate{
33+
Identity: testUtils.ClientIdentity(1),
34+
Schema: `
35+
type User {
36+
name: String
37+
}
38+
`,
39+
},
40+
// Note: Setup is now done, the test code that follows is what we want to assert.
41+
42+
// We haven't authorized non-identities. So, this should error.
43+
testUtils.GetIndexes{
44+
Identity: testUtils.NoIdentity(),
45+
CollectionID: 0,
46+
ExpectedError: "not authorized to perform operation",
47+
},
48+
49+
// Wrong user/identity will also not be authorized.
50+
testUtils.GetIndexes{
51+
Identity: testUtils.ClientIdentity(2),
52+
CollectionID: 0,
53+
ExpectedError: "not authorized to perform operation",
54+
},
55+
56+
// This should work as the identity is authorized.
57+
testUtils.GetIndexes{
58+
Identity: testUtils.ClientIdentity(1),
59+
CollectionID: 0,
60+
ExpectedIndexes: []client.IndexDescription{},
61+
},
62+
},
63+
}
64+
65+
testUtils.ExecuteTestCase(t, test)
66+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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_setup_then_start
12+
13+
import (
14+
"testing"
15+
16+
"github.com/sourcenetwork/immutable"
17+
18+
testUtils "github.com/sourcenetwork/defradb/tests/integration"
19+
)
20+
21+
func TestAAC_GatesIndexCreatePreSetup_AllowIfAuthorizedElseError(t *testing.T) {
22+
test := testUtils.TestCase{
23+
Description: "admin acp correctly gates index create operation (setup before aac), allow if authorized, otherwise error",
24+
SupportedDatabaseTypes: immutable.Some(
25+
[]testUtils.DatabaseType{
26+
// This test only supports file type databases since the setup steps will be done before
27+
// the node is re-started with aac enabled (if it's in-memory it will loose setup state).
28+
testUtils.BadgerFileType,
29+
},
30+
),
31+
Actions: []any{
32+
// Note: Since this is not an in-memory test, we can do the setup steps before aac is enabled.
33+
testUtils.SchemaUpdate{
34+
Schema: `
35+
type User {
36+
name: String
37+
}
38+
`,
39+
},
40+
41+
// Starting with ACC, so only authorized user(s) can perform operations from here on out.
42+
testUtils.Close{},
43+
testUtils.Start{
44+
Identity: testUtils.ClientIdentity(1),
45+
EnableNAC: true,
46+
},
47+
48+
// We haven't authorized non-identities. So, this should error.
49+
testUtils.CreateIndex{
50+
Identity: testUtils.NoIdentity(),
51+
CollectionID: 0,
52+
FieldName: "name",
53+
ExpectedError: "not authorized to perform operation",
54+
},
55+
56+
// Wrong user/identity will also not be authorized.
57+
testUtils.CreateIndex{
58+
Identity: testUtils.ClientIdentity(2),
59+
CollectionID: 0,
60+
FieldName: "name",
61+
ExpectedError: "not authorized to perform operation",
62+
},
63+
64+
// This should work as the identity is authorized.
65+
testUtils.CreateIndex{
66+
Identity: testUtils.ClientIdentity(1),
67+
CollectionID: 0,
68+
FieldName: "name",
69+
},
70+
},
71+
}
72+
73+
testUtils.ExecuteTestCase(t, test)
74+
}

0 commit comments

Comments
 (0)