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,7 +1,17 @@
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 {
constructor() {
this.getOpenInterests = this.getOpenInterests.bind(this);
this.changeInterest = this.changeInterest.bind(this);
this.deleteInterest = this.deleteInterest.bind(this);
this.changeTranslation = this.changeTranslation.bind(this);
this.getOpenContacts = this.getOpenContacts.bind(this);
this.answerContact = this.answerContact.bind(this);
}
async getOpenInterests(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const openInterests = await AdminService.getOpenInterests(userId); const openInterests = await AdminService.getOpenInterests(userId);
@@ -11,40 +21,43 @@ export const getOpenInterests = async (req, res) => {
} }
} }
export const changeInterest = async (req, res) => { async changeInterest(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const { id: interestId, active, adult: adultOnly } = req.body; const { id: interestId, active, adult: adultOnly } = req.body;
AdminService.changeInterest(userId, interestId, active, adultOnly); await AdminService.changeInterest(userId, interestId, active, adultOnly);
res.status(200).json(AdminService.getOpenInterests(userId)); const updatedInterests = await AdminService.getOpenInterests(userId);
res.status(200).json(updatedInterests);
} catch (error) { } catch (error) {
res.status(403).json({ error: error.message }); res.status(403).json({ error: error.message });
} }
} }
export const deleteInterest = async (req, res) => { async deleteInterest(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const { id: interestId } = req.params; const { id: interestId } = req.params;
AdminService.deleteInterest(userId, interestId); await AdminService.deleteInterest(userId, interestId);
res.status(200).json(AdminService.getOpenInterests(userId)); const updatedInterests = await AdminService.getOpenInterests(userId);
res.status(200).json(updatedInterests);
} catch (error) { } catch (error) {
res.status(403).json({ error: error.message }); res.status(403).json({ error: error.message });
} }
} }
export const changeTranslation = async (req, res) => { async changeTranslation(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const { id: interestId, translations } = req.body; const { id: interestId, translations } = req.body;
AdminService.changeTranslation(userId, interestId, translations); await AdminService.changeTranslation(userId, interestId, translations);
res.status(200).json(AdminService.getOpenInterests(userId)) const updatedInterests = await AdminService.getOpenInterests(userId);
res.status(200).json(updatedInterests);
} catch (error) { } catch (error) {
res.status(403).json({ error: error.message }); res.status(403).json({ error: error.message });
} }
} }
export const getOpenContacts = async (req, res) => { async getOpenContacts(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const openContacts = await AdminService.getOpenContacts(userId); const openContacts = await AdminService.getOpenContacts(userId);
@@ -54,11 +67,11 @@ export const getOpenContacts = async (req, res) => {
} }
} }
export const answerContact = async (req, res) => { async answerContact(req, res) {
try { try {
const schema = Joi.object({ const schema = Joi.object({
id: Joi.number().integer().required(), id: Joi.number().integer().required(),
answer: Joi.string().min(1).required() answer: Joi.string().min(1).required(),
}); });
const { error, value } = schema.validate(req.body); const { error, value } = schema.validate(req.body);
@@ -70,10 +83,12 @@ export const answerContact = async (req, res) => {
const { id, answer } = value; const { id, answer } = value;
await AdminService.answerContact(id, answer); await AdminService.answerContact(id, answer);
res.status(200).json({ status: 'ok' }); res.status(200).json({ status: 'ok' });
} catch (error) { } catch (error) {
console.error('Error in answerContact:', error); console.error('Error in answerContact:', error);
res.status(error.status || 500).json({ error: error.message || 'Internal Server Error' }); res.status(error.status || 500).json({ error: error.message || 'Internal Server Error' });
} }
}; }
}
export default AdminController;

View File

@@ -1,8 +1,15 @@
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);
this.login = this.login.bind(this);
this.forgotPassword = this.forgotPassword.bind(this);
this.activateAccount = this.activateAccount.bind(this);
}
async register(req, res) {
const { email, username, password, language } = req.body;
try { try {
const result = await userService.registerUser({ email, username, password, language }); const result = await userService.registerUser({ email, username, password, language });
res.status(201).json(result); res.status(201).json(result);
@@ -10,40 +17,41 @@ export const register = async (req, res) => {
console.log(error); console.log(error);
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });
} }
}; }
export const login = async (req, res) => { async login(req, res) {
const { username, password } = req.body; const { username, password } = req.body;
try { try {
const result = await userService.loginUser({ username, password }); const result = await userService.loginUser({ username, password });
res.status(200).json(result); res.status(200).json(result);
} catch (error) { } catch (error) {
if (error.message === 'credentialsinvalid') { if (error.message === 'credentialsinvalid') {
res.status(404).json({ error: error.message }) res.status(404).json({ error: error.message });
} else { } else {
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });
} }
} }
}; }
export const forgotPassword = async (req, res) => { async forgotPassword(req, res) {
const { email } = req.body; const { email } = req.body;
try { try {
const result = await userService.handleForgotPassword({ email }); const result = await userService.handleForgotPassword({ email });
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 });
} }
}; }
export const activateAccount = async (req, res) => { async activateAccount(req, res) {
const { token } = req.body; const { token } = req.body;
try { try {
const result = await userService.activateUserAccount({ token }); 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 });
} }
}; }
}
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 {
constructor() {
this.getMessages = this.getMessages.bind(this);
this.findRandomChatMatch = this.findRandomChatMatch.bind(this);
this.registerUser = this.registerUser.bind(this);
this.sendMessage = this.sendMessage.bind(this);
this.stopChat = this.stopChat.bind(this);
this.removeUser = this.removeUser.bind(this);
}
async getMessages(req, res) {
const { to, from } = req.body; const { to, from } = req.body;
const messages = getMessagesService(to, from); try {
const messages = await getMessagesService(to, from);
res.status(200).json(messages); res.status(200).json(messages);
}; } catch (error) {
res.status(500).json({ error: error.message });
}
}
export const findRandomChatMatch = (req, res) => { async findRandomChatMatch(req, res) {
const { genders, age, id } = req.body; const { genders, age, id } = req.body;
const match = findMatch(genders, age, id); try {
const match = await findMatch(genders, age, id);
if (match) { if (match) {
res.status(200).json({ status: 'matched', user: match }); res.status(200).json({ status: 'matched', user: match });
} else { } else {
res.status(200).json({ status: 'waiting' }); res.status(200).json({ status: 'waiting' });
} }
}; } catch (error) {
res.status(500).json({ error: error.message });
export const registerUser = (req, res) => {
const { gender, age } = req.body;
const userId = registerUserService(gender, age);
res.status(200).json({ id: userId });
};
export const sendMessage = (req, res) => {
const from = req.body.from;
const to = req.body.to;
const text = req.body.text;
const message = addMessage(from, to, text);
res.status(200).json(message);
};
export const removeUser = (req, res) => {
const { id } = req.body;
removeUserService(id);
res.sendStatus(200);
};
export const stopChat = (req, res) => {
const { id } = req.body;
endChat(id);
res.sendStatus(200);
} }
}
async registerUser(req, res) {
const { gender, age } = req.body;
try {
const userId = await registerUserService(gender, age);
res.status(200).json({ id: userId });
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async sendMessage(req, res) {
const { from, to, text } = req.body;
try {
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 {
constructor() {
this.addContactMessage = this.addContactMessage.bind(this);
}
async addContactMessage(req, res) {
try { try {
const { email, name, message, acceptDataSave } = req.body; const { email, name, message, acceptDataSave } = req.body;
await ContactService.addContactMessage(email, name, message, acceptDataSave); await ContactService.addContactMessage(email, name, message, acceptDataSave);
res.status(200).json({ status: 'ok' }); res.status(200).json({ status: 'ok' });
} catch (error) { } catch (error) {
res.status(409).json({ error: error }); res.status(409).json({ error: error.message });
} }
} }
}
export default ContactController;

View File

@@ -220,7 +220,12 @@ const menuStructure = {
} }
}; };
const calculateAge = (birthDate) => { class NavigationController {
constructor() {
this.menu = this.menu.bind(this);
}
calculateAge(birthDate) {
const today = new Date(); const today = new Date();
const birthDateObj = new Date(birthDate); const birthDateObj = new Date(birthDate);
let age = today.getFullYear() - birthDateObj.getFullYear(); let age = today.getFullYear() - birthDateObj.getFullYear();
@@ -228,11 +233,10 @@ const calculateAge = (birthDate) => {
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDateObj.getDate())) { if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDateObj.getDate())) {
age--; age--;
} }
return 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")
@@ -242,14 +246,14 @@ const filterMenu = (menu, rights, age) => {
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 } });
@@ -265,30 +269,25 @@ export const menu = async (req, res) => {
}] }]
}); });
const userBirthdateParams = await UserParam.findAll({ const userBirthdateParams = await UserParam.findAll({
where: { where: { userId: user.id },
userId: user.id
},
include: [ include: [
{ {
model: UserParamType, model: UserParamType,
as: 'paramType', as: 'paramType',
where: { where: { description: 'birthdate' }
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 age = ageFunction();
const rights = userRights.map(ur => ur.rightType.title); const rights = userRights.map(ur => ur.rightType.title);
const filteredMenu = filterMenu(menuStructure, rights, age); const filteredMenu = this.filterMenu(menuStructure, rights, age);
res.status(200).json(filteredMenu); res.status(200).json(filteredMenu);
} catch (error) { } catch (error) {
console.error('Error fetching menu:', error); console.error('Error fetching menu:', error);
res.status(500).json({ error: 'An error occurred while fetching the menu' }); res.status(500).json({ error: 'An error occurred while fetching the menu' });
} }
}; }
}
export default NavigationController;

View File

@@ -1,6 +1,7 @@
import settingsService from '../services/settingsService.js'; import settingsService from '../services/settingsService.js';
export const filterSettings = async (req, res) => { class SettingsController {
async filterSettings(req, res) {
const { userid, type } = req.body; const { userid, type } = req.body;
try { try {
const responseFields = await settingsService.filterSettings(userid, type); const responseFields = await settingsService.filterSettings(userid, type);
@@ -9,9 +10,9 @@ export const filterSettings = async (req, res) => {
console.error('Error filtering settings:', error); console.error('Error filtering settings:', error);
res.status(500).json({ error: 'An error occurred while filtering the settings' }); 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);
@@ -20,9 +21,9 @@ export const updateSetting = async (req, res) => {
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);
@@ -31,9 +32,9 @@ export const getTypeParamValueId = async (req, res) => {
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);
@@ -44,7 +45,7 @@ export const getTypeParamValues = async (req, res) => {
} }
} }
export const getTypeParamValue = async (req, res) => { async getTypeParamValue(req, res) {
const { id } = req.params; const { id } = req.params;
try { try {
const paramValue = await settingsService.getTypeParamValue(id); const paramValue = await settingsService.getTypeParamValue(id);
@@ -53,9 +54,9 @@ export const getTypeParamValue = async (req, res) => {
console.error('Error retrieving parameter value:', error); console.error('Error retrieving parameter value:', error);
res.status(404).json({ error: "notfound" }); res.status(404).json({ error: "notfound" });
} }
}; }
export const getAccountSettings = async (req, res) => { async getAccountSettings(req, res) {
try { try {
const { userId } = req.body; const { userId } = req.body;
const accountSettings = await settingsService.getAccountSettings(userId); const accountSettings = await settingsService.getAccountSettings(userId);
@@ -64,9 +65,9 @@ export const getAccountSettings = async (req, res) => {
console.error('Error retrieving account settings:', error); console.error('Error retrieving account settings:', error);
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: 'Internal server error' });
} }
}; }
export const setAccountSettings = async (req, res) => { async setAccountSettings(req, res) {
try { try {
await settingsService.setAccountSettings(req.body); await settingsService.setAccountSettings(req.body);
res.status(200).json({ message: 'Account settings updated successfully' }); res.status(200).json({ message: 'Account settings updated successfully' });
@@ -74,9 +75,9 @@ export const setAccountSettings = async (req, res) => {
console.error('Error updating account settings:', error); console.error('Error updating account settings:', error);
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: 'Internal server error' });
} }
}; }
export const getPossibleInterests = async (req, res) => { async getPossibleInterests(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const interests = await settingsService.getPossibleInterests(userId); const interests = await settingsService.getPossibleInterests(userId);
@@ -87,7 +88,7 @@ export const getPossibleInterests = async (req, res) => {
} }
} }
export const getInterests = async (req, res) => { async getInterests(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const interests = await settingsService.getInterests(userId); const interests = await settingsService.getInterests(userId);
@@ -98,7 +99,7 @@ export const getInterests = async (req, res) => {
} }
} }
export const addInterest = async (req, res) => { async addInterest(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const { name } = req.body; const { name } = req.body;
@@ -110,7 +111,7 @@ export const addInterest = async (req, res) => {
} }
} }
export const addUserInterest = async (req, res) => { async addUserInterest(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const { interestid: interestId } = req.body; const { interestid: interestId } = req.body;
@@ -122,7 +123,7 @@ export const addUserInterest = async (req, res) => {
} }
} }
export const removeInterest = async (req, res) => { async removeInterest(req, res) {
try { try {
const { userid: userId } = req.headers; const { userid: userId } = req.headers;
const { id: interestId } = req.params; const { id: interestId } = req.params;
@@ -134,7 +135,7 @@ export const removeInterest = async (req, res) => {
} }
} }
export const getVisibilities = async (req, res) => { async getVisibilities(req, res) {
try { try {
const visibilities = await settingsService.getVisibilities(); const visibilities = await settingsService.getVisibilities();
res.status(200).json(visibilities); res.status(200).json(visibilities);
@@ -144,7 +145,7 @@ export const getVisibilities = async (req, res) => {
} }
} }
export const updateVisibility = async (req, res) => { async updateVisibility(req, res) {
const { userParamTypeId, visibilityId } = req.body; const { userParamTypeId, visibilityId } = req.body;
const hashedUserId = req.headers.userid; const hashedUserId = req.headers.userid;
try { try {
@@ -154,4 +155,7 @@ export const updateVisibility = async (req, res) => {
console.error('Error updating visibility:', error); console.error('Error updating visibility:', error);
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: 'Internal server error' });
} }
}; }
}
export default SettingsController;

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);
}
async getFolders(userId) {
await this.checkUserAccess(userId);
return await Folder.findAll({ where: { userId } });
}
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);
} }
} }
const user = await User.findOne({ return results;
where: { }
hashedId: hashedUserId,
active: true, extractUserDetails(user) {
searchable: true, 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: [ include: [
{ {
model: UserParam, model: UserParam,
as: 'user_params', as: 'user_params',
include: [ include: [
{ { model: UserParamType, as: 'paramType' },
model: UserParamType, { model: UserParamVisibility, as: 'param_visibilities', include: [{ model: UserParamVisibilityType, as: 'visibility_type' }] }
as: 'paramType',
},
{
model: UserParamVisibility,
as: 'param_visibilities',
include: [
{
model: UserParamVisibilityType,
as: 'visibility_type'
}
]
}
], ],
order: [['order_id', 'asc']] order: [['order_id', 'asc']]
} }
] ]
}); });
if (user) { }
async constructUserProfile(user, requestingUserId) {
const userParams = {}; const userParams = {};
await Promise.all(user.user_params.map(async (param) => { const requestingUserAge = await this.getUserAge(requestingUserId);
const visibilityData = param.param_visibilities?.[0]?.visibility_type; for (const param of user.user_params) {
const visibility = visibilityData ? visibilityData.description : 'Invisible'; const visibility = param.param_visibilities?.[0]?.visibility_type?.description || 'Invisible';
let paramValue = param.value; if (visibility === 'Invisible') continue;
let paramValueChanged = false; if (this.isVisibleToUser(visibility, requestingUserAge)) {
try { userParams[param.paramType.description] = {
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, type: param.paramType.datatype,
value: paramValue value: await this.getParamValue(param)
}; };
if (paramTypeDescription === 'birthdate') {
userParams['age'] = { value: this.calculateAge(Date.parse(paramValue)), type: "int"};
} }
} }
})); return {
const userProfile = {
username: user.username, username: user.username,
registrationDate: user.registrationDate, registrationDate: user.registrationDate,
params: userParams params: userParams
}; };
}
return userProfile; 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;
} }
return null;
} catch (error) { isVisibleToUser(visibility, requestingUserAge) {
console.error('Error in getProfile:', error); return visibility === 'All' ||
throw new Error('Error getting profile'); (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": {