create-saas-app-ai-chat
Version:
Create a production-ready AI SaaS with Next.js, Supabase, Stripe, and OpenRouter - 15+ AI models included
129 lines (100 loc) • 3.39 kB
text/typescript
'use server';
import { redirect } from 'next/navigation';
import { createClient } from '@/lib/supabase/server';
import { logActivity } from '@/lib/db/queries';
import { ActivityType } from '@/lib/db/schema';
import messages from '../messages.json';
/**
* Password Management Actions
*
* Handles password reset, update, and change operations
*/
type ForgotPasswordState = {
error?: string;
success?: string;
} | null;
type PasswordState = {
error?: string;
success?: string;
} | null;
/**
* Send password reset email
*/
export async function forgotPasswordAction(
prevState: ForgotPasswordState,
formData: FormData
): Promise<ForgotPasswordState> {
const email = formData.get('email') as string;
const supabase = await createClient();
const { error } = await supabase.auth.resetPasswordForEmail(email, {
redirectTo: `${process.env.NEXT_PUBLIC_BASE_URL}/api/auth/callback?next=/auth/update-password`,
});
if (error) {
return { error: error.message };
}
return { success: messages.auth.password.forgot.success };
}
/**
* Update password (used after password reset)
*/
export async function updatePasswordAction(
prevState: PasswordState,
formData: FormData
): Promise<PasswordState> {
const password = formData.get('password') as string;
const supabase = await createClient();
const { error } = await supabase.auth.updateUser({
password,
});
if (error) {
return { error: error.message };
}
const { data: { user } } = await supabase.auth.getUser();
if (user) {
await logActivity(user.id, ActivityType.UPDATE_PASSWORD);
}
redirect('/dashboard');
}
/**
* Change password (requires current password verification)
*/
export async function changePasswordAction(
prevState: PasswordState,
formData: FormData
): Promise<PasswordState> {
const currentPassword = formData.get('currentPassword') as string;
const newPassword = formData.get('newPassword') as string;
const confirmPassword = formData.get('confirmPassword') as string;
if (!currentPassword || !newPassword || !confirmPassword) {
return { error: messages.auth.password.change.errors.allFieldsRequired };
}
if (newPassword !== confirmPassword) {
return { error: messages.auth.password.change.errors.passwordsDoNotMatch };
}
if (newPassword.length < 8) {
return { error: messages.auth.password.change.errors.passwordTooShort };
}
const supabase = await createClient();
// Verify current password by trying to sign in
const { data: { user } } = await supabase.auth.getUser();
if (!user?.email) {
return { error: messages.auth.password.change.errors.notAuthenticated };
}
// Verify current password
const { error: signInError } = await supabase.auth.signInWithPassword({
email: user.email,
password: currentPassword,
});
if (signInError) {
return { error: messages.auth.password.change.errors.currentPasswordIncorrect };
}
// Update to new password
const { error: updateError } = await supabase.auth.updateUser({
password: newPassword,
});
if (updateError) {
return { error: updateError.message };
}
await logActivity(user.id, ActivityType.UPDATE_PASSWORD);
return { success: messages.auth.password.change.success };
}