diff --git a/shop/components/admin/user-dialog.tsx b/shop/components/admin/user-dialog.tsx index 28414a3..20eaf80 100644 --- a/shop/components/admin/user-dialog.tsx +++ b/shop/components/admin/user-dialog.tsx @@ -96,12 +96,17 @@ export function UserDialog({ companies }: UserDialogProps) { first_name: values.first_name || undefined, last_name: values.last_name || undefined, } - await createUser(payload) - setOpen(false) - form.reset() - router.refresh() + const res = await createUser(payload) + if (res.success) { + setOpen(false) + form.reset() + router.refresh() + } else { + alert(res.error || 'Fehler beim Erstellen des Benutzers.') + } } catch (error) { console.error('Error creating user:', error) + alert('Ein unerwarteter Fehler ist aufgetreten.') } } diff --git a/shop/components/admin/user-list.tsx b/shop/components/admin/user-list.tsx index 12d7fcc..4561cea 100644 --- a/shop/components/admin/user-list.tsx +++ b/shop/components/admin/user-list.tsx @@ -63,17 +63,22 @@ export function UserList({ initialUsers, companies }: UserListProps) { if (confirm('Möchten Sie diesen Benutzer wirklich löschen?')) { setLoadingId(id) try { - await deleteUser(id) - router.refresh() + const res = await deleteUser(id) + if (res.success) { + router.refresh() + } else { + console.error('Fehler beim Löschen des Benutzers:', res.error) + if (res.error?.includes('Belege')) { + if (confirm('Löschen nicht möglich! Auf diesen User existieren bereits Belege. Möchten Sie diesen Benutzer stattdessen sperren?')) { + await handleRoleChange(id, 'gesperrt') + } + } else { + alert('Fehler beim Löschen: ' + res.error) + } + } } catch (e: any) { console.error('Fehler beim Löschen des Benutzers:', e) - if (e.message?.includes('Belege')) { - if (confirm('Löschen nicht möglich! Auf diesen User existieren bereits Belege. Möchten Sie diesen Benutzer stattdessen sperren?')) { - await handleRoleChange(id, 'gesperrt') - } - } else { - alert('Fehler beim Löschen: ' + (e.message || JSON.stringify(e))) - } + alert('Fehler beim Löschen: ' + (e.message || JSON.stringify(e))) } finally { setLoadingId(null) } @@ -83,10 +88,15 @@ export function UserList({ initialUsers, companies }: UserListProps) { const handleRoleChange = async (id: string, newRole: Role) => { setLoadingId(id + '-role') try { - await updateUserRole(id, newRole) - router.refresh() - } catch (e) { + const res = await updateUserRole(id, newRole) + if (res.success) { + router.refresh() + } else { + alert(res.error || 'Fehler beim Ändern der Rolle.') + } + } catch (e: any) { console.error('Fehler beim Ändern der Rolle:', e) + alert('Fehler beim Ändern der Rolle: ' + (e.message || JSON.stringify(e))) } finally { setLoadingId(null) } @@ -96,10 +106,15 @@ export function UserList({ initialUsers, companies }: UserListProps) { const newRole = currentRole === 'gesperrt' ? 'partner' : 'gesperrt' setLoadingId(id + '-lock') try { - await updateUserRole(id, newRole) - router.refresh() - } catch (e) { + const res = await updateUserRole(id, newRole) + if (res.success) { + router.refresh() + } else { + alert(res.error || 'Fehler beim Sperren/Entsperren.') + } + } catch (e: any) { console.error('Fehler beim Sperren/Entsperren:', e) + alert('Fehler beim Sperren/Entsperren: ' + (e.message || JSON.stringify(e))) } finally { setLoadingId(null) } @@ -241,10 +256,15 @@ export function UserList({ initialUsers, companies }: UserListProps) { const val = e.target.value.trim() if (val !== (user.first_name || '')) { try { - await updateUserProfile(user.id, { first_name: val || null, last_name: user.last_name }) - router.refresh() - } catch (err) { + const res = await updateUserProfile(user.id, { first_name: val || null, last_name: user.last_name }) + if (res.success) { + router.refresh() + } else { + alert(res.error || 'Fehler beim Aktualisieren des Vornamens.') + } + } catch (err: any) { console.error('Failed to update first name:', err) + alert('Fehler beim Aktualisieren des Vornamens: ' + (err.message || JSON.stringify(err))) } } }} @@ -263,10 +283,15 @@ export function UserList({ initialUsers, companies }: UserListProps) { const val = e.target.value.trim() if (val !== (user.last_name || '')) { try { - await updateUserProfile(user.id, { first_name: user.first_name, last_name: val || null }) - router.refresh() - } catch (err) { + const res = await updateUserProfile(user.id, { first_name: user.first_name, last_name: val || null }) + if (res.success) { + router.refresh() + } else { + alert(res.error || 'Fehler beim Aktualisieren des Nachnamens.') + } + } catch (err: any) { console.error('Failed to update last name:', err) + alert('Fehler beim Aktualisieren des Nachnamens: ' + (err.message || JSON.stringify(err))) } } }} diff --git a/shop/lib/actions/users.ts b/shop/lib/actions/users.ts index 1bf432f..deea5ba 100644 --- a/shop/lib/actions/users.ts +++ b/shop/lib/actions/users.ts @@ -50,64 +50,77 @@ export async function getUsers() { } export async function createUser(data: { email: string; role?: 'admin' | 'partner' | 'verwaltung'; email_confirm?: boolean; company_id?: string; first_name?: string; last_name?: 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; - - const { error: profileError } = await admin - .from('profiles') - .upsert({ - id: user.id, - first_name: data.first_name || null, - last_name: data.last_name || null, - }, { onConflict: 'id' }); - if (profileError) throw profileError; - - // Generate recovery link to let user set password try { - const { data: linkData, error: linkError } = await admin.auth.admin.generateLink({ - type: 'recovery', + 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 (!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/verify-link?token_hash=${tokenHash}&type=recovery&next=/auth/update-password`; - await sendMail({ - to: data.email, - subject: 'Willkommen bei CASPOS Shop – Ihr Benutzerkonto wurde erstellt', - text: `Hallo,\n\nein neues Benutzerkonto wurde für Sie auf CASPOS Shop erstellt.\n\nBitte klicken Sie auf den folgenden Link, um Ihr persönliches Passwort festzulegen und Ihr Konto zu aktivieren:\n${setupLink}\n\nViele Grüße,\nIhr CASPOS Shop-Team`, - html: getBeautifulEmailHtml( - 'Willkommen bei CASPOS Shop', - ` -

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 festlegen', - setupLink - ), - }); - } + if (error) { + return { success: false, error: error.message }; + } + if (!user) { + return { success: false, error: 'Benutzer konnte nicht erstellt werden.' }; } - } catch (mailError) { - console.error('Failed to send welcome setup mail:', mailError); - } - revalidatePath('/admin/users'); - return user; + 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) { + return { success: false, error: dbError.message }; + } + + const { error: profileError } = await admin + .from('profiles') + .upsert({ + id: user.id, + first_name: data.first_name || null, + last_name: data.last_name || null, + }, { onConflict: 'id' }); + if (profileError) { + return { success: false, error: profileError.message }; + } + + // 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/verify-link?token_hash=${tokenHash}&type=recovery&next=/auth/update-password`; + await sendMail({ + to: data.email, + subject: 'Willkommen bei CASPOS Shop – Ihr Benutzerkonto wurde erstellt', + text: `Hallo,\n\nein neues Benutzerkonto wurde für Sie auf CASPOS Shop erstellt.\n\nBitte klicken Sie auf den folgenden Link, um Ihr persönliches Passwort festzulegen und Ihr Konto zu aktivieren:\n${setupLink}\n\nViele Grüße,\nIhr CASPOS Shop-Team`, + html: getBeautifulEmailHtml( + 'Willkommen bei CASPOS Shop', + ` +

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 festlegen', + setupLink + ), + }); + } + } + } catch (mailError) { + console.error('Failed to send welcome setup mail:', mailError); + } + + revalidatePath('/admin/users'); + return { success: true, user }; + } catch (err: any) { + console.error('Error creating user in action:', err); + return { success: false, error: err.message || 'Ein unerwarteter Fehler ist aufgetreten.' }; + } } export async function deleteUser(id: string) { @@ -125,35 +138,44 @@ export async function deleteUser(id: string) { } if (count && count > 0) { - throw new Error('Auf diesen User gibt es bereits Belege. Sperren möglich.'); + return { success: false, error: 'Auf diesen User gibt es bereits Belege. Sperren möglich.' }; } // Delete from public.users first to satisfy foreign key constraints const { error: dbError } = await admin.from('users').delete().eq('id', id); if (dbError) { console.error('Database delete user error:', dbError); - throw new Error(`Datenbank-Fehler beim Löschen des Benutzers: ${dbError.message}`); + return { success: false, error: `Datenbank-Fehler beim Löschen des Benutzers: ${dbError.message}` }; } const { error } = await admin.auth.admin.deleteUser(id); if (error) { console.error('Auth delete user error:', error); - throw new Error(`Auth-Fehler beim Löschen des Benutzers: ${error.message}`); + return { success: false, error: `Auth-Fehler beim Löschen des Benutzers: ${error.message}` }; } revalidatePath('/admin/users'); + return { success: true }; } catch (err: any) { console.error('deleteUser Server Action failed:', err); - throw new Error(err.message || 'Benutzer konnte nicht gelöscht werden.'); + return { success: false, error: err.message || 'Benutzer konnte nicht gelöscht werden.' }; } } export async function updateUserRole(id: string, role: 'admin' | 'partner' | 'verwaltung' | 'gesperrt') { - const admin = createAdminClient(); - const { error } = await admin - .from('users') - .upsert({ id, role }, { onConflict: 'id' }); - if (error) throw error; - revalidatePath('/admin/users'); + try { + const admin = createAdminClient(); + const { error } = await admin + .from('users') + .upsert({ id, role }, { onConflict: 'id' }); + if (error) { + return { success: false, error: error.message }; + } + revalidatePath('/admin/users'); + return { success: true }; + } catch (err: any) { + console.error('updateUserRole Server Action failed:', err); + return { success: false, error: err.message || 'Rolle konnte nicht aktualisiert werden.' }; + } } export async function updateUserStatus(id: string, ban: boolean) { @@ -224,12 +246,20 @@ export async function getPartners() { } export async function updateUserProfile(id: string, data: { first_name: string | null; last_name: string | null }) { - const admin = createAdminClient(); - const { error } = await admin - .from('profiles') - .upsert({ id, first_name: data.first_name, last_name: data.last_name }, { onConflict: 'id' }); - if (error) throw error; - revalidatePath('/admin/users'); + try { + const admin = createAdminClient(); + const { error } = await admin + .from('profiles') + .upsert({ id, first_name: data.first_name, last_name: data.last_name }, { onConflict: 'id' }); + if (error) { + return { success: false, error: error.message }; + } + revalidatePath('/admin/users'); + return { success: true }; + } catch (err: any) { + console.error('updateUserProfile Server Action failed:', err); + return { success: false, error: err.message || 'Profil konnte nicht aktualisiert werden.' }; + } } function getBeautifulEmailHtml(title: string, messageHtml: string, buttonText?: string, buttonUrl?: string) {