Retro_tom
New Member
- Jul 2, 2024
- 11
- 6
Hello Devbest!
I am currently working on a project to enhance my skills in Node.js. I'm developing a CMS specifically for a Habbo retro using Node.js, Express, and EJS. I would love to hear your ideas and suggestions on how I can improve it!
The CMS is being designed to work with Nitro and the Arcturus Emulator.
The template I’m using is temporary and will likely be replaced in the future.
Here are some snippets of the code:
I am currently working on a project to enhance my skills in Node.js. I'm developing a CMS specifically for a Habbo retro using Node.js, Express, and EJS. I would love to hear your ideas and suggestions on how I can improve it!
The CMS is being designed to work with Nitro and the Arcturus Emulator.
The template I’m using is temporary and will likely be replaced in the future.
- Arcturus Morningstar Emulator support 100%
- Login & Registration 70%
- Articles 20%
- Client login SSO 100%
Here are some snippets of the code:
JavaScript:
require('dotenv').config();
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const helmet = require('helmet');
const cors = require('cors');
const sessionMiddleware = require('./app/middlewares/sessionMiddleware');
const addUserInfoToLocals = require('./app/middlewares/userMiddleware');
const routes = require('./app/routes');
const app = express();
app.use(
helmet({
contentSecurityPolicy: {
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
'script-src': ["'self'", "'unsafe-inline'", "'unsafe-eval'", "blob:", "*"],
'connect-src': ["'self'", "*"],
'img-src': ["'self'", "*", "data:"],
'worker-src': ["'self'", "blob:"],
},
},
})
);
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'app', 'views'));
app.use(sessionMiddleware);
app.use(addUserInfoToLocals);
app.use('/', routes);
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
const port = process.env.SERVER_PORT;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
JavaScript:
const { promisify } = require('util');
const connection = require('../config/database');
const {
userIdSchema,
authTicketSchema,
usernameSchema,
emailSchema,
updateUserCredentialsSchema,
userSchema,
ipSchema,
dateSchema,
limitSchema
} = require('../validation/userValidation');
const query = promisify(connection.query).bind(connection);
const addUser = async (username, email, password, registerIp, registerIpC, registerDate) => {
try {
// Valideer de invoer met userSchema inclusief passwordSchema
await userSchema.validateAsync({ username, email, password, registerIp, registerIpC, registerDate });
// Voer de query uit om de gebruiker toe te voegen met het gehashte wachtwoord
const result = await query(
'INSERT INTO users (username, mail, password, ip_register, ip_current, account_created) VALUES (?, ?, ?, ?, ?, ?)',
[username, email, password, registerIp, registerIpC, registerDate]
);
return result.insertId;
} catch (error) {
console.error('Error adding user:', error.message);
throw error;
}
};
const updateUserAuthTicket = async (userId, authTicket) => {
try {
await userIdSchema.validateAsync(userId);
await authTicketSchema.validateAsync(authTicket);
const result = await query('UPDATE users SET auth_ticket = ? WHERE id = ?', [authTicket, userId]);
if (result.affectedRows === 0) {
throw new Error('No rows updated');
}
} catch (error) {
console.error('Error updating auth_ticket in database:', error.message);
throw error;
}
};
const getUserByUsername = async (username) => {
try {
await usernameSchema.validateAsync(username);
const results = await query('SELECT * FROM users WHERE username = ?', [username]);
return results.length > 0 ? results[0] : null;
} catch (error) {
console.error('Error fetching user by username:', error.message);
throw error;
}
};
const getUserByEmail = async (email) => {
try {
await emailSchema.validateAsync(email);
const results = await query('SELECT * FROM users WHERE mail = ?', [email]);
return results.length > 0 ? results[0] : null;
} catch (error) {
console.error('Error fetching user by email:', error.message);
throw error;
}
};
const updateUserCredentials = async (userId, newUsername, newEmail, newPassword) => {
try {
await updateUserCredentialsSchema.validateAsync({ userId, newUsername, newEmail, newPassword });
let updateFields = [];
let params = [];
if (newUsername) {
updateFields.push('username = ?');
params.push(newUsername);
}
if (newEmail) {
updateFields.push('mail = ?');
params.push(newEmail);
}
if (newPassword) {
updateFields.push('password = ?');
params.push(newPassword);
}
params.push(userId);
const updateQuery = `UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`;
await query(updateQuery, params);
} catch (error) {
console.error('Error updating user credentials:', error.message);
throw error;
}
};
const validateUsername = async (username, currentUserUsername = null) => {
try {
await usernameSchema.validateAsync(username);
const existingUsername = await getUserByUsername(username);
if (existingUsername && existingUsername.username !== currentUserUsername) {
throw new Error('Username is already taken');
}
} catch (error) {
console.error('Error validating username:', error.message);
throw error;
}
};
const updateUserLastInfo = async (username, lastIp, lastDate) => {
try {
await usernameSchema.validateAsync(username);
await ipSchema.validateAsync(lastIp);
await dateSchema.validateAsync(lastDate);
await query('UPDATE users SET ip_current = ?, last_login = ? WHERE username = ?', [lastIp, lastDate, username]);
} catch (error) {
console.error('Error updating user last info:', error.message);
throw error;
}
};
const getLatestUsers = async (limit = 3) => {
try {
await limitSchema.validateAsync(limit);
const results = await query('SELECT username, look FROM users ORDER BY id DESC LIMIT ?', [limit]);
return results;
} catch (error) {
console.error('Error fetching latest users:', error.message);
throw error;
}
};
module.exports = {
addUser,
getUserByUsername,
getUserByEmail,
updateUserCredentials,
validateUsername,
updateUserLastInfo,
updateUserAuthTicket,
getLatestUsers
};
JavaScript:
// controllers/userController.js
const { v4: uuidv4 } = require('uuid');
const { getLatestNews } = require('../models/newsModel');
const { updateUserAuthTicket, updateUserCredentials, validateUsername, getUserByEmail, getLatestUsers } = require('../models/userModel');
const bcrypt = require('bcrypt');
const { hashPassword, validateEmail } = require('../utils/userUtils');
const schema = require('../utils/passwordUtils');
exports.mePage = async (req, res) => {
try {
const news = await getLatestNews();
const users = await getLatestUsers();
res.render('me', { news, users, errorMessage: '' });
} catch (error) {
console.error('Error loading index page:', error.message);
res.render('me', { news: [], users: [], errorMessage: 'Failed to load content' });
}
};
exports.settingsPage = (req, res) => {
res.render('settings', { errorMessage: '' });
};
exports.updateSettings = async (req, res) => {
const { username, email, currentPassword, newPassword, confirmNewPassword } = req.body;
try {
if (!username || !email || !currentPassword) {
throw new Error('Please fill in all fields!');
}
await validateUsername(username, res.locals.user.username);
if (newPassword && newPassword !== confirmNewPassword) {
throw new Error('New passwords do not match!');
}
if (newPassword && !schema.validate(newPassword)) {
throw new Error('New password does not meet requirements!');
}
const user = res.locals.user;
const match = await bcrypt.compare(currentPassword, user.password);
if (!match) {
throw new Error('Incorrect current password!');
}
let hashedNewPassword = user.password;
if (newPassword) {
hashedNewPassword = await hashPassword(newPassword);
}
if (email !== user.mail) {
if (!validateEmail(email)) {
throw new Error('Invalid email address!');
}
const existingEmail = await getUserByEmail(email);
if (existingEmail) {
throw new Error('Email is already registered');
}
}
await updateUserCredentials(user.id, username, email, hashedNewPassword);
req.session.username = username;
req.session.email = email;
res.redirect('/settings?success=true');
} catch (error) {
console.error(`Error updating settings: ${error.message}`);
res.render('settings', {
loggedIn: req.session.loggedin,
errorMessage: error.message
});
}
};
exports.indexPage = async (req, res) => {
try {
const news = await getLatestNews();
const users = await getLatestUsers();
res.render('index', { news, users, errorMessage: '' });
} catch (error) {
console.error('Error loading index page:', error.message);
res.render('index', { news: [], users: [], errorMessage: 'Failed to load content' });
}
};
exports.clientPage = async (req, res) => {
const authTicket = `NodeJsRetro-v1-${uuidv4()}`;
const room = req.params.room || null;
const friend = req.params.friend || null;
try {
await updateUserAuthTicket(res.locals.user.id, authTicket);
res.render('hotel', { authTicket, room, friend });
} catch (error) {
console.error('Error updating auth_ticket:', error.message);
res.render('hotel', { errorMessage: 'Failed to update auth ticket', room, friend });
}
};
You must be registered for see images attach
You must be registered for see images attach
You must be registered for see images attach
Last edited: