Add password reset localization and chat configuration

- Implemented German and English localization for password reset functionality.
- Added WebSocket URL resolution logic in chat services to support various environments and configurations.
- Created centralized chat configuration for event keys and payload mappings.
- Developed RoomsView component for admin chat room management, including create, edit, and delete functionalities.
This commit is contained in:
Torsten Schulz (local)
2025-08-18 07:44:56 +02:00
parent 23f698d8fd
commit 19ee6ba0a1
50 changed files with 3117 additions and 359 deletions

View File

@@ -177,9 +177,60 @@ class AdminController {
}
}
async updateRoom(req, res) {
try {
const userId = req.headers.userid;
if (!userId || !(await AdminService.hasUserAccess(userId, 'chatrooms'))) {
return res.status(403).json({ error: 'Keine Berechtigung.' });
}
const schema = Joi.object({
title: Joi.string().min(1).max(255).required(),
roomTypeId: Joi.number().integer().required(),
isPublic: Joi.boolean().required(),
genderRestrictionId: Joi.number().integer().allow(null),
minAge: Joi.number().integer().min(0).allow(null),
maxAge: Joi.number().integer().min(0).allow(null),
password: Joi.string().allow('', null),
friendsOfOwnerOnly: Joi.boolean().allow(null),
requiredUserRightId: Joi.number().integer().allow(null)
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
const room = await AdminService.updateRoom(req.params.id, value);
res.status(200).json(room);
} catch (error) {
console.log(error);
res.status(500).json({ error: error.message });
}
}
async createRoom(req, res) {
try {
const room = await AdminService.createRoom(req.body);
const userId = req.headers.userid;
if (!userId || !(await AdminService.hasUserAccess(userId, 'chatrooms'))) {
return res.status(403).json({ error: 'Keine Berechtigung.' });
}
const schema = Joi.object({
title: Joi.string().min(1).max(255).required(),
roomTypeId: Joi.number().integer().required(),
isPublic: Joi.boolean().required(),
genderRestrictionId: Joi.number().integer().allow(null),
minAge: Joi.number().integer().min(0).allow(null),
maxAge: Joi.number().integer().min(0).allow(null),
password: Joi.string().allow('', null),
friendsOfOwnerOnly: Joi.boolean().allow(null),
requiredUserRightId: Joi.number().integer().allow(null)
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
const room = await AdminService.createRoom(value);
res.status(201).json(room);
} catch (error) {
console.log(error);
@@ -189,6 +240,10 @@ class AdminController {
async deleteRoom(req, res) {
try {
const userId = req.headers.userid;
if (!userId || !(await AdminService.hasUserAccess(userId, 'chatrooms'))) {
return res.status(403).json({ error: 'Keine Berechtigung.' });
}
await AdminService.deleteRoom(req.params.id);
res.sendStatus(204);
} catch (error) {

View File

@@ -1,4 +1,5 @@
import chatService from '../services/chatService.js';
import Joi from 'joi';
class ChatController {
constructor() {
@@ -11,12 +12,20 @@ class ChatController {
this.initOneToOne = this.initOneToOne.bind(this);
this.sendOneToOneMessage = this.sendOneToOneMessage.bind(this);
this.getOneToOneMessageHistory = this.getOneToOneMessageHistory.bind(this);
this.getRoomList = this.getRoomList.bind(this);
}
async getMessages(req, res) {
const { to, from } = req.body;
const schema = Joi.object({
to: Joi.string().required(),
from: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const messages = await chatService.getMessages(to, from);
const messages = await chatService.getMessages(value.to, value.from);
res.status(200).json(messages);
} catch (error) {
res.status(500).json({ error: error.message });
@@ -24,9 +33,17 @@ class ChatController {
}
async findRandomChatMatch(req, res) {
const { genders, age, id } = req.body;
const schema = Joi.object({
genders: Joi.array().items(Joi.string()).required(),
age: Joi.number().integer().min(0).required(),
id: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const match = await chatService.findMatch(genders, age, id);
const match = await chatService.findMatch(value.genders, value.age, value.id);
if (match) {
res.status(200).json({ status: 'matched', user: match });
} else {
@@ -38,9 +55,16 @@ class ChatController {
}
async registerUser(req, res) {
const { gender, age } = req.body;
const schema = Joi.object({
gender: Joi.string().required(),
age: Joi.number().integer().min(0).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const userId = await chatService.registerUser(gender, age);
const userId = await chatService.registerUser(value.gender, value.age);
res.status(200).json({ id: userId });
} catch (error) {
res.status(500).json({ error: error.message });
@@ -48,9 +72,17 @@ class ChatController {
}
async sendMessage(req, res) {
const { from, to, text } = req.body;
const schema = Joi.object({
from: Joi.string().required(),
to: Joi.string().required(),
text: Joi.string().min(1).max(2000).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const message = await chatService.addMessage(from, to, text);
const message = await chatService.addMessage(value.from, value.to, value.text);
res.status(200).json(message);
} catch (error) {
res.status(500).json({ error: error.message });
@@ -58,9 +90,15 @@ class ChatController {
}
async removeUser(req, res) {
const { id } = req.body;
const schema = Joi.object({
id: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
await chatService.removeUser(id);
await chatService.removeUser(value.id);
res.sendStatus(200);
} catch (error) {
res.status(500).json({ error: error.message });
@@ -68,9 +106,15 @@ class ChatController {
}
async stopChat(req, res) {
const { id } = req.body;
const schema = Joi.object({
id: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
await chatService.endChat(id);
await chatService.endChat(value.id);
res.sendStatus(200);
} catch (error) {
res.status(500).json({ error: error.message });
@@ -78,10 +122,16 @@ class ChatController {
}
async initOneToOne(req, res) {
const schema = Joi.object({
partnerHashId: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
const { userid: hashedUserId } = req.headers;
const { partnerHashId } = req.body;
try {
await chatService.initOneToOne(hashedUserId, partnerHashId);
await chatService.initOneToOne(hashedUserId, value.partnerHashId);
res.status(200).json({ message: 'One-to-one chat initialization is pending implementation.' });
} catch (error) {
res.status(500).json({ error: error.message });
@@ -89,9 +139,17 @@ class ChatController {
}
async sendOneToOneMessage(req, res) {
const { user1HashId, user2HashId, message } = req.body;
const schema = Joi.object({
user1HashId: Joi.string().required(),
user2HashId: Joi.string().required(),
message: Joi.string().min(1).max(2000).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
await chatService.sendOneToOneMessage(user1HashId, user2HashId, message);
await chatService.sendOneToOneMessage(value.user1HashId, value.user2HashId, value.message);
res.status(200).json({ status: 'message sent' });
} catch (error) {
res.status(500).json({ error: error.message });
@@ -107,6 +165,16 @@ class ChatController {
res.status(500).json({ error: error.message });
}
}
async getRoomList(req, res) {
// Öffentliche Räume für Chat-Frontend
try {
const rooms = await chatService.getRoomList();
res.status(200).json(rooms);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
export default ChatController;

View File

@@ -1,4 +1,5 @@
import ContactService from '../services/ContactService.js';
import Joi from 'joi';
class ContactController {
constructor() {
@@ -6,9 +7,18 @@ class ContactController {
}
async addContactMessage(req, res) {
const schema = Joi.object({
email: Joi.string().email().required(),
name: Joi.string().min(1).max(255).required(),
message: Joi.string().min(1).max(2000).required(),
acceptDataSave: Joi.boolean().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { email, name, message, acceptDataSave } = req.body;
await ContactService.addContactMessage(email, name, message, acceptDataSave);
await ContactService.addContactMessage(value.email, value.name, value.message, value.acceptDataSave);
res.status(200).json({ status: 'ok' });
} catch (error) {
res.status(409).json({ error: error.message });

View File

@@ -1,11 +1,19 @@
import forumService from '../services/forumService.js';
import Joi from 'joi';
const forumController = {
async createForum(req, res) {
const schema = Joi.object({
name: Joi.string().min(1).max(255).required(),
permissions: Joi.array().items(Joi.string().min(1).max(255)).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: userId } = req.headers;
const { name, permissions } = req.body;
const forum = await forumService.createForum(userId, name, permissions);
const forum = await forumService.createForum(userId, value.name, value.permissions);
res.status(201).json(forum);
} catch (error) {
console.error('Error in createForum:', error);
@@ -49,10 +57,18 @@ const forumController = {
},
async createTopic(req, res) {
const schema = Joi.object({
forumId: Joi.number().integer().required(),
title: Joi.string().min(1).max(255).required(),
content: Joi.string().min(1).max(5000).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: userId } = req.headers;
const { forumId, title, content } = req.body;
const result = await forumService.createTopic(userId, forumId, title, content);
const result = await forumService.createTopic(userId, value.forumId, value.title, value.content);
res.status(201).json(result);
} catch (error) {
console.error('Error in createTopic:', error);
@@ -73,11 +89,17 @@ const forumController = {
},
async addMessage(req, res) {
const schema = Joi.object({
content: Joi.string().min(1).max(5000).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: userId } = req.headers;
const { id: topicId } = req.params;
const { content } = req.body;
const result = await forumService.addMessage(userId, topicId, content);
const result = await forumService.addMessage(userId, topicId, value.content);
res.status(201).json(result);
} catch (error) {
console.error('Error in addMessage:', error);

View File

@@ -1,12 +1,18 @@
import friendshipService from '../services/friendshipService.js';
import Joi from 'joi';
const friendshipController = {
async endFriendship(req, res) {
const schema = Joi.object({
friendUserId: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: hashedUserId } = req.headers;
const { friendUserId } = req.body;
await friendshipService.endFriendship(hashedUserId, friendUserId);
await friendshipService.endFriendship(hashedUserId, value.friendUserId);
res.status(200).json({ message: 'Friendship ended successfully' });
} catch (error) {
console.error('Error in endFriendship:', error);
@@ -15,11 +21,16 @@ const friendshipController = {
},
async acceptFriendship(req, res) {
const schema = Joi.object({
friendUserId: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: hashedUserId } = req.headers;
const { friendUserId } = req.body;
await friendshipService.acceptFriendship(hashedUserId, friendUserId);
await friendshipService.acceptFriendship(hashedUserId, value.friendUserId);
res.status(200).json({ message: 'Friendship accepted successfully' });
} catch (error) {
console.error('Error in acceptFriendship:', error);
@@ -28,11 +39,16 @@ const friendshipController = {
},
async rejectFriendship(req, res) {
const schema = Joi.object({
friendUserId: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: hashedUserId } = req.headers;
const { friendUserId } = req.body;
await friendshipService.rejectFriendship(hashedUserId, friendUserId);
await friendshipService.rejectFriendship(hashedUserId, value.friendUserId);
res.status(200).json({ message: 'Friendship rejected successfully' });
} catch (error) {
console.error('Error in rejectFriendship:', error);
@@ -41,10 +57,16 @@ const friendshipController = {
},
async withdrawRequest(req, res) {
const schema = Joi.object({
friendUserId: Joi.string().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: hashedUserId } = req.headers;
const { friendUserId } = req.body;
await friendshipService.withdrawRequest(hashedUserId, friendUserId);
await friendshipService.withdrawRequest(hashedUserId, value.friendUserId);
res.status(200).json({ message: 'Friendship request withdrawn successfully' });
} catch (error) {
console.error('Error in withdrawRequest:', error);

View File

@@ -80,7 +80,8 @@ const menuStructure = {
visible: ["over12"],
action: "openMultiChat",
view: "window",
class: "multiChatWindow"
class: "multiChatDialog",
icon: "multichat24.png"
},
randomChat: {
visible: ["over12"],

View File

@@ -1,4 +1,5 @@
import settingsService from '../services/settingsService.js';
import Joi from 'joi';
class SettingsController {
async filterSettings(req, res) {
@@ -13,9 +14,17 @@ class SettingsController {
}
async updateSetting(req, res) {
const { userid, settingId, value } = req.body;
const schema = Joi.object({
userid: Joi.string().required(),
settingId: Joi.number().integer().required(),
value: Joi.any().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
await settingsService.updateSetting(userid, settingId, value);
await settingsService.updateSetting(value.userid, value.settingId, value.value);
res.status(200).json({ message: 'Setting updated successfully' });
} catch (error) {
console.error('Error updating user setting:', error);
@@ -68,8 +77,16 @@ class SettingsController {
}
async setAccountSettings(req, res) {
const schema = Joi.object({
userId: Joi.string().required(),
settings: Joi.object().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
await settingsService.setAccountSettings(req.body);
await settingsService.setAccountSettings(value);
res.status(200).json({ message: 'Account settings updated successfully' });
} catch (error) {
console.error('Error updating account settings:', error);
@@ -100,10 +117,16 @@ class SettingsController {
}
async addInterest(req, res) {
const schema = Joi.object({
name: Joi.string().min(1).max(255).required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: userId } = req.headers;
const { name } = req.body;
const interest = await settingsService.addInterest(userId, name);
const interest = await settingsService.addInterest(userId, value.name);
res.status(200).json({ interest });
} catch (error) {
console.error('Error adding interest:', error);
@@ -112,10 +135,16 @@ class SettingsController {
}
async addUserInterest(req, res) {
const schema = Joi.object({
interestid: Joi.number().integer().required()
});
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
try {
const { userid: userId } = req.headers;
const { interestid: interestId } = req.body;
await settingsService.addUserInterest(userId, interestId);
await settingsService.addUserInterest(userId, value.interestid);
res.status(200).json({ message: 'User interest added successfully' });
} catch (error) {
console.error('Error adding user interest:', error);