fosrl.pangolin/server/auth/actions.ts

152 lines
4.8 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",
2024-10-06 18:05:20 -04:00
getOrg = "getOrg",
updateOrg = "updateOrg",
2024-12-22 12:03:46 -05:00
deleteOrg = "deleteOrg",
2024-10-06 18:05:20 -04:00
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",
inviteUser = "inviteUser",
2024-10-12 22:31:24 -04:00
removeUser = "removeUser",
2024-10-12 21:36:14 -04:00
listUsers = "listUsers",
listSiteRoles = "listSiteRoles",
listResourceRoles = "listResourceRoles",
2024-11-15 23:38:08 -05:00
setResourceUsers = "setResourceUsers",
setResourceRoles = "setResourceRoles",
2024-11-15 23:38:08 -05:00
listResourceUsers = "listResourceUsers",
// removeRoleSite = "removeRoleSite",
// addRoleAction = "addRoleAction",
// removeRoleAction = "removeRoleAction",
2024-11-15 23:38:08 -05:00
// listRoleSites = "listRoleSites",
2024-10-12 21:36:14 -04:00
listRoleResources = "listRoleResources",
2024-11-15 23:38:08 -05:00
// listRoleActions = "listRoleActions",
2024-10-12 22:31:24 -04:00
addUserRole = "addUserRole",
2024-11-15 23:38:08 -05:00
// addUserSite = "addUserSite",
// addUserAction = "addUserAction",
// removeUserAction = "removeUserAction",
2024-11-15 23:38:08 -05:00
// removeUserSite = "removeUserSite",
getOrgUser = "getOrgUser",
setResourcePassword = "setResourcePassword",
setResourcePincode = "setResourcePincode",
setResourceWhitelist = "setResourceWhitelist",
getResourceWhitelist = "getResourceWhitelist",
generateAccessToken = "generateAccessToken",
deleteAcessToken = "deleteAcessToken",
listAccessTokens = "listAccessTokens",
createResourceRule = "createResourceRule",
deleteResourceRule = "deleteResourceRule",
2025-02-08 17:10:37 -05:00
listResourceRules = "listResourceRules",
updateResourceRule = "updateResourceRule",
2025-02-16 18:09:17 -05:00
listOrgDomains = "listOrgDomains",
2024-10-06 16:43:59 -04:00
}
2024-10-14 21:54:43 -04:00
export async function checkUserActionPermission(
actionId: string,
req: Request
2024-10-14 21:54:43 -04:00
): 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-14 21:54:43 -04:00
);
}
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-14 21:54:43 -04:00
)
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-14 21:54:43 -04:00
);
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),
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!)
)
2024-10-14 21:54:43 -04:00
)
.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-14 21:54:43 -04:00
);
2024-10-06 18:05:20 -04:00
}
2024-10-13 17:13:47 -04:00
}