registration errors in progress
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 6m16s
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 6m16s
This commit is contained in:
60
README.md
60
README.md
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user