Files
yourpart3/backend/services/authService.js
Torsten Schulz (local) c3ea7eecc2 Update dependencies and refactor authentication logic
- Replaced `bcrypt` with `bcryptjs` for compatibility in `authService.js` and `settingsService.js`.
- Updated package versions in `package.json` and `package-lock.json`, including `multer`, `nodemailer`, and others.
- Added storage management features in the frontend, including free storage calculation and localization updates for new terms in `falukant.json` files.
2025-11-26 18:14:36 +01:00

194 lines
6.3 KiB
JavaScript

import bcrypt from 'bcryptjs';
import crypto from 'crypto';
import { v4 as uuidv4 } from 'uuid';
import User from '../models/community/user.js';
import UserParam from '../models/community/user_param.js';
import UserParamType from '../models/type/user_param.js';
import { sendAccountActivationEmail, sendPasswordResetEmail } from './emailService.js';
import { sequelize } from '../utils/sequelize.js';
import { Op } from 'sequelize';
import { setUserSession, deleteUserSession } from '../utils/redis.js';
import { encrypt } from '../utils/encryption.js';
import { notifyUser } from '../utils/socket.js';
import Friendship from '../models/community/friendship.js';
const saltRounds = 10;
const getFriends = async (userId) => {
console.log('getFriends', userId);
try {
const friendships = await Friendship.findAll({
where: {
[Op.or]: [
{ user1Id: userId },
{ user2Id: userId },
],
accepted: true,
},
include: [
{
model: User,
as: 'friendSender',
attributes: ['hashedId', 'username'],
},
{
model: User,
as: 'friendReceiver',
attributes: ['hashedId', 'username'],
},
],
});
console.log('did read out friends');
return friendships.map((friendship) => {
if (friendship.user1Id === userId) {
return friendship.friendReceiver;
} else {
return friendship.friendSender;
}
});
} catch (error) {
console.error('Error fetching friends:', error);
throw error;
}
};
export const registerUser = async ({ email, username, password, language }) => {
const encryptedEmail = encrypt(email);
const query = `
SELECT id FROM community.user
WHERE email = :encryptedEmail
`;
const existingUser = await sequelize.query(query, {
replacements: { encryptedEmail },
type: sequelize.QueryTypes.SELECT,
});
if (existingUser.length > 0) {
throw new Error('emailinuse');
}
const hashedPassword = await bcrypt.hash(password, saltRounds);
const resetToken = uuidv4();
const user = await User.create({
email: email,
username,
password: hashedPassword,
resetToken: resetToken,
active: false,
registration_date: new Date()
});
const languageType = await UserParamType.findOne({ where: { description: 'language' } });
if (!languageType) {
throw new Error('languagenotfound');
}
const languageParam = await UserParam.create({
userId: user.id,
paramTypeId: languageType.id,
value: language
});
const activationLink = `${process.env.FRONTEND_URL}/activate?token=${resetToken}`;
await sendAccountActivationEmail(email, activationLink, username, resetToken, language);
const authCode = crypto.randomBytes(20).toString('hex');
return { id: user.hashedId, username: user.username, active: user.active, param: [languageParam], authCode };
};
export const loginUser = async ({ username, password }) => {
const user = await User.findOne({ where: { username } });
if (!user) {
throw new Error('credentialsinvalid');
}
const match = await bcrypt.compare(password, user.password);
if (!match) {
throw new Error('credentialsinvalid');
}
const authCode = crypto.randomBytes(20).toString('hex');
user.authCode = authCode;
await user.save();
const friends = await getFriends(user.id);
for (const friend of friends) {
await notifyUser(friend.hashedId, 'friendloginchanged', {
userId: user.hashedId,
status: 'online',
});
}
console.log('set user session');
const sessionData = {
id: user.hashedId,
username: user.username,
active: user.active,
authCode,
timestamp: Date.now()
};
await setUserSession(user.id, sessionData);
console.log('get user params');
const params = await UserParam.findAll({
where: {
userId: user.id
},
include: {
model: UserParamType,
as: 'paramType',
where: {
description: ['birthdate', 'gender', 'language']
}
}
});
const mappedParams = params.map(param => {
return { 'name': param.paramType.description, 'value': param.value };
});
console.log('return user');
return {
id: user.hashedId,
username: user.username,
active: user.active,
param: mappedParams,
authCode
};
};
export const logoutUser = async (hashedUserId) => {
try {
const user = await User.findOne({
where: {
hashedId: hashedUserId
}
})
if (!user) {
return;
}
const friends = await getFriends(user.id);
for (const friend of friends) {
await notifyUser(friend.hashedId, 'friendloginchanged', {
userId: user.hashedId,
status: 'online',
});
}
await deleteUserSession(user.id);
} catch (error) {
console.error('Fehler beim Logout:', error);
throw new Error('logoutfailed');
}
};
export const handleForgotPassword = async ({ email }) => {
const user = await User.findOne({ where: { email } });
if (!user) {
throw new Error('Email not found');
}
const resetToken = uuidv4();
const resetLink = `${process.env.FRONTEND_URL}/reset-password?token=${resetToken}`;
await user.update({ reset_token: resetToken });
const languageParam = await UserParam.findOne({ where: { user_id: user.id, param_type_id: languageType.id } });
const userLanguage = languageParam ? languageParam.value : 'en';
await sendPasswordResetEmail(email, resetLink, userLanguage);
return { message: 'Password reset email sent' };
};
export const activateUserAccount = async ({ token }) => {
const user = await User.findOne({ where: { reset_token: token } });
if (!user) {
throw new Error('Invalid token');
}
await user.update({ active: true, reset_token: null });
return { message: 'Account activated' };
};