108 lines
3.2 KiB
TypeScript
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,
|
|
}));
|
|
}
|