'use server'; import { createAdminClient } from '@/lib/supabase/admin'; import { revalidatePath } from 'next/cache'; import { sendMail } from '@/utils/mail'; export async function getUsers() { const admin = createAdminClient(); const { data: { users }, error } = await admin.auth.admin.listUsers(); if (error) throw error; const { data: dbUsers, error: dbError } = await admin .from('users') .select('id, role, company_id, companies(id, name)'); const userMap: Record = {}; if (!dbError && dbUsers) { dbUsers.forEach((u: any) => { userMap[u.id] = { role: u.role, company_id: u.company_id || null, company_name: Array.isArray(u.companies) ? u.companies[0]?.name || null : u.companies?.name || null, }; }); } return users.map((u) => ({ ...u, role: userMap[u.id]?.role || 'partner', company_id: userMap[u.id]?.company_id || null, company_name: userMap[u.id]?.company_name || null, })); } export async function createUser(data: { email: string; role?: 'admin' | 'partner'; email_confirm?: boolean; company_id?: string }) { const admin = createAdminClient(); const { data: { user }, error } = await admin.auth.admin.createUser({ email: data.email, password: Math.random().toString(36).slice(-10) + Math.random().toString(36).slice(-10), email_confirm: data.email_confirm ?? true, }); if (error) throw error; if (!user) throw new Error('Benutzer konnte nicht erstellt werden.'); const role = data.role || 'partner'; const { error: dbError } = await admin .from('users') .upsert({ id: user.id, role, company_id: data.company_id || null }, { onConflict: 'id' }); if (dbError) throw dbError; // Generate recovery link to let user set password try { const { data: linkData, error: linkError } = await admin.auth.admin.generateLink({ type: 'recovery', email: data.email, }); if (!linkError && linkData) { const tokenHash = (linkData as any)?.properties?.hashed_token; if (tokenHash) { const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://staging.hephex.de'; const setupLink = `${siteUrl}/auth/confirm?token_hash=${tokenHash}&type=recovery&next=/auth/update-password`; await sendMail({ to: data.email, subject: 'Willkommen bei CASPOS – Ihr Benutzerkonto wurde erstellt', text: `Hallo,\n\nein neues Benutzerkonto wurde für Sie auf CASPOS erstellt.\n\nBitte klicken Sie auf den folgenden Link, um Ihr persönliches Passwort festzulegen und Ihr Konto zu aktivieren:\n${setupLink}\n\nDieser Link ist zeitlich begrenzt gültig.\n\nViele Grüße,\nIhr CASPOS-Team`, html: `

Willkommen bei CASPOS!

Hallo,

für Sie wurde erfolgreich ein neues Benutzerkonto auf unserer Plattform eingerichtet.

Bitte klicken Sie auf den untenstehenden Button, um Ihr Passwort festzulegen und Ihr Konto zu aktivieren:

Passwort jetzt festlegen

Falls der Button nicht funktioniert, können Sie auch folgenden Link in Ihren Browser kopieren:
${setupLink}


Diese E-Mail wurde automatisch generiert. Bitte antworten Sie nicht darauf.

`, }); } } } catch (mailError) { console.error('Failed to send welcome setup mail:', mailError); } revalidatePath('/admin/users'); return user; } export async function deleteUser(id: string) { const admin = createAdminClient(); const { error } = await admin.auth.admin.deleteUser(id); if (error) throw error; revalidatePath('/admin/users'); } export async function updateUserRole(id: string, role: 'admin' | 'partner' | 'gesperrt') { const admin = createAdminClient(); const { error } = await admin .from('users') .upsert({ id, role }, { onConflict: 'id' }); if (error) throw error; revalidatePath('/admin/users'); } export async function updateUserStatus(id: string, ban: boolean) { const admin = createAdminClient(); const { error } = await admin.auth.admin.updateUserById(id, { ban_duration: ban ? '876000h' : '0h', }); if (error) throw error; revalidatePath('/admin/users'); } export async function resetPassword(email: string) { const admin = createAdminClient(); const { data, error } = await admin.auth.admin.generateLink({ type: 'recovery', email, }); if (error) throw error; const linkData = data as any; // Extract token_hash from the generated link properties const tokenHash = linkData?.properties?.hashed_token; if (!tokenHash) throw new Error('Recovery token not generated'); // Build link pointing to our own /auth/confirm route const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://staging.hephex.de'; const resetLink = `${siteUrl}/auth/confirm?token_hash=${tokenHash}&type=recovery&next=/auth/update-password`; await sendMail({ to: email, subject: 'Passwort zurücksetzen', text: `Klicken Sie auf den folgenden Link, um Ihr Passwort zurückzusetzen: ${resetLink}`, html: `

Klicken Sie hier, um Ihr Passwort zurückzusetzen.

`, }); } export async function getPartners() { const admin = createAdminClient(); const { data: { users }, error } = await admin.auth.admin.listUsers(); if (error) throw error; const { data: dbUsers, error: dbError } = await admin .from('users') .select('id, role, company_id, companies(id, name)') .in('role', ['partner', 'gesperrt']); if (dbError) throw dbError; const userMap: Record = {}; dbUsers.forEach((u: any) => { userMap[u.id] = { role: u.role, company_id: u.company_id || null, company_name: Array.isArray(u.companies) ? u.companies[0]?.name || null : u.companies?.name || null, }; }); const partnerIds = new Set(dbUsers.map((u: any) => u.id)); return users .filter((u) => partnerIds.has(u.id)) .map((u) => ({ ...u, role: userMap[u.id]?.role || 'partner', company_id: userMap[u.id]?.company_id || null, company_name: userMap[u.id]?.company_name || null, })); }