Skip to content
Snippets Groups Projects
Forked from an inaccessible project.
resolvers.ts 27.35 KiB
/**
 * @file Résolveurs des requêtes GraphQL.
 * @author akka vodol, ofacklam
 * @memberof GraphQL
 * @desc On ne définit dans ce fichier que les resolvers pour les types Query et Mutations. 
 * En effet on exploite les default resolvers fournis par Apollo Server (le deuxième point) :
 * 
 * > Explicit resolvers are not needed for every type, since Apollo Server provides a default that can perform two actions depending on the contents of parent:
 * > - Return the property from parent with the relevant field name
 * > - Calls a function on parent with the relevant field name and provide the remaining resolver parameters as arguments
 * https://www.apollographql.com/docs/apollo-server/v2/essentials/data.html#default
 *
 * Dans notre cas, le type de retour de chaque resolver est un objet JS (Group, Message, Request ou User)
 * défini dans un des fichiers de `./object_resolvers/` ; donc les méthodes des classes Group, Message, Request et User
 * dont le prototype est (parent, args, context: Context, info) sont utilisées comme resolvers de l'objet GraphQL respectif.
 */

import { AuthenticationError } from "apollo-server-core";
import { Context } from "./typeDefs/queries";
import { User } from "./object_resolvers/users";
import { Group, SimpleGroup, MetaGroup } from "./object_resolvers/groups";
import { Announcement, Event, PrivatePost, Question, Answer, Message } from "./object_resolvers/messages";
import { UserJoinGroup, GroupJoinMetagroup, GroupCoauthorEvent, Request } from "./object_resolvers/requests";
import { GroupCollection, GroupSet } from "./models/tools";

