Skip to content

Commit

Permalink
feat(client): add method for removeUserFromGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
david-r-cox committed Oct 10, 2024
1 parent 972debd commit dd9b234
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
46 changes: 46 additions & 0 deletions client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import {
assignPermissionToRole,
addUserToGroup,
removeUserFromGroup,
createRole,
createPermission,
getParentRole,
Expand Down Expand Up @@ -506,6 +507,51 @@ export class KeyHippo {
}
}

/**
* Removes a user from a group in the RBAC system.
*
* @param userId - The unique identifier of the user to be removed from the group.
* @param groupId - The unique identifier of the group from which the user is being removed.
* @returns A Promise that resolves when the removal is successful.
*
* User removal process:
* 1. Validates the input parameters.
* 2. Checks if the user is a member of the specified group.
* 3. Removes the user-group association from the user_groups table within the RBAC schema.
* 4. Handles potential cascading effects (e.g., removing associated roles or permissions).
*
* Usage example:
* ```typescript
* try {
* await keyHippo.removeUserFromGroup('user123', 'group456');
* console.log('User successfully removed from group');
* } catch (error) {
* console.error('Failed to remove user from group:', error);
* }
* ```
*
* Security implications:
* - Ensure that only authorized administrators can remove users from groups.
* - Removing a user from a group affects their access rights within the application.
* - Consider implementing an audit log for user-group removals.
*
* Error handling:
* - Throws an error if the user or group does not exist.
* - Throws an error if the user is not a member of the specified group.
* - Throws an error if there are database connectivity issues.
*/
async removeUserFromGroup(userId: UserId, groupId: GroupId): Promise<void> {
try {
await removeUserFromGroup(this.supabase, userId, groupId, this.logger);
} catch (error) {
this.logger.error(
`Error removing user from group: ${error instanceof Error ? error.message : String(error)}`,
);
throw error;
}
}

/**
* Retrieves the parent role of a specified role in the RBAC system.
*
Expand Down
1 change: 1 addition & 0 deletions client/src/rbac/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./addUserToGroup";
export * from "./removeUserFromGroup";
export * from "./assignPermissionToRole";
export * from "./createPermission";
export * from "./createRole";
Expand Down
105 changes: 105 additions & 0 deletions client/src/rbac/removeUserFromGroup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { SupabaseClient } from "@supabase/supabase-js";
import { Logger, UserId, GroupId } from "../types";
import { logDebug, logInfo, logError, createDatabaseError } from "../utils";

/**
* Logs the attempt to remove a user from a group.
* @param logger - The logger instance used for logging.
* @param userId - The ID of the user being removed from the group.
* @param groupId - The ID of the group from which the user is being removed.
*/
const logRemoveUserFromGroupAttempt = (
logger: Logger,
userId: UserId,
groupId: GroupId,
): void => {
logDebug(
logger,
`Attempting to remove user '${userId}' from group '${groupId}'`,
);
};

/**
* Executes the RPC call to remove a user from a group in the database.
* @param supabase - The Supabase client instance.
* @param userId - The ID of the user being removed from the group.
* @param groupId - The ID of the group from which the user is being removed.
* @throws Error if the RPC call fails to remove the user from the group.
*/
const executeRemoveUserFromGroupRpc = async (
supabase: SupabaseClient<any, "public", any>,
userId: UserId,
groupId: GroupId,
): Promise<void> => {
const { error } = await supabase
.schema("keyhippo_rbac")
.rpc("remove_user_from_group", {
p_user_id: userId,
p_group_id: groupId,
});

if (error) {
throw new Error(`Remove User from Group RPC failed: ${error.message}`);
}
};

/**
* Logs the successful removal of a user from a group.
* @param logger - The logger instance used for logging.
* @param userId - The ID of the user removed from the group.
* @param groupId - The ID of the group from which the user was removed.
*/
const logRemoveUserFromGroupSuccess = (
logger: Logger,
userId: UserId,
groupId: GroupId,
): void => {
logInfo(
logger,
`Successfully removed user '${userId}' from group '${groupId}'`,
);
};

/**
* Handles errors that occur during the remove user from group process.
* @param error - The error encountered during the process.
* @param logger - The logger instance used for logging errors.
* @param userId - The ID of the user involved in the failed operation.
* @param groupId - The ID of the group involved in the failed operation.
* @throws ApplicationError encapsulating the original error with a descriptive message.
*/
const handleRemoveUserFromGroupError = (
error: unknown,
logger: Logger,
userId: UserId,
groupId: GroupId,
): never => {
logError(
logger,
`Failed to remove user '${userId}' from group '${groupId}'. Error: ${error}`,
);
throw createDatabaseError(`Failed to remove user from group: ${error}`);
};

/**
* Removes a user from a group.
* @param supabase - The Supabase client.
* @param userId - The ID of the user to be removed from the group.
* @param groupId - The ID of the group from which the user is being removed.
* @param logger - The logger instance.
* @throws ApplicationError if the process fails.
*/
export const removeUserFromGroup = async (
supabase: SupabaseClient<any, "public", any>,
userId: UserId,
groupId: GroupId,
logger: Logger,
): Promise<void> => {
try {
logRemoveUserFromGroupAttempt(logger, userId, groupId);
await executeRemoveUserFromGroupRpc(supabase, userId, groupId);
logRemoveUserFromGroupSuccess(logger, userId, groupId);
} catch (error) {
handleRemoveUserFromGroupError(error, logger, userId, groupId);
}
};

0 comments on commit dd9b234

Please sign in to comment.