import { API_ERROR } from "../../controllers/errors.js"; import type { Community, Invite, User } from "../../generated/prisma/client.js"; import { getDB } from "../../store/store.js"; import { getUserFromAuth, isUserAllowed, isUserOwnerOrAdmin, } from "../auth/helpers.js"; import { PERMISSION } from "../auth/permission.js"; import { getChannelById } from "../channel/channel.js"; import { getRoleById } from "../role/role.js"; import { getUserIdsInCommunity } from "../user/user.js"; import { SocketMessageTypes } from "../websocket/types.js"; import { sendMessageToUsersWS } from "../websocket/websocket.js"; import type { ICreateCommunity, IUpdateCommunity, ICommunityChannel, ICommunityMember, ICommunityRole, ICreateInvite, } from "./types.js"; const getCommunityById = async (id: string): Promise => { return await getDB().community.findUnique({ where: { id: id }, }); }; const createCommunity = async ( ownerId: string, create: ICreateCommunity, ): Promise => { return await getDB().community.create({ data: { ownerId: ownerId, ...create, members: { connect: { id: ownerId, }, }, }, }); }; const createCommunityAuth = async ( create: ICreateCommunity, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); if (!authUser) { return API_ERROR.ACCESS_DENIED; } return await createCommunity(authUser.id, create); }; const updateCommunityById = async ( id: string, update: IUpdateCommunity, ): Promise => { const updatedCommunity = await getDB().community.update({ where: { id: id, }, data: { ...update, }, }); const userIds = await getUserIdsInCommunity(id); sendMessageToUsersWS(userIds, { type: SocketMessageTypes.UPDATE_COMMUNITY, payload: { communityId: id, }, }); return updatedCommunity; }; const updateCommunityByIdAuth = async ( id: string, update: IUpdateCommunity, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.COMMUNITY_MANAGE], )) ) { return API_ERROR.ACCESS_DENIED; } return await updateCommunityById(id, update); }; const deleteCommunityById = async (id: string): Promise => { return await getDB().community.delete({ where: { id: id }, }); }; const deleteCommunityByIdAuth = async ( id: string, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserOwnerOrAdmin(authUser, { community: community, })) ) { return API_ERROR.ACCESS_DENIED; } return await deleteCommunityById(id); }; const getCommunityMembersById = async ( id: string, ): Promise => { return await getDB().user.findMany({ where: { communities: { some: { id: id, }, }, }, select: { id: true, username: true, nickname: true, avatar: true, }, }); }; const getCommunityMembersByIdAuth = async ( id: string, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.MEMBERS_READ], )) ) { return API_ERROR.ACCESS_DENIED; } return await getCommunityMembersById(id); }; const getCommunityChannelsById = async ( id: string, ): Promise => { return await getDB().channel.findMany({ where: { communityId: id, }, select: { id: true, name: true, description: true, category: true, order: true, }, }); }; const getCommunityChannelsByIdAuth = async ( id: string, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.CHANNELS_READ], )) ) { return API_ERROR.ACCESS_DENIED; } return await getCommunityChannelsById(id); }; const getCommunityRolesById = async (id: string): Promise => { return await getDB().role.findMany({ where: { communityId: id, }, select: { id: true, name: true, color: true, order: true, showInMembers: true, }, }); }; const getCommunityRolesByIdAuth = async ( id: string, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.ROLES_READ], )) ) { return API_ERROR.ACCESS_DENIED; } return await getCommunityRolesById(id); }; const getCommunityInvitesById = async (id: string): Promise => { return await getDB().invite.findMany({ where: { communityId: id, }, }); }; const getCommunityInvitesByIdAuth = async ( id: string, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.INVITES_READ], )) ) { return API_ERROR.ACCESS_DENIED; } return await getCommunityInvitesById(id); }; const updateCommunityChannelOrderById = async (id: string, order: string[]) => { for (let i = 0; i < order.length; i++) { const channelId = order[i]; if (!channelId) { continue; } const channel = await getChannelById(channelId); if (channel?.communityId !== id) { continue; } await getDB().channel.update({ where: { id: channelId, }, data: { order: i, }, }); } const userIds = await getUserIdsInCommunity(id); sendMessageToUsersWS(userIds, { type: SocketMessageTypes.UPDATE_CHANNELS, payload: { communityId: id, }, }); }; const updateCommunityChannelOrderByIdAuth = async ( id: string, order: string[], authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.CHANNELS_MANAGE], )) ) { return API_ERROR.ACCESS_DENIED; } await updateCommunityChannelOrderById(id, order); }; const updateCommunityRoleOrderById = async (id: string, order: string[]) => { for (let i = 0; i < order.length; i++) { const roleId = order[i]; if (!roleId) { continue; } const role = await getRoleById(roleId); if (role?.communityId !== id) { continue; } await getDB().role.update({ where: { id: roleId, }, data: { order: i, }, }); } const userIds = await getUserIdsInCommunity(id); sendMessageToUsersWS(userIds, { type: SocketMessageTypes.UPDATE_ROLES, payload: { communityId: id, }, }); }; const updateCommunityRoleOrderByIdAuth = async ( id: string, order: string[], authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.ROLES_MANAGE], )) ) { return API_ERROR.ACCESS_DENIED; } await updateCommunityRoleOrderById(id, order); }; const createInvite = async ( id: string, creatorId: string, createInviteData: ICreateInvite, ): Promise => { return await getDB().invite.create({ data: { ...createInviteData, creatorId: creatorId, communityId: id, }, }); }; const createInviteAuth = async ( id: string, createInviteData: ICreateInvite, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !authUser || !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.INVITES_CREATE], )) ) { return API_ERROR.ACCESS_DENIED; } return await createInvite(id, authUser.id, createInviteData); }; const deleteMemberById = async ( id: string, memberId: string, ): Promise => { const updatedCommunity = await getDB().community.update({ where: { id: id, }, data: { members: { disconnect: { id: memberId, }, }, }, }); const userIds = await getUserIdsInCommunity(updatedCommunity.id); sendMessageToUsersWS(userIds, { type: SocketMessageTypes.UPDATE_MEMBERS, payload: { communityId: updatedCommunity.id, }, }); return updatedCommunity; }; const deleteMemberByIdAuth = async ( id: string, memberId: string, authHeader: string | undefined, ): Promise => { const authUser = await getUserFromAuth(authHeader); const community = await getCommunityById(id); if ( !(await isUserAllowed( authUser, { community: community, }, community, [PERMISSION.MEMBERS_KICK], )) && authUser?.id !== memberId ) { return API_ERROR.ACCESS_DENIED; } return await deleteMemberById(id, memberId); }; export { getCommunityById, createCommunity, createCommunityAuth, updateCommunityById, updateCommunityByIdAuth, deleteCommunityById, deleteCommunityByIdAuth, getCommunityMembersById, getCommunityMembersByIdAuth, getCommunityChannelsById, getCommunityChannelsByIdAuth, getCommunityRolesById, getCommunityRolesByIdAuth, getCommunityInvitesById, getCommunityInvitesByIdAuth, updateCommunityChannelOrderById, updateCommunityChannelOrderByIdAuth, updateCommunityRoleOrderById, updateCommunityRoleOrderByIdAuth, createInvite, createInviteAuth, deleteMemberById, deleteMemberByIdAuth, };