export const resolvers = {
    Query: {

        // User queries de base
        // @rights connectedOrOnplatal
        user: async function (root, args, context: Context): Promise<User> {
            if(context.models.auth.isConnectedOrOnplatal()) {
                return context.models.user.getUser(args.uid);
            }
            throw new AuthenticationError("Not connected or on-platal");
        },

        // Group queries de base
        // @rights connectedOrOnplatal
        group: async function (root, args, context: Context): Promise<Group> {
            if (context.models.auth.isConnectedOrOnplatal()) {
                return context.models.group.getGroup(args.gid);
            }
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights connectedOrOnplatal
        simpleGroup: async function (obj, args, context: Context): Promise<SimpleGroup> {
            if (context.models.auth.isConnectedOrOnplatal()) {
                return context.models.group.getSimpleGroup(args.gid);
            }
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights connectedOrOnplatal
        metaGroup: async function (obj, args, context: Context): Promise<MetaGroup> {
            if (context.models.auth.isConnectedOrOnplatal()) {
                return context.models.group.getMetaGroup(args.gid);
            }
            throw new AuthenticationError("Not connected or on-platal");
        },

        // Message queries de base
        //message -> not implemented -> message(mid: ID!): Message

        // @rights membre d'un groupe author ou d'un groupe recipient
        announcement: async function (root, args, context: Context): Promise<Announcement> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.message.getAnnouncement(args.mid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights membre d'un groupe author ou d'un groupe recipient
        event: async function (root, args, context: Context): Promise<Event> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.message.getEvent(args.mid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights membre du groupe recipient
        privatePost: async function (root, args, context: Context): Promise<PrivatePost> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.message.getPrivatePost(args.mid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights viewer du groupe recipient
        question: async function (root, args, context: Context): Promise<Question> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.message.getQuestion(args.mid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights viewer du groupe author
        answer: async function (root, args, context: Context): Promise<Answer> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.message.getAnswer(args.mid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // Request queries de base
        //request -> not implemented -> request(rid: ID!): Request

        // @rights admin du groupe destinaire ou le user émetteur
        userJoinGroupRequest: async function (root, args, context: Context): Promise<UserJoinGroup> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.request.getUserJoinGroupRequest(args.rid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights admin du groupe émetteur ou destinataire
        groupJoinMetagroupRequest: async function (root, args, context: Context): Promise<GroupJoinMetagroup> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.request.getGroupJoinMetagroupRequest(args.rid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // @rights admin du groupe émetteur ou destinataire
        groupCoauthorEventRequest: async function (root, args, context: Context): Promise<GroupCoauthorEvent> {
            //TODO : verifier les autorisations
            throw "Not implemented";
            return context.models.request.getGroupCoauthorEventRequest(args.rid);
            throw new AuthenticationError("Not connected or on-platal");
        },

        // Tous les Messages visibles par un utilisateur(dont le uid, et donc les autorisations, est passé par context)
        // @rights member of groups
        allMessages: async function (root, args, context: Context): Promise<Message[]> {
            let groups = context.models.auth.groupsMember();
            return context.models.message.getAllMessages(groups);
        },

        // @rights member of groups
        allAnnouncements: async function (root, args, context: Context): Promise<Announcement[]> {
            let groups = context.models.auth.groupsMember();
            return context.models.message.getAllAnnouncements(groups);
        },

        // @rights member of groups
        allEvents: async function (root, args, context: Context): Promise<Event[]> {
            let groups = context.models.auth.groupsMember();
            return context.models.message.getAllEvents(groups);
        },

        // @rights member of groups
        allPrivatePosts: async function (root, args, context: Context): Promise<PrivatePost[]> {
            let groups = context.models.auth.groupsMember();
            return context.models.message.getAllPrivatePosts(groups);
        },

        // Tous les Groupes visibles par un utilisateur.
        // Correspondrait au sous - champ "viewerOf" de User, volontairement non - défini comme tel.Tous les autres cas de figure sont couverts par les sous - champs "<permission>Of" de User
        // @rights viewer of groups
        allGroups: async function (root, args, context: Context): Promise<Group[]> {
            let visibleGroupCollection = context.models.auth.groupsViewer();
            return context.models.group.getAllGroupsByCollection(visibleGroupCollection);
        },

        // @rights viewer of groups
        allSimpleGroups: async function (root, args, context: Context): Promise<SimpleGroup[]> {
            let visibleGroupCollection = context.models.auth.groupsViewer();
            return context.models.group.getAllSimpleGroups(visibleGroupCollection.simpleGroups);
        },

        // TOL
        // @rights connectedOrOnplatal
        searchTOL: async function (root, args, context: Context): Promise<User[]> {
            if (context.models.auth.isConnectedOrOnplatal()) {
                return context.models.user.searchTOL(args);
            }
            throw new AuthenticationError("Not connected or on-platal");
        }
    },

    Mutation: {

        // Groups - independent mutations
        // @rights authenticated
        editProfile: async function (root, args, context: Context): Promise<User> {
            if(context.models.auth.isAuthenticated()) {
                return context.models.user.editProfile(args);
            }
            throw new AuthenticationError("Not authenticated");
        },

        // Viewer mutations
        // @rights viewer
        likeGroup: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isViewer(args.gid)) {
                return context.models.group.likeGroup(args.gid)
            }
            throw new AuthenticationError("Not a viewer");
        },

        // @rights viewer
        unlikeGroup: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isViewer(args.gid)) {
                return context.models.group.unlikeGroup(args.gid)
            }
            throw new AuthenticationError("Not a viewer");
        },

        // @rights member d'un groupe author ou recipient
        userParticipate: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            return context.models.message.userParticipate(context.user.uid, args.forEvent);
            throw new AuthenticationError("Not a viewer");
        },

        // @rights member d'un groupe author ou recipient
        userUnparticipate: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            return context.models.message.userUnparticipate(context.user.uid, args.forEvent);
            throw new AuthenticationError("Not a viewer");
        },

        // @rights viewer
        userRequestJoinGroup: async function (root, args, context: Context): Promise<UserJoinGroup> {
            if(context.models.auth.isViewer(args.toGroup)) {
                return context.models.request.userRequestJoinGroup(args.toGroup, args.comment);
            }
            throw new AuthenticationError("Not a viewer");
        },

        // @rights viewer
        createQuestion: async function (root, args, context: Context): Promise<Question> {
            if (context.models.auth.isViewer(args.toGroup)) {
                return context.models.message.createQuestion(args.toGroup, args.title, args.content);
            }
            throw new AuthenticationError("Not a viewer");
        },

        // @rights viewer du groupe et author de la question
        editQuestion: async function (root, args, context: Context): Promise<Question> {
            throw "Not implemented";
            // TODO : Vérifier qu'il est l'auteur de la question et viewer
            return context.models.message.editQuestion(args.questionToEdit, args.title, args.content);
            throw new AuthenticationError("Not a viewer");
        },

        // @rights viewer du groupe et author de la question
        removeQuestion: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            // TODO : Vérifier qu'il est l'auteur de la question et viewer
            return context.models.message.removeQuestion(args.questionToRemove);
            throw new AuthenticationError("Not a viewer");
        },

        // Member mutations
        // @rights member
        userLeaveGroup: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isMember(args.gid)) {
                return context.models.group.userLeaveGroup(args.gid);
            }
            throw new AuthenticationError("Not a member");
        },

        // @rights member
        createPrivatePost: async function (root, args, context: Context): Promise<PrivatePost> {
            if (context.models.auth.isMember(args.toGroup)) {
                return context.models.message.createPrivatePost(args.toGroup, args.title, args.content);
            }
            throw new AuthenticationError("Not a member");
        },

        // @rights member du groupe et author du post
        editPrivatePost: async function (root, args, context: Context): Promise<PrivatePost> {
            throw "Not implemented";
            // TODO : Vérifier qu'il est l'auteur du post et member
            return context.models.message.editPrivatePost(args.privatePostToEdit, args.title, args.content);
            throw new AuthenticationError("Not a member");
        },

        // @rights member du groupe et author du post
        removePrivatePost: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            // TODO : Vérifier qu'il est l'auteur du post et member
            return context.models.message.removePrivatePost(args.privatePostToRemove);
            throw new AuthenticationError("Not a member");
        },

        // Speaker mutations
        // @rights speaker
        writePostsSummary: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isSpeaker(args.forGroup)) {
                return context.models.group.writePostsSummary(args.forGroup, args.content);
            }
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker
        groupParticipate: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isSpeaker(args.gid)) {
                return context.models.message.groupParticipate(args.gid, args.forEvent);
            }
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker
        groupUnparticipate: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isSpeaker(args.gid)) {
                return context.models.message.groupUnparticipate(args.gid, args.forEvent);
            }
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe émetteur
        groupRequestCoauthorEvent: async function (root, args, context: Context): Promise<GroupCoauthorEvent> {
            if (context.models.auth.isSpeaker(args.fromGroup)) {
                return context.models.request.groupRequestCoauthorEvent(args.fromGroup, args.toGroup, args.forEvent, args.comment);
            }
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe émetteur
        createAnnouncement: async function (root, args, context: Context): Promise<Announcement> {
            if (context.models.auth.isSpeaker(args.fromGroup)) {
                return context.models.message.createAnnouncement(args.fromGroup, new GroupSet(args.toGroups), args.title, args.content, args.forEvent);
            }
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe émetteur
        editAnnouncement: async function (root, args, context: Context): Promise<Announcement> {
            throw "Not implemented";
            // TODO : Vérifier les autorisations.
            return context.models.message.editAnnouncement(args.announcementToEdit, args.title, args.content, args.forEvent);
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe émetteur
        removeAnnouncement: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            // TODO : Vérifier les autorisations
            return context.models.message.removeAnnouncement(args.announcementToRemove);
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe émetteur
        createEvent: async function (root, args, context: Context): Promise<Event> {
            if (context.models.auth.isSpeaker(args.fromGroup)) {
                return context.models.message.createEvent(args.fromGroup,
                    new GroupSet(args.toGroups), 
                    args.title, 
                    args.content, 
                    args.location, 
                    args.startTime, 
                    args.endTime, 
                    args.forAnnouncement);
            }
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe émetteur
        editEvent: async function (root, args, context: Context): Promise<Event> {
            throw "Not implemented";
            // TODO : Vérifier les autorisations.
            return context.models.message.editEvent(args.eventToEdit,
                args.title,
                args.content,
                args.location,
                args.startTime,
                args.endTime,
                args.forAnnouncement);
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe émetteur
        removeEvent: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            // TODO : Vérifier les autorisations
            return context.models.message.removeEvent(args.eventToRemove);
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe
        createAnswer: async function (root, args, context: Context): Promise<Answer> {
            throw "Not implemented";
            // TODO : Vérifier les autorisations.
            return context.models.message.createAnswer(args.forQuestion, args.title, args.content);
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe
        editAnswer: async function (root, args, context: Context): Promise<Answer> {
            throw "Not implemented";
            // TODO : Vérifier les autorisations.
            return context.models.message.editAnswer(args.answerToEdit, args.title, args.content);
            throw new AuthenticationError("Not a speaker");
        },

        // @rights speaker du groupe
        removeAnswer: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            // TODO : Vérifier les autorisations
            return context.models.message.removeAnswer(args.answerToRemove);
            throw new AuthenticationError("Not a speaker");
        },

        // Admin mutations
        // @rights admin of parent group
        createSubgroup: async function (root, args, context: Context): Promise<Group> {
            if(context.models.auth.isAdmin(args.fromGroup)) {
                return context.models.group.createSubgroup(args);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        makeAdmin: async function (root, args, context: Context): Promise<User> {
            if (context.models.auth.isAdmin(args.forGroup)) {
                return context.models.group.makeAdmin(args.forGroup, args.uid);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        unmakeAdmin: async function (root, args, context: Context): Promise<User> {
            if (context.models.auth.isAdmin(args.forGroup)) {
                return context.models.group.unmakeAdmin(args.forGroup, args.uid);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        makeSpeaker: async function (root, args, context: Context): Promise<User> {
            if (context.models.auth.isAdmin(args.forGroup)) {
                return context.models.group.makeSpeaker(args.forGroup, args.uid);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        unmakeSpeaker: async function (root, args, context: Context): Promise<User> {
            if (context.models.auth.isAdmin(args.forGroup)) {
                return context.models.group.unmakeSpeaker(args.forGroup, args.uid);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        editGroup: async function (root, args, context: Context): Promise<Group> {
            if (context.models.auth.isAdmin(args.forGroup)) {
                return context.models.group.editGroup(args);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        addVisibilityEdge: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isAdmin(args.forGroup)) {
                return context.models.group.addVisibilityEdge(args.forGroup, args.visibleBy);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        removeVisibilityEdge: async function (root, args, context: Context): Promise<boolean> {
            if (context.models.auth.isAdmin(args.forGroup)) {
                return context.models.group.removeVisibilityEdge(args.forGroup, args.visibleBy);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe émetteur
        groupRequestJoinMetagroup: async function (root, args, context: Context): Promise<GroupJoinMetagroup> {
            if (context.models.auth.isAdmin(args.fromGroup)) {
                return context.models.request.groupRequestJoinMetagroup(args.fromGroup, args.toMetagroup, args.comment);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe destinataire
        acceptUserJoinRequest: async function (root, args, context: Context): Promise<boolean> {
            let req = await UserJoinGroup.tryCreate(args.request);
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            //if (context.models.auth.isAdmin(req.to)) {
                return context.models.request.acceptUserJoinRequest(req, args.comment);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe destinataire
        acceptGroupJoinRequest: async function (root, args, context: Context): Promise<boolean> {
            let req = await GroupJoinMetagroup.tryCreate(args.request);
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            //if (context.models.auth.isAdmin(req.to)) {
            return context.models.request.acceptGroupJoinRequest(req, args.comment);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe destinataire
        refuseUserJoinRequest: async function (root, args, context: Context): Promise<boolean> {
            let req = await UserJoinGroup.tryCreate(args.request);
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            //if (context.models.auth.isAdmin(req.to)) {
            return context.models.request.refuseUserJoinRequest(req, args.comment);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe destinataire
        refuseGroupJoinRequest: async function (root, args, context: Context): Promise<boolean> {
            let req = await GroupJoinMetagroup.tryCreate(args.request);
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            //if (context.models.auth.isAdmin(req.to)) {
            return context.models.request.refuseGroupJoinRequest(req, args.comment);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin
        removeUser: async function (root, args, context: Context): Promise<User> {
            if(context.models.auth.isAdmin(args.fromGroup)) {
                return context.models.group.removeUser(args.fromGroup, args.uid);
            }
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe destinataire
        acceptGroupCoauthorEventRequest: async function (root, args, context: Context): Promise<boolean> {
            // Pour l'instant, ce n'est pas a implémenter...
            let req = await GroupCoauthorEvent.tryCreate(args.request);
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            //if (context.models.auth.isAdmin(req.to)) {
            return context.models.request.acceptGroupCoauthorEventRequest(req, args.comment);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe destinataire
        refuseGroupCoauthorEventRequest: async function (root, args, context: Context): Promise<boolean> {
            // Pour l'instant, ce n'est pas a implémenter...
            let req = await GroupCoauthorEvent.tryCreate(args.request);
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            //if (context.models.auth.isAdmin(req.to)) {
            return context.models.request.refuseGroupCoauthorEventRequest(req, args.comment);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe
        censorQuestion: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            return context.models.message.censorQuestion(args.questionToCensor);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe
        censorAnswer: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            return context.models.message.censorAnswer(args.answerToCensor);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin du groupe
        censorPrivatePost: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            return context.models.message.censorPrivatePost(args.privatePostToCensor);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin d'un groupe author
        censorAnnouncement: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            return context.models.message.censorAnnouncement(args.announcementToCensor);
            throw new AuthenticationError("Not an admin");
        },

        // @rights admin d'un groupe author
        censorEvent: async function (root, args, context: Context): Promise<boolean> {
            throw "Not implemented";
            //TODO : Vérifier les autorisations
            return context.models.message.censorEvent(args.eventToCensor);
            throw new AuthenticationError("Not an admin");
        }
    }
};