Skip to content

Commit 27a567e

Browse files
committed
feat(breaking): include user types in user assignments
1 parent fe3c995 commit 27a567e

File tree

7 files changed

+81
-23
lines changed

7 files changed

+81
-23
lines changed

src/openapi/types.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { definitions } from './schema.js';
1+
import { definitions, operations } from './schema.js';
22

33
type Override<T1, T2> = Omit<T1, keyof T2> & T2;
44
type DefaultProperties = { [key: string]: unknown };
@@ -54,11 +54,6 @@ 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['UserOwnInfo'];
58-
export type WeaviateDBUser = definitions['DBUserInfo'];
59-
export type WeaviateUserType = definitions['UserTypeOutput'];
60-
export type WeaviateUserTypeInternal = definitions['UserTypeInput'];
61-
export type WeaviateUserTypeDB = definitions['DBUserInfo']['dbUserType'];
6257
export type WeaviateVectorIndexConfig = WeaviateClass['vectorIndexConfig'];
6358
export type WeaviateVectorsConfig = WeaviateClass['vectorConfig'];
6459
export type WeaviateVectorConfig = definitions['VectorConfig'];
@@ -73,3 +68,9 @@ export type Meta = definitions['Meta'];
7368
export type Role = definitions['Role'];
7469
export type Permission = definitions['Permission'];
7570
export type Action = definitions['Permission']['action'];
71+
export type WeaviateUser = definitions['UserOwnInfo'];
72+
export type WeaviateDBUser = definitions['DBUserInfo'];
73+
export type WeaviateUserType = definitions['UserTypeOutput'];
74+
export type WeaviateUserTypeInternal = definitions['UserTypeInput'];
75+
export type WeaviateUserTypeDB = definitions['DBUserInfo']['dbUserType'];
76+
export type WeaviateAssignedUser = operations['getUsersForRole']['responses']['200']['schema'][0];

src/roles/index.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { ConnectionREST } from '../index.js';
2-
import { Permission as WeaviatePermission, Role as WeaviateRole } from '../openapi/types.js';
2+
import {
3+
WeaviateAssignedUser,
4+
Permission as WeaviatePermission,
5+
Role as WeaviateRole,
6+
} from '../openapi/types.js';
37
import {
48
BackupsPermission,
59
ClusterPermission,
@@ -11,6 +15,7 @@ import {
1115
Role,
1216
RolesPermission,
1317
TenantsPermission,
18+
UserAssignment,
1419
UsersPermission,
1520
} from './types.js';
1621
import { Map } from './util.js';
@@ -35,7 +40,7 @@ export interface Roles {
3540
* @param {string} roleName The name of the role to retrieve the assigned user IDs for.
3641
* @returns {Promise<string[]>} The user IDs assigned to the role.
3742
*/
38-
assignedUserIds: (roleName: string) => Promise<string[]>;
43+
userAssignments: (roleName: string) => Promise<UserAssignment[]>;
3944
/**
4045
* Delete a role by its name.
4146
*
@@ -89,7 +94,10 @@ const roles = (connection: ConnectionREST): Roles => {
8994
listAll: () => connection.get<WeaviateRole[]>('/authz/roles').then(Map.roles),
9095
byName: (roleName: string) =>
9196
connection.get<WeaviateRole>(`/authz/roles/${roleName}`).then(Map.roleFromWeaviate),
92-
assignedUserIds: (roleName: string) => connection.get<string[]>(`/authz/roles/${roleName}/users`),
97+
userAssignments: (roleName: string) =>
98+
connection
99+
.get<WeaviateAssignedUser[]>(`/authz/roles/${roleName}/user-assignments`, true)
100+
.then(Map.assignedUsers),
93101
create: (roleName: string, permissions?: PermissionsInput) => {
94102
const perms = permissions
95103
? Map.flattenPermissions(permissions).flatMap(Map.permissionToWeaviate)

src/roles/integration.test.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import weaviate, {
77
RolesAction,
88
TenantsAction,
99
WeaviateClient,
10+
UserAssignment,
1011
} from '..';
12+
import { requireAtLeast } from '../../test/version';
1113
import { WeaviateStartUpError, WeaviateUnexpectedStatusCodeError } from '../errors';
12-
import { DbVersion } from '../utils/dbVersion';
1314

1415
type TestCase = {
1516
roleName: string;
@@ -278,11 +279,11 @@ const testCases: TestCase[] = [
278279
},
279280
];
280281

281-
const maybe = DbVersion.fromString(`v${process.env.WEAVIATE_VERSION!}`).isAtLeast(1, 29, 0)
282-
? describe
283-
: describe.skip;
284-
285-
maybe('Integration testing of the roles namespace', () => {
282+
requireAtLeast(
283+
1,
284+
29,
285+
0
286+
)('Integration testing of the roles namespace', () => {
286287
let client: WeaviateClient;
287288

288289
beforeAll(async () => {
@@ -316,6 +317,37 @@ maybe('Integration testing of the roles namespace', () => {
316317
expect(exists).toBeFalsy();
317318
});
318319

320+
requireAtLeast(
321+
1,
322+
30,
323+
0
324+
)('namespaced users', () => {
325+
it('retrieves assigned users with namespace', async () => {
326+
await client.roles.create('landlord', {
327+
collection: 'Buildings',
328+
tenant: 'john doe',
329+
actions: ['create_tenants', 'delete_tenants'],
330+
});
331+
332+
await client.users.db.create('Innkeeper').catch((res) => expect(res.code).toEqual(409));
333+
334+
await client.users.db.assignRoles('landlord', 'custom-user');
335+
await client.users.db.assignRoles('landlord', 'Innkeeper');
336+
337+
const assignments = await client.roles.userAssignments('landlord');
338+
339+
expect(assignments).toEqual(
340+
expect.arrayContaining([
341+
expect.objectContaining<UserAssignment>({ id: 'custom-user', userType: 'db_env_user' }),
342+
expect.objectContaining<UserAssignment>({ id: 'Innkeeper', userType: 'db_user' }),
343+
])
344+
);
345+
346+
await client.users.db.delete('Innkeeper');
347+
await client.roles.delete('landlord');
348+
});
349+
});
350+
319351
describe('should be able to create roles using the permissions factory', () => {
320352
testCases.forEach((testCase) => {
321353
it(`with ${testCase.roleName} permissions`, async () => {

src/roles/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Action } from '../openapi/types.js';
1+
import { Action, WeaviateUserType } from '../openapi/types.js';
22

33
export type BackupsAction = Extract<Action, 'manage_backups'>;
44
export type ClusterAction = Extract<Action, 'read_cluster'>;
@@ -22,6 +22,11 @@ export type TenantsAction = Extract<
2222
>;
2323
export type UsersAction = Extract<Action, 'read_users' | 'assign_and_revoke_users'>;
2424

25+
export type UserAssignment = {
26+
id: string;
27+
userType: WeaviateUserType;
28+
};
29+
2530
export type BackupsPermission = {
2631
collection: string;
2732
actions: BackupsAction[];

src/roles/util.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
WeaviateAssignedUser,
23
WeaviateDBUser,
34
Permission as WeaviatePermission,
45
Role as WeaviateRole,
@@ -23,6 +24,7 @@ import {
2324
RolesPermission,
2425
TenantsAction,
2526
TenantsPermission,
27+
UserAssignment,
2628
UsersAction,
2729
UsersPermission,
2830
} from './types.js';
@@ -153,6 +155,15 @@ export class Map {
153155
acc.push(Map.dbUser(user));
154156
return acc;
155157
}, [] as UserDB[]);
158+
159+
static assignedUsers = (users: WeaviateAssignedUser[]): UserAssignment[] =>
160+
users.reduce((acc, user) => {
161+
acc.push({
162+
id: user.userId || '',
163+
userType: user.userType,
164+
});
165+
return acc;
166+
}, [] as UserAssignment[]);
156167
}
157168

158169
class PermissionsMapping {

src/users/integration.test.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
import weaviate, { ApiKey } from '..';
2-
import { DbVersion } from '../utils/dbVersion';
2+
import { requireAtLeast } from '../../test/version.js';
33
import { WeaviateUserTypeDB } from '../v2';
44
import { UserDB } from './types.js';
55

6-
const version = DbVersion.fromString(`v${process.env.WEAVIATE_VERSION!}`);
7-
8-
/** Run the suite / test only for Weaviate version above this. */
9-
const requireAtLeast = (...semver: [...Parameters<DbVersion['isAtLeast']>]) =>
10-
version.isAtLeast(...semver) ? describe : describe.skip;
11-
126
requireAtLeast(
137
1,
148
29,

test/version.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { DbVersion } from '../src/utils/dbVersion';
2+
3+
const version = DbVersion.fromString(`v${process.env.WEAVIATE_VERSION!}`);
4+
5+
/** Run the suite / test only for Weaviate version above this. */
6+
export const requireAtLeast = (...semver: [...Parameters<DbVersion['isAtLeast']>]) =>
7+
version.isAtLeast(...semver) ? describe : describe.skip;

0 commit comments

Comments
 (0)