fosrl.pangolin/server/auth/actions.ts

140 lines
4.3 KiB
TypeScript
Raw Normal View History

2024-10-14 21:54:43 -04:00
import { Request } from "express";
import { db } from "@server/db";
import { userActions, roleActions, userOrgs } from "@server/db/schema";
import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
2024-10-06 18:05:20 -04:00
export enum ActionsEnum {
createOrg = "createOrg",
deleteOrg = "deleteOrg",
getOrg = "getOrg",
updateOrg = "updateOrg",
createSite = "createSite",
deleteSite = "deleteSite",
getSite = "getSite",
listSites = "listSites",
updateSite = "updateSite",
createResource = "createResource",
deleteResource = "deleteResource",
getResource = "getResource",
listResources = "listResources",
updateResource = "updateResource",
createTarget = "createTarget",
deleteTarget = "deleteTarget",
getTarget = "getTarget",
listTargets = "listTargets",
updateTarget = "updateTarget",
2024-10-12 21:36:14 -04:00
createRole = "createRole",
deleteRole = "deleteRole",
getRole = "getRole",
listRoles = "listRoles",
updateRole = "updateRole",
2024-10-12 22:31:24 -04:00
addUser = "addUser",
removeUser = "removeUser",
2024-10-12 21:36:14 -04:00
listUsers = "listUsers",
listSiteRoles = "listSiteRoles",
listResourceRoles = "listResourceRoles",
addRoleSite = "addRoleSite",
addRoleResource = "addRoleResource",
removeRoleResource = "removeRoleResource",
removeRoleSite = "removeRoleSite",
addRoleAction = "addRoleAction",
removeRoleAction = "removeRoleAction",
listRoleSites = "listRoleSites",
listRoleResources = "listRoleResources",
2024-10-12 22:31:24 -04:00
listRoleActions = "listRoleActions",
addUserRole = "addUserRole",
addUserResource = "addUserResource",
addUserSite = "addUserSite",
addUserAction = "addUserAction",
removeUserAction = "removeUserAction",
removeUserResource = "removeUserResource",
removeUserSite = "removeUserSite",
2024-10-06 16:43:59 -04:00
}
2024-10-14 21:54:43 -04:00
export async function checkUserActionPermission(
actionId: string,
req: Request,
): Promise<boolean> {
2024-10-13 17:13:47 -04:00
const userId = req.user?.userId;
2024-10-14 19:30:38 -04:00
2024-10-06 18:05:20 -04:00
if (!userId) {
2024-10-14 21:54:43 -04:00
throw createHttpError(HttpCode.UNAUTHORIZED, "User not authenticated");
2024-10-06 16:43:59 -04:00
}
2024-10-14 21:54:43 -04:00
if (!req.userOrgId) {
throw createHttpError(
HttpCode.BAD_REQUEST,
"Organization ID is required",
);
}
2024-10-06 18:05:20 -04:00
try {
let userOrgRoleId = req.userOrgRoleId;
// If userOrgRoleId is not available on the request, fetch it
2024-10-14 21:54:43 -04:00
if (userOrgRoleId === undefined) {
const userOrgRole = await db
.select()
2024-10-06 18:05:20 -04:00
.from(userOrgs)
2024-10-14 21:54:43 -04:00
.where(
and(
eq(userOrgs.userId, userId),
eq(userOrgs.orgId, req.userOrgId!),
),
)
2024-10-06 18:05:20 -04:00
.limit(1);
if (userOrgRole.length === 0) {
2024-10-14 21:54:43 -04:00
throw createHttpError(
HttpCode.FORBIDDEN,
"User does not have access to this organization",
);
2024-10-06 18:05:20 -04:00
}
userOrgRoleId = userOrgRole[0].roleId;
}
// Check if the user has direct permission for the action in the current org
2024-10-14 21:54:43 -04:00
const userActionPermission = await db
.select()
2024-10-06 18:05:20 -04:00
.from(userActions)
.where(
and(
eq(userActions.userId, userId),
eq(userActions.actionId, actionId),
2024-10-14 21:54:43 -04:00
eq(userActions.orgId, req.userOrgId!), // TODO: we cant pass the org id if we are not checking the org
),
2024-10-06 18:05:20 -04:00
)
.limit(1);
if (userActionPermission.length > 0) {
return true;
}
2024-10-14 21:54:43 -04:00
// If no direct permission, check role-based permission
const roleActionPermission = await db
.select()
.from(roleActions)
.where(
and(
eq(roleActions.actionId, actionId),
eq(roleActions.roleId, userOrgRoleId!),
eq(roleActions.orgId, req.userOrgId!),
),
)
.limit(1);
2024-10-14 19:30:38 -04:00
2024-10-14 21:54:43 -04:00
return roleActionPermission.length > 0;
2024-10-06 18:05:20 -04:00
2024-10-14 19:30:38 -04:00
return false;
2024-10-06 18:05:20 -04:00
} catch (error) {
2024-10-14 21:54:43 -04:00
console.error("Error checking user action permission:", error);
throw createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Error checking action permission",
);
2024-10-06 18:05:20 -04:00
}
2024-10-13 17:13:47 -04:00
}