![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/.cursor-server/data/User/History/12d101c1/ |
import type { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '@/lib/prisma';
import bcrypt from 'bcryptjs';
import { sendEmail } from '@/utils/email';
import crypto from 'crypto';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method not allowed' });
}
const { email, password, firstName, lastName, preferredLanguage, role, businessProfileId } = req.body;
if (!email || !password) {
return res.status(400).json({ message: 'Email and password are required' });
}
try {
console.log('Starting user registration process...');
console.log('Received data:', { email, firstName, lastName, preferredLanguage, role, businessProfileId });
// Validate email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return res.status(400).json({ message: 'Please enter a valid email address' });
}
// Validate password length
if (password.length < 8) {
return res.status(400).json({ message: 'Password must be at least 8 characters long' });
}
// Validate role for lawyers
if (role === 'LAWYER' && !businessProfileId) {
return res.status(400).json({ message: 'Lawyers must be associated with a business profile' });
}
// Check if user with this email already exists
console.log('Checking for existing user...');
const existingUser = await prisma.user.findUnique({
where: { email },
});
if (existingUser) {
console.log('User already exists:', email);
return res.status(409).json({ message: 'An account with this email already exists. Please try logging in instead.' });
}
// Hash the password
console.log('Hashing password...');
const hashedPassword = await bcrypt.hash(password, 10);
// Create new user
console.log('Creating new user...');
const newUser = await prisma.user.create({
data: {
email,
password: hashedPassword,
name: firstName ? `${firstName} ${lastName || ''}`.trim() : email.split('@')[0],
role: role || 'USER',
},
});
// Handle business profile association for lawyers
if (role === 'LAWYER' && businessProfileId) {
console.log('Adding lawyer to business profile:', businessProfileId);
try {
await prisma.businessProfile.update({
where: { id: businessProfileId },
data: {
members: {
connect: { id: newUser.id }
}
}
});
console.log('Successfully added lawyer to business profile');
} catch (businessError: any) {
console.error('Error adding lawyer to business profile:', businessError);
// If business profile association fails, we should still create the user
// but log the error for debugging
}
}
// Link orphaned registrations to this user
await prisma.registration.updateMany({
where: {
email: email,
userId: null,
},
data: {
userId: newUser.id,
},
});
console.log('User created successfully:', { id: newUser.id, email: newUser.email, role: newUser.role });
// Send welcome email
try {
const isFrench = preferredLanguage === 'fr';
console.log('Sending welcome email...');
const baseUrl = process.env.NODE_ENV === 'production'
? 'https://lavocat.ca'
: 'https://localhost';
// Generate verification token
const verificationToken = crypto.randomBytes(32).toString('hex');
// Store verification token in database
await prisma.verificationToken.create({
data: {
identifier: email,
token: verificationToken,
expires: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours from now
},
});
const verificationUrl = `${baseUrl}/auth/verify?token=${verificationToken}`;
await sendEmail({
to: email,
subject: isFrench ? 'Bienvenue chez Action Collective !' : 'Welcome to Action Collective!',
text: isFrench
? `Bienvenue, ${firstName || newUser.name || email.split('@')[0]} ! Merci de rejoindre le mouvement pour la justice et les droits humains.`
: `Welcome, ${firstName || newUser.name || email.split('@')[0]}! Thank you for joining Action Collective.`,
html: isFrench
? `<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: #f9f9f9; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.07);">
<div style="background: #1a2238; color: #fff; padding: 32px 24px 16px 24px;">
<h1 style="margin: 0 0 8px 0; font-size: 2em;">Bienvenue${firstName ? `, ${firstName}` : ''} chez Action Collective !</h1>
<p style="margin: 0; font-size: 1.1em;">Merci de rejoindre le mouvement pour la justice et les droits humains.</p>
</div>
<div style="padding: 24px;">
<h2 style="color: #2563eb; margin-top: 0;">🛡️ À propos du fondateur – Danny William Perez</h2>
<p><strong>Tel que présenté dans le Journal de Montréal d'aujourd'hui – 31 mai 2025</strong></p>
<p>
<a href="https://www.Action-Collective.info" style="color: #2563eb;">www.Action-Collective.info</a> |
<a href="https://www.Class-Action.info" style="color: #2563eb;">www.Class-Action.info</a>
</p>
<blockquote style="border-left: 4px solid #2563eb; margin: 16px 0; padding-left: 16px; color: #444;">
"Je n'ai pas attendu un avocat. Je suis devenu la loi."<br>
<em>Ce mouvement n'a pas commencé dans une salle d'audience — il a commencé dans une cellule de prison.</em>
</blockquote>
<p>
Danny William Perez, détenu à la prison de Bordeaux de mars à octobre 2023, s'est vu systématiquement refuser son droit légal à une heure de sortie quotidienne — un droit humain fondamental garanti par la loi québécoise et les traités internationaux.
</p>
<ul>
<li>🖋️ Il a rédigé une demande d'habeas corpus sur l'ordinateur juridique limité de la prison</li>
<li>🧾 L'a fait assermenter avec l'aide d'un agent correctionnel</li>
<li>📠 L'a déposée lui-même auprès du greffe du tribunal</li>
<li>⚖️ A poursuivi le gouvernement du Québec devant la Cour supérieure — deux fois, et a gagné les deux fois</li>
</ul>
<p>
Ses actions ont forcé la reconnaissance, ouvert la porte à la justice et jeté les bases de ce qui allait devenir :<br>
<strong>🔥 RECOURS COLLECTIF DOSSIER N° 500-06-001298-245</strong><br>
Officiellement autorisé par la Cour supérieure du Québec le 12 décembre 2024
</p>
<blockquote style="border-left: 4px solid #2563eb; margin: 16px 0; padding-left: 16px; color: #444;">
"Prendre la parole derrière les barreaux est un acte de résistance.<br>
Déposer cette action est un acte d'espoir — pour ceux qui sont encore à l'intérieur, et pour ceux qu'on a oubliés à l'extérieur."<br>
<strong>— Danny William Perez</strong>
</blockquote>
<h3 style="color: #2563eb;">❗ Pourquoi c'est important</h3>
<ul>
<li><strong>💥 Le droit violé :</strong> Tout détenu au Québec a le droit légal à au moins une heure d'exercice en plein air par jour (article 10 du règlement sur les services correctionnels du Québec). Ce droit est garanti par la Charte des droits et libertés de la personne et les Règles Mandela de l'ONU.</li>
<li><strong>⚠️ L'impact humain :</strong> Effondrement de la santé mentale, déclin physique, et déshumanisation causés par le refus d'air, de lumière et de mouvement.</li>
<li><strong>💼 Ce que le recours collectif réclame :</strong> 1 500 $ par jour refusé, 2 000 000 $ en dommages punitifs, une injonction permanente et la responsabilisation du système.</li>
<li><strong>📢 Qui est inclus ?</strong> Toute personne détenue à la prison de Bordeaux entre le 1er janvier 2022 et le jugement final, à qui on a refusé la sortie (avec certaines exclusions).</li>
</ul>
<p>
📣 <strong>Un avis officiel a été publié aujourd'hui — 31 mai 2025 — dans le Journal de Montréal.</strong>
</p>
<p>
📎 Jugement complet : <a href="https://www.canlii.org/fr/qc/qccs/doc/2024/2024qccs4539/2024qccs4539.html" style="color: #2563eb;">2024 QCCS 4539 sur CanLII</a><br>
🧑⚖️ Avocats : Arsenault Dufresne Wee Avocats<br>
🌐 <a href="https://www.class-action.info" style="color: #2563eb;">www.class-action.info</a> | <a href="https://www.action-collective.info" style="color: #2563eb;">www.action-collective.info</a>
</p>
<p style="margin-top: 32px; font-size: 1.1em;">
<strong>Ce n'est pas qu'un procès. C'est un mouvement pour les droits humains.<br>
Liberté Même en Prison | Freedom Even in Prison</strong>
</p>
<p style="color: #888; font-size: 0.95em;">
#DannyWilliamPerez #RecoursCollectif #LibertéMêmeEnCellule #FreedomEvenInPrison #JusticePourBordeaux #JusticeQuébec #DroitsDesDétenus #UneHeureParJour #RéformeDesPrisons #ADWAvocats
</p>
</div>
</div>`
: `<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: #f9f9f9; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.07);">
<div style="background: #1a2238; color: #fff; padding: 32px 24px 16px 24px;">
<h1 style="margin: 0 0 8px 0; font-size: 2em;">Welcome${firstName ? `, ${firstName}` : ''} to Action Collective!</h1>
<p style="margin: 0; font-size: 1.1em;">Thank you for joining the movement for justice and human rights.</p>
</div>
<div style="padding: 24px;">
<h2 style="color: #2563eb; margin-top: 0;">🛡️ About the Founder – Danny William Perez</h2>
<p><strong>As featured in today's Journal de Montréal – May 31, 2025</strong></p>
<p>
<a href="https://www.Action-Collective.info" style="color: #2563eb;">www.Action-Collective.info</a> |
<a href="https://www.Class-Action.info" style="color: #2563eb;">www.Class-Action.info</a>
</p>
<blockquote style="border-left: 4px solid #2563eb; margin: 16px 0; padding-left: 16px; color: #444;">
"I didn't wait for a lawyer. I became the law."<br>
<em>This movement didn't start in a courtroom — it started in a prison cell.</em>
</blockquote>
<p>
Danny William Perez, detained at Bordeaux Prison from March to October 2023, was systematically denied his legal right to one hour of daily outdoor time — a basic human right enshrined in Quebec law and international treaties.
</p>
<ul>
<li>🖋️ Drafted a habeas corpus application using the jail's limited legal computer</li>
<li>🧾 Had it sworn in with the help of a correctional officer</li>
<li>📠 Filed it himself through the court clerk</li>
<li>⚖️ Brought the Quebec government before the Superior Court — twice, and won both times</li>
</ul>
<p>
His actions forced recognition, opened the door to justice, and laid the foundation for what would become:<br>
<strong>🔥 CLASS ACTION FILE NO. 500-06-001298-245</strong><br>
Officially authorized by the Superior Court of Quebec on December 12, 2024
</p>
<blockquote style="border-left: 4px solid #2563eb; margin: 16px 0; padding-left: 16px; color: #444;">
"Speaking up from behind bars is an act of resistance.<br>
Filing this action is an act of hope — for those still inside, and for those forgotten outside."<br>
<strong>— Danny William Perez</strong>
</blockquote>
<h3 style="color: #2563eb;">❗ Why This Matters</h3>
<ul>
<li><strong>💥 The Right Being Violated:</strong> Every detainee in Quebec has the legal right to at least one hour of outdoor exercise per day (Article 10 of Quebec's correctional regulations). This is backed by the Quebec Charter of Human Rights and the UN Mandela Rules.</li>
<li><strong>⚠️ The Human Impact:</strong> Mental health breakdown, physical decline, and dehumanization from denial of air, light, and movement.</li>
<li><strong>💼 What the Class Action Demands:</strong> $1,500 per day denied, $2,000,000 in punitive damages, a permanent injunction, and accountability.</li>
<li><strong>📢 Who Is Included?</strong> Everyone detained at Bordeaux Prison between January 1, 2022, and the final judgment, who was denied outdoor time (with some exclusions).</li>
</ul>
<p>
📣 <strong>An official notice has been published today — May 31, 2025 — in the Journal de Montréal.</strong>
</p>
<p>
📎 Full case judgment: <a href="https://www.canlii.org/en/qc/qccs/doc/2024/2024qccs4539/2024qccs4539.html" style="color: #2563eb;">2024 QCCS 4539 on CanLII</a><br>
🧑⚖️ Legal counsel: Arsenault Dufresne Wee Avocats<br>
🌐 <a href="https://www.class-action.info" style="color: #2563eb;">www.class-action.info</a> | <a href="https://www.action-collective.info" style="color: #2563eb;">www.action-collective.info</a>
</p>
<p style="margin-top: 32px; font-size: 1.1em;">
<strong>This isn't just a lawsuit. It's a human rights movement.<br>
Liberté Même en Prison | Freedom Even in Prison</strong>
</p>
<p style="color: #888; font-size: 0.95em;">
#DannyWilliamPerez #ClassAction #LibertéMêmeEnCellule #FreedomEvenInPrison #JusticePourBordeaux #QuebecJustice #DroitsDesDétenus #OneHourADay #PrisonReform #ADWAvocats
</p>
</div>
</div>`
});
console.log('Welcome email sent successfully');
} catch (emailError) {
console.error('Error sending welcome email:', emailError);
// Do not fail signup if email fails
}
// Return new user (excluding password)
const { password: _, ...userWithoutPassword } = newUser;
return res.status(201).json(userWithoutPassword);
} catch (error: any) {
console.error('Error during user registration:', error);
console.error('Error details:', {
code: error.code,
message: error.message,
meta: error.meta,
stack: error.stack
});
// Handle specific Prisma errors
if (error.code === 'P2002') {
return res.status(409).json({ message: 'An account with this email already exists' });
}
if (error.code === 'P1001') {
return res.status(500).json({ message: 'Database connection error. Please try again later.' });
}
return res.status(500).json({
message: 'An error occurred during registration',
error: process.env.NODE_ENV === 'development' ? error.message : undefined
});
}
}