routing improved, settings initialized

This commit is contained in:
Torsten Schulz
2024-07-21 18:47:45 +02:00
parent 12d66d6f9c
commit cd0699f3fd
23 changed files with 476 additions and 69 deletions

View File

@@ -18,7 +18,11 @@ export const login = async (req, res) => {
const result = await userService.loginUser({ username, password });
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
if (error.message === 'credentialsinvalid') {
res.status(404).json({ error: error.message })
} else {
res.status(500).json({ error: error.message });
}
}
};

View File

@@ -1,3 +1,7 @@
import User from '../models/community/user.js';
import UserRight from '../models/community/user_right.js';
import UserRightType from '../models/type/user_right.js';
const menuStructure = {
home: {
visible: ["all"],
@@ -49,7 +53,7 @@ const menuStructure = {
}
},
chats: {
visible: ["all"],
visible: ["over12"],
children: {
multiChat: {
visible: ["over12"],
@@ -138,11 +142,11 @@ const menuStructure = {
},
personal: {
visible: ["all"],
path: "/settings/account"
path: "/settings/personal"
},
view: {
visible: ["all"],
path: "/settings/account"
path: "/settings/view"
},
interrests: {
visible: ["all"],
@@ -202,7 +206,41 @@ const menuStructure = {
}
};
const filterMenu = (menu, rights) => {
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))) {
const { visible, ...itemWithoutVisible } = value;
filteredMenu[key] = { ...itemWithoutVisible };
if (value.children) {
filteredMenu[key].children = filterMenu(value.children, rights);
}
}
}
return filteredMenu;
};
export const menu = async (req, res) => {
const { userid } = req.params;
res.status(200).json({ userId: userid });
}
try {
const { userid } = req.params;
const user = await User.findOne({ where: { hashedId: userid } });
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
const userRights = await UserRight.findAll({
where: { userId: user.id },
include: [{
model: UserRightType,
as: 'rightType'
}]
});
const rights = userRights.map(ur => ur.rightType.title);
const filteredMenu = filterMenu(menuStructure, rights);
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' });
}
};

View File

@@ -28,9 +28,6 @@ const User = sequelize.define('user', {
password: {
type: DataTypes.STRING,
allowNull: false,
set(value) {
this.setDataValue('password', bcrypt.hashSync(value, 10));
}
},
registrationDate: {
type: DataTypes.DATE,

View File

@@ -0,0 +1,32 @@
import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
import User from './user.js';
import UserRightType from '../type/user_right.js';
const UserRight = sequelize.define('user_right', {
userId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: User,
key: 'id'
}
},
rightTypeId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: UserRightType,
key: 'id'
}
},
}, {
tableName: 'user_right',
schema: 'community',
underscored: true,
});
UserRight.belongsTo(User, { foreignKey: 'userId' });
UserRight.belongsTo(UserRightType, { foreignKey: 'rightTypeId', as: 'rightType' });
export default UserRight;

View File

@@ -2,12 +2,18 @@ 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_type.js';
const models = {
User,
UserParam,
UserParamType,
Login
Login,
UserRightType,
UserRight,
SettingsType,
};
export default models;

View File

@@ -0,0 +1,15 @@
import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
const SettingsType = sequelize.define('settings_type', {
name: {
type: DataTypes.STRING,
allowNull: false
},
}, {
tableName: 'settings',
schema: 'type',
underscored: true
});
export default SettingsType;

View File

@@ -1,15 +1,39 @@
import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
import SettingsType from './settings_type.js';
const UserParamType = sequelize.define('user_param_type', {
description: {
type: DataTypes.STRING,
allowNull: false
}
},
minAge: {
type: DataTypes.INTEGER,
allowNull: true
},
gender: {
type: DataTypes.STRING,
allowNull: true
},
datatype: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'string'
},
settingsTypeId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: SettingsType,
key: 'id'
}
},
}, {
tableName: 'user_param',
schema: 'type',
underscored: true
});
UserParamType.belongsTo(SettingsType, { foreignKey: 'settingsTypeId' });
export default UserParamType;

View File

@@ -0,0 +1,15 @@
import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
const UserRightType = sequelize.define('user_right_type', {
title: {
type: DataTypes.STRING,
allowNull: false
}
}, {
tableName: 'user_right',
schema: 'type',
underscored: true
});
export default UserRightType;

View File

