132 lines
4.5 KiB
TypeScript
132 lines
4.5 KiB
TypeScript
'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<string, { role: string; company_id: string | null; company_name: string | null }> = {};
|
|
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; password?: 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: data.password || 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;
|
|
|
|
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: `<p>Klicken Sie <a href="${resetLink}">hier</a>, um Ihr Passwort zurückzusetzen.</p>`,
|
|
});
|
|
}
|
|
|
|
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<string, { role: string; company_id: string | null; company_name: string | null }> = {};
|
|
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,
|
|
}));
|
|
}
|