46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
import { randomBytes } from 'node:crypto';
|
|
import { prisma } from '@/lib/db/client';
|
|
import type { AuthenticatedUser } from '@/lib/permissions/permissions';
|
|
import type { Role } from '@prisma/client';
|
|
|
|
interface MpmIdentity {
|
|
userId: string;
|
|
username: string;
|
|
displayName: string | null;
|
|
role: 'ADMIN' | 'USER';
|
|
}
|
|
|
|
/**
|
|
* MPM is the identity and role authority in module mode. The module's local
|
|
* user row supplies stable foreign keys for calendars and reservations.
|
|
*/
|
|
export async function provisionMpmUser(identity: MpmIdentity): Promise<AuthenticatedUser> {
|
|
const hubId = `mpm:${identity.userId}`;
|
|
const email = `mpm-${Buffer.from(identity.userId).toString('base64url')}@users.invalid`;
|
|
const user = await prisma.user.upsert({
|
|
where: { hubId },
|
|
create: {
|
|
hubId,
|
|
email,
|
|
username: identity.username,
|
|
passwordHash: randomBytes(48).toString('hex'),
|
|
role: identity.role as Role,
|
|
},
|
|
update: {
|
|
email,
|
|
username: identity.username,
|
|
role: identity.role as Role,
|
|
},
|
|
select: { id: true, email: true, username: true, role: true },
|
|
});
|
|
|
|
// Keep the external display name available as the profile label when MPM
|
|
// has no separate username. Username is the stable, unique MPM account name.
|
|
return {
|
|
id: user.id,
|
|
email: user.email,
|
|
username: identity.displayName || user.username,
|
|
role: user.role,
|
|
};
|
|
}
|