Skip to content

fix: revert breaking change and add deprecation notices #285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 9, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
14 changes: 11 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 All @@ -45,6 +50,8 @@ export interface Users extends UsersBase {
*
* @param {string} userId The ID of the user to retrieve the assigned roles for.
* @returns {Promise<Record<string, Role>>} A map of role names to their respective roles.
*
* @deprecated: Use `users.db.getAssignedRoles` or `users.oidc.getAssignedRoles` instead.
*/
getAssignedRoles: (userId: string) => Promise<Record<string, Role>>;

Expand Down Expand Up @@ -147,11 +154,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
14 changes: 10 additions & 4 deletions src/users/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,22 @@ 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 expect(client.users.db.deactivate('dynamic-dave')).resolves.toEqual(true);
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);

// Re-activate
await expect(client.users.db.activate('dynamic-dave')).resolves.toEqual(true);

await client.users.db.delete('dynamic-dave');
await expect(client.users.db.delete('dynamic-dave')).resolves.toEqual(true);
await expectDave(false).toHaveProperty('code', 404);

// Second deletion is a no-op
await expect(client.users.db.delete('dynamic-dave')).resolves.toEqual(false);
});

it('should be able to obtain and rotate api keys', async () => {
Expand Down