@@ -4,24 +4,30 @@ 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 { encrypt, generateIv } from '../utils/encryption.js';
const saltRounds = 10;
export const registerUser = async ({ email, username, password, language }) => {
const [results] = await sequelize.query(
'SELECT * FROM "community"."user" WHERE pgp_sym_decrypt("email", :key) = :email',
const iv = generateIv();
const encryptedEmail = encrypt(email, iv);
const results = await sequelize.query(
`SELECT * FROM "community"."user" WHERE public.pgp_sym_decrypt("email"::bytea, :key::text) = :email`,
{
replacements: { key: process.env.SECRET_KEY, email },
type: sequelize.QueryTypes.SELECT
}
);
if (results.length > 0) {
console.log(results);
if (results.length && results.length > 0) {
throw new Error('Email already in use');
}
const iv = generateIv();
const encryptedEmail = encrypt(email, iv);
const hashedPassword = await bcrypt.hash(password, saltRounds);
const resetToken = uuidv4();
const user = await User.create({
email: encryptedEmail,
iv: iv.toString('hex'),
@@ -31,17 +37,21 @@ 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);
return { id: user.hashedId, username: user.username, active: user.active };
};
@@ -52,10 +62,22 @@ export const loginUser = async ({ username, password }) => {
throw new Error('credentialsinvalid');
}
const match = await bcrypt.compare(password, user.password);
console.log(match, password, user.password, await bcrypt.hash(password, saltRounds));
if (!match) {
throw new Error('credentialsinvalid');
}
return { id: user.hashedId, username: user.username, active: user.active };
const neededParams = await UserParam.findAll({
where: {
userId: user.id
},
include: {
model: UserParamType,
where: {
description: ['birthdate', 'gender']
}
}
});
return { id: user.hashedId, username: user.username, active: user.active, forwardDataInput: neededParams.length < 2 };
};
export const handleForgotPassword = async ({ email }) => {

View File

@@ -0,0 +1,18 @@
import SettingsType from "../models/type/settings_type.js";
const initializeSettings = async () => {
await SettingsType.findOrCreate({
where: { name: 'personal' },
defaults: { name: 'personal' }
});
await SettingsType.findOrCreate({
where: { name: 'view' },
defaults: { name: 'view' }
});
await SettingsType.findOrCreate({
where: { name: 'sexuality' },
defaults: { name: 'sexuality' }
});
};
export default initializeSettings;

View File

@@ -1,9 +1,86 @@
import UserParamType from '../models/type/user_param.js';
import SettingsType from '../models/type/settings_type.js'; // Importiere SettingsType
const initializeTypes = async () => {
const settingsTypes = await SettingsType.findAll();
const settingsTypeMap = settingsTypes.reduce((map, type) => {
map[type.name] = type.id;
return map;
}, {});
const getSettingsTypeId = (name) => settingsTypeMap[name];
await UserParamType.findOrCreate({
where: { description: 'language' },
defaults: { description: 'language' }
defaults: { description: 'language', datatype: 'string', settingsTypeId: getSettingsTypeId('personal') }
});
await UserParamType.findOrCreate({
where: { description: 'birthdate' },
defaults: { description: 'birthdate', datatype: 'date', settingsTypeId: getSettingsTypeId('personal') }
});
await UserParamType.findOrCreate({
where: { description: 'zip' },
defaults: { description: 'zip', datatype: 'string', settingsTypeId: getSettingsTypeId('personal') }
});
await UserParamType.findOrCreate({
where: { description: 'town' },
defaults: { description: 'town', datatype: 'string', settingsTypeId: getSettingsTypeId('personal') }
});
await UserParamType.findOrCreate({
where: { description: 'bodyheight' },
defaults: { description: 'bodyheight', datatype: 'float', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'weight' },
defaults: { description: 'weight', datatype: 'float', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'eyecolor' },
defaults: { description: 'eyecolor', datatype: 'string', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'haircolor' },
defaults: { description: 'haircolor', datatype: 'string', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'hairlength' },
defaults: { description: 'hairlength', datatype: 'int', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'skincolor' },
defaults: { description: 'skincolor', datatype: 'int', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'freckles' },
defaults: { description: 'freckles', datatype: 'int', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'piercings' },
defaults: { description: 'piercings', datatype: 'bool', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'tattoos' },
defaults: { description: 'tattoos', datatype: 'bool', settingsTypeId: getSettingsTypeId('view') }
});
await UserParamType.findOrCreate({
where: { description: 'sexualpreference' },
defaults: { description: 'sexualpreference', minAge: 14, datatype: 'int', settingsTypeId: getSettingsTypeId('sexuality') }
});
await UserParamType.findOrCreate({
where: { description: 'gender' },
defaults: { description: 'gender', datatype: 'string', settingsTypeId: getSettingsTypeId('personal') }
});
await UserParamType.findOrCreate({
where: { description: 'pubichair' },
defaults: { description: 'pubichair', minAge: 14, datatype: 'int', settingsTypeId: getSettingsTypeId('sexuality') }
});
await UserParamType.findOrCreate({
where: { description: 'penislength' },
defaults: { description: 'penislength', minAge: 14, gender: 'm', datatype: 'int', settingsTypeId: getSettingsTypeId('sexuality') }
});
await UserParamType.findOrCreate({
where: { description: 'brasize' },
defaults: { description: 'brasize', minAge: 14, gender: 'f', datatype: 'string', settingsTypeId: getSettingsTypeId('sexuality') }
});
};

View File

@@ -0,0 +1,39 @@
import UserRightType from "../models/type/user_right.js";
const initializeUserRights = async() => {
await UserRightType.findOrCreate({
where: { title: "mainadmin"},
defaults: { title: "mainadmin"}
});
await UserRightType.findOrCreate({
where: { title: "contactrequests"},
defaults: { title: "contactrequests"}
});
await UserRightType.findOrCreate({
where: { title: "useradministration"},
defaults: { title: "useradministration"}
});
await UserRightType.findOrCreate({
where: { title: "forum"},
defaults: { title: "forum"}
});
await UserRightType.findOrCreate({
where: { title: "rights"},
defaults: { title: "rights"}
});
await UserRightType.findOrCreate({
where: { title: "interrests"},
defaults: { title: "interrests"}
});
await UserRightType.findOrCreate({
where: { title: "falukant"},
defaults: { title: "falukant"}
});
await UserRightType.findOrCreate({
where: { title: "developer"},
defaults: { title: "developer"}
});
};
export default initializeUserRights;

View File

@@ -1,10 +1,14 @@
import { initializeDatabase } from './sequelize.js';
import initializeTypes from './initializeTypes.js';
import initializeSettings from './initializeSettings.js';
import initializeUserRights from './initializeUserRights.js';
const syncDatabase = async () => {
try {
await initializeDatabase();
await initializeSettings();
await initializeTypes();
await initializeUserRights();
console.log('All models were synchronized successfully.');
} catch (error) {
console.error('Unable to synchronize the database:', error);