portail-associations/server/internalAccess.ts

108 lines
3.2 KiB
TypeScript

import type { User } from "../drizzle/schema";
import * as db from "./db";
import { userHasLogisticsAccess } from "./logisticsGroup";
import {
getDelegatedSignerIdsForDirectrice,
getDirectriceIdsDelegatingToUser,
} from "./salleSignatureDelegation";
export type AuthenticatedPortalUser = User & {
canManageLogistics: boolean;
canSignSalle: boolean;
salleSignatureDelegatedByUserIds: number[];
};
type MinimalUser = Pick<User, "id" | "role" | "canManageLogistics">;
export async function userHasSalleSignatureAccess(user: Pick<User, "id" | "role">) {
if (user.role === "super_admin" || user.role === "directrice") {
return true;
}
const [internalUsers, delegatedBySetting] = await Promise.all([
db.getAdminUsers(),
getDirectriceIdsDelegatingToUser(user.id),
]);
return internalUsers.some((entry) => {
if (entry.role !== "directrice" || !entry.isActive) return false;
return entry.delegatedSalleSignerUserId === user.id || delegatedBySetting.includes(entry.id);
});
}
export async function getSalleSignatureDelegatedByUserIds(userId: number) {
const [internalUsers, delegatedBySetting] = await Promise.all([
db.getAdminUsers(),
getDirectriceIdsDelegatingToUser(userId),
]);
return Array.from(
new Set(
internalUsers
.filter(
(entry) =>
entry.role === "directrice"
&& entry.isActive
&& entry.delegatedSalleSignerUserId === userId
)
.map((entry) => entry.id)
.concat(delegatedBySetting)
)
);
}
export async function withEffectiveInternalAccess<TUser extends User | null>(
user: TUser
): Promise<(AuthenticatedPortalUser & NonNullable<TUser>) | null> {
if (!user) return null;
const [effectiveLogisticsAccess, effectiveSalleSignatureAccess, delegatedByUserIds] =
await Promise.all([
userHasLogisticsAccess(user as MinimalUser),
userHasSalleSignatureAccess(user),
getSalleSignatureDelegatedByUserIds(user.id),
]);
return {
...user,
canManageLogistics: effectiveLogisticsAccess,
canSignSalle: effectiveSalleSignatureAccess,
salleSignatureDelegatedByUserIds: delegatedByUserIds,
} as AuthenticatedPortalUser & NonNullable<TUser>;
}
export async function getSalleSignatureDelegateCandidates(currentUserId: number) {
const internalUsers = await db.getAdminUsers();
return internalUsers
.filter(
(entry) =>
entry.isActive
&& entry.id !== currentUserId
&& (
entry.role === "accueil"
|| entry.role === "admin"
|| entry.role === "directrice"
|| entry.role === "super_admin"
)
)
.map((entry) => ({
id: entry.id,
name: entry.name || "Sans nom",
email: entry.email || "",
role: entry.role,
}));
}
export async function getSalleSignatureDelegates(directriceUserId: number) {
const delegateIds = await getDelegatedSignerIdsForDirectrice(directriceUserId);
const delegates = await Promise.all(delegateIds.map((id) => db.getUserById(id)));
return delegates
.filter((entry): entry is NonNullable<typeof entry> => Boolean(entry?.isActive))
.map((entry) => ({
id: entry.id,
name: entry.name || "Sans nom",
email: entry.email || "",
role: entry.role,
}));
}