Changed controllers to classes, added image functionality

This commit is contained in:
Torsten Schulz
2024-09-21 15:26:29 +02:00
parent e494fe41db
commit f1b6dd74f7
20 changed files with 836 additions and 581 deletions

View File

@@ -1,79 +1,94 @@
import AdminService from '../services/adminService.js'; import AdminService from '../services/adminService.js';
import Joi from 'joi'; import Joi from 'joi';
export const getOpenInterests = async (req, res) => { class AdminController {
try { constructor() {
const { userid: userId} = req.headers; this.getOpenInterests = this.getOpenInterests.bind(this);
const openInterests = await AdminService.getOpenInterests(userId); this.changeInterest = this.changeInterest.bind(this);
res.status(200).json(openInterests); this.deleteInterest = this.deleteInterest.bind(this);
} catch (error) { this.changeTranslation = this.changeTranslation.bind(this);
res.status(403).json({error: error.message }); this.getOpenContacts = this.getOpenContacts.bind(this);
this.answerContact = this.answerContact.bind(this);
} }
}
export const changeInterest = async (req, res) => { async getOpenInterests(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const { id: interestId, active, adult: adultOnly} = req.body; const openInterests = await AdminService.getOpenInterests(userId);
AdminService.changeInterest(userId, interestId, active, adultOnly); res.status(200).json(openInterests);
res.status(200).json(AdminService.getOpenInterests(userId)); } catch (error) {
} catch (error) { res.status(403).json({ error: error.message });
res.status(403).json({ error: error.message });
}
}
export const deleteInterest = async (req, res) => {
try {
const { userid: userId } = req.headers;
const { id: interestId } = req.params;
AdminService.deleteInterest(userId, interestId);
res.status(200).json(AdminService.getOpenInterests(userId));
} catch (error) {
res.status(403).json({ error: error.message });
}
}
export const changeTranslation = async (req, res) => {
try {
const { userid: userId } = req.headers;
const { id: interestId, translations } = req.body;
AdminService.changeTranslation(userId, interestId, translations);
res.status(200).json(AdminService.getOpenInterests(userId))
} catch(error) {
res.status(403).json({ error: error.message });
}
}
export const getOpenContacts = async (req, res) => {
try {
const { userid: userId } = req.headers;
const openContacts = await AdminService.getOpenContacts(userId);
res.status(200).json(openContacts);
} catch (error) {
res.status(403).json({ error: error.message });
}
}
export const answerContact = async (req, res) => {
try {
const schema = Joi.object({
id: Joi.number().integer().required(),
answer: Joi.string().min(1).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
} }
const { id, answer } = value;
await AdminService.answerContact(id, answer);
res.status(200).json({ status: 'ok' });
} catch (error) {
console.error('Error in answerContact:', error);
res.status(error.status || 500).json({ error: error.message || 'Internal Server Error' });
} }
};
async changeInterest(req, res) {
try {
const { userid: userId } = req.headers;
const { id: interestId, active, adult: adultOnly } = req.body;
await AdminService.changeInterest(userId, interestId, active, adultOnly);
const updatedInterests = await AdminService.getOpenInterests(userId);
res.status(200).json(updatedInterests);
} catch (error) {
res.status(403).json({ error: error.message });
}
}
async deleteInterest(req, res) {
try {
const { userid: userId } = req.headers;
const { id: interestId } = req.params;
await AdminService.deleteInterest(userId, interestId);
const updatedInterests = await AdminService.getOpenInterests(userId);
res.status(200).json(updatedInterests);
} catch (error) {
res.status(403).json({ error: error.message });
}
}
async changeTranslation(req, res) {
try {
const { userid: userId } = req.headers;
const { id: interestId, translations } = req.body;
await AdminService.changeTranslation(userId, interestId, translations);
const updatedInterests = await AdminService.getOpenInterests(userId);
res.status(200).json(updatedInterests);
} catch (error) {
res.status(403).json({ error: error.message });
}
}
async getOpenContacts(req, res) {
try {
const { userid: userId } = req.headers;
const openContacts = await AdminService.getOpenContacts(userId);
res.status(200).json(openContacts);
} catch (error) {
res.status(403).json({ error: error.message });
}
}
async answerContact(req, res) {
try {
const schema = Joi.object({
id: Joi.number().integer().required(),
answer: Joi.string().min(1).required(),
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
const { id, answer } = value;
await AdminService.answerContact(id, answer);
res.status(200).json({ status: 'ok' });
} catch (error) {
console.error('Error in answerContact:', error);
res.status(error.status || 500).json({ error: error.message || 'Internal Server Error' });
}
}
}
export default AdminController;

View File

@@ -1,49 +1,57 @@
import * as userService from '../services/authService.js'; import * as userService from '../services/authService.js';
export const register = async (req, res) => { class AuthController {
const { email, username, password, language } = req.body; constructor() {
this.register = this.register.bind(this);
try { this.login = this.login.bind(this);
const result = await userService.registerUser({ email, username, password, language }); this.forgotPassword = this.forgotPassword.bind(this);
res.status(201).json(result); this.activateAccount = this.activateAccount.bind(this);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
} }
};
export const login = async (req, res) => { async register(req, res) {
const { username, password } = req.body; const { email, username, password, language } = req.body;
try { try {
const result = await userService.loginUser({ username, password }); const result = await userService.registerUser({ email, username, password, language });
res.status(200).json(result); res.status(201).json(result);
} catch (error) { } catch (error) {
if (error.message === 'credentialsinvalid') { console.log(error);
res.status(404).json({ error: error.message })
} else {
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });
} }
} }
};
export const forgotPassword = async (req, res) => { async login(req, res) {
const { email } = req.body; const { username, password } = req.body;
try {
try { const result = await userService.loginUser({ username, password });
const result = await userService.handleForgotPassword({ email }); res.status(200).json(result);
res.status(200).json(result); } catch (error) {
} catch (error) { if (error.message === 'credentialsinvalid') {
res.status(500).json({ error: error.message }); res.status(404).json({ error: error.message });
} else {
res.status(500).json({ error: error.message });
}
}
} }
};
export const activateAccount = async (req, res) => { async forgotPassword(req, res) {
const { token } = req.body; const { email } = req.body;
try {
try { const result = await userService.handleForgotPassword({ email });
const result = await userService.activateUserAccount({ token }); res.status(200).json(result);
res.status(200).json(result); } catch (error) {
} catch (error) { res.status(500).json({ error: error.message });
res.status(500).json({ error: error.message }); }
} }
};
async activateAccount(req, res) {
const { token } = req.body;
try {
const result = await userService.activateUserAccount({ token });
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
export default AuthController;

View File

@@ -1,43 +1,85 @@
import { getMessages as getMessagesService, findMatch, registerUser as registerUserService, addMessage, endChat } from '../services/chatService.js'; import {
getMessages as getMessagesService,
findMatch,
registerUser as registerUserService,
addMessage,
endChat,
removeUser as removeUserService
} from '../services/chatService.js';
export const getMessages = (req, res) => { class ChatController {
const { to, from } = req.body; constructor() {
const messages = getMessagesService(to, from); this.getMessages = this.getMessages.bind(this);
res.status(200).json(messages); this.findRandomChatMatch = this.findRandomChatMatch.bind(this);
}; this.registerUser = this.registerUser.bind(this);
this.sendMessage = this.sendMessage.bind(this);
export const findRandomChatMatch = (req, res) => { this.stopChat = this.stopChat.bind(this);
const { genders, age, id } = req.body; this.removeUser = this.removeUser.bind(this);
const match = findMatch(genders, age, id);
if (match) {
res.status(200).json({ status: 'matched', user: match });
} else {
res.status(200).json({ status: 'waiting' });
} }
};
export const registerUser = (req, res) => { async getMessages(req, res) {
const { gender, age } = req.body; const { to, from } = req.body;
const userId = registerUserService(gender, age); try {
res.status(200).json({ id: userId }); const messages = await getMessagesService(to, from);
}; res.status(200).json(messages);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
export const sendMessage = (req, res) => { async findRandomChatMatch(req, res) {
const from = req.body.from; const { genders, age, id } = req.body;
const to = req.body.to; try {
const text = req.body.text; const match = await findMatch(genders, age, id);
const message = addMessage(from, to, text); if (match) {
res.status(200).json(message); res.status(200).json({ status: 'matched', user: match });
}; } else {
res.status(200).json({ status: 'waiting' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
export const removeUser = (req, res) => { async registerUser(req, res) {
const { id } = req.body; const { gender, age } = req.body;
removeUserService(id); try {
res.sendStatus(200); const userId = await registerUserService(gender, age);
}; res.status(200).json({ id: userId });
} catch (error) {
res.status(500).json({ error: error.message });
}
}
export const stopChat = (req, res) => { async sendMessage(req, res) {
const { id } = req.body; const { from, to, text } = req.body;
endChat(id); try {
res.sendStatus(200); const message = await addMessage(from, to, text);
res.status(200).json(message);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async removeUser(req, res) {
const { id } = req.body;
try {
await removeUserService(id);
res.sendStatus(200);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async stopChat(req, res) {
const { id } = req.body;
try {
await endChat(id);
res.sendStatus(200);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
} }
export default ChatController;

View File

@@ -1,11 +1,19 @@
import ContactService from '../services/ContactService.js'; import ContactService from '../services/ContactService.js';
export const addContactMessage = async(req, res) => { class ContactController {
try { constructor() {
const { email, name, message, acceptDataSave } = req.body; this.addContactMessage = this.addContactMessage.bind(this);
await ContactService.addContactMessage(email, name, message, acceptDataSave); }
res.status(200).json({ status: 'ok' });
} catch (error) { async addContactMessage(req, res) {
res.status(409).json({ error: error }); try {
const { email, name, message, acceptDataSave } = req.body;
await ContactService.addContactMessage(email, name, message, acceptDataSave);
res.status(200).json({ status: 'ok' });
} catch (error) {
res.status(409).json({ error: error.message });
}
} }
} }
export default ContactController;

View File

@@ -2,7 +2,7 @@ import User from '../models/community/user.js';
import UserParam from '../models/community/user_param.js'; import UserParam from '../models/community/user_param.js';
import UserRight from '../models/community/user_right.js'; import UserRight from '../models/community/user_right.js';
import UserRightType from '../models/type/user_right.js'; import UserRightType from '../models/type/user_right.js';
import UserParamType from '../models/type/user_param.js'; import UserParamType from '../models/type/user_param.js';
const menuStructure = { const menuStructure = {
home: { home: {
@@ -14,7 +14,7 @@ const menuStructure = {
friends: { friends: {
visible: ["all"], visible: ["all"],
children: { children: {
manageFriends : { manageFriends: {
visible: ["all"], visible: ["all"],
path: "/socialnetwork/friends", path: "/socialnetwork/friends",
icon: "friends24.png" icon: "friends24.png"
@@ -220,75 +220,74 @@ const menuStructure = {
} }
}; };
const calculateAge = (birthDate) => { class NavigationController {
const today = new Date(); constructor() {
const birthDateObj = new Date(birthDate); this.menu = this.menu.bind(this);
let age = today.getFullYear() - birthDateObj.getFullYear();
const monthDiff = today.getMonth() - birthDateObj.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDateObj.getDate())) {
age--;
} }
return age; 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) => { filterMenu(menu, rights, age) {
const filteredMenu = {}; const filteredMenu = {};
for (const [key, value] of Object.entries(menu)) { for (const [key, value] of Object.entries(menu)) {
if (value.visible.includes("all") if (value.visible.includes("all")
|| value.visible.some(v => rights.includes(v) || 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)) { || (value.visible.includes("over14") && age >= 14)) {
const { visible, ...itemWithoutVisible } = value; const { visible, ...itemWithoutVisible } = value;
filteredMenu[key] = { ...itemWithoutVisible }; filteredMenu[key] = { ...itemWithoutVisible };
if (value.children) { if (value.children) {
filteredMenu[key].children = filterMenu(value.children, rights, age); filteredMenu[key].children = this.filterMenu(value.children, rights, age);
}
} }
} }
return filteredMenu;
} }
return filteredMenu;
};
export const menu = async (req, res) => { async menu(req, res) {
try { try {
const { userid } = req.params; const { userid } = req.params;
const user = await User.findOne({ where: { hashedId: userid } }); const user = await User.findOne({ where: { hashedId: userid } });
if (!user) { if (!user) {
return res.status(404).json({ error: 'User not found' }); return res.status(404).json({ error: 'User not found' });
} }
const userRights = await UserRight.findAll({ const userRights = await UserRight.findAll({
where: { userId: user.id }, where: { userId: user.id },
include: [{ include: [{
model: UserRightType, model: UserRightType,
as: 'rightType', as: 'rightType',
required: false required: false
}] }]
}); });
const userBirthdateParams = await UserParam.findAll({ const userBirthdateParams = await UserParam.findAll({
where: { where: { userId: user.id },
userId: user.id include: [
}, {
include: [ model: UserParamType,
{ as: 'paramType',
model: UserParamType, where: { description: 'birthdate' }
as: 'paramType',
where: {
description: 'birthdate'
} }
} ]
] });
});
const ageFunction = function() {
const birthDate = userBirthdateParams.length > 0 ? userBirthdateParams[0].value : (new Date()).toDateString(); const birthDate = userBirthdateParams.length > 0 ? userBirthdateParams[0].value : (new Date()).toDateString();
const age = calculateAge(birthDate); const age = this.calculateAge(birthDate);
return age; const rights = userRights.map(ur => ur.rightType.title);
const filteredMenu = this.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' });
} }
const age = ageFunction();
const rights = userRights.map(ur => ur.rightType.title);
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' });
} }
}; }
export default NavigationController;

View File

@@ -1,157 +1,161 @@
import settingsService from '../services/settingsService.js'; import settingsService from '../services/settingsService.js';
export const filterSettings = async (req, res) => { class SettingsController {
const { userid, type } = req.body; async filterSettings(req, res) {
try { const { userid, type } = req.body;
const responseFields = await settingsService.filterSettings(userid, type); try {
res.status(200).json(responseFields); const responseFields = await settingsService.filterSettings(userid, type);
} catch (error) { res.status(200).json(responseFields);
console.error('Error filtering settings:', error); } catch (error) {
res.status(500).json({ error: 'An error occurred while filtering the settings' }); console.error('Error filtering settings:', error);
res.status(500).json({ error: 'An error occurred while filtering the settings' });
}
} }
};
export const updateSetting = async (req, res) => { async updateSetting(req, res) {
const { userid, settingId, value } = req.body; const { userid, settingId, value } = req.body;
try { try {
await settingsService.updateSetting(userid, settingId, value); await settingsService.updateSetting(userid, settingId, value);
res.status(200).json({ message: 'Setting updated successfully' }); res.status(200).json({ message: 'Setting updated successfully' });
} catch (error) { } catch (error) {
console.error('Error updating user setting:', error); console.error('Error updating user setting:', error);
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: 'Internal server error' });
}
} }
};
export const getTypeParamValueId = async (req, res) => { async getTypeParamValueId(req, res) {
const { paramValue } = req.body; const { paramValue } = req.body;
try { try {
const paramValueId = await settingsService.getTypeParamValueId(paramValue); const paramValueId = await settingsService.getTypeParamValueId(paramValue);
res.status(200).json({ paramValueId }); res.status(200).json({ paramValueId });
} catch (error) { } catch (error) {
console.error('Error retrieving parameter value ID:', error); console.error('Error retrieving parameter value ID:', error);
res.status(404).json({ error: "notfound" }); res.status(404).json({ error: "notfound" });
}
} }
};
export const getTypeParamValues = async (req, res) => { async getTypeParamValues(req, res) {
const { type } = req.body; const { type } = req.body;
try { try {
const paramValues = await settingsService.getTypeParamValues(type); const paramValues = await settingsService.getTypeParamValues(type);
res.status(200).json(paramValues); res.status(200).json(paramValues);
} catch (error) { } catch (error) {
console.error('Error retrieving parameter values:', error); console.error('Error retrieving parameter values:', error);
res.status(500).json({ error: 'An error occurred while retrieving the parameter values' }); res.status(500).json({ error: 'An error occurred while retrieving the parameter values' });
}
}
async getTypeParamValue(req, res) {
const { id } = req.params;
try {
const paramValue = await settingsService.getTypeParamValue(id);
res.status(200).json({ paramValue });
} catch (error) {
console.error('Error retrieving parameter value:', error);
res.status(404).json({ error: "notfound" });
}
}
async getAccountSettings(req, res) {
try {
const { userId } = req.body;
const accountSettings = await settingsService.getAccountSettings(userId);
res.status(200).json(accountSettings);
} catch (error) {
console.error('Error retrieving account settings:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
async setAccountSettings(req, res) {
try {
await settingsService.setAccountSettings(req.body);
res.status(200).json({ message: 'Account settings updated successfully' });
} catch (error) {
console.error('Error updating account settings:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
async getPossibleInterests(req, res) {
try {
const { userid: userId } = req.headers;
const interests = await settingsService.getPossibleInterests(userId);
res.status(200).json(interests);
} catch (error) {
console.error('Error retrieving possible interests:', error);
res.status(500).json({ error: 'An error occurred while retrieving the possible interests' });
}
}
async getInterests(req, res) {
try {
const { userid: userId } = req.headers;
const interests = await settingsService.getInterests(userId);
res.status(200).json(interests);
} catch (error) {
console.error('Error retrieving interests:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
async addInterest(req, res) {
try {
const { userid: userId } = req.headers;
const { name } = req.body;
const interest = await settingsService.addInterest(userId, name);
res.status(200).json({ interest });
} catch (error) {
console.error('Error adding interest:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
async addUserInterest(req, res) {
try {
const { userid: userId } = req.headers;
const { interestid: interestId } = req.body;
await settingsService.addUserInterest(userId, interestId);
res.status(200).json({ message: 'User interest added successfully' });
} catch (error) {
console.error('Error adding user interest:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
async removeInterest(req, res) {
try {
const { userid: userId } = req.headers;
const { id: interestId } = req.params;
await settingsService.removeInterest(userId, interestId);
res.status(200).json({ message: 'Interest removed successfully' });
} catch (error) {
console.error('Error removing interest:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
async getVisibilities(req, res) {
try {
const visibilities = await settingsService.getVisibilities();
res.status(200).json(visibilities);
} catch (error) {
console.error('Error retrieving visibilities:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
async updateVisibility(req, res) {
const { userParamTypeId, visibilityId } = req.body;
const hashedUserId = req.headers.userid;
try {
await settingsService.updateVisibility(hashedUserId, userParamTypeId, visibilityId);
res.status(200).json({ message: 'Visibility updated successfully' });
} catch (error) {
console.error('Error updating visibility:', error);
res.status(500).json({ error: 'Internal server error' });
}
} }
} }
export const getTypeParamValue = async (req, res) => { export default SettingsController;
const { id } = req.params;
try {
const paramValue = await settingsService.getTypeParamValue(id);
res.status(200).json({ paramValue });
} catch (error) {
console.error('Error retrieving parameter value:', error);
res.status(404).json({ error: "notfound" });
}
};
export const getAccountSettings = async (req, res) => {
try {
const { userId } = req.body;
const accountSettings = await settingsService.getAccountSettings(userId);
res.status(200).json(accountSettings);
} catch (error) {
console.error('Error retrieving account settings:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
export const setAccountSettings = async (req, res) => {
try {
await settingsService.setAccountSettings(req.body);
res.status(200).json({ message: 'Account settings updated successfully' });
} catch (error) {
console.error('Error updating account settings:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
export const getPossibleInterests = async (req, res) => {
try {
const { userid: userId } = req.headers;
const interests = await settingsService.getPossibleInterests(userId);
res.status(200).json(interests);
} catch (error) {
console.error('Error retrieving possible interests:', error);
res.status(500).json({ error: 'An error occurred while retrieving the possible interests' });
}
}
export const getInterests = async (req, res) => {
try {
const { userid: userId } = req.headers;
const interests = await settingsService.getInterests(userId);
res.status(200).json(interests);
} catch (error) {
console.error('Error retrieving interests:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
export const addInterest = async (req, res) => {
try {
const { userid: userId } = req.headers;
const { name } = req.body;
const interest = await settingsService.addInterest(userId, name);
res.status(200).json({ interest });
} catch (error) {
console.error('Error adding interest:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
export const addUserInterest = async (req, res) => {
try {
const { userid: userId } = req.headers;
const { interestid: interestId } = req.body;
await settingsService.addUserInterest(userId, interestId);
res.status(200).json({ message: 'User interest added successfully' });
} catch (error) {
console.error('Error adding user interest:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
export const removeInterest = async (req, res) => {
try {
const { userid: userId } = req.headers;
const { id: interestId } = req.params;
await settingsService.removeInterest(userId, interestId);
res.status(200).json({ message: 'Interest removed successfully' });
} catch (error) {
console.error('Error removing interest:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
export const getVisibilities = async (req, res) => {
try {
const visibilities = await settingsService.getVisibilities();
res.status(200).json(visibilities);
} catch (error) {
console.error('Error retrieving visibilities:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
export const updateVisibility = async (req, res) => {
const { userParamTypeId, visibilityId } = req.body;
const hashedUserId = req.headers.userid;
try {
await settingsService.updateVisibility(hashedUserId, userParamTypeId, visibilityId);
res.status(200).json({ message: 'Visibility updated successfully' });
} catch (error) {
console.error('Error updating visibility:', error);
res.status(500).json({ error: 'Internal server error' });
}
};

View File

@@ -5,6 +5,10 @@ class SocialNetworkController {
this.socialNetworkService = new SocialNetworkService(); this.socialNetworkService = new SocialNetworkService();
this.userSearch = this.userSearch.bind(this); this.userSearch = this.userSearch.bind(this);
this.profile = this.profile.bind(this); this.profile = this.profile.bind(this);
this.createFolder = this.createFolder.bind(this);
this.getFolders = this.getFolders.bind(this);
this.uploadImage = this.uploadImage.bind(this);
this.getImage = this.getImage.bind(this);
} }
async userSearch(req, res) { async userSearch(req, res) {
@@ -32,6 +36,50 @@ class SocialNetworkController {
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });
} }
} }
async createFolder(req, res) {
try {
const folderData = req.body;
const folder = await this.socialNetworkService.createFolder(folderData);
res.status(201).json(folder);
} catch (error) {
console.error('Error in createFolder:', error);
res.status(500).json({ error: error.message });
}
}
async getFolders(req, res) {
try {
const userId = req.headers.userid;
const folders = await this.socialNetworkService.getFolders(userId);
res.status(200).json(folders);
} catch (error) {
console.error('Error in getFolders:', error);
res.status(500).json({ error: error.message });
}
}
async uploadImage(req, res) {
try {
const imageData = req.body;
const image = await this.socialNetworkService.uploadImage(imageData);
res.status(201).json(image);
} catch (error) {
console.error('Error in uploadImage:', error);
res.status(500).json({ error: error.message });
}
}
async getImage(req, res) {
try {
const { imageId } = req.params;
const image = await this.socialNetworkService.getImage(imageId);
res.status(200).json(image);
} catch (error) {
console.error('Error in getImage:', error);
res.status(500).json({ error: error.message });
}
}
} }
export default SocialNetworkController; export default SocialNetworkController;

View File

@@ -10,6 +10,8 @@ import InterestTranslationType from './type/interest_translation.js';
import Interest from './community/interest.js'; import Interest from './community/interest.js';
import UserParamVisibilityType from './type/user_param_visibility.js'; import UserParamVisibilityType from './type/user_param_visibility.js';
import UserParamVisibility from './community/user_param_visibility.js'; import UserParamVisibility from './community/user_param_visibility.js';
import Folder from './community/folder.js';
import Image from './community/image.js';
export default function setupAssociations() { export default function setupAssociations() {
SettingsType.hasMany(UserParamType, { foreignKey: 'settingsId', as: 'user_param_types' }); SettingsType.hasMany(UserParamType, { foreignKey: 'settingsId', as: 'user_param_types' });
@@ -43,4 +45,16 @@ export default function setupAssociations() {
UserParamVisibility.belongsTo(UserParamVisibilityType, { foreignKey: 'visibility', as: 'visibility_type' }); UserParamVisibility.belongsTo(UserParamVisibilityType, { foreignKey: 'visibility', as: 'visibility_type' });
UserParamVisibilityType.hasMany(UserParamVisibility, { foreignKey: 'visibility', as: 'user_param_visibilities' }); UserParamVisibilityType.hasMany(UserParamVisibility, { foreignKey: 'visibility', as: 'user_param_visibilities' });
Folder.belongsTo(User, { foreignKey: 'userId' });
User.hasMany(Folder, { foreignKey: 'userId' });
Folder.belongsTo(Folder, { foreignKey: 'parentId', as: 'parent' });
Folder.hasMany(Folder, { foreignKey: 'parentId', as: 'children' });
Image.belongsTo(Folder, { foreignKey: 'folderId' });
Folder.hasMany(Image, { foreignKey: 'folderId' });
Image.belongsTo(User, { foreignKey: 'userId' });
User.hasMany(Image, { foreignKey: 'userId' });
} }

View File

@@ -0,0 +1,41 @@
import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
import UserParamVisibilityType from '../type/user_param_visibility.js';
const Folder = sequelize.define('folder', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
parentId: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'folder',
key: 'id',
},
},
userId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id',
},
},
visibilityType: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: UserParamVisibilityType,
key: 'id',
},
},
}, {
tableName: 'folder',
schema: 'community',
underscored: true,
timestamps: true,
});
export default Folder;

View File

@@ -0,0 +1,54 @@
import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
import UserParamVisibilityType from '../type/user_param_visibility.js';
const Image = sequelize.define('image', {
title: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
allowNull: true,
},
originalFileName: {
type: DataTypes.STRING,
allowNull: false,
},
hash: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
folderId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'folder',
key: 'id',
},
},
userId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id',
},
},
visibilityType: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: UserParamVisibilityType,
key: 'id',
},
},
}, {
tableName: 'image',
schema: 'community',
underscored: true,
timestamps: true,
});
export default Image;

View File

@@ -12,6 +12,8 @@ import Interest from './community/interest.js';
import ContactMessage from './service/contactmessage.js'; import ContactMessage from './service/contactmessage.js';
import UserParamVisibilityType from './type/user_param_visibility.js'; import UserParamVisibilityType from './type/user_param_visibility.js';
import UserParamVisibility from './community/user_param_visibility.js'; import UserParamVisibility from './community/user_param_visibility.js';
import Folder from './community/folder.js';
import Image from './community/image.js';
const models = { const models = {
SettingsType, SettingsType,
@@ -28,6 +30,8 @@ const models = {
ContactMessage, ContactMessage,
UserParamVisibilityType, UserParamVisibilityType,
UserParamVisibility, UserParamVisibility,
Folder,
Image,
}; };
export default models; export default models;

View File

@@ -1,16 +1,15 @@
import { Router } from 'express'; import { Router } from 'express';
import { authenticate } from '../middleware/authMiddleware.js'; import { authenticate } from '../middleware/authMiddleware.js';
import { getOpenInterests, changeInterest, deleteInterest, changeTranslation, getOpenContacts, answerContact } from '../controllers/adminController.js'; import AdminController from '../controllers/adminController.js';
const router = Router(); const router = Router();
const adminController = new AdminController();
router.get('/interests/open', authenticate, getOpenInterests); router.get('/interests/open', authenticate, adminController.getOpenInterests);
router.post('/interest', authenticate, changeInterest); router.post('/interest', authenticate, adminController.changeInterest);
router.post('/interest/translation', authenticate, changeTranslation); router.post('/interest/translation', authenticate, adminController.changeTranslation);
router.delete('/interest/:id', authenticate, deleteInterest); router.delete('/interest/:id', authenticate, adminController.deleteInterest);
router.get('/opencontacts', authenticate, adminController.getOpenContacts);
router.get('/opencontacts', authenticate, getOpenContacts); router.post('/contacts/answer', authenticate, adminController.answerContact);
router.post('/contacts/answer', answerContact);
export default router; export default router;

View File

@@ -1,11 +1,12 @@
import { Router } from 'express'; import { Router } from 'express';
import { register, login, forgotPassword, activateAccount } from '../controllers/authController.js'; import AuthController from '../controllers/authController.js';
const router = Router(); const router = Router();
const authController = new AuthController();
router.post('/register', register); router.post('/register', authController.register);
router.post('/login', login); router.post('/login', authController.login);
router.post('/forgot-password', forgotPassword); router.post('/forgot-password', authController.forgotPassword);
router.post('/activate', activateAccount); router.post('/activate', authController.activateAccount);
export default router; export default router;

View File

@@ -1,14 +1,14 @@
import { Router } from 'express'; import { Router } from 'express';
import { getMessages, findRandomChatMatch, registerUser, sendMessage, stopChat, removeUser } from '../controllers/chatController.js'; import ChatController from '../controllers/chatController.js';
const router = Router(); const router = Router();
const chatController = new ChatController();
router.get('/messages', getMessages); router.get('/messages', chatController.getMessages);
router.post('/findMatch', findRandomChatMatch); router.post('/findMatch', chatController.findRandomChatMatch);
router.post('/register', registerUser); router.post('/register', chatController.registerUser);
router.post('/sendMessage', sendMessage); router.post('/sendMessage', chatController.sendMessage);
router.post('/getMessages', getMessages); router.post('/leave', chatController.stopChat);
router.post('/leave', stopChat); router.post('/exit', chatController.removeUser);
router.post('/exit', removeUser);
export default router; export default router;

View File

@@ -1,8 +1,19 @@
import { Router } from 'express'; import ContactService from '../services/ContactService.js';
import { addContactMessage } from '../controllers/contactController.js';
const router = Router(); class ContactController {
constructor() {
this.addContactMessage = this.addContactMessage.bind(this);
}
router.post('/', addContactMessage); async addContactMessage(req, res) {
try {
const { email, name, message, acceptDataSave } = req.body;
await ContactService.addContactMessage(email, name, message, acceptDataSave);
res.status(200).json({ status: 'ok' });
} catch (error) {
res.status(409).json({ error: error.message });
}
}
}
export default router; export default ContactController;

View File

@@ -1,10 +1,11 @@
import { Router } from 'express'; import { Router } from 'express';
import { menu } from '../controllers/navigationController.js'; import NavigationController from '../controllers/navigationController.js';
import { authenticate } from '../middleware/authMiddleware.js'; import { authenticate } from '../middleware/authMiddleware.js';
const router = Router(); const router = Router();
const navigationController = new NavigationController();
router.use(authenticate); router.use(authenticate);
router.get('/:userid', menu); router.get('/:userid', navigationController.menu);
export default router; export default router;

View File

@@ -1,24 +1,22 @@
import { Router } from 'express'; import { Router } from 'express';
import { filterSettings, updateSetting, getTypeParamValueId, getTypeParamValues, getTypeParamValue, getAccountSettings, import SettingsController from '../controllers/settingsController.js';
getPossibleInterests, getInterests, addInterest, addUserInterest, removeInterest, getVisibilities, updateVisibility }
from '../controllers/settingsController.js';
import { authenticate } from '../middleware/authMiddleware.js'; import { authenticate } from '../middleware/authMiddleware.js';
const router = Router(); const router = Router();
const settingsController = new SettingsController();
router.post('/filter', authenticate, filterSettings); router.post('/filter', authenticate, settingsController.filterSettings.bind(settingsController));
router.post('/update', authenticate, updateSetting); router.post('/update', authenticate, settingsController.updateSetting.bind(settingsController));
router.post('/account', authenticate, getAccountSettings); router.post('/account', authenticate, settingsController.getAccountSettings.bind(settingsController));
router.post('/getparamvalues', settingsController.getTypeParamValues.bind(settingsController));
router.post('/getparamvalues', getTypeParamValues); router.post('/getparamvalueid', settingsController.getTypeParamValueId.bind(settingsController));
router.post('/getparamvalueid', getTypeParamValueId); router.post('/getparamvalue/:id', settingsController.getTypeParamValue.bind(settingsController));
router.post('/getparamvalue/:id', getTypeParamValue); router.get('/getpossibleinterests', authenticate, settingsController.getPossibleInterests.bind(settingsController));
router.get('/getpossibleinterests', authenticate, getPossibleInterests); router.get('/getuserinterests', authenticate, settingsController.getInterests.bind(settingsController));
router.get('/getuserinterests', authenticate, getInterests); router.post('/addinterest', authenticate, settingsController.addInterest.bind(settingsController));
router.post('/addinterest', authenticate, addInterest); router.post('/setinterest', authenticate, settingsController.addUserInterest.bind(settingsController));
router.post('/setinterest', authenticate, addUserInterest); router.get('/removeinterest/:id', authenticate, settingsController.removeInterest.bind(settingsController));
router.get('/removeinterest/:id', authenticate, removeInterest); router.get('/visibilities', authenticate, settingsController.getVisibilities.bind(settingsController));
router.get('/visibilities', authenticate, getVisibilities); router.post('/update-visibility', authenticate, settingsController.updateVisibility.bind(settingsController));
router.post('/update-visibility', authenticate, updateVisibility);
export default router; export default router;

View File

@@ -7,5 +7,11 @@ const socialNetworkController = new SocialNetworkController();
router.post('/usersearch', authenticate, socialNetworkController.userSearch); router.post('/usersearch', authenticate, socialNetworkController.userSearch);
router.get('/profile/:userId', authenticate, socialNetworkController.profile); router.get('/profile/:userId', authenticate, socialNetworkController.profile);
router.post('/usersearch', authenticate, socialNetworkController.userSearch);
router.get('/profile/:userId', authenticate, socialNetworkController.profile);
router.post('/folders', authenticate, socialNetworkController.createFolder);
router.get('/folders', authenticate, socialNetworkController.getFolders);
router.post('/images', authenticate, socialNetworkController.uploadImage);
router.get('/images/:imageId', authenticate, socialNetworkController.getImage);
export default router; export default router;

View File

@@ -1,186 +1,188 @@
import BaseService from './BaseService.js'; import BaseService from './BaseService.js';
import { Op, col } from 'sequelize'; import { Op } from 'sequelize';
import User from '../models/community/user.js'; import User from '../models/community/user.js';
import UserParam from '../models/community/user_param.js'; import UserParam from '../models/community/user_param.js';
import UserParamType from '../models/type/user_param.js'; import UserParamType from '../models/type/user_param.js';
import UserParamValue from '../models/type/user_param_value.js'; import UserParamValue from '../models/type/user_param_value.js';
import UserParamVisibility from '../models/community/user_param_visibility.js'; import UserParamVisibility from '../models/community/user_param_visibility.js';
import UserParamVisibilityType from '../models/type/user_param_visibility.js'; import UserParamVisibilityType from '../models/type/user_param_visibility.js';
import Folder from '../models/community/folder.js';
import Image from '../models/community/image.js';
class SocialNetworkService extends BaseService { class SocialNetworkService extends BaseService {
async searchUsers({ username, ageFrom, ageTo, genders }) { async searchUsers({ username, ageFrom, ageTo, genders }) {
try { const whereClause = this.buildSearchWhereClause(username);
const whereClause = { const users = await User.findAll({ where: whereClause, include: this.getUserParamsInclude() });
active: true, return this.filterUsersByCriteria(users, ageFrom, ageTo, genders);
searchable: true
};
if (username) {
whereClause.username = { [Op.iLike]: `%${username}%` };
}
const users = await User.findAll({
where: whereClause,
include: [
{
model: UserParam,
as: 'user_params',
include: [
{
model: UserParamType,
as: 'paramType',
where: {
description: {
[Op.in]: ['gender', 'birthdate']
}
},
required: true
}
],
required: true
}
]
});
const results = [];
for (const user of users) {
const id = user.hashedId;
const birthdateParam = user.user_params.find(param => param.paramType.description === 'birthdate');
const genderParam = user.user_params.find(param => param.paramType.description === 'gender');
const age = birthdateParam ? this.calculateAge(birthdateParam.value) : null;
const decryptedGenderValue = genderParam ? genderParam.value : null;
let gender = null;
if (decryptedGenderValue) {
const genderValue = await UserParamValue.findOne({
where: {
id: decryptedGenderValue
}
});
gender = genderValue ? genderValue.value : null;
}
const isWithinAgeRange = (!ageFrom || age >= ageFrom) && (!ageTo || age <= ageTo);
if (isWithinAgeRange && (!genders || !genders.length || (gender && genders.includes(gender))) && age >= 14) {
results.push({
id: id,
username: user.username,
email: user.email,
gender: gender,
age: age
});
}
}
return results;
} catch (error) {
console.error('Error in searchUsers:', error);
throw new Error('Error searching users');
}
} }
async getProfile(hashedUserId, requestingUserId) { async getProfile(hashedUserId, requestingUserId) {
try { await this.checkUserAccess(requestingUserId);
const requestingUser = await this.getUserByHashedId(requestingUserId); const user = await this.fetchUserProfile(hashedUserId);
const requestingUserParams = await this.getUserParams(requestingUser.id, ['birthdate']); if (!user) return null;
let requestingUserAge = 0; return this.constructUserProfile(user, requestingUserId);
}
for (const param of requestingUserParams) { async createFolder(data) {
if (param.paramType.description === 'birthdate') { this.validateFolderData(data);
requestingUserAge = this.calculateAge(param.value); await this.checkUserAccess(data.userId);
break; return await Folder.create(data);
} }
}
const user = await User.findOne({
where: {
hashedId: hashedUserId,
active: true,
searchable: true,
},
include: [
{
model: UserParam,
as: 'user_params',
include: [
{
model: UserParamType,
as: 'paramType',
},
{
model: UserParamVisibility,
as: 'param_visibilities',
include: [
{
model: UserParamVisibilityType,
as: 'visibility_type'
}
]
}
],
order: [[ 'order_id', 'asc']]
}
]
});
if (user) {
const userParams = {};
await Promise.all(user.user_params.map(async (param) => {
const visibilityData = param.param_visibilities?.[0]?.visibility_type;
const visibility = visibilityData ? visibilityData.description : 'Invisible';
let paramValue = param.value;
let paramValueChanged = false;
try {
const parsedValue = JSON.parse(paramValue);
if (Array.isArray(parsedValue)) {
paramValue = await Promise.all(parsedValue.map(async (value) => {
if (/^\d+$/.test(value)) {
const userParamValue = await UserParamValue.findOne({
where: {
id: parseInt(value, 10),
userParamTypeId: param.paramTypeId
}
});
paramValueChanged = true;
return userParamValue ? userParamValue.value : value;
}
return value;
}));
}
} catch (e) {
}
if (!paramValueChanged) {
if (/^\d+$/.test(paramValue)) {
const userParamValue = await UserParamValue.findOne({
where: {
id: parseInt(paramValue, 10),
userParamTypeId: param.paramTypeId
}
});
if (userParamValue) {
paramValue = userParamValue.value;
}
}
}
const paramTypeDescription = param.paramType.description;
if (visibility === 'Invisible') {
return;
}
if (visibility === 'All' || (visibility === 'FriendsAndAdults' && requestingUserAge >= 18) || (visibility === 'AdultsOnly' && requestingUserAge >= 18)) {
userParams[paramTypeDescription] = {
type: param.paramType.datatype,
value: paramValue
};
if (paramTypeDescription === 'birthdate') {
userParams['age'] = { value: this.calculateAge(Date.parse(paramValue)), type: "int"};
}
}
}));
const userProfile = {
username: user.username,
registrationDate: user.registrationDate,
params: userParams
};
return userProfile; async getFolders(userId) {
} await this.checkUserAccess(userId);
return null; return await Folder.findAll({ where: { userId } });
} catch (error) { }
console.error('Error in getProfile:', error);
throw new Error('Error getting profile'); async uploadImage(imageData) {
this.validateImageData(imageData);
await this.checkUserAccess(imageData.userId);
return await Image.create(imageData);
}
async getImage(imageId) {
const image = await Image.findByPk(imageId);
if (!image) throw new Error('Image not found');
await this.checkUserAccess(image.userId);
return image;
}
async checkUserAccess(userId) {
const user = await User.findByPk(userId);
if (!user || !user.active) throw new Error('Access denied: User not found or inactive');
}
validateFolderData(data) {
if (!data.name || typeof data.name !== 'string') throw new Error('Invalid folder data: Name is required');
}
validateImageData(imageData) {
if (!imageData.url || typeof imageData.url !== 'string') throw new Error('Invalid image data: URL is required');
}
buildSearchWhereClause(username) {
const whereClause = { active: true, searchable: true };
if (username) {
whereClause.username = { [Op.iLike]: `%${username}%` };
} }
return whereClause;
}
getUserParamsInclude() {
return [
{
model: UserParam,
as: 'user_params',
include: [{ model: UserParamType, as: 'paramType', required: true }]
}
];
}
filterUsersByCriteria(users, ageFrom, ageTo, genders) {
const results = [];
for (const user of users) {
const userDetails = this.extractUserDetails(user);
if (this.isUserValid(userDetails, ageFrom, ageTo, genders)) {
results.push(userDetails);
}
}
return results;
}
extractUserDetails(user) {
const birthdateParam = user.user_params.find(param => param.paramType.description === 'birthdate');
const genderParam = user.user_params.find(param => param.paramType.description === 'gender');
const age = birthdateParam ? this.calculateAge(birthdateParam.value) : null;
const gender = genderParam ? this.getGenderValue(genderParam.value) : null;
return {
id: user.hashedId,
username: user.username,
email: user.email,
gender,
age
};
}
async getGenderValue(genderId) {
const genderValue = await UserParamValue.findOne({ where: { id: genderId } });
return genderValue ? genderValue.value : null;
}
isUserValid(userDetails, ageFrom, ageTo, genders) {
const { age, gender } = userDetails;
const isWithinAgeRange = (!ageFrom || age >= ageFrom) && (!ageTo || age <= ageTo);
const isGenderValid = !genders || !genders.length || (gender && genders.includes(gender));
return isWithinAgeRange && isGenderValid && age >= 14;
}
async fetchUserProfile(hashedUserId) {
return await User.findOne({
where: { hashedId: hashedUserId, active: true, searchable: true },
include: [
{
model: UserParam,
as: 'user_params',
include: [
{ model: UserParamType, as: 'paramType' },
{ model: UserParamVisibility, as: 'param_visibilities', include: [{ model: UserParamVisibilityType, as: 'visibility_type' }] }
],
order: [['order_id', 'asc']]
}
]
});
}
async constructUserProfile(user, requestingUserId) {
const userParams = {};
const requestingUserAge = await this.getUserAge(requestingUserId);
for (const param of user.user_params) {
const visibility = param.param_visibilities?.[0]?.visibility_type?.description || 'Invisible';
if (visibility === 'Invisible') continue;
if (this.isVisibleToUser(visibility, requestingUserAge)) {
userParams[param.paramType.description] = {
type: param.paramType.datatype,
value: await this.getParamValue(param)
};
}
}
return {
username: user.username,
registrationDate: user.registrationDate,
params: userParams
};
}
async getUserAge(userId) {
const params = await this.getUserParams(userId, ['birthdate']);
const birthdateParam = params.find(param => param.paramType.description === 'birthdate');
return birthdateParam ? this.calculateAge(birthdateParam.value) : 0;
}
isVisibleToUser(visibility, requestingUserAge) {
return visibility === 'All' ||
(visibility === 'FriendsAndAdults' && requestingUserAge >= 18) ||
(visibility === 'AdultsOnly' && requestingUserAge >= 18);
}
async getParamValue(param) {
let paramValue = param.value;
try {
const parsedValue = JSON.parse(paramValue);
if (Array.isArray(parsedValue)) {
paramValue = await Promise.all(parsedValue.map(value => this.getValueFromDatabase(value, param.paramTypeId)));
} else if (/^\d+$/.test(paramValue)) {
paramValue = await this.getValueFromDatabase(paramValue, param.paramTypeId);
}
} catch (e) {
}
return paramValue;
}
async getValueFromDatabase(value, paramTypeId) {
const userParamValue = await UserParamValue.findOne({
where: { id: parseInt(value, 10), userParamTypeId: paramTypeId }
});
return userParamValue ? userParamValue.value : value;
} }
} }

View File

@@ -22,7 +22,7 @@
"tab": { "tab": {
"general": "Allgemeines", "general": "Allgemeines",
"sexuality": "Sexualität", "sexuality": "Sexualität",
"images": "Bilder", "images": "Galerie",
"guestbook": "Gästebuch" "guestbook": "Gästebuch"
}, },
"values": { "values": {