source: app/(app)/profile/actions.ts@ 22fc16d

nextjs
Last change on this file since 22fc16d was 82cef6a, checked in by Vasilaki Tocili <vasilakigorgi@…>, 4 months ago

refactor: improve profile UX

  • The throwing erros in the editing of the profile stuff was throwing to

server, now it returns strings and those are shown to the user on the
screen, improving the UX

  • Now there are two forms for the username and email and for password

change which also affect the buttons. When the form is submitting to
the server, the buttons are turned off and are showing "Saving..." or
"Updating..."

  • Property mode set to 100644
File size: 2.5 KB
Line 
1'use server';
2
3import { auth } from '@/auth';
4import { redirect } from 'next/navigation';
5import postgres from 'postgres';
6import bcrypt from 'bcrypt';
7
8const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });
9
10type ActionResult = string | undefined; // string = error message, undefined = success
11
12export async function updateProfile(
13 _prevState: ActionResult,
14 formData: FormData
15): Promise<ActionResult> {
16 const session = await auth();
17 if (!session?.user?.id) {
18 redirect('/login');
19 }
20
21 const userId = Number(session.user.id);
22 if (!Number.isInteger(userId)) {
23 return 'Invalid session. Please log in again.';
24 }
25 const name = String(formData.get('name') ?? '').trim();
26 const email = String(formData.get('email') ?? '').trim().toLowerCase();
27
28 if (!name) {
29 return 'Name is required.';
30 }
31 if (!email || !email.includes('@')) {
32 return 'Please enter a valid email.';
33 }
34
35 // Email already exists check
36 const existing = await sql`
37 SELECT user_id FROM "user"
38 WHERE email = ${email} AND user_id != ${userId}
39 `;
40 if (existing.length > 0) {
41 return 'Email already exists.';
42 }
43
44 await sql`
45 UPDATE "user"
46 SET user_name = ${name},
47 email = ${email}
48 WHERE user_id = ${userId}
49 `;
50
51 redirect('/profile');
52}
53
54export async function updatePassword(
55 _prevState: ActionResult,
56 formData: FormData
57): Promise<ActionResult> {
58 const session = await auth();
59 if (!session?.user?.id) {
60 redirect('/login');
61 }
62
63 const userId = Number(session.user.id);
64 if (!Number.isInteger(userId)) {
65 return 'Invalid session. Please log in again.';
66 }
67 const currentPassword = String(formData.get('currentPassword') ?? '');
68 const newPassword = String(formData.get('newPassword') ?? '');
69
70 if (newPassword.length < 6) {
71 return 'New password must be at least 6 characters.';
72 }
73
74 const users = await sql`
75 SELECT password
76 FROM "user"
77 WHERE user_id = ${userId}
78 `;
79 const user = users[0];
80 if (!user) {
81 return 'User not found. Please log in again.';
82 }
83
84 const match = await bcrypt.compare(currentPassword, user.password);
85 if (!match) {
86 return 'Current password is incorrect.';
87 }
88
89 const hashed = await bcrypt.hash(newPassword, 10);
90
91 await sql`
92 UPDATE "user"
93 SET password = ${hashed}
94 WHERE user_id = ${userId}
95 `;
96
97 redirect('/profile');
98}
Note: See TracBrowser for help on using the repository browser.