From 4c12303edc04af2232427bdc3802940413f24375 Mon Sep 17 00:00:00 2001 From: Torsten Schulz Date: Mon, 22 Jul 2024 20:55:33 +0200 Subject: [PATCH] =?UTF-8?q?Verschieden=20Settings=20hinzugef=C3=BCgt=20(in?= =?UTF-8?q?komplett)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controllers/authController.js | 2 - backend/controllers/navigationController.js | 45 ++++- backend/controllers/settingsController.js | 2 - backend/models/community/user_param.js | 5 +- backend/models/index.js | 24 +-- backend/server.js | 7 - backend/services/authService.js | 33 +--- backend/services/emailService.js | 9 +- backend/utils/encryption.js | 1 - backend/utils/initializeTypes.js | 178 +++++------------- backend/utils/sequelize.js | 24 ++- backend/utils/syncDatabase.js | 1 - frontend/src/App.vue | 1 + frontend/src/components/SettingsWidget.vue | 23 ++- .../src/components/form/InputNumberWidget.vue | 14 ++ .../src/dialogues/auth/RegisterDialog.vue | 1 - .../src/dialogues/chat/RandomChatDialog.vue | 2 - frontend/src/i18n/locales/de/settings.json | 64 ++++++- frontend/src/router/index.js | 9 +- frontend/src/store/index.js | 6 + frontend/src/views/home/NoLoginView.vue | 4 - frontend/src/views/settings/PersonalView.vue | 5 +- frontend/src/views/settings/ViewView.vue | 17 ++ 23 files changed, 269 insertions(+), 208 deletions(-) create mode 100644 frontend/src/views/settings/ViewView.vue diff --git a/backend/controllers/authController.js b/backend/controllers/authController.js index 95cb51b..6a1aae2 100644 --- a/backend/controllers/authController.js +++ b/backend/controllers/authController.js @@ -7,7 +7,6 @@ export const register = async (req, res) => { const result = await userService.registerUser({ email, username, password, language }); res.status(201).json(result); } catch (error) { - console.log(error); res.status(500).json({ error: error.message }); } }; @@ -21,7 +20,6 @@ export const login = async (req, res) => { if (error.message === 'credentialsinvalid') { res.status(404).json({ error: error.message }) } else { - console.log(error); res.status(500).json({ error: error.message }); } } diff --git a/backend/controllers/navigationController.js b/backend/controllers/navigationController.js index 3e091bc..32a9c6f 100644 --- a/backend/controllers/navigationController.js +++ b/backend/controllers/navigationController.js @@ -1,6 +1,8 @@ import User from '../models/community/user.js'; +import UserParam from '../models/community/user_param.js'; import UserRight from '../models/community/user_right.js'; import UserRightType from '../models/type/user_right.js'; +import UserParamType from '../models/type/user_param.js'; const menuStructure = { home: { @@ -206,16 +208,29 @@ const menuStructure = { } }; -const filterMenu = (menu, rights) => { +const calculateAge = (birthDate) => { + const today = new Date(); + const birthDateObj = new Date(birthDate); + let age = today.getFullYear() - birthDateObj.getFullYear(); + const monthDiff = today.getMonth() - birthDateObj.getMonth(); + if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDateObj.getDate())) { + age--; + } + + return age; +}; + +const filterMenu = (menu, rights, age) => { const filteredMenu = {}; for (const [key, value] of Object.entries(menu)) { if (value.visible.includes("all") || value.visible.some(v => rights.includes(v) - || (value.visible.includes("anyadmin") && rights.length > 0))) { + || (value.visible.includes("anyadmin") && rights.length > 0)) + || (value.visible.includes("over14") && age >= 14)) { const { visible, ...itemWithoutVisible } = value; filteredMenu[key] = { ...itemWithoutVisible }; if (value.children) { - filteredMenu[key].children = filterMenu(value.children, rights); + filteredMenu[key].children = filterMenu(value.children, rights, age); } } } @@ -236,11 +251,31 @@ export const menu = async (req, res) => { as: 'rightType' }] }); + const userBirthdateParams = await UserParam.findAll({ + where: { + userId: user.id + }, + include: [ + { + model: UserParamType, + as: 'paramType', + where: { + description: 'birthdate' + } + } + ] + }); + const ageFunction = function() { + const birthDate = userBirthdateParams.length > 0 ? userBirthdateParams[0].value : (new Date()).toDateString(); + const age = calculateAge(birthDate); + return age; + } + const age = ageFunction(); const rights = userRights.map(ur => ur.rightType.title); - const filteredMenu = filterMenu(menuStructure, rights); + const filteredMenu = filterMenu(menuStructure, rights, age); res.status(200).json(filteredMenu); } catch (error) { console.error('Error fetching menu:', error); res.status(500).json({ error: 'An error occurred while fetching the menu' }); } -}; \ No newline at end of file +}; \ No newline at end of file diff --git a/backend/controllers/settingsController.js b/backend/controllers/settingsController.js index 35d6b03..b720922 100644 --- a/backend/controllers/settingsController.js +++ b/backend/controllers/settingsController.js @@ -6,7 +6,6 @@ import UserParamValue from '../models/type/user_param_value.js'; export const filterSettings = async (req, res) => { const { userid, type } = req.body; - console.log(userid, type); try { const fields = await UserParamType.findAll({ include: [ @@ -65,7 +64,6 @@ export const updateSetting = async (req, res) => { if (!paramType) { return res.status(404).json({ error: 'Parameter type not found' }); } - console.log(value); await UserParam.upsertParam(user.id, paramType.id, value); res.status(200).json({ message: 'Setting updated successfully' }); } catch (error) { diff --git a/backend/models/community/user_param.js b/backend/models/community/user_param.js index 7bf58c8..f1bc236 100644 --- a/backend/models/community/user_param.js +++ b/backend/models/community/user_param.js @@ -28,11 +28,9 @@ const UserParam = sequelize.define('user_param', { if (value) { try { const iv = generateIv(); - console.log(value); this.setDataValue('iv', iv.toString('hex')); - this.setDataValue('value', encrypt(value, iv)); + this.setDataValue('value', encrypt(value.toString(), iv)); } catch (error) { - console.log('Error setting value:', error); this.setDataValue('value', ''); } } @@ -43,7 +41,6 @@ const UserParam = sequelize.define('user_param', { const iv = Buffer.from(this.getDataValue('iv'), 'hex'); return decrypt(value, iv); } catch (error) { - console.log('Error getting value:', error); return ''; } } diff --git a/backend/models/index.js b/backend/models/index.js index ee3d9b3..d60bce6 100644 --- a/backend/models/index.js +++ b/backend/models/index.js @@ -1,21 +1,21 @@ -import User from './community/user.js'; -import UserParam from './community/user_param.js'; -import UserParamType from './type/user_param.js'; -import Login from './logs/login.js'; -import UserRightType from './type/user_right.js'; -import UserRight from './community/user_right.js'; import SettingsType from './type/settings.js'; import UserParamValue from './type/user_param_value.js'; +import UserParamType from './type/user_param.js'; +import UserRightType from './type/user_right.js'; +import User from './community/user.js'; +import UserParam from './community/user_param.js'; +import Login from './logs/login.js'; +import UserRight from './community/user_right.js'; const models = { - User, - UserParam, - UserParamType, - Login, - UserRightType, - UserRight, SettingsType, UserParamValue, + UserParamType, + UserRightType, + User, + UserParam, + Login, + UserRight, }; export default models; diff --git a/backend/server.js b/backend/server.js index 99d32ab..cf29864 100644 --- a/backend/server.js +++ b/backend/server.js @@ -19,23 +19,16 @@ amqp.connect(RABBITMQ_URL, (err, connection) => { if (err) { throw err; } - channel.assertQueue(QUEUE, { durable: false }); - io.on('connection', (socket) => { - console.log('A user connected'); - channel.consume(QUEUE, (msg) => { const message = JSON.parse(msg.content.toString()); io.emit('newMessage', message); }, { noAck: true }); - socket.on('newMessage', (message) => { channel.sendToQueue(QUEUE, Buffer.from(JSON.stringify(message))); }); - socket.on('disconnect', () => { - console.log('A user disconnected'); }); }); diff --git a/backend/services/authService.js b/backend/services/authService.js index 8437d0b..a4ef5c8 100644 --- a/backend/services/authService.js +++ b/backend/services/authService.js @@ -12,7 +12,6 @@ const saltRounds = 10; export const registerUser = async ({ email, username, password, language }) => { const iv = generateIv(); const encryptedEmail = encrypt(email, iv); - console.log(email, iv, process.env.SECRET_KEY); const results = await sequelize.query( `SELECT * FROM "community"."user" WHERE "email" = :email`, { @@ -20,14 +19,11 @@ export const registerUser = async ({ email, username, password, language }) => { type: sequelize.QueryTypes.SELECT } ); - console.log(results); if (results.length && results.length > 0) { throw new Error('Email already in use'); } - const hashedPassword = await bcrypt.hash(password, saltRounds); const resetToken = uuidv4(); - const user = await User.create({ email: encryptedEmail, iv: iv.toString('hex'), @@ -37,18 +33,15 @@ export const registerUser = async ({ email, username, password, language }) => { active: false, registration_date: new Date() }); - const languageType = await UserParamType.findOne({ where: { description: 'language' } }); if (!languageType) { throw new Error('Language type not found'); } - 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); @@ -56,7 +49,6 @@ export const registerUser = async ({ email, username, password, language }) => { }; export const loginUser = async ({ username, password }) => { - console.log('check login'); const user = await User.findOne({ where: { username } }); if (!user) { throw new Error('credentialsinvalid'); @@ -65,7 +57,7 @@ export const loginUser = async ({ username, password }) => { if (!match) { throw new Error('credentialsinvalid'); } - const neededParams = await UserParam.findAll({ + const params = await UserParam.findAll({ where: { userId: user.id }, @@ -73,23 +65,13 @@ export const loginUser = async ({ username, password }) => { model: UserParamType, as: 'paramType', where: { - description: ['birthdate', 'gender'] + description: ['birthdate', 'gender', 'language'] } } }); - const language = await UserParam.findOne({ - where: { - userId: user.id - }, - include: { - model: UserParamType, - as: 'paramType', - where: { - description: 'language' - } - } - }); - return { id: user.hashedId, username: user.username, active: user.active, forwardDataInput: neededParams.length < 2, language: language.value }; + const mappedParams = params.map(param => { + return { 'name': param.paramType.description, 'value': param.value }; }); + return { id: user.hashedId, username: user.username, active: user.active, param: mappedParams }; }; export const handleForgotPassword = async ({ email }) => { @@ -97,16 +79,12 @@ export const handleForgotPassword = async ({ 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' }; }; @@ -115,7 +93,6 @@ export const activateUserAccount = async ({ token }) => { if (!user) { throw new Error('Invalid token'); } - await user.update({ active: true, reset_token: null }); return { message: 'Account activated' }; }; diff --git a/backend/services/emailService.js b/backend/services/emailService.js index c9f82de..8150542 100644 --- a/backend/services/emailService.js +++ b/backend/services/emailService.js @@ -1,5 +1,6 @@ import nodemailer from 'nodemailer'; import i18n from '../utils/i18n.js'; +import UserParamValue from '../models/type/user_param_value.js'; const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, @@ -23,7 +24,13 @@ export const sendPasswordResetEmail = async (email, resetLink, language) => { await transporter.sendMail(mailOptions); }; -export const sendAccountActivationEmail = async (email, activationLink, username, resetToken, language) => { +export const sendAccountActivationEmail = async (email, activationLink, username, resetToken, languageId) => { + const languageObject = await UserParamValue.findOne({ + where: { + id: languageId + } + }); + const language = languageObject.value; i18n.setLocale(language); const mailOptions = { from: process.env.SMTP_FROM, diff --git a/backend/utils/encryption.js b/backend/utils/encryption.js index 5f7af4c..7011fa6 100644 --- a/backend/utils/encryption.js +++ b/backend/utils/encryption.js @@ -15,7 +15,6 @@ export const encrypt = (text, iv) => { }; export const decrypt = (text, iv) => { - console.log(text, secretKey, iv); const decipher = crypto.createDecipheriv(algorithm, Buffer.from(secretKey, 'utf-8'), iv); let decrypted = decipher.update(text, 'hex', 'utf8'); decrypted += decipher.final('utf8'); diff --git a/backend/utils/initializeTypes.js b/backend/utils/initializeTypes.js index 212ca71..38dcfbc 100644 --- a/backend/utils/initializeTypes.js +++ b/backend/utils/initializeTypes.js @@ -10,8 +10,6 @@ const initializeTypes = async () => { }, {}); const getSettingsTypeId = (name) => settingsTypeMap[name]; - console.log(settingsTypeMap, getSettingsTypeId('personal')); - const getUserParamTypeId = async(name) => { const userParamType = await UserParamType.findOne({ where: { @@ -20,132 +18,58 @@ const initializeTypes = async () => { }); return userParamType.id; }; - - await UserParamType.findOrCreate({ - where: { description: 'language' }, - defaults: { description: 'language', datatype: 'singleselect', settingsId: getSettingsTypeId('personal') } + const userParams = { + language: {type: 'singleselect', setting: 'personal'}, + birthdate: { type: 'date', setting: 'personal' }, + zip: { type: 'string', setting: 'personal' }, + town: { type: 'string', setting: 'personal' }, + bodyheight: { type: 'float', setting: 'view' }, + weight: { type: 'float', setting: 'view' }, + eyecolor: { type: 'singleselect', setting: 'view' }, + haircolor: { type: 'singleselect', setting: 'view' }, + hairlength: { type: 'singleselect', setting: 'view' }, + skincolor: { type: 'singleselect', setting: 'view' }, + freckles: { type: 'singleselect', setting: 'view' }, + piercings: { type: 'bool', setting: 'view' }, + tattoos: { type: 'bool', setting: 'view' }, + sexualpreference: { type: 'singleselect', 'setting': 'sexuality', minAge: 14 }, + gender: { type: 'singleselect', setting: 'personal' }, + pubichair: { type: 'singleselect', setting: 'sexuality', minAge: 14 }, + penislenght: { type: 'int', setting: 'sexuality', minAge: 14, gender: 'm' }, + brasize: { type: 'string', setting: 'sexuality', minAge: 14, gender: 'f' } + }; + Object.keys(userParams).forEach(async(key) => { + const item = userParams[key]; + const createItem = { description: key, datatype: item.type, settingsId: getSettingsTypeId(item.setting) }; + if (item.minAge) createItem.minAge = item.minAge; + if (item.gender) createItem.gender = item.gender; + await UserParamType.findOrCreate({ + where: { description: key }, + defaults: createItem + }); }); - await UserParamType.findOrCreate({ - where: { description: 'birthdate' }, - defaults: { description: 'birthdate', datatype: 'date', settingsId: getSettingsTypeId('personal') } + const valuesList = { + gender: ['male', 'female', 'transfemale', 'transmale', 'nonbinary'], + language: ['de', 'en'], + eyecolor: ['blue', 'green', 'brown', 'black', 'grey', 'hazel', 'amber', 'red', 'other'], + haircolor: ['black', 'brown', 'blonde', 'red', 'grey', 'white', 'other'], + hairlength: ['short', 'medium', 'long', 'bald', 'other'], + skincolor: ['light', 'medium', 'dark', 'other'], + freckles: ['much', 'medium', 'less', 'none'], + }; + Object.keys(valuesList).forEach(async(key) => { + const values = valuesList[key]; + const userParamTypeId = await getUserParamTypeId(key); + values.forEach(async(value) => { + await UserParamValue.findOrCreate({ + where: { + userParamTypeId: userParamTypeId, + value: value + }, + defaults: { userParamTypeId: userParamTypeId, value: value } + }) + }); }); - await UserParamType.findOrCreate({ - where: { description: 'zip' }, - defaults: { description: 'zip', datatype: 'string', settingsId: getSettingsTypeId('personal') } - }); - await UserParamType.findOrCreate({ - where: { description: 'town' }, - defaults: { description: 'town', datatype: 'string', settingsId: getSettingsTypeId('personal') } - }); - await UserParamType.findOrCreate({ - where: { description: 'bodyheight' }, - defaults: { description: 'bodyheight', datatype: 'float', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'weight' }, - defaults: { description: 'weight', datatype: 'float', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'eyecolor' }, - defaults: { description: 'eyecolor', datatype: 'string', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'haircolor' }, - defaults: { description: 'haircolor', datatype: 'string', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'hairlength' }, - defaults: { description: 'hairlength', datatype: 'int', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'skincolor' }, - defaults: { description: 'skincolor', datatype: 'int', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'freckles' }, - defaults: { description: 'freckles', datatype: 'int', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'piercings' }, - defaults: { description: 'piercings', datatype: 'bool', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'tattoos' }, - defaults: { description: 'tattoos', datatype: 'bool', settingsId: getSettingsTypeId('view') } - }); - await UserParamType.findOrCreate({ - where: { description: 'sexualpreference' }, - defaults: { description: 'sexualpreference', minAge: 14, datatype: 'int', settingsId: getSettingsTypeId('sexuality') } - }); - await UserParamType.findOrCreate({ - where: { description: 'gender' }, - defaults: { description: 'gender', datatype: 'singleselect', settingsId: getSettingsTypeId('personal') } - }); - await UserParamType.findOrCreate({ - where: { description: 'pubichair' }, - defaults: { description: 'pubichair', minAge: 14, datatype: 'int', settingsId: getSettingsTypeId('sexuality') } - }); - await UserParamType.findOrCreate({ - where: { description: 'penislength' }, - defaults: { description: 'penislength', minAge: 14, gender: 'm', datatype: 'int', settingsId: getSettingsTypeId('sexuality') } - }); - await UserParamType.findOrCreate({ - where: { description: 'brasize' }, - defaults: { description: 'brasize', minAge: 14, gender: 'f', datatype: 'string', settingsId: getSettingsTypeId('sexuality') } - }); - - const genderId = await getUserParamTypeId('gender'); - await UserParamValue.findOrCreate({ - where: { - userParamTypeId: genderId, - value: 'male' - }, - defaults: { userParamTypeId: genderId, value: 'male' } - }); - await UserParamValue.findOrCreate({ - where: { - userParamTypeId: genderId, - value: 'female' - }, - defaults: { userParamTypeId: genderId, value: 'female' } - }); - await UserParamValue.findOrCreate({ - where: { - userParamTypeId: genderId, - value: 'transfemale' - }, - defaults: { userParamTypeId: genderId, value: 'transfemale' } - }); - await UserParamValue.findOrCreate({ - where: { - userParamTypeId: genderId, - value: 'transmale' - }, - defaults: { userParamTypeId: genderId, value: 'transmale' } - }); - await UserParamValue.findOrCreate({ - where: { - userParamTypeId: genderId, - value: 'nonbinary' - }, - defaults: { userParamTypeId: genderId, value: 'nonbinary' } - }); - - const languageId = await getUserParamTypeId('language'); - await UserParamValue.findOrCreate({ - where: { - userParamTypeId: languageId, - value: 'de' - }, - defaults: { userParamTypeId: languageId, value: 'de' } - }); - await UserParamValue.findOrCreate({ - where: { - userParamTypeId: languageId, - value: 'en' - }, - defaults: { userParamTypeId: languageId, value: 'en' } - }); -}; +} export default initializeTypes; diff --git a/backend/utils/sequelize.js b/backend/utils/sequelize.js index d7fa8aa..75264e8 100644 --- a/backend/utils/sequelize.js +++ b/backend/utils/sequelize.js @@ -16,11 +16,29 @@ const createSchemas = async () => { await sequelize.query('CREATE SCHEMA IF NOT EXISTS logs'); await sequelize.query('CREATE SCHEMA IF NOT EXISTS type'); }; - + const initializeDatabase = async () => { await createSchemas(); - const models = await import('../models/index.js'); - await sequelize.sync({ alter: true }); + const { default: models } = await import('../models/index.js'); + await syncModels(models); +}; + +const syncModels = async (models) => { + // Stellen Sie sicher, dass alle Modelle vorhanden sind + if (!models.SettingsType || !models.UserParamValue || !models.UserParamType || !models.UserRightType || + !models.User || !models.UserParam || !models.Login || !models.UserRight) { + throw new Error('Models are not properly loaded.'); + } + + // Synchronisieren Sie die Modelle in der gewünschten Reihenfolge + await models.SettingsType.sync({ alter: true }); + await models.UserParamValue.sync({ alter: true }); + await models.UserParamType.sync({ alter: true }); + await models.UserRightType.sync({ alter: true }); + await models.User.sync({ alter: true }); + await models.UserParam.sync({ alter: true }); + await models.Login.sync({ alter: true }); + await models.UserRight.sync({ alter: true }); }; export { sequelize, initializeDatabase }; diff --git a/backend/utils/syncDatabase.js b/backend/utils/syncDatabase.js index 7a87f6b..d43e681 100644 --- a/backend/utils/syncDatabase.js +++ b/backend/utils/syncDatabase.js @@ -18,7 +18,6 @@ const syncDatabase = async () => { await initializeSettings(); await initializeTypes(); await initializeUserRights(); - console.log('All models were synchronized successfully.'); } catch (error) { console.error('Unable to synchronize the database:', error); } diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 6cbec26..b76aabd 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -30,6 +30,7 @@ export default { }, created() { this.$store.dispatch('loadLoginState'); + this.$store.dispatch('loadMenu'); this.$i18n.locale = this.$store.getters.language; }, }; diff --git a/frontend/src/components/SettingsWidget.vue b/frontend/src/components/SettingsWidget.vue index a4f5ec7..4b46b3f 100644 --- a/frontend/src/components/SettingsWidget.vue +++ b/frontend/src/components/SettingsWidget.vue @@ -1,9 +1,7 @@