routing improved, settings initialized
This commit is contained in:
@@ -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 });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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' });
|
||||
}
|
||||
};
|
||||
@@ -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,
|
||||
|
||||
32
backend/models/community/user_right.js
Normal file
32
backend/models/community/user_right.js
Normal 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;
|
||||
@@ -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;
|
||||
|
||||
15
backend/models/type/settings_type.js
Normal file
15
backend/models/type/settings_type.js
Normal 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;
|
||||
@@ -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;
|
||||
|
||||
15
backend/models/type/user_right.js
Normal file
15
backend/models/type/user_right.js
Normal 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;
|
||||
@@ -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 }) => {
|
||||
|
||||
18
backend/utils/initializeSettings.js
Normal file
18
backend/utils/initializeSettings.js
Normal 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;
|
||||
@@ -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') }
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
39
backend/utils/initializeUserRights.js
Normal file
39
backend/utils/initializeUserRights.js
Normal 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;
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user