Skip to content

Commit 8151e1f

Browse files
committed
Several refactorings:
- Split `roles` with `users` - make `actions` an array inside `permissions` - rename several methods to be aligned with py client in a non-BC way - only run roles/users tests for `>1.29` due to no BC
1 parent c7be3f2 commit 8151e1f

File tree

10 files changed

+249
-172
lines changed

10 files changed

+249
-172
lines changed

.github/workflows/main.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ env:
1212
WEAVIATE_126: 1.26.14
1313
WEAVIATE_127: 1.27.11
1414
WEAVIATE_128: 1.28.4
15-
WEAVIATE_129: 1.29.0-rc.0
15+
WEAVIATE_129: 1.29.0-rc.0-a8c0bce
1616

1717
jobs:
1818
checks:

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { LiveChecker, OpenidConfigurationGetter, ReadyChecker } from './misc/ind
3939
import weaviateV2 from './v2/index.js';
4040

4141
import { ConsistencyLevel } from './data/replication.js';
42+
import users, { Users } from './users/index.js';
4243

4344
export type ProtocolParams = {
4445
/**
@@ -105,6 +106,7 @@ export interface WeaviateClient {
105106
collections: Collections;
106107
oidcAuth?: OidcAuthenticator;
107108
roles: Roles;
109+
users: Users;
108110

109111
close: () => Promise<void>;
110112
getMeta: () => Promise<Meta>;
@@ -224,6 +226,7 @@ async function client(params: ClientParams): Promise<WeaviateClient> {
224226
cluster: cluster(connection),
225227
collections: collections(connection, dbVersionSupport),
226228
roles: roles(connection),
229+
users: users(connection),
227230
close: () => Promise.resolve(connection.close()), // hedge against future changes to add I/O to .close()
228231
getMeta: () => new MetaGetter(connection).do(),
229232
getOpenIDConfig: () => new OpenidConfigurationGetter(connection.http).do(),

src/openapi/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export type WeaviateMultiTenancyConfig = WeaviateClass['multiTenancyConfig'];
5454
export type WeaviateReplicationConfig = WeaviateClass['replicationConfig'];
5555
export type WeaviateShardingConfig = WeaviateClass['shardingConfig'];
5656
export type WeaviateShardStatus = definitions['ShardStatusGetResponse'];
57+
export type WeaviateUser = definitions['UserInfo'];
5758
export type WeaviateVectorIndexConfig = WeaviateClass['vectorIndexConfig'];
5859
export type WeaviateVectorsConfig = WeaviateClass['vectorConfig'];
5960
export type WeaviateVectorConfig = definitions['VectorConfig'];

src/roles/index.ts

Lines changed: 36 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,29 @@ import {
1010
PermissionsInput,
1111
Role,
1212
RolesPermission,
13-
User,
1413
} from './types.js';
1514
import { Map } from './util.js';
1615

1716
export interface Roles {
1817
listAll: () => Promise<Record<string, Role>>;
19-
ofCurrentUser: () => Promise<Record<string, Role>>;
2018
byName: (roleName: string) => Promise<Role | null>;
21-
byUser: (user: string) => Promise<Record<string, Role>>;
22-
assignedUsers: (roleName: string) => Promise<Record<string, User>>;
19+
assignedUserIds: (roleName: string) => Promise<string[]>;
2320
delete: (roleName: string) => Promise<void>;
2421
create: (roleName: string, permissions: PermissionsInput) => Promise<Role>;
25-
assignToUser: (roleNames: string | string[], user: string) => Promise<void>;
2622
exists: (roleName: string) => Promise<boolean>;
27-
revokeFromUser: (roleNames: string | string[], user: string) => Promise<void>;
2823
addPermissions: (roleName: string, permissions: PermissionsInput) => Promise<void>;
2924
removePermissions: (roleName: string, permissions: PermissionsInput) => Promise<void>;
30-
hasPermission: (roleName: string, permission: Permission) => Promise<boolean>;
25+
hasPermissions: (roleName: string, permission: Permission) => Promise<boolean>;
3126
}
3227

3328
const roles = (connection: ConnectionREST): Roles => {
3429
return {
3530
listAll: () => connection.get<WeaviateRole[]>('/authz/roles').then(Map.roles),
36-
ofCurrentUser: () => connection.get<WeaviateRole[]>('/authz/users/own-roles').then(Map.roles),
3731
byName: (roleName: string) =>
3832
connection.get<WeaviateRole>(`/authz/roles/${roleName}`).then(Map.roleFromWeaviate),
39-
byUser: (user: string) => connection.get<WeaviateRole[]>(`/authz/users/${user}/roles`).then(Map.roles),
40-
assignedUsers: (roleName: string) =>
41-
connection.get<string[]>(`/authz/roles/${roleName}/users`).then(Map.users),
33+
assignedUserIds: (roleName: string) => connection.get<string[]>(`/authz/roles/${roleName}/users`),
4234
create: (roleName: string, permissions: PermissionsInput) => {
43-
const perms = Map.flattenPermissions(permissions).map(Map.permissionToWeaviate);
35+
const perms = Map.flattenPermissions(permissions).flatMap(Map.permissionToWeaviate);
4436
return connection
4537
.postEmpty<WeaviateRole>('/authz/roles', {
4638
name: roleName,
@@ -54,43 +46,34 @@ const roles = (connection: ConnectionREST): Roles => {
5446
.get(`/authz/roles/${roleName}`)
5547
.then(() => true)
5648
.catch(() => false),
57-
assignToUser: (roleNames: string | string[], user: string) =>
58-
connection.postEmpty(`/authz/users/${user}/assign`, {
59-
roles: Array.isArray(roleNames) ? roleNames : [roleNames],
60-
}),
61-
revokeFromUser: (roleNames: string | string[], user: string) =>
62-
connection.postEmpty(`/authz/users/${user}/revoke`, {
63-
roles: Array.isArray(roleNames) ? roleNames : [roleNames],
64-
}),
6549
addPermissions: (roleName: string, permissions: PermissionsInput) =>
6650
connection.postEmpty(`/authz/roles/${roleName}/add-permissions`, { permissions }),
6751
removePermissions: (roleName: string, permissions: PermissionsInput) =>
6852
connection.postEmpty(`/authz/roles/${roleName}/remove-permissions`, { permissions }),
69-
hasPermission: (roleName: string, permission: Permission) =>
70-
connection.postReturn<WeaviatePermission, boolean>(
71-
`/authz/roles/${roleName}/has-permission`,
72-
Map.permissionToWeaviate(permission)
73-
),
53+
hasPermissions: (roleName: string, permission: Permission | Permission[]) =>
54+
Promise.all(
55+
(Array.isArray(permission) ? permission : [permission])
56+
.flatMap((p) => Map.permissionToWeaviate(p))
57+
.map((p) =>
58+
connection.postReturn<WeaviatePermission, boolean>(`/authz/roles/${roleName}/has-permission`, p)
59+
)
60+
).then((r) => r.every((b) => b)),
7461
};
7562
};
7663

7764
export const permissions = {
7865
backup: (args: { collection: string | string[]; manage?: boolean }): BackupsPermission[] => {
7966
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
8067
return collections.flatMap((collection) => {
81-
const out: BackupsPermission[] = [];
82-
if (args.manage) {
83-
out.push({ collection, action: 'manage_backups' });
84-
}
68+
const out: BackupsPermission = { collection, actions: [] };
69+
if (args.manage) out.actions.push('manage_backups');
8570
return out;
8671
});
8772
},
8873
cluster: (args: { read?: boolean }): ClusterPermission[] => {
89-
const out: ClusterPermission[] = [];
90-
if (args.read) {
91-
out.push({ action: 'read_cluster' });
92-
}
93-
return out;
74+
const out: ClusterPermission = { actions: [] };
75+
if (args.read) out.actions.push('read_cluster');
76+
return [out];
9477
},
9578
collections: (args: {
9679
collection: string | string[];
@@ -101,19 +84,11 @@ export const permissions = {
10184
}): CollectionsPermission[] => {
10285
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
10386
return collections.flatMap((collection) => {
104-
const out: CollectionsPermission[] = [];
105-
if (args.create_collection) {
106-
out.push({ collection, action: 'create_collections' });
107-
}
108-
if (args.read_config) {
109-
out.push({ collection, action: 'read_collections' });
110-
}
111-
if (args.update_config) {
112-
out.push({ collection, action: 'update_collections' });
113-
}
114-
if (args.delete_collection) {
115-
out.push({ collection, action: 'delete_collections' });
116-
}
87+
const out: CollectionsPermission = { collection, actions: [] };
88+
if (args.create_collection) out.actions.push('create_collections');
89+
if (args.read_config) out.actions.push('read_collections');
90+
if (args.update_config) out.actions.push('update_collections');
91+
if (args.delete_collection) out.actions.push('delete_collections');
11792
return out;
11893
});
11994
},
@@ -126,19 +101,11 @@ export const permissions = {
126101
}): DataPermission[] => {
127102
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
128103
return collections.flatMap((collection) => {
129-
const out: DataPermission[] = [];
130-
if (args.create) {
131-
out.push({ collection, action: 'create_data' });
132-
}
133-
if (args.read) {
134-
out.push({ collection, action: 'read_data' });
135-
}
136-
if (args.update) {
137-
out.push({ collection, action: 'update_data' });
138-
}
139-
if (args.delete) {
140-
out.push({ collection, action: 'delete_data' });
141-
}
104+
const out: DataPermission = { collection, actions: [] };
105+
if (args.create) out.actions.push('create_data');
106+
if (args.read) out.actions.push('read_data');
107+
if (args.update) out.actions.push('update_data');
108+
if (args.delete) out.actions.push('delete_data');
142109
return out;
143110
});
144111
},
@@ -149,23 +116,21 @@ export const permissions = {
149116
}): NodesPermission[] => {
150117
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
151118
return collections.flatMap((collection) => {
152-
const out: NodesPermission[] = [];
153-
if (args.read) {
154-
out.push({ collection, action: 'read_nodes', verbosity: args.verbosity || 'verbose' });
155-
}
119+
const out: NodesPermission = {
120+
collection,
121+
actions: [],
122+
verbosity: args.verbosity || 'verbose',
123+
};
124+
if (args.read) out.actions.push('read_nodes');
156125
return out;
157126
});
158127
},
159128
roles: (args: { role: string | string[]; read?: boolean; manage?: boolean }): RolesPermission[] => {
160129
const roles = Array.isArray(args.role) ? args.role : [args.role];
161130
return roles.flatMap((role) => {
162-
const out: RolesPermission[] = [];
163-
if (args.read) {
164-
out.push({ role, action: 'read_roles' });
165-
}
166-
if (args.manage) {
167-
out.push({ role, action: 'manage_roles' });
168-
}
131+
const out: RolesPermission = { role, actions: [] };
132+
if (args.read) out.actions.push('read_roles');
133+
if (args.manage) out.actions.push('manage_roles');
169134
return out;
170135
});
171136
},

src/roles/integration.test.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from '../errors';
77
import { DbVersion } from '../utils/dbVersion';
88

9-
const only = DbVersion.fromString(`v${process.env.WEAVIATE_VERSION!}`).isAtLeast(1, 28, 0)
9+
const only = DbVersion.fromString(`v${process.env.WEAVIATE_VERSION!}`).isAtLeast(1, 29, 0)
1010
? describe
1111
: describe.skip;
1212

@@ -45,11 +45,6 @@ only('Integration testing of the roles namespace', () => {
4545
);
4646
});
4747

48-
it('should get roles by user', async () => {
49-
const roles = await client.roles.byUser('admin-user');
50-
expect(Object.keys(roles).length).toBeGreaterThan(0);
51-
});
52-
5348
it('should check the existance of a real role', async () => {
5449
const exists = await client.roles.exists('admin');
5550
expect(exists).toBeTruthy();
@@ -72,7 +67,7 @@ only('Integration testing of the roles namespace', () => {
7267
permissions: weaviate.permissions.backup({ collection: 'Some-collection', manage: true }),
7368
expected: {
7469
name: 'backups',
75-
backupsPermissions: [{ collection: 'Some-collection', action: 'manage_backups' }],
70+
backupsPermissions: [{ collection: 'Some-collection', actions: ['manage_backups'] }],
7671
clusterPermissions: [],
7772
collectionsPermissions: [],
7873
dataPermissions: [],
@@ -86,7 +81,7 @@ only('Integration testing of the roles namespace', () => {
8681
expected: {
8782
name: 'cluster',
8883
backupsPermissions: [],
89-
clusterPermissions: [{ action: 'read_cluster' }],
84+
clusterPermissions: [{ actions: ['read_cluster'] }],
9085
collectionsPermissions: [],
9186
dataPermissions: [],
9287
nodesPermissions: [],
@@ -107,10 +102,10 @@ only('Integration testing of the roles namespace', () => {
107102
backupsPermissions: [],
108103
clusterPermissions: [],
109104
collectionsPermissions: [
110-
{ collection: 'Some-collection', action: 'create_collections' },
111-
{ collection: 'Some-collection', action: 'read_collections' },
112-
{ collection: 'Some-collection', action: 'update_collections' },
113-
{ collection: 'Some-collection', action: 'delete_collections' },
105+
{
106+
collection: 'Some-collection',
107+
actions: ['create_collections', 'read_collections', 'update_collections', 'delete_collections'],
108+
},
114109
],
115110
dataPermissions: [],
116111
nodesPermissions: [],
@@ -132,10 +127,10 @@ only('Integration testing of the roles namespace', () => {
132127
clusterPermissions: [],
133128
collectionsPermissions: [],
134129
dataPermissions: [
135-
{ collection: 'Some-collection', action: 'create_data' },
136-
{ collection: 'Some-collection', action: 'read_data' },
137-
{ collection: 'Some-collection', action: 'update_data' },
138-
{ collection: 'Some-collection', action: 'delete_data' },
130+
{
131+
collection: 'Some-collection',
132+
actions: ['create_data', 'read_data', 'update_data', 'delete_data'],
133+
},
139134
],
140135
nodesPermissions: [],
141136
rolesPermissions: [],
@@ -154,7 +149,9 @@ only('Integration testing of the roles namespace', () => {
154149
clusterPermissions: [],
155150
collectionsPermissions: [],
156151
dataPermissions: [],
157-
nodesPermissions: [{ collection: 'Some-collection', verbosity: 'verbose', action: 'read_nodes' }],
152+
nodesPermissions: [
153+
{ collection: 'Some-collection', verbosity: 'verbose', actions: ['read_nodes'] },
154+
],
158155
rolesPermissions: [],
159156
},
160157
},
@@ -168,7 +165,7 @@ only('Integration testing of the roles namespace', () => {
168165
collectionsPermissions: [],
169166
dataPermissions: [],
170167
nodesPermissions: [],
171-
rolesPermissions: [{ role: 'some-role', action: 'manage_roles' }],
168+
rolesPermissions: [{ role: 'some-role', actions: ['manage_roles'] }],
172169
},
173170
},
174171
];
@@ -186,4 +183,10 @@ only('Integration testing of the roles namespace', () => {
186183
await expect(client.roles.byName('backups')).rejects.toThrowError(WeaviateUnexpectedStatusCodeError);
187184
await expect(client.roles.exists('backups')).resolves.toBeFalsy();
188185
});
186+
187+
afterAll(() =>
188+
Promise.all(
189+
['backups', 'cluster', 'collections', 'data', 'nodes', 'roles'].map((n) => client.roles.delete(n))
190+
)
191+
);
189192
});

src/roles/types.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,32 @@ export type RolesAction = Extract<Action, 'manage_roles' | 'read_roles'>;
1919

2020
export type BackupsPermission = {
2121
collection: string;
22-
action: BackupsAction;
22+
actions: BackupsAction[];
2323
};
2424

2525
export type ClusterPermission = {
26-
action: ClusterAction;
26+
actions: ClusterAction[];
2727
};
2828

2929
export type CollectionsPermission = {
3030
collection: string;
31-
action: CollectionsAction;
31+
actions: CollectionsAction[];
3232
};
3333

3434
export type DataPermission = {
3535
collection: string;
36-
action: DataAction;
36+
actions: DataAction[];
3737
};
3838

3939
export type NodesPermission = {
4040
collection: string;
4141
verbosity: 'verbose' | 'minimal';
42-
action: NodesAction;
42+
actions: NodesAction[];
4343
};
4444

4545
export type RolesPermission = {
4646
role: string;
47-
action: RolesAction;
47+
actions: RolesAction[];
4848
};
4949

5050
export type Role = {
@@ -57,10 +57,6 @@ export type Role = {
5757
rolesPermissions: RolesPermission[];
5858
};
5959

60-
export type User = {
61-
name: string;
62-
};
63-
6460
export type Permission =
6561
| BackupsPermission
6662
| ClusterPermission

0 commit comments

Comments
 (0)