Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ env:
WEAVIATE_127: 1.27.15
WEAVIATE_128: 1.28.11
WEAVIATE_129: 1.29.1
WEAVIATE_130: 1.30.0-rc.0-6b9a01c
WEAVIATE_130: 1.30.0

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down
16 changes: 15 additions & 1 deletion src/roles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,25 @@ export interface Roles {
* @returns {Promise<Role | null>} The role if it exists, or null if it does not.
*/
byName: (roleName: string) => Promise<Role | null>;

/**
* Retrieve the user IDs assigned to a role.
*
* @param {string} roleName The name of the role to retrieve the assigned user IDs for.
* @returns {Promise<string[]>} The user IDs assigned to the role.
*
* @deprecated: Use `userAssignments` instead.
*/
assignedUserIds: (roleName: string) => Promise<string[]>;
/**
* Retrieve the user IDs assigned to a role. Each user has a qualifying user type,
* e.g. `'db_user' | 'db_env_user' | 'oidc'`.
*
* Note, unlike `assignedUserIds`, this method may return multiple entries for the same username,
* if OIDC authentication is enabled: once with 'db_*' and once with 'oidc' user type.
*
* @param {string} roleName The name of the role to retrieve the assigned user IDs for.
* @returns {Promise<string[]>} The user IDs assigned to the role.
* @returns {Promise<UserAssignment[]>} User IDs and user types assigned to the role.
*/
userAssignments: (roleName: string) => Promise<UserAssignment[]>;
/**
Expand Down Expand Up @@ -95,6 +108,7 @@ const roles = (connection: ConnectionREST): Roles => {
listAll: () => connection.get<WeaviateRole[]>('/authz/roles').then(Map.roles),
byName: (roleName: string) =>
connection.get<WeaviateRole>(`/authz/roles/${roleName}`).then(Map.roleFromWeaviate),
assignedUserIds: (roleName: string) => connection.get<string[]>(`/authz/roles/${roleName}/users`),
userAssignments: (roleName: string) =>
connection
.get<WeaviateAssignedUser[]>(`/authz/roles/${roleName}/user-assignments`, true)
Expand Down
6 changes: 5 additions & 1 deletion src/roles/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ requireAtLeast(
30,
0
)('namespaced users', () => {
it('retrieves assigned users with namespace', async () => {
it('retrieves assigned users with/without namespace', async () => {
await client.roles.create('landlord', {
collection: 'Buildings',
tenant: 'john-doe',
Expand All @@ -342,6 +342,10 @@ requireAtLeast(
])
);

// Legacy
const assignedUsers = await client.roles.assignedUserIds('landlord');
expect(assignedUsers).toEqual(['Innkeeper', 'custom-user']);

await client.users.db.delete('Innkeeper');
await client.roles.delete('landlord');
});
Expand Down
12 changes: 9 additions & 3 deletions src/users/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ interface UsersBase {
}

export interface Users extends UsersBase {
/** @deprecated: Use `users.db.assignRoles` or `users.oidc.assignRoles` instead. */
assignRoles: (roleNames: string | string[], userId: string) => Promise<void>;
/** @deprecated: Use `users.db.revokeRoles` or `users.oidc.revokeRoles` instead. */
revokeRoles: (roleNames: string | string[], userId: string) => Promise<void>;

/**
* Retrieve the information relevant to the currently authenticated user.
*
Expand Down Expand Up @@ -147,11 +152,12 @@ const users = (connection: ConnectionREST): Users => {
const db = (connection: ConnectionREST): DBUsers => {
const ns = namespacedUsers(connection);

/** expectCode returns true if the error contained an expected status code. */
/** expectCode returns false if the contained WeaviateUnexpectedStatusCodeError
* has an known error code and rethrows the error otherwise. */
const expectCode = (code: number): ((_: any) => boolean) => {
return (error) => {
if (error instanceof WeaviateUnexpectedStatusCodeError) {
return error.code === code;
if (error instanceof WeaviateUnexpectedStatusCodeError && error.code === code) {
return false;
}
throw error;
};
Expand Down
4 changes: 2 additions & 2 deletions src/users/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ requireAtLeast(
await expectDave().toHaveProperty('active', true);

// Second activation is a no-op
await expect(client.users.db.activate('dynamic-dave')).resolves.toEqual(true);
await expect(client.users.db.activate('dynamic-dave')).resolves.toEqual(false);

await client.users.db.deactivate('dynamic-dave');
await expectDave().toHaveProperty('active', false);

// Second deactivation is a no-op
await expect(client.users.db.deactivate('dynamic-dave', { revokeKey: true })).resolves.toEqual(true);
await expect(client.users.db.deactivate('dynamic-dave', { revokeKey: true })).resolves.toEqual(false);

await client.users.db.delete('dynamic-dave');
await expectDave(false).toHaveProperty('code', 404);
Expand Down