115 lines
4.4 KiB
TypeScript
115 lines
4.4 KiB
TypeScript
import { getTenantUserType } from "./db/tenants.db.server";
|
|
import { getTenantIdFromUrl, resolveTenantLookupSource } from "./services/.server/urlService";
|
|
import { getUserInfo } from "./session.server";
|
|
import { db } from "./db.server";
|
|
import { getUserRoleInTenant } from "./db/permissions/userRoles.db.server";
|
|
import { Params } from "react-router";
|
|
import { DefaultAppRoles } from "~/application/dtos/shared/DefaultAppRoles";
|
|
import { loadRequiredWebConfig } from "@toolctrl/config";
|
|
import { getHostRoutingContextFromRequest } from "./app/HostRouting.server";
|
|
|
|
const webConfig = loadRequiredWebConfig();
|
|
|
|
export type AuthErrorCode = "UNAUTHORIZED" | "FORBIDDEN";
|
|
|
|
export function authErrorEnvelope(code: AuthErrorCode, messageKey: string) {
|
|
return { error: { code, messageKey } };
|
|
}
|
|
|
|
const UNAUTHORIZED_ENVELOPE = authErrorEnvelope("UNAUTHORIZED", "errors.unauthorized");
|
|
const FORBIDDEN_ADMINS_ONLY_ENVELOPE = authErrorEnvelope("FORBIDDEN", "errors.adminsOnly");
|
|
|
|
export async function requireAuth({ request, params, adminOnly }: { request: Request; params: { tenant?: string }; adminOnly?: boolean }) {
|
|
const userInfo = await getUserInfo(request);
|
|
const hostContext = getHostRoutingContextFromRequest(request);
|
|
if (hostContext === "admin") {
|
|
return await requireSuperAdmin({ request });
|
|
}
|
|
|
|
const tenantLookupSource = resolveTenantLookupSource({ request, params });
|
|
if (tenantLookupSource.source === "app-route-param") {
|
|
const tenantId = await getTenantIdFromUrl({ tenant: tenantLookupSource.tenant });
|
|
if (!userInfo.userId || !tenantId) {
|
|
throw Response.json(UNAUTHORIZED_ENVELOPE, { status: 401 });
|
|
}
|
|
const member = await getTenantUserType(userInfo.userId, tenantId);
|
|
if (!member) {
|
|
const isSuperAdmin = await getIsSuperAdminByUserId(userInfo.userId);
|
|
if (!isSuperAdmin) {
|
|
throw Response.json(UNAUTHORIZED_ENVELOPE, { status: 401 });
|
|
}
|
|
}
|
|
}
|
|
|
|
if (adminOnly) {
|
|
const isSuperUserOrAdmin = await getIsSuperUserOrAdmin({ request, params });
|
|
if (!isSuperUserOrAdmin && webConfig.nodeEnv !== "development") {
|
|
throw Response.json(FORBIDDEN_ADMINS_ONLY_ENVELOPE, { status: 401 });
|
|
}
|
|
}
|
|
|
|
return { ...userInfo };
|
|
}
|
|
|
|
export async function requireSuperAdmin({ request }: { request: Request }) {
|
|
const userInfo = await getUserInfo(request);
|
|
if (!userInfo.userId) {
|
|
throw Response.json(UNAUTHORIZED_ENVELOPE, { status: 401 });
|
|
}
|
|
const isSuperAdmin = await db.adminUser.findUnique({ where: { userId: userInfo.userId } });
|
|
if (!isSuperAdmin) {
|
|
throw Response.json(UNAUTHORIZED_ENVELOPE, { status: 401 });
|
|
}
|
|
return { ...userInfo, isSuperAdmin };
|
|
}
|
|
|
|
export async function getIsSuperUserOrAdmin({ request, params }: { request: Request; params: Params }) {
|
|
const { userId } = await getUserInfo(request);
|
|
const tenantId = await getTenantIdFromUrl(params);
|
|
if (!userId || !tenantId) return false;
|
|
|
|
const isSuperAdmin = await getIsSuperAdmin({ request });
|
|
if (isSuperAdmin) return true;
|
|
|
|
const isSuperUser = await getUserRoleInTenant(userId, tenantId, DefaultAppRoles.SuperUser);
|
|
if (isSuperUser) return true;
|
|
|
|
const isAdmin = await getUserRoleInTenant(userId, tenantId, DefaultAppRoles.Admin);
|
|
if (isAdmin) return true;
|
|
return false;
|
|
}
|
|
|
|
export async function getIsSuperUserOrAdminByIds({ userId, tenantId }: { userId: string; tenantId: string }) {
|
|
if (!userId || !tenantId) return false;
|
|
|
|
const isSuperAdmin = await db.adminUser.findUnique({ where: { userId: userId } });
|
|
if (isSuperAdmin) return true;
|
|
|
|
const isSuperUser = await getUserRoleInTenant(userId, tenantId, DefaultAppRoles.SuperUser);
|
|
if (isSuperUser) return true;
|
|
|
|
const isAdmin = await getUserRoleInTenant(userId, tenantId, DefaultAppRoles.Admin);
|
|
if (isAdmin) return true;
|
|
return false;
|
|
}
|
|
|
|
export async function getIsSuperAdmin({ request }: { request: Request }) {
|
|
const { userId } = await getUserInfo(request);
|
|
if (!userId) return false;
|
|
return getIsSuperAdminByUserId(userId);
|
|
}
|
|
|
|
export async function getIsSuperAdminByUserId(userId: string) {
|
|
if (!userId) return false;
|
|
const isSuperAdmin = await db.adminUser.findUnique({ where: { userId } });
|
|
return !!isSuperAdmin;
|
|
}
|
|
|
|
export async function requireSuperUserOrAdmin({ request, params }: { request: Request; params: Params }) {
|
|
const isSuperUserOrAdmin = await getIsSuperUserOrAdmin({ request, params });
|
|
if (!isSuperUserOrAdmin) {
|
|
throw Response.json(UNAUTHORIZED_ENVELOPE, { status: 401 });
|
|
}
|
|
return true;
|
|
}
|