212 lines
9.8 KiB
TypeScript
212 lines
9.8 KiB
TypeScript
import { Resolver, Query, FieldResolver, Root, Arg, Mutation, Ctx, Args, Authorized } from 'type-graphql';
|
|
|
|
import { addOneGeneric } from '@seed/graphql/BaseService';
|
|
import RoomModel, {
|
|
RoomArgs,
|
|
RemovePeopleFromRoomInput,
|
|
AddPeopleToRoomInput,
|
|
NewRoomInput,
|
|
} from '@services/api-messaging/functions/rooms/room.model';
|
|
import { ApolloContext } from '@seed/interfaces/context';
|
|
import { ApolloError } from 'apollo-server-lambda';
|
|
import AccountModel from '@src/accounts/account.model';
|
|
import { onCreate } from '@services/api-messaging/functions/rooms/room.model';
|
|
import _ from 'lodash';
|
|
import MessageModel, { MessageArgs } from '../messages/message.model';
|
|
import { oneToManyComplexity } from '@seed/graphql/Middleware';
|
|
import { UnreadCount } from '@services/api-messaging/components';
|
|
|
|
@Resolver(RoomModel)
|
|
export default class RoomResolver {
|
|
/*
|
|
███████╗██╗███████╗██╗ ██████╗ ███████╗
|
|
██╔════╝██║██╔════╝██║ ██╔══██╗██╔════╝
|
|
█████╗ ██║█████╗ ██║ ██║ ██║███████╗
|
|
██╔══╝ ██║██╔══╝ ██║ ██║ ██║╚════██║
|
|
██║ ██║███████╗███████╗██████╔╝███████║
|
|
╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝ ╚══════╝
|
|
*/
|
|
|
|
@FieldResolver()
|
|
async getAccounts(@Root() room: RoomModel, @Ctx() ctx: ApolloContext): Promise<(AccountModel | Error)[]> {
|
|
return await ctx.ctx.loaders.accountLoader.loadMany(room.r);
|
|
}
|
|
@FieldResolver(() => [MessageModel], { complexity: oneToManyComplexity })
|
|
async getMessages(@Args() args: MessageArgs, @Root() room: RoomModel, @Ctx() ctx: ApolloContext): Promise<MessageModel[]> {
|
|
try {
|
|
if (!args.pagination) args.pagination = { limit: 10, skip: 0, sort: 'createdAt desc' };
|
|
else if (args.pagination && !args.pagination.sort) args.pagination = { ...args.pagination, sort: 'createdAt desc' };
|
|
|
|
return new MessageModel().getMany({ roomId: room._id }, args.pagination, ctx);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/*
|
|
██████╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗
|
|
██╔═══██╗██║ ██║██╔════╝██╔══██╗╚██╗ ██╔╝
|
|
██║ ██║██║ ██║█████╗ ██████╔╝ ╚████╔╝
|
|
██║▄▄ ██║██║ ██║██╔══╝ ██╔══██╗ ╚██╔╝
|
|
╚██████╔╝╚██████╔╝███████╗██║ ██║ ██║
|
|
╚══▀▀═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝
|
|
*/
|
|
@Query(() => RoomModel)
|
|
@Authorized()
|
|
async roomsGetOne(@Arg('id') id: string, @Ctx() ctx: ApolloContext): Promise<RoomModel> {
|
|
const model = new RoomModel();
|
|
const roomData = await model.getOne({ _id: id }, ctx);
|
|
if (!roomData.r.includes(ctx.ctx.user._id))
|
|
throw new ApolloError('permissions.notAllowed', '400', { you: ctx.ctx.user._id, allowed: roomData.r });
|
|
|
|
return roomData;
|
|
}
|
|
|
|
@Query(() => [RoomModel])
|
|
@Authorized()
|
|
async roomsGetMany(@Args() args: RoomArgs, @Ctx() ctx: ApolloContext): Promise<RoomModel[]> {
|
|
const model = new RoomModel();
|
|
const result = await model.getMany({ accountIds: ctx.ctx.user._id }, args.pagination, ctx);
|
|
return result;
|
|
}
|
|
|
|
@Query(() => [MessageModel])
|
|
@Authorized()
|
|
async roomsGetMessages(@Arg('id') id: string, @Args() args: RoomArgs, @Ctx() ctx: ApolloContext): Promise<MessageModel[]> {
|
|
const model = new RoomModel();
|
|
const roomData = await model.getOne({ _id: id }, ctx);
|
|
if (!roomData.r.includes(ctx.ctx.user._id))
|
|
throw new ApolloError('permissions.notAllowed', '400', { you: ctx.ctx.user._id, allowed: roomData.r });
|
|
|
|
if (!args.pagination) args.pagination = { limit: 10, skip: 0, sort: 'createdAt desc' };
|
|
else if (args.pagination && !args.pagination.sort) args.pagination = { ...args.pagination, sort: 'createdAt desc' };
|
|
|
|
return new MessageModel().getMany({ roomId: id }, args.pagination, ctx);
|
|
}
|
|
|
|
/*
|
|
███╗ ███╗██╗ ██╗████████╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗
|
|
████╗ ████║██║ ██║╚══██╔══╝██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗██╔════╝
|
|
██╔████╔██║██║ ██║ ██║ ███████║ ██║ ██║ ██║██████╔╝███████╗
|
|
██║╚██╔╝██║██║ ██║ ██║ ██╔══██║ ██║ ██║ ██║██╔══██╗╚════██║
|
|
██║ ╚═╝ ██║╚██████╔╝ ██║ ██║ ██║ ██║ ╚██████╔╝██║ ██║███████║
|
|
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
|
*/
|
|
@Mutation(() => RoomModel)
|
|
@Authorized()
|
|
async roomsCreateOne(@Arg('input') input: NewRoomInput, @Ctx() ctx: ApolloContext): Promise<RoomModel> {
|
|
const model = new RoomModel();
|
|
|
|
try {
|
|
await onCreate(input, ctx);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
|
|
input.accountIds.push(ctx.ctx.user._id);
|
|
input.accountIds = _.uniq(input.accountIds);
|
|
|
|
// Check if a room with the same user doesn't exists already
|
|
|
|
try {
|
|
return await model.getOne(
|
|
{
|
|
r: { $all: input.accountIds },
|
|
},
|
|
ctx,
|
|
);
|
|
} catch (error) {
|
|
const unreadCounts: UnreadCount[] = [];
|
|
for (let index = 0; index < input.accountIds.length; index++) {
|
|
unreadCounts.push({
|
|
accountId: input.accountIds[index],
|
|
count: 0,
|
|
});
|
|
}
|
|
|
|
const dataToSave: Partial<RoomModel> = {
|
|
...input,
|
|
r: input.accountIds,
|
|
w: input.accountIds,
|
|
stats: {
|
|
unreadCounts: unreadCounts,
|
|
},
|
|
};
|
|
return addOneGeneric(model, dataToSave, ctx);
|
|
}
|
|
}
|
|
|
|
@Mutation(() => RoomModel)
|
|
@Authorized()
|
|
async roomsAddPeople(@Arg('input') input: AddPeopleToRoomInput, @Ctx() ctx: ApolloContext): Promise<RoomModel> {
|
|
const model = new RoomModel();
|
|
|
|
// Get the room first to see if allowed
|
|
const roomData = await model.getOne({ _id: input.roomId }, ctx);
|
|
if (!roomData.r.includes(ctx.ctx.user._id))
|
|
throw new ApolloError('permissions.notAllowed', '400', { you: ctx.ctx.user._id, allowed: roomData.r });
|
|
|
|
const newAccountIds = _.uniq(roomData.r.concat(input.accountIds));
|
|
|
|
try {
|
|
await onCreate(input, ctx);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
|
|
// TODO : Remove from stats
|
|
return roomData.updateOne({ _id: input.roomId }, { r: newAccountIds, w: newAccountIds }, ctx);
|
|
}
|
|
|
|
@Mutation(() => RoomModel)
|
|
@Authorized()
|
|
async roomsRemovePeople(@Arg('input') input: RemovePeopleFromRoomInput, @Ctx() ctx: ApolloContext): Promise<RoomModel> {
|
|
const model = new RoomModel();
|
|
|
|
// Get the room first to see if allowed
|
|
const roomData = await model.getOne({ _id: input.roomId }, ctx);
|
|
if (!roomData.r.includes(ctx.ctx.user._id))
|
|
throw new ApolloError('permissions.notAllowed', '400', { you: ctx.ctx.user._id, allowed: roomData.r });
|
|
|
|
const newAccountIds = _.uniq(
|
|
roomData.r.filter(function(element) {
|
|
return roomData.r.indexOf(element) === -1;
|
|
}),
|
|
);
|
|
|
|
// TODO : Remove from stats
|
|
|
|
return roomData.updateOne({ _id: input.roomId }, { r: newAccountIds, w: newAccountIds }, ctx);
|
|
}
|
|
|
|
@Mutation(() => RoomModel)
|
|
@Authorized()
|
|
async roomsMarkAllMessageAsRead(@Arg('roomId') roomId: string, @Ctx() ctx: ApolloContext): Promise<RoomModel> {
|
|
const roomModel = new RoomModel();
|
|
await roomModel.getOne({ _id: roomId }, ctx);
|
|
|
|
// The hypothesis here is that the message are accessible only by concerned people.
|
|
const model = new MessageModel();
|
|
await (await model.db()).updateMany(
|
|
{ roomId: roomId, 'readBy.accountId': { $ne: ctx.ctx.user._id } },
|
|
{
|
|
$push: { readBy: { accountId: ctx.ctx.user._id, readAt: new Date() } },
|
|
},
|
|
);
|
|
|
|
// Update stats & notify
|
|
for (let index = 0; index < roomModel.stats.unreadCounts.length; index++) {
|
|
// Add a count to all the other one
|
|
if (roomModel.stats.unreadCounts[index].accountId == ctx.ctx.user._id) roomModel.stats.unreadCounts[index].count = 0;
|
|
}
|
|
|
|
await (await roomModel.db()).findOneAndUpdate(
|
|
{ _id: roomModel._id },
|
|
{ $set: { stats: roomModel.stats } },
|
|
{ upsert: false, returnOriginal: false },
|
|
);
|
|
|
|
return roomModel;
|
|
}
|
|
}
|