websockets implemented
This commit is contained in:
@@ -9,9 +9,11 @@ import UserRightType from '../models/type/user_right.js';
|
||||
|
||||
class BaseService {
|
||||
async getUserByHashedId(hashedId) {
|
||||
const user = await User.findOne({ where: { hashedId } });
|
||||
console.log('async getUserByHashedId: ', hashedId);
|
||||
const user = await User.findOne({ where: { hashedId: hashedId } });
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
console.log('User not found: ', hashedId);
|
||||
throw new Error('User not found: ', hashedId);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -6,20 +6,64 @@ import UserParam from '../models/community/user_param.js';
|
||||
import UserParamType from '../models/type/user_param.js';
|
||||
import { sendAccountActivationEmail, sendPasswordResetEmail } from './emailService.js';
|
||||
import { sequelize } from '../utils/sequelize.js';
|
||||
import { Op } from 'sequelize';
|
||||
import { setUserSession, deleteUserSession } from '../utils/redis.js';
|
||||
import { encrypt } from '../utils/encryption.js';
|
||||
import { notifyUser } from '../utils/socket.js';
|
||||
import Friendship from '../models/community/friendship.js';
|
||||
|
||||
const saltRounds = 10;
|
||||
|
||||
const getFriends = async (userId) => {
|
||||
console.log('getFriends', userId);
|
||||
try {
|
||||
const friendships = await Friendship.findAll({
|
||||
where: {
|
||||
[Op.or]: [
|
||||
{ user1Id: userId },
|
||||
{ user2Id: userId },
|
||||
],
|
||||
accepted: true,
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'friendSender',
|
||||
attributes: ['hashedId', 'username'],
|
||||
},
|
||||
{
|
||||
model: User,
|
||||
as: 'friendReceiver',
|
||||
attributes: ['hashedId', 'username'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
console.log('did read out friends');
|
||||
return friendships.map((friendship) => {
|
||||
if (friendship.user1Id === userId) {
|
||||
return friendship.friendReceiver;
|
||||
} else {
|
||||
return friendship.friendSender;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching friends:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const registerUser = async ({ email, username, password, language }) => {
|
||||
const encryptionKey = process.env.SECRET_KEY;
|
||||
const results = await sequelize.query(
|
||||
`SELECT * FROM community.user WHERE pgp_sym_decrypt(email::bytea, :key) = :email`,
|
||||
{
|
||||
replacements: { key: encryptionKey, email },
|
||||
type: sequelize.QueryTypes.SELECT
|
||||
}
|
||||
);
|
||||
if (results.length > 0) {
|
||||
const encryptedEmail = encrypt(email);
|
||||
const query = `
|
||||
SELECT id FROM community.user
|
||||
WHERE email = :encryptedEmail
|
||||
`;
|
||||
const existingUser = await sequelize.query(query, {
|
||||
replacements: { encryptedEmail },
|
||||
type: sequelize.QueryTypes.SELECT,
|
||||
});
|
||||
if (existingUser.length > 0) {
|
||||
throw new Error('emailinuse');
|
||||
}
|
||||
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
||||
@@ -59,6 +103,13 @@ export const loginUser = async ({ username, password }) => {
|
||||
const authCode = crypto.randomBytes(20).toString('hex');
|
||||
user.authCode = authCode;
|
||||
await user.save();
|
||||
const friends = await getFriends(user.id);
|
||||
for (const friend of friends) {
|
||||
await notifyUser(friend.hashedId, 'friendloginchanged', {
|
||||
userId: user.hashedId,
|
||||
status: 'online',
|
||||
});
|
||||
}
|
||||
const sessionData = {
|
||||
id: user.hashedId,
|
||||
username: user.username,
|
||||
@@ -86,14 +137,14 @@ export const loginUser = async ({ username, password }) => {
|
||||
id: user.hashedId,
|
||||
username: user.username,
|
||||
active: user.active,
|
||||
param: mappedParams,
|
||||
param: mappedParams,
|
||||
authCode
|
||||
};
|
||||
};
|
||||
|
||||
export const logoutUser = async (hashedUserId) => {
|
||||
try {
|
||||
const user = User.findOne({
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
hashedId: hashedUserId
|
||||
}
|
||||
@@ -101,8 +152,14 @@ export const logoutUser = async (hashedUserId) => {
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
const friends = await getFriends(user.id);
|
||||
for (const friend of friends) {
|
||||
await notifyUser(friend.hashedId, 'friendloginchanged', {
|
||||
userId: user.hashedId,
|
||||
status: 'online',
|
||||
});
|
||||
}
|
||||
await deleteUserSession(user.id);
|
||||
console.log('Benutzer erfolgreich aus Redis entfernt:', userId);
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Logout:', error);
|
||||
throw new Error('logoutfailed');
|
||||
|
||||
@@ -1,76 +1,137 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import amqp from 'amqplib/callback_api.js';
|
||||
|
||||
let messages = [];
|
||||
let searchQueue = [];
|
||||
let users = [];
|
||||
let currentChats = [];
|
||||
const RABBITMQ_URL = 'amqp://localhost';
|
||||
const QUEUE = 'oneToOne_messages';
|
||||
|
||||
export const getMessages = (toId, fromId) => {
|
||||
const userChats = currentChats.filter(chat => chat.includes(toId) && chat.includes(fromId));
|
||||
if (userChats.length === 0) {
|
||||
fromId = '';
|
||||
class ChatService {
|
||||
constructor() {
|
||||
this.messages = [];
|
||||
this.searchQueue = [];
|
||||
this.users = [];
|
||||
this.randomChats = [];
|
||||
this.oneToOneChats = [];
|
||||
amqp.connect(RABBITMQ_URL, (err, connection) => {
|
||||
if (err) throw err;
|
||||
connection.createChannel((err, channel) => {
|
||||
if (err) throw err;
|
||||
this.channel = channel;
|
||||
channel.assertQueue(QUEUE, { durable: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
const userMessages = messages.filter(message => message.to = toId && ["system", fromId].includes(message.from));
|
||||
messages = messages.filter(message => message.to === toId && ["system", fromId].includes(message.from));
|
||||
return userMessages;
|
||||
};
|
||||
|
||||
export const addMessage = (from, to, text) => {
|
||||
const userChats = currentChats.filter(chat => chat.includes(from) && chat.includes(to));
|
||||
if (userChats.length === 0) {
|
||||
return;
|
||||
getMessages(toId, fromId) {
|
||||
const userChats = this.randomChats.filter(chat => chat.includes(toId) && chat.includes(fromId));
|
||||
if (userChats.length === 0) {
|
||||
fromId = '';
|
||||
}
|
||||
const userMessages = this.messages.filter(message => message.to === toId && ["system", fromId].includes(message.from));
|
||||
this.messages = this.messages.filter(message => message.to === toId && ["system", fromId].includes(message.from));
|
||||
return userMessages;
|
||||
}
|
||||
messages.push({ from: from, to: to, text: text });
|
||||
return { text: text };
|
||||
};
|
||||
|
||||
export const findMatch = (genders, age, id) => {
|
||||
const currentUsersChat = currentChats.filter(chat => chat.includes(id));
|
||||
if (currentUsersChat.length > 0) {
|
||||
return findUser(currentUsersChat[0][0] === id ? currentUsersChat[0][1] : currentUsersChat[0][0]);
|
||||
async addMessage(from, to, text) {
|
||||
const userChats = this.randomChats.filter(chat => chat.includes(from) && chat.includes(to));
|
||||
if (userChats.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.messages.push({ from: from, to: to, text: text });
|
||||
return { text: text };
|
||||
}
|
||||
let filteredSearchQueue = users.filter(user =>
|
||||
searchQueue.some(sq => sq.id === user.id) && user.id !== id
|
||||
&& currentChats.filter(chat => chat.includes(user.id)).length === 0
|
||||
).sort(() => Math.random() - 0.5);
|
||||
for (let i = 0; i < filteredSearchQueue.length; i++) {
|
||||
const user = filteredSearchQueue[i];
|
||||
const ageMatch = user.age >= age.min && user.age <= age.max;
|
||||
const genderMatch = genders.includes(user.gender);
|
||||
if (ageMatch && genderMatch) {
|
||||
for (let j = searchQueue.length - 1; j >= 0; j--) {
|
||||
if ([id, user.id].includes(searchQueue[j].id)) {
|
||||
searchQueue.splice(j, 1);
|
||||
|
||||
findMatch(genders, age, id) {
|
||||
const currentUsersChat = this.randomChats.filter(chat => chat.includes(id));
|
||||
if (currentUsersChat.length > 0) {
|
||||
return this.findUser(currentUsersChat[0][0] === id ? currentUsersChat[0][1] : currentUsersChat[0][0]);
|
||||
}
|
||||
let filteredSearchQueue = this.users.filter(user =>
|
||||
this.searchQueue.some(sq => sq.id === user.id) && user.id !== id
|
||||
&& this.randomChats.filter(chat => chat.includes(user.id)).length === 0
|
||||
).sort(() => Math.random() - 0.5);
|
||||
|
||||
for (let i = 0; i < filteredSearchQueue.length; i++) {
|
||||
const user = filteredSearchQueue[i];
|
||||
const ageMatch = user.age >= age.min && user.age <= age.max;
|
||||
const genderMatch = genders.includes(user.gender);
|
||||
if (ageMatch && genderMatch) {
|
||||
for (let j = this.searchQueue.length - 1; j >= 0; j--) {
|
||||
if ([id, user.id].includes(this.searchQueue[j].id)) {
|
||||
this.searchQueue.splice(j, 1);
|
||||
}
|
||||
}
|
||||
this.randomChats.push([user.id, id]);
|
||||
return user;
|
||||
}
|
||||
currentChats.push([user.id, id]);
|
||||
return user;
|
||||
}
|
||||
if (!this.searchQueue.find(user => user.id === id)) {
|
||||
this.searchQueue.push({ id, genders, age });
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
findUser(id) {
|
||||
return this.users.find(user => user.id === id);
|
||||
}
|
||||
|
||||
async registerUser(gender, age) {
|
||||
const id = uuidv4();
|
||||
this.users.push({ gender, age, id });
|
||||
return id;
|
||||
}
|
||||
|
||||
async removeUser(id) {
|
||||
this.searchQueue = this.searchQueue.filter(user => user.id !== id);
|
||||
this.users = this.users.filter(user => user.id !== id);
|
||||
this.randomChats = this.randomChats.filter(pair => pair[0] === id || pair[1] === id);
|
||||
this.messages = this.messages.filter(message => message.from === id || message.to === id);
|
||||
}
|
||||
|
||||
async endChat(userId) {
|
||||
this.randomChats = this.randomChats.filter(chat => !chat.includes(userId));
|
||||
this.messages.push({ to: userId, from: 'system', activity: 'otheruserleft' });
|
||||
}
|
||||
|
||||
async initOneToOne(user1HashId, user2HashId) {
|
||||
const chat = this.searchOneToOneChat(user1HashId, user2HashId);
|
||||
if (!chat) {
|
||||
this.oneToOneChats.push({ user1Id: user1HashId, user2Id: user2HashId, history: [] });
|
||||
}
|
||||
}
|
||||
if (!searchQueue.find(user => user.id === id)) {
|
||||
searchQueue.push({ id, genders, age });
|
||||
|
||||
async sendOneToOneMessage(user1HashId, user2HashId, message) {
|
||||
const messageBundle = {
|
||||
timestamp: Date.now(),
|
||||
sender: user1HashId,
|
||||
recipient: user2HashId,
|
||||
message: message,
|
||||
};
|
||||
const chat = this.searchOneToOneChat(user1HashId, user2HashId);
|
||||
if (chat) {
|
||||
chat.history.push(messageBundle);
|
||||
} else {
|
||||
this.oneToOneChats.push({
|
||||
user1Id: user1HashId,
|
||||
user2Id: user2HashId,
|
||||
history: [messageBundle],
|
||||
});
|
||||
}
|
||||
if (this.channel) {
|
||||
this.channel.sendToQueue(QUEUE, Buffer.from(JSON.stringify(messageBundle)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const findUser = (id) => {
|
||||
return users.find(user => user.id === id);
|
||||
};
|
||||
async getOneToOneMessageHistory(user1HashId, user2HashId) {
|
||||
const chat = this.searchOneToOneChat(user1HashId, user2HashId);
|
||||
return chat ? chat.history : [];
|
||||
}
|
||||
|
||||
export const registerUser = (gender, age) => {
|
||||
const id = uuidv4();
|
||||
users.push({ gender, age, id });
|
||||
return id;
|
||||
};
|
||||
searchOneToOneChat(user1HashId, user2HashId) {
|
||||
return this.oneToOneChats.find(chat =>
|
||||
(chat.user1Id === user1HashId && chat.user2Id === user2HashId) ||
|
||||
(chat.user1Id === user2HashId && chat.user2Id === user1HashId)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const removeUser = (id) => {
|
||||
searchQueue = searchQueue.filter(user => user.id !== id);
|
||||
users = users.filter(user => user.id !== id);
|
||||
currentChats = currentChats.filter(pair => pair[0] === id || pair[1] === id);
|
||||
messages = messages.filter(message => message.from === id || message.to === id);
|
||||
};
|
||||
|
||||
export const endChat = (userId) => {
|
||||
currentChats = currentChats.filter(chat => !chat.includes(userId));
|
||||
messages.push({ to: userId, from: 'system', activity: 'otheruserleft'})
|
||||
}
|
||||
export default new ChatService();
|
||||
|
||||
7
backend/services/falukantService.js
Normal file
7
backend/services/falukantService.js
Normal file
@@ -0,0 +1,7 @@
|
||||
class FalukantService {
|
||||
async exampleMethod() {
|
||||
// Logik für die Methode
|
||||
}
|
||||
}
|
||||
|
||||
export default new FalukantService();
|
||||
@@ -10,7 +10,8 @@ import User from '../models/community/user.js';
|
||||
import ForumForumPermission from '../models/forum/forum_forum_permission.js';
|
||||
import Title from '../models/forum/title.js';
|
||||
import Message from '../models/forum/message.js';
|
||||
|
||||
import { notifyAllUsers } from '../utils/socket.js';
|
||||
|
||||
class ForumService extends BaseService {
|
||||
|
||||
async createForum(hashedUserId, name, permissions) {
|
||||
@@ -30,6 +31,7 @@ class ForumService extends BaseService {
|
||||
}
|
||||
}
|
||||
}
|
||||
await notifyAllUsers('forumschanged', {});
|
||||
return newForum;
|
||||
}
|
||||
|
||||
@@ -60,6 +62,7 @@ class ForumService extends BaseService {
|
||||
await forum.destroy({ transaction });
|
||||
|
||||
await transaction.commit();
|
||||
await notifyAllUsers('forumschanged', {});
|
||||
return forum;
|
||||
} catch (error) {
|
||||
await transaction.rollback();
|
||||
@@ -193,6 +196,7 @@ class ForumService extends BaseService {
|
||||
}
|
||||
const newTopic = await Title.create({ title, forumId, createdBy: user.id });
|
||||
await Message.create({ titleId: newTopic.id, text: content, createdBy: user.id})
|
||||
await notifyAllUsers('topicschanged', { forumId, topic: newTopic });
|
||||
return this.getForum(hashedUserId, forumId, 1);
|
||||
}
|
||||
|
||||
@@ -289,6 +293,7 @@ class ForumService extends BaseService {
|
||||
}
|
||||
console.log('[ForumService.addMessage] - create new message');
|
||||
await Message.create({ titleId: topicId, text: content, createdBy: user.id });
|
||||
await notifyAllUsers('messageschanged', { topicId, message });
|
||||
console.log('[ForumService.addMessage] - return topic');
|
||||
return this.getTopic(hashedUserId, topicId);
|
||||
}
|
||||
|
||||
180
backend/services/friendshipService.js
Normal file
180
backend/services/friendshipService.js
Normal file
@@ -0,0 +1,180 @@
|
||||
import BaseService from './BaseService.js';
|
||||
import Friendship from '../models/community/friendship.js';
|
||||
import User from '../models/community/user.js';
|
||||
import { Op } from 'sequelize';
|
||||
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 { notifyUser } from '../utils/socket.js';
|
||||
|
||||
class FriendshipService extends BaseService {
|
||||
genders = {};
|
||||
|
||||
async endFriendship(hashedUserId, friendUserId) {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
const friend = await this.getUserByHashedId(friendUserId);
|
||||
if (!user) throw new Error('User not found.');
|
||||
|
||||
const friendship = await Friendship.findOne({
|
||||
where: {
|
||||
[Op.or]: [
|
||||
{ user1Id: user.id, user2Id: friend.id },
|
||||
{ user1Id: friend.id, user2Id: user.id },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
if (!friendship) throw new Error('Friendship not found.');
|
||||
await friendship.destroy();
|
||||
notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId });
|
||||
}
|
||||
|
||||
async acceptFriendship(hashedUserId, friendUserId) {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
const friend = await this.getUserByHashedId(friendUserId);
|
||||
if (!user) throw new Error('User not found.');
|
||||
const friendship = await Friendship.findOne({
|
||||
where: { user1Id: friend.id, user2Id: user.id, accepted: false },
|
||||
});
|
||||
|
||||
if (!friendship) throw new Error('Cannot accept this friendship.');
|
||||
friendship.accepted = true;
|
||||
await friendship.save();
|
||||
notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId });
|
||||
}
|
||||
|
||||
async rejectFriendship(hashedUserId, friendUserId) {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
const friend = await this.getUserByHashedId(friendUserId);
|
||||
if (!user) throw new Error('User not found.');
|
||||
const friendship = await Friendship.findOne({
|
||||
where: { user1Id: friend.id, user2Id: user.id, accepted: false },
|
||||
});
|
||||
|
||||
if (!friendship) throw new Error('Cannot reject this friendship.');
|
||||
friendship.denied = true;
|
||||
await friendship.save();
|
||||
notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId });
|
||||
}
|
||||
|
||||
async withdrawRequest(hashedUserId, friendUserId) {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
const friend = await this.getUserByHashedId(friendUserId);
|
||||
if (!user) throw new Error('User not found.');
|
||||
|
||||
const friendship = await Friendship.findOne({
|
||||
where: { user1Id: user.id, user2Id: friend.id, accepted: false },
|
||||
});
|
||||
|
||||
if (!friendship) throw new Error('Cannot withdraw this request.');
|
||||
await friendship.destroy();
|
||||
notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId });
|
||||
}
|
||||
|
||||
|
||||
async getFriendships(hashedUserId, acceptedOnly) {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
if (!user) throw new Error('User not found.');
|
||||
|
||||
const whereCondition = acceptedOnly
|
||||
? { accepted: true, withdrawn: false, denied: false }
|
||||
: {};
|
||||
|
||||
const friendships = await Friendship.findAll({
|
||||
where: {
|
||||
...whereCondition,
|
||||
[Op.or]: [
|
||||
{ user1Id: user.id },
|
||||
{ user2Id: user.id },
|
||||
],
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'friendSender',
|
||||
attributes: ['username', 'hashedId'],
|
||||
include: [
|
||||
{
|
||||
model: UserParam,
|
||||
as: 'user_params',
|
||||
required: false,
|
||||
include: [
|
||||
{
|
||||
model: UserParamType,
|
||||
as: 'paramType',
|
||||
required: true,
|
||||
where: { description: 'gender' },
|
||||
attributes: ['description'],
|
||||
},
|
||||
],
|
||||
attributes: ['value'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
model: User,
|
||||
as: 'friendReceiver',
|
||||
attributes: ['username', 'hashedId'],
|
||||
include: [
|
||||
{
|
||||
model: UserParam,
|
||||
as: 'user_params',
|
||||
required: false,
|
||||
include: [
|
||||
{
|
||||
model: UserParamType,
|
||||
as: 'paramType',
|
||||
required: true,
|
||||
where: { description: 'gender' },
|
||||
attributes: ['description'],
|
||||
},
|
||||
],
|
||||
attributes: ['value'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const processedFriendships = await Promise.all(
|
||||
friendships.map(async (friendship) => {
|
||||
const isInitiator = friendship.user1Id === user.id;
|
||||
const otherUser = isInitiator ? friendship.friendReceiver : friendship.friendSender;
|
||||
const genderParam = otherUser.user_params?.find(param => param.paramType.description === 'gender');
|
||||
const gender = genderParam ? await this.getGender(genderParam) : null;
|
||||
|
||||
return {
|
||||
id: friendship.id,
|
||||
user: {
|
||||
username: otherUser.username,
|
||||
hashedId: otherUser.hashedId,
|
||||
gender,
|
||||
},
|
||||
accepted: friendship.accepted,
|
||||
denied: friendship.denied,
|
||||
withdrawn: friendship.withdrawn,
|
||||
isInitiator,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return processedFriendships;
|
||||
}
|
||||
|
||||
async getGender(genderParam) {
|
||||
if (!this.genders) {
|
||||
this.genders = {};
|
||||
}
|
||||
if (this.genders[genderParam.value]) return this.genders[genderParam.value];
|
||||
const genderObject = await UserParamValue.findOne({
|
||||
where: { id: genderParam.value },
|
||||
});
|
||||
if (genderObject) {
|
||||
this.genders[genderParam.value] = genderObject.value;
|
||||
return genderObject.value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export default new FriendshipService();
|
||||
@@ -156,7 +156,7 @@ class SettingsService extends BaseService{
|
||||
include: [
|
||||
{
|
||||
model: UserParamType,
|
||||
as: 'user_param_type',
|
||||
as: 'user_param_value_type',
|
||||
where: { description: type }
|
||||
}
|
||||
]
|
||||
@@ -264,7 +264,6 @@ class SettingsService extends BaseService{
|
||||
async updateVisibility(hashedUserId, userParamTypeId, visibilityId) {
|
||||
try {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
console.log(JSON.stringify(user));
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
|
||||
@@ -24,15 +24,22 @@ import DOMPurify from 'dompurify';
|
||||
import sharp from 'sharp';
|
||||
import Diary from '../models/community/diary.js';
|
||||
import Friendship from '../models/community/friendship.js';
|
||||
import { getUserSession } from '../utils/redis.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
class SocialNetworkService extends BaseService {
|
||||
async searchUsers({ username, ageFrom, ageTo, genders }) {
|
||||
async searchUsers({ hashedUserId, username, ageFrom, ageTo, genders }) {
|
||||
const whereClause = this.buildSearchWhereClause(username);
|
||||
const user = await this.loadUserByHash(hashedUserId);
|
||||
console.log(hashedUserId, user);
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
whereClause.id = { [Op.ne]: user.id };
|
||||
const users = await User.findAll({ where: whereClause, include: this.getUserParamsInclude() });
|
||||
return this.filterUsersByCriteria(users, ageFrom, ageTo, genders);
|
||||
return await this.filterUsersByCriteria(users, ageFrom, ageTo, genders);
|
||||
}
|
||||
|
||||
async getProfile(hashedUserId, requestingUserId) {
|
||||
@@ -48,16 +55,18 @@ class SocialNetworkService extends BaseService {
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
console.log('given data', data, folderId);
|
||||
const parentFolder = data.parentId ? await Folder.findOne({
|
||||
where: { id: data.parentId, userId: user.id }
|
||||
}) : null;
|
||||
if (data.parentId && !parentFolder) {
|
||||
throw new Error('Parent folder not found');
|
||||
}
|
||||
console.log('parentFolder', parentFolder);
|
||||
let newFolder;
|
||||
if (folderId === 0) {
|
||||
if (parentFolder) {
|
||||
newFolder = await Folder.create({
|
||||
parentId: data.parentId || null,
|
||||
parentId: parentFolder.id || null,
|
||||
userId: user.id,
|
||||
name: data.name
|
||||
});
|
||||
@@ -267,7 +276,8 @@ class SocialNetworkService extends BaseService {
|
||||
}
|
||||
|
||||
async loadUserByHash(hashedId) {
|
||||
return await User.findOne({ hashedId });
|
||||
console.log('Loading user by hashedId:', hashedId);
|
||||
return await User.findOne({ where: { hashedId: hashedId } });
|
||||
}
|
||||
|
||||
async loadUserByName(userName) {
|
||||
@@ -300,10 +310,10 @@ class SocialNetworkService extends BaseService {
|
||||
];
|
||||
}
|
||||
|
||||
filterUsersByCriteria(users, ageFrom, ageTo, genders) {
|
||||
async filterUsersByCriteria(users, ageFrom, ageTo, genders) {
|
||||
const results = [];
|
||||
for (const user of users) {
|
||||
const userDetails = this.extractUserDetails(user);
|
||||
const userDetails = await this.extractUserDetails(user);
|
||||
if (this.isUserValid(userDetails, ageFrom, ageTo, genders)) {
|
||||
results.push(userDetails);
|
||||
}
|
||||
@@ -311,11 +321,11 @@ class SocialNetworkService extends BaseService {
|
||||
return results;
|
||||
}
|
||||
|
||||
extractUserDetails(user) {
|
||||
async 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;
|
||||
const gender = genderParam ? await this.getGenderValue(genderParam.value) : null;
|
||||
return {
|
||||
id: user.hashedId,
|
||||
username: user.username,
|
||||
@@ -735,8 +745,9 @@ class SocialNetworkService extends BaseService {
|
||||
}
|
||||
|
||||
async addFriend(hashedUserid, friendUserid) {
|
||||
console.log('--------', friendUserid, hashedUserid);
|
||||
const requestingUserId = await this.checkUserAccess(hashedUserid);
|
||||
const friend = await this.loadUserByHash(friendUserid);
|
||||
const friend = await User.findOne({ where: { hashedId: friendUserid } });
|
||||
if (!friend) {
|
||||
throw new Error('notfound');
|
||||
}
|
||||
@@ -748,10 +759,10 @@ class SocialNetworkService extends BaseService {
|
||||
]
|
||||
}
|
||||
});
|
||||
console.log('friendship', friend, requestingUserId);
|
||||
if (friendship) {
|
||||
if (friendship.withdrawn) {
|
||||
friendship.withdrawn = false;
|
||||
|
||||
if (friendship.withdrawn && friendship.user1Id === requestingUserId) {
|
||||
friendship.update({ withdrawn: false });
|
||||
} else {
|
||||
throw new Error('alreadyexists');
|
||||
}
|
||||
@@ -811,5 +822,37 @@ class SocialNetworkService extends BaseService {
|
||||
throw new Error('notfound');
|
||||
}
|
||||
}
|
||||
|
||||
async getLoggedInFriends(hashedUserId) {
|
||||
const userId = await this.checkUserAccess(hashedUserId);
|
||||
const activeFriendships = await Friendship.findAll({
|
||||
where: {
|
||||
accepted: true,
|
||||
denied: false,
|
||||
withdrawn: false,
|
||||
[Op.or]: [
|
||||
{ user1Id: userId },
|
||||
{ user2Id: userId }
|
||||
]
|
||||
}
|
||||
});
|
||||
const friendIds = activeFriendships.map(friendship =>
|
||||
friendship.user1Id === userId ? friendship.user2Id : friendship.user1Id
|
||||
);
|
||||
const loggedInFriends = [];
|
||||
for (const friendId of friendIds) {
|
||||
const session = await getUserSession(friendId);
|
||||
if (session && session.id) {
|
||||
const friend = await User.findOne({ where: { hashedId: session.id } });
|
||||
if (friend) {
|
||||
loggedInFriends.push({
|
||||
id: friend.hashedId,
|
||||
username: friend.username,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return loggedInFriends;
|
||||
}
|
||||
}
|
||||
export default SocialNetworkService;
|
||||
|
||||
39
backend/services/webSocketService.js
Normal file
39
backend/services/webSocketService.js
Normal file
@@ -0,0 +1,39 @@
|
||||
// services/webSocketService.js
|
||||
import { Server } from 'socket.io';
|
||||
import amqp from 'amqplib/callback_api.js';
|
||||
|
||||
const RABBITMQ_URL = 'amqp://localhost';
|
||||
const QUEUE = 'chat_messages';
|
||||
|
||||
export function setupWebSocket(server) {
|
||||
const io = new Server(server);
|
||||
|
||||
amqp.connect(RABBITMQ_URL, (err, connection) => {
|
||||
if (err) throw err;
|
||||
|
||||
connection.createChannel((err, channel) => {
|
||||
if (err) throw err;
|
||||
|
||||
channel.assertQueue(QUEUE, { durable: false });
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
console.log('Client connected via WebSocket');
|
||||
|
||||
// Konsumiert Nachrichten aus RabbitMQ und sendet sie an den WebSocket-Client
|
||||
channel.consume(QUEUE, (msg) => {
|
||||
const message = JSON.parse(msg.content.toString());
|
||||
io.emit('newMessage', message); // Broadcast an alle Clients
|
||||
}, { noAck: true });
|
||||
|
||||
// Empfangt eine Nachricht vom WebSocket-Client und sendet sie an die RabbitMQ-Warteschlange
|
||||
socket.on('newMessage', (message) => {
|
||||
channel.sendToQueue(QUEUE, Buffer.from(JSON.stringify(message)));
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log('Client disconnected');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user