registration errors in progress
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 6m16s

This commit is contained in:
2025-12-10 08:41:30 -08:00
parent 7912d29961
commit 8da5a2118e
3 changed files with 109 additions and 45 deletions

View File

@@ -349,3 +349,63 @@ $ pm2 set pm2-logrotate:workerInterval 30
$ pm2 set pm2-logrotate:rotateInterval 0 0 * * *
$ pm2 set pm2-logrotate:rotateModule true
gitea-runner@projectium:~$
## dev server setup:
Here are the steps to set up the development environment on Windows using Podman with an Ubuntu container:
1. Install Prerequisites on Windows
Install WSL 2: Podman on Windows relies on the Windows Subsystem for Linux. Install it by running wsl --install in an administrator PowerShell.
Install Podman Desktop: Download and install Podman Desktop for Windows.
2. Set Up Podman
Initialize Podman: Launch Podman Desktop. It will automatically set up its WSL 2 machine.
Start Podman: Ensure the Podman machine is running from the Podman Desktop interface.
3. Set Up the Ubuntu Container
- Pull Ubuntu Image: Open a PowerShell or command prompt and pull the latest Ubuntu image:
podman pull ubuntu:latest
- Create a Podman Volume: Create a volume to persist node_modules and avoid installing them every time the container starts.
podman volume create node_modules_cache
- Run the Ubuntu Container: Start a new container with the project directory mounted and the necessary ports forwarded.
- Open a terminal in your project's root directory on Windows.
- Run the following command, replacing D:\gitea\flyer-crawler.projectium.com\flyer-crawler.projectium.com with the full path to your project:
podman run -it -p 3001:3001 -p 5173:5173 --name flyer-dev -v "D:\gitea\flyer-crawler.projectium.com\flyer-crawler.projectium.com:/app" -v "node_modules_cache:/app/node_modules" ubuntu:latest
-p 3001:3001: Forwards the backend server port.
-p 5173:5173: Forwards the Vite frontend server port.
--name flyer-dev: Names the container for easy reference.
-v "...:/app": Mounts your project directory into the container at /app.
-v "node_modules_cache:/app/node_modules": Mounts the named volume for node_modules.
4. Configure the Ubuntu Environment
You are now inside the Ubuntu container's shell.
- Update Package Lists:
apt-get update
- Install Dependencies: Install curl, git, and nodejs (which includes npm).
apt-get install -y curl git
curl -sL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
- Navigate to Project Directory:
cd /app
- Install Project Dependencies:
npm install
5. Run the Development Server
- Start the Application:
npm run dev
6. Accessing the Application
- Frontend: Open your browser and go to http://localhost:5173.
- Backend: The frontend will make API calls to http://localhost:3001.
Managing the Environment
- Stopping the Container: Press Ctrl+C in the container terminal, then type exit.
- Restarting the Container:
podman start -a -i flyer-dev

View File

@@ -74,62 +74,47 @@ router.post('/register', async (req, res, next) => {
return res.status(400).json({ message: passwordValidation.feedback });
}
const client = await getPool().connect();
let newUser;
try {
await client.query('BEGIN');
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(password, saltRounds);
logger.info(`Hashing password for new user: ${email}`);
const repoWithTransaction = new (await import('../services/db/user.db')).UserRepository(client);
try {
newUser = await repoWithTransaction.createUser(email, hashedPassword, { full_name, avatar_url });
} catch (error) {
if (error instanceof UniqueConstraintError) {
return res.status(409).json({ message: error.message });
}
throw error;
}
// The createUser method in UserRepository now handles its own transaction.
const newUser = await userRepo.createUser(email, hashedPassword, { full_name, avatar_url });
await client.query('COMMIT');
const userEmail = newUser.user.email || 'unknown';
const userId = newUser.user_id || 'unknown';
logger.info(`Successfully created new user in DB: ${userEmail} (ID: ${userId})`);
// Use the new standardized logging function
await adminRepo.logActivity({
userId: newUser.user_id,
action: 'user_registered',
displayText: `${userEmail} has registered.`,
icon: 'user-plus',
});
const payload = { user_id: newUser.user_id, email: userEmail };
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '1h' });
const refreshToken = crypto.randomBytes(64).toString('hex');
await userRepo.saveRefreshToken(newUser.user_id, refreshToken);
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});
return res.status(201).json({ message: 'User registered successfully!', user: payload, token });
} catch (error: unknown) {
if (error instanceof UniqueConstraintError) {
// If the email is a duplicate, return a 409 Conflict status.
return res.status(409).json({ message: error.message });
}
await client.query('ROLLBACK');
logger.error(`Transaction failed during user registration for email: ${email}.`, { error });
// The createUser method now handles its own transaction logging, so we just log the route failure.
logger.error(`User registration route failed for email: ${email}.`, { error });
return next(error);
} finally {
client.release();
}
// Safe access to prevent crashing if the returned object structure is unexpected during tests
const userEmail = (newUser as UserProfile)?.user?.email || 'unknown';
const userId = newUser?.user_id || 'unknown';
logger.info(`Successfully created new user in DB: ${userEmail} (ID: ${userId})`);
// Use the new standardized logging function
await adminRepo.logActivity({
userId: newUser.user_id,
action: 'user_registered',
displayText: `${userEmail} has registered.`,
icon: 'user-plus',
});
const payload = { user_id: newUser.user_id, email: userEmail };
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '1h' });
const refreshToken = crypto.randomBytes(64).toString('hex');
await userRepo.saveRefreshToken(newUser.user_id, refreshToken);
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});
return res.status(201).json({ message: 'User registered successfully!', user: payload, token });
});
// Login Route

View File

@@ -86,8 +86,27 @@ export class UserRepository {
JOIN public.profiles p ON u.user_id = p.user_id
WHERE u.user_id = $1;
`;
const finalProfileRes = await client.query<UserProfile>(profileQuery, [newUserId]);
const fullUserProfile = finalProfileRes.rows[0];
const finalProfileRes = await client.query(profileQuery, [newUserId]);
const flatProfile = finalProfileRes.rows[0];
if (!flatProfile) {
throw new Error('Failed to create or retrieve user profile after registration.');
}
// Construct the nested UserProfile object to match the type definition.
const fullUserProfile: UserProfile = {
user: {
user_id: flatProfile.user_id,
email: flatProfile.email,
},
user_id: flatProfile.user_id,
full_name: flatProfile.full_name,
avatar_url: flatProfile.avatar_url,
role: flatProfile.role,
points: flatProfile.points,
preferences: flatProfile.preferences,
};
logger.debug(`[DB createUser] Fetched full profile for new user:`, { user: fullUserProfile });
await client.query('COMMIT');