28 lines
1.9 KiB
TypeScript
28 lines
1.9 KiB
TypeScript
|
|
import { randomUUID } from 'node:crypto';
|
||
|
|
import type { PoolConnection } from 'mysql2/promise';
|
||
|
|
import { run } from './db.js';
|
||
|
|
import { randomToken, sha256 } from './crypto.js';
|
||
|
|
import { config } from './config.js';
|
||
|
|
import { sendMail } from './mail.js';
|
||
|
|
|
||
|
|
export const INVITE_DAYS = 7;
|
||
|
|
|
||
|
|
/** Legt einen eingeladenen Benutzer an und liefert den Einladungslink (Token nur als Hash gespeichert). */
|
||
|
|
export async function createInvitedUser(c: PoolConnection, u: { email: string; name: string; kind: 'customer' | 'staff'; staffRole?: string | null }): Promise<{ userId: string; token: string }> {
|
||
|
|
const userId = randomUUID();
|
||
|
|
await run('INSERT INTO users (id, email, name, kind, staff_role, status) VALUES (?,?,?,?,?,\'invited\')', [userId, u.email.toLowerCase(), u.name, u.kind, u.staffRole ?? null], c);
|
||
|
|
return { userId, token: await createToken(c, userId, 'invite') };
|
||
|
|
}
|
||
|
|
export async function createToken(c: PoolConnection | undefined, userId: string, purpose: 'invite' | 'password_reset' | 'verify_email'): Promise<string> {
|
||
|
|
const token = randomToken(32);
|
||
|
|
const hours = purpose === 'invite' ? INVITE_DAYS * 24 : 1;
|
||
|
|
await run('INSERT INTO user_tokens (id, user_id, purpose, token_hash, expires_at) VALUES (?,?,?,?, DATE_ADD(UTC_TIMESTAMP(3), INTERVAL ? HOUR))', [randomUUID(), userId, purpose, sha256(token), hours], c);
|
||
|
|
return token;
|
||
|
|
}
|
||
|
|
export const inviteLink = (token: string): string => `${config.baseUrl}/einladung?token=${encodeURIComponent(token)}`;
|
||
|
|
export const resetLink = (token: string): string => `${config.baseUrl}/passwort-reset?token=${encodeURIComponent(token)}`;
|
||
|
|
|
||
|
|
export async function mailInvite(email: string, name: string, token: string): Promise<string> {
|
||
|
|
return sendMail(email, 'invite', 'Ihr Zugang zum Kundencenter', `Hallo ${name},\n\nfür Sie wurde ein Zugang eingerichtet. Bitte legen Sie hier Ihr Passwort fest (${INVITE_DAYS} Tage gültig):\n${inviteLink(token)}\n`);
|
||
|
|
}
|