281 lines
9.7 KiB
JavaScript
281 lines
9.7 KiB
JavaScript
import BaseService from './BaseService.js';
|
|
import Forum from '../models/forum/forum.js';
|
|
import ForumPermission from '../models/forum/forum_permission.js';
|
|
import ForumUserPermission from '../models/forum/forum_user_permission.js';
|
|
import UserRight from '../models/community/user_right.js';
|
|
import UserRightType from '../models/type/user_right.js';
|
|
import { Op } from 'sequelize';
|
|
import { sequelize } from '../utils/sequelize.js';
|
|
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';
|
|
|
|
class ForumService extends BaseService {
|
|
|
|
async createForum(hashedUserId, name, permissions) {
|
|
const user = await this.getUserByHashedId(hashedUserId);
|
|
const isAdmin = await this.hasUserRight(user.id, ['mainadmin', 'forum']);
|
|
if (!isAdmin) {
|
|
throw new Error('Access denied: Only admins can create forums.');
|
|
}
|
|
const newForum = await Forum.create({ name });
|
|
if (permissions && permissions.length > 0) {
|
|
for (const permission of permissions) {
|
|
const forumPermission = await ForumPermission.findOne({
|
|
where: { name: permission.value }
|
|
});
|
|
if (forumPermission) {
|
|
await newForum.addAssociatedPermissions(forumPermission);
|
|
}
|
|
}
|
|
}
|
|
return newForum;
|
|
}
|
|
|
|
async deleteForum(hashedUserId, forumId) {
|
|
const user = await this.getUserByHashedId(hashedUserId);
|
|
const isAdmin = await this.hasUserRight(user.id, ['mainadmin', 'forum']);
|
|
if (!isAdmin) {
|
|
throw new Error('Access denied: Only admins can delete forums.');
|
|
}
|
|
const forum = await Forum.findByPk(forumId);
|
|
if (!forum) {
|
|
throw new Error('Forum not found.');
|
|
}
|
|
const transaction = await sequelize.transaction();
|
|
try {
|
|
const forumFormRights = await ForumForumPermission.findAll({
|
|
where: { forumId: forumId }
|
|
});
|
|
for (const forumFormRight of forumFormRights) {
|
|
await forumFormRight.destroy({ transaction });
|
|
}
|
|
const forumUserRights = await ForumUserPermission.findAll({
|
|
where: { forumId: forumId }
|
|
});
|
|
for (const forumUserRight of forumUserRights) {
|
|
await forumUserRight.destroy({ transaction });
|
|
}
|
|
await forum.destroy({ transaction });
|
|
|
|
await transaction.commit();
|
|
return forum;
|
|
} catch (error) {
|
|
await transaction.rollback();
|
|
throw new Error(`Error deleting forum: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
async getAllForums(hashedUserId) {
|
|
const user = await this.getUserByHashedId(hashedUserId);
|
|
if (!user) throw new Error('User not found.');
|
|
const forums = await Forum.findAll({
|
|
include: [
|
|
{
|
|
model: ForumPermission,
|
|
as: 'associatedPermissions',
|
|
},
|
|
{
|
|
model: ForumUserPermission,
|
|
as: 'userPermissions',
|
|
}
|
|
]
|
|
});
|
|
const accessibleForums = [];
|
|
for (const forum of forums) {
|
|
const hasAccess = await this.checkForumAccess(forum, user);
|
|
if (hasAccess) {
|
|
accessibleForums.push(forum);
|
|
}
|
|
}
|
|
return accessibleForums;
|
|
}
|
|
|
|
async getForum(hashedUserId, forumId, page) {
|
|
const user = await this.getUserByHashedId(hashedUserId);
|
|
if (!user) throw new Error('User not found.');
|
|
const forum = await Forum.findByPk(forumId, {
|
|
include: [
|
|
{
|
|
model: ForumPermission,
|
|
as: 'associatedPermissions',
|
|
},
|
|
{
|
|
model: ForumUserPermission,
|
|
as: 'userPermissions',
|
|
}
|
|
]
|
|
});
|
|
const hasAccess = await this.checkForumAccess(forum, user);
|
|
if (!hasAccess) {
|
|
throw new Error('Access denied.');
|
|
}
|
|
const titlesRaw = await Title.findAll({
|
|
where: {
|
|
forumId
|
|
},
|
|
attributes: [
|
|
'id',
|
|
'title',
|
|
'createdBy',
|
|
'forumId',
|
|
'createdAt',
|
|
'updatedAt',
|
|
[sequelize.literal(`(SELECT COUNT(*) FROM forum.message WHERE message.title_id = title.id)`), 'messageCount'],
|
|
[sequelize.literal(`(SELECT MAX("created_at") FROM forum.message WHERE message.title_id = title.id)`), 'lastMessageDate']
|
|
],
|
|
include: [
|
|
{
|
|
model: User,
|
|
as: 'createdByUser',
|
|
attributes: ['id', 'username', 'hashedId']
|
|
},
|
|
{
|
|
model: Message,
|
|
as: 'messages',
|
|
attributes: [],
|
|
include: [
|
|
{
|
|
model: User,
|
|
as: 'lastMessageUser',
|
|
attributes: ['id', 'username']
|
|
}
|
|
]
|
|
}
|
|
],
|
|
offset: (page - 1) * 25,
|
|
limit: 25,
|
|
order: [
|
|
['createdAt', 'DESC']
|
|
],
|
|
group: [
|
|
'title.id',
|
|
'title.created_at',
|
|
]
|
|
});
|
|
const totalTopics = await Title.count({ where: { forumId } });
|
|
const titles = titlesRaw.map(title => ({
|
|
id: title.dataValues.id,
|
|
title: title.dataValues.title,
|
|
createdBy: title.createdByUser.username,
|
|
createdByHash: title.createdByUser.hashedId,
|
|
createdAt: title.dataValues.createdAt,
|
|
numberOfItems: title.dataValues.messageCount,
|
|
lastMessageDate: title.dataValues.lastMessageDate
|
|
}));
|
|
return {
|
|
name: forum.name,
|
|
titles,
|
|
page,
|
|
totalTopics,
|
|
};
|
|
}
|
|
|
|
async createTopic(hashedUserId, forumId, title, content) {
|
|
const user = await this.getUserByHashedId(hashedUserId);
|
|
if (!user) throw new Error('User not found.');
|
|
const forum = await Forum.findByPk(forumId, {
|
|
include: [
|
|
{
|
|
model: ForumPermission,
|
|
as: 'associatedPermissions',
|
|
},
|
|
{
|
|
model: ForumUserPermission,
|
|
as: 'userPermissions',
|
|
}
|
|
]
|
|
});
|
|
const hasAccess = await this.checkForumAccess(forum, user);
|
|
if (!hasAccess) {
|
|
throw new Error('Access denied.');
|
|
}
|
|
const newTopic = await Title.create({ title, forumId, createdBy: user.id });
|
|
await Message.create({ titleId: newTopic.id, text: content, createdBy: user.id})
|
|
return this.getForum(hashedUserId, forumId, 1);
|
|
}
|
|
|
|
async checkForumAccess(forum, user) {
|
|
console.log('[ForumService.checkForumAccess] - start');
|
|
const { age } = user;
|
|
console.log('[ForumService.checkForumAccess] - read user permissions');
|
|
const userPermission = await ForumUserPermission.findOne({
|
|
where: {
|
|
userId: user.id,
|
|
forumId: forum.id
|
|
}
|
|
});
|
|
if (userPermission) {
|
|
return true;
|
|
}
|
|
console.log('[ForumService.checkForumAccess] - read forum permissions');
|
|
const forumPermissions = await ForumForumPermission.findAll({
|
|
where: {
|
|
forumId: forum.id
|
|
}
|
|
});
|
|
console.log('[ForumService.checkForumAccess] - filter persmissions');
|
|
for (const permission of forumPermissions) {
|
|
if (permission.permission === 'age' && age >= parseInt(permission.value, 10)) {
|
|
return true;
|
|
}
|
|
if (permission.permission === 'all' || permission.permission === 'user') {
|
|
return true;
|
|
}
|
|
const userRight = await UserRight.findOne({
|
|
where: {
|
|
userId: user.id,
|
|
},
|
|
include: {
|
|
model: UserRightType,
|
|
as: 'rightType',
|
|
where: {
|
|
[Op.or]: [
|
|
{ title: 'mainadmin' },
|
|
{ title: 'forum' }
|
|
]
|
|
|
|
}
|
|
}
|
|
});
|
|
|
|
if (userRight) {
|
|
return true;
|
|
}
|
|
}
|
|
console.log('[ForumService.checkForumAccess] - not successful');
|
|
|
|
return false;
|
|
}
|
|
|
|
async setPermissions(forumId, permissions) {
|
|
if (permissions && Array.isArray(permissions)) {
|
|
for (const permission of permissions) {
|
|
await ForumPermission.create({
|
|
forumId,
|
|
permission: permission.type,
|
|
value: permission.value
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
async checkAdminRights(userId) {
|
|
const userRight = await UserRight.findOne({
|
|
where: { userId },
|
|
include: {
|
|
model: UserRightType,
|
|
as: 'rightType',
|
|
where: { title: ['mainadmin', 'forum'] }
|
|
}
|
|
});
|
|
|
|
if (!userRight) {
|
|
throw new Error('Unauthorized: Only admins can perform this action.');
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new ForumService();
|