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 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 {
const { userid: userId } = req.headers;
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 {
const { userid: userId } = req.headers;
const { id: interestId, active, adult: adultOnly } = req.body;
AdminService.changeInterest(userId, interestId, active, adultOnly);
res.status(200).json(AdminService.getOpenInterests(userId));
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 });
}
}
export const deleteInterest = async (req, res) => {
async deleteInterest(req, res) {
try {
const { userid: userId } = req.headers;
const { id: interestId } = req.params;
AdminService.deleteInterest(userId, interestId);
res.status(200).json(AdminService.getOpenInterests(userId));
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 });
}
}
export const changeTranslation = async (req, res) => {
async changeTranslation(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))
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 });
}
}
export const getOpenContacts = async (req, res) => {
async getOpenContacts(req, res) {
try {
const { userid: userId } = req.headers;
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 {
const schema = Joi.object({
id: Joi.number().integer().required(),
answer: Joi.string().min(1).required()
answer: Joi.string().min(1).required(),
});
const { error, value } = schema.validate(req.body);
@@ -70,10 +83,12 @@ export const answerContact = async (req, res) => {
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,8 +1,15 @@
import * as userService from '../services/authService.js';
export const register = async (req, res) => {
const { email, username, password, language } = req.body;
class AuthController {
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 {
const result = await userService.registerUser({ email, username, password, language });
res.status(201).json(result);
@@ -10,40 +17,41 @@ export const register = async (req, res) => {
console.log(error);
res.status(500).json({ error: error.message });
}
};
}
export const login = async (req, res) => {
async login(req, res) {
const { username, password } = req.body;
try {
const result = await userService.loginUser({ username, password });
res.status(200).json(result);
} catch (error) {
if (error.message === 'credentialsinvalid') {
res.status(404).json({ error: error.message })
res.status(404).json({ error: error.message });
} else {
res.status(500).json({ error: error.message });
}
}
};
}
export const forgotPassword = async (req, res) => {
async forgotPassword(req, res) {
const { email } = req.body;
try {
const result = await userService.handleForgotPassword({ email });
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
}
export const activateAccount = async (req, res) => {
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 {
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 messages = getMessagesService(to, from);
try {
const messages = await getMessagesService(to, from);
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 match = findMatch(genders, age, id);
try {
const match = await 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) => {
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);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
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';
export const addContactMessage = async(req, res) => {
class ContactController {
constructor() {
this.addContactMessage = this.addContactMessage.bind(this);
}
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 });
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 birthDateObj = new Date(birthDate);
let age = today.getFullYear() - birthDateObj.getFullYear();
@@ -228,11 +233,10 @@ const calculateAge = (birthDate) => {
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDateObj.getDate())) {
age--;
}
return age;
};
}
const filterMenu = (menu, rights, age) => {
filterMenu(menu, rights, age) {
const filteredMenu = {};
for (const [key, value] of Object.entries(menu)) {
if (value.visible.includes("all")
@@ -242,14 +246,14 @@ const filterMenu = (menu, rights, age) => {
const { visible, ...itemWithoutVisible } = value;
filteredMenu[key] = { ...itemWithoutVisible };
if (value.children) {
filteredMenu[key].children = filterMenu(value.children, rights, age);
filteredMenu[key].children = this.filterMenu(value.children, rights, age);
}
}
}
return filteredMenu;
};
}
export const menu = async (req, res) => {
async menu(req, res) {
try {
const { userid } = req.params;
const user = await User.findOne({ where: { hashedId: userid } });
@@ -265,30 +269,25 @@ export const menu = async (req, res) => {
}]
});
const userBirthdateParams = await UserParam.findAll({
where: {
userId: user.id
},
where: { userId: user.id },
include: [
{
model: UserParamType,
as: 'paramType',
where: {
description: 'birthdate'
}
where: { description: 'birthdate' }
}
]
});
const ageFunction = function() {
const birthDate = userBirthdateParams.length > 0 ? userBirthdateParams[0].value : (new Date()).toDateString();
const age = calculateAge(birthDate);
return age;
}
const age = ageFunction();
const age = this.calculateAge(birthDate);
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);
} 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,6 +1,7 @@
import settingsService from '../services/settingsService.js';
export const filterSettings = async (req, res) => {
class SettingsController {
async filterSettings(req, res) {
const { userid, type } = req.body;
try {
const responseFields = await settingsService.filterSettings(userid, type);
@@ -9,9 +10,9 @@ export const filterSettings = async (req, res) => {
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;
try {
await settingsService.updateSetting(userid, settingId, value);
@@ -20,9 +21,9 @@ export const updateSetting = async (req, res) => {
console.error('Error updating user setting:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
}
export const getTypeParamValueId = async (req, res) => {
async getTypeParamValueId(req, res) {
const { paramValue } = req.body;
try {
const paramValueId = await settingsService.getTypeParamValueId(paramValue);
@@ -31,9 +32,9 @@ export const getTypeParamValueId = async (req, res) => {
console.error('Error retrieving parameter value ID:', error);
res.status(404).json({ error: "notfound" });
}
};
}
export const getTypeParamValues = async (req, res) => {
async getTypeParamValues(req, res) {
const { type } = req.body;
try {
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;
try {
const paramValue = await settingsService.getTypeParamValue(id);
@@ -53,9 +54,9 @@ export const getTypeParamValue = async (req, res) => {
console.error('Error retrieving parameter value:', error);
res.status(404).json({ error: "notfound" });
}
};
}
export const getAccountSettings = async (req, res) => {
async getAccountSettings(req, res) {
try {
const { userId } = req.body;
const accountSettings = await settingsService.getAccountSettings(userId);
@@ -64,9 +65,9 @@ export const getAccountSettings = async (req, res) => {
console.error('Error retrieving account settings:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
}
export const setAccountSettings = async (req, res) => {
async setAccountSettings(req, res) {
try {
await settingsService.setAccountSettings(req.body);
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);
res.status(500).json({ error: 'Internal server error' });
}
};
}
export const getPossibleInterests = async (req, res) => {
async getPossibleInterests(req, res) {
try {
const { userid: userId } = req.headers;
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 {
const { userid: userId } = req.headers;
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 {
const { userid: userId } = req.headers;
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 {
const { userid: userId } = req.headers;
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 {
const { userid: userId } = req.headers;
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 {
const visibilities = await settingsService.getVisibilities();
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 hashedUserId = req.headers.userid;
try {
@@ -154,4 +155,7 @@ export const updateVisibility = async (req, res) => {
console.error('Error updating visibility:', 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.userSearch = this.userSearch.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) {
@@ -32,6 +36,50 @@ class SocialNetworkController {
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;

View File

@@ -10,6 +10,8 @@ import InterestTranslationType from './type/interest_translation.js';
import Interest from './community/interest.js';
import UserParamVisibilityType from './type/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() {
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' });
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 UserParamVisibilityType from './type/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 = {
SettingsType,
@@ -28,6 +30,8 @@ const models = {
ContactMessage,
UserParamVisibilityType,
UserParamVisibility,
Folder,
Image,
};
export default models;

View File

@@ -1,16 +1,15 @@
import { Router } from 'express';
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 adminController = new AdminController();
router.get('/interests/open', authenticate, getOpenInterests);
router.post('/interest', authenticate, changeInterest);
router.post('/interest/translation', authenticate, changeTranslation);
router.delete('/interest/:id', authenticate, deleteInterest);
router.get('/opencontacts', authenticate, getOpenContacts);
router.post('/contacts/answer', answerContact);
router.get('/interests/open', authenticate, adminController.getOpenInterests);
router.post('/interest', authenticate, adminController.changeInterest);
router.post('/interest/translation', authenticate, adminController.changeTranslation);
router.delete('/interest/:id', authenticate, adminController.deleteInterest);
router.get('/opencontacts', authenticate, adminController.getOpenContacts);
router.post('/contacts/answer', authenticate, adminController.answerContact);
export default router;

View File

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

View File

@@ -1,14 +1,14 @@
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 chatController = new ChatController();
router.get('/messages', getMessages);
router.post('/findMatch', findRandomChatMatch);
router.post('/register', registerUser);
router.post('/sendMessage', sendMessage);
router.post('/getMessages', getMessages);
router.post('/leave', stopChat);
router.post('/exit', removeUser);
router.get('/messages', chatController.getMessages);
router.post('/findMatch', chatController.findRandomChatMatch);
router.post('/register', chatController.registerUser);
router.post('/sendMessage', chatController.sendMessage);
router.post('/leave', chatController.stopChat);
router.post('/exit', chatController.removeUser);
export default router;

View File

@@ -1,8 +1,19 @@
import { Router } from 'express';
import { addContactMessage } from '../controllers/contactController.js';
import ContactService from '../services/ContactService.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 { menu } from '../controllers/navigationController.js';
import NavigationController from '../controllers/navigationController.js';
import { authenticate } from '../middleware/authMiddleware.js';
const router = Router();
const navigationController = new NavigationController();
router.use(authenticate);
router.get('/:userid', menu);
router.get('/:userid', navigationController.menu);
export default router;

View File

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

View File

@@ -7,5 +7,11 @@ const socialNetworkController = new SocialNetworkController();
router.post('/usersearch', authenticate, socialNetworkController.userSearch);
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;

View File

@@ -1,186 +1,188 @@
import BaseService from './BaseService.js';
import { Op, col } from 'sequelize';
import { Op } from 'sequelize';
import User from '../models/community/user.js';
import UserParam from '../models/community/user_param.js';
import UserParamType from '../models/type/user_param.js';
import UserParamValue from '../models/type/user_param_value.js';
import UserParamVisibility from '../models/community/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 {
async searchUsers({ username, ageFrom, ageTo, genders }) {
try {
const whereClause = {
active: true,
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');
}
const whereClause = this.buildSearchWhereClause(username);
const users = await User.findAll({ where: whereClause, include: this.getUserParamsInclude() });
return this.filterUsersByCriteria(users, ageFrom, ageTo, genders);
}
async getProfile(hashedUserId, requestingUserId) {
try {
const requestingUser = await this.getUserByHashedId(requestingUserId);
const requestingUserParams = await this.getUserParams(requestingUser.id, ['birthdate']);
let requestingUserAge = 0;
await this.checkUserAccess(requestingUserId);
const user = await this.fetchUserProfile(hashedUserId);
if (!user) return null;
return this.constructUserProfile(user, requestingUserId);
}
for (const param of requestingUserParams) {
if (param.paramType.description === 'birthdate') {
requestingUserAge = this.calculateAge(param.value);
break;
async createFolder(data) {
this.validateFolderData(data);
await this.checkUserAccess(data.userId);
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({
where: {
hashedId: hashedUserId,
active: true,
searchable: true,
},
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'
}
]
}
{ model: UserParamType, as: 'paramType' },
{ model: UserParamVisibility, as: 'param_visibilities', include: [{ model: UserParamVisibilityType, as: 'visibility_type' }] }
],
order: [['order_id', 'asc']]
}
]
});
if (user) {
}
async constructUserProfile(user, requestingUserId) {
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] = {
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: paramValue
value: await this.getParamValue(param)
};
if (paramTypeDescription === 'birthdate') {
userParams['age'] = { value: this.calculateAge(Date.parse(paramValue)), type: "int"};
}
}
}));
const userProfile = {
return {
username: user.username,
registrationDate: user.registrationDate,
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) {
console.error('Error in getProfile:', error);
throw new Error('Error getting profile');
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": {
"general": "Allgemeines",
"sexuality": "Sexualität",
"images": "Bilder",
"images": "Galerie",
"guestbook": "Gästebuch"
},
"values": {