/** * Namespace qui regroupe toutes les classes et toutes les fonctions qui permettent l'implémentation des resolvers du schéma GraphQL * @namespace GraphQL */ /** * @file Fonctions génériques de recherche dans la BDD et le LDAP réutilisables dans l'authorisation et/ou dans les resolvers * @author ofacklam * @memberof GraphQL */ import { User as UT, userData } from '../../ldap/export/user' import knex from '../../../db/knex_router'; export class GroupSet extends Set<string> { addList(l: string[]) { for(let elt of l) { this.add(elt); } } } export interface GroupCollection { simpleGroups: GroupSet, metaGroups: GroupSet } export class Tools { /** * @memberof GraphQL * @class Tools * @summary Outils intermédiaires LDAP / BDD. * @classdesc Cette classe contient des fonctions intermédiaires de recherche dans le LDAP / la BDD. */ constructor() { } /** * @memberof GraphQL * @summary Fonction qui escape l'id donné en argument * @arg {string} id - L'identifiant a escape. * @return {Promise(Group)} Renvoie l'identifiant escapé. * @static */ static escapeID(id: string) { return String(id).replace(' ', '_').replace(/\W/g, '').toLowerCase(); //the REGEXP matches all non-word characters (\W) in a global search (/../g) } /** * @memberof GraphQL * @summary Fonction qui renvoit l'union de deux ensembles * @arg {GroupSet} A - Le premier ensemble. * @arg {GroupSet} B - Le deuxieme ensemble. * @return {Promise(GroupSet)} Renvoie un nouveau GroupSet contenant l'union de A et B. * @static */ static union(A: GroupSet, B: GroupSet): GroupSet { let union = new GroupSet(A); for(let b of B) { union.add(b); } return union; } /** * @memberof GraphQL * @summary Fonction qui renvoit tous les groupes simples dont le user est membre. * @arg {userData} data - Données de l'utilisateur. * @return {Promise(GroupSet)} Renvoie un GroupSet contenant le nom des groupes simples. * @static * @async */ static async memberOfSimple(data: userData): Promise<GroupSet> { return new GroupSet(data.groups); } /** * @memberof GraphQL * @summary Fonction qui renvoit tous les groupes simples dont le user est speaker. * @arg {userData} data - Données de l'utilisateur. * @return {Promise(GroupSet)} Renvoie un GroupSet contenant le nom des groupes simples. * @static * @async */ static async speakerOfSimple(data: userData): Promise<GroupSet> { throw "Not implemented"; } /** * @memberof GraphQL * @summary Fonction qui renvoit tous les groupes simples dont le user est administrateur. * @arg {userData} data - Données de l'utilisateur. * @return {Promise(GroupSet)} Renvoie un GroupSet contenant le nom des groupes simples. * @static * @async */ static async adminOfSimple(data: userData): Promise<GroupSet> { return new GroupSet(data.groupsIsAdmin); } /** * @memberof GraphQL * @summary Fonction qui renvoit tous les méta-groupes dont ces groupes sont membres. * @arg {GroupSet} groups - Un ensemble de gid des groupes a considérer. * @return {Promise(GroupSet)} Renvoie un GroupSet contenant le nom des méta-groupes. * @static * @async */ static async metaGroupsOfGroups(groups: GroupSet): Promise<GroupSet> { let metas = await knex.select('meta_group_gid').from('metagroup_memberships').whereIn('simple_group_gid', groups); return new GroupSet(metas.map( elt => { return elt.meta_group_gid; })); } /** * @memberof GraphQL * @summary Fonction qui renvoit tous les groupes (simples ou méta) dont le user est membre. * @arg {userData} data - Données de l'utilisateur. * @return {Promise(GroupCollection)} Renvoie une GroupCollection contenant le nom des groupes. * @static * @async */ static async memberOf(data: userData): Promise<GroupCollection> { let simple = await Tools.memberOfSimple(data); return { simpleGroups: simple, metaGroups: await Tools.metaGroupsOfGroups(simple) }; } /** * @memberof GraphQL * @summary Fonction qui renvoit tous les groupes (simples ou méta) dont le user est speaker. * @arg {userData} data - Données de l'utilisateur. * @return {Promise(GroupCollection)} Renvoie une GroupCollection contenant le nom des groupes. * @static * @async */ static async speakerOf(data: userData): Promise<GroupCollection> { let speaker = await Tools.speakerOfSimple(data); let admin = await Tools.adminOfSimple(data); return { simpleGroups: speaker, metaGroups: await Tools.metaGroupsOfGroups(admin) }; } /** * @memberof GraphQL * @summary Fonction qui renvoit tous les groupes (simples ou méta) dont le user est administrateur. * @arg {userData} data - Données de l'utilisateur. * @return {Promise(GroupCollection)} Renvoie une GroupCollection contenant le nom des groupes. * @static * @async */ static async adminOf(data: userData): Promise<GroupCollection> { let simple = await Tools.adminOfSimple(data); return { simpleGroups: simple, metaGroups: await Tools.metaGroupsOfGroups(simple) }; } /** * @memberof GraphQL * @summary Fonction qui fait un parcours en profondeur de l'arbre de racine `gid` et renvoie la liste de tous les noeuds. * @arg {string} gid - Identifiant du groupe, supposé valide. * @return {Promise(string[])} Renvoie une liste contenant le nom des groupes dans cet arbre. * @static * @async */ static async DFS(gid: string): Promise<string[]> { let res = [gid]; let children = await knex.select('gid').from('groups').where('parent_gid', gid); for(let child of children) { let sub_tree = await Tools.DFS(child.gid); res = res.concat(sub_tree); } return res; } /** * @memberof GraphQL * @summary Fonction qui fait un parcours a profondeur 1 de l'arbre de racine `gid` et renvoie la liste des noeuds. * @arg {string} gid - Identifiant du groupe, supposé valide. * @return {Promise(string[])} Renvoie une liste contenant le nom des groupes a profondeur 1. * @static * @async */ static async oneDownSearch(gid: string): Promise<string[]> { let res = [gid]; let children = await knex.select('gid').from('groups').where('parent_gid', gid); for (let child of children) { res.push(child.gid); } return res; } /** * @memberof GraphQL * @summary Fonction qui renvoie tous les groupes dont l'utilisateur est supervisor. * @desc Utilise {@link Tools.oneDownSearch} pour avoir la profondeur 1 des arbres enracinés en chacun des groupes dont il est admin. * @arg {userData} data - Données du user. * @return {Promise(GroupCollection)} Renvoie une GroupCollection contenant le nom des groupes. * @static * @async */ static async supervisorOf(data: userData): Promise<GroupCollection> { let groups = await Tools.adminOf(data); let simple = new GroupSet(); let meta = new GroupSet(); for(let g of groups.simpleGroups) { simple.addList(await Tools.oneDownSearch(g)); } for(let g of groups.metaGroups) { meta.addList(await Tools.oneDownSearch(g)); } return { simpleGroups: simple, metaGroups: meta }; } /** * @memberof GraphQL * @summary Fonction qui renvoie tous les groupes dont l'utilisateur est viewer. * @desc Utilise {@link Tools.oneDownSearch} pour avoir la profondeur 1 des arbres enracinés en chacun des groupes dont il est membre. * @arg {userData} data - Données du user. * @return {Promise(GroupCollection)} Renvoie une GroupCollection contenant le nom des groupes. * @static * @async */ static async viewerOf(data: userData): Promise<GroupCollection> { let groups = await Tools.memberOf(data); let simple = new GroupSet(); let meta = new GroupSet(); //Ajouter les groupes dont il est membre + les fils a profondeur 1 for(let g of groups.simpleGroups) { simple.addList(await Tools.oneDownSearch(g)); } for(let g of groups.metaGroups) { meta.addList(await Tools.oneDownSearch(g)); } //Ajouter les groupes simples qui sont dans ses métagroupes let s = await knex.select('simple_group_gid').from('metagroup_memberships').whereIn('meta_group_gid', groups.metaGroups); simple.addList(s.map( elt => { return elt.simple_group_gid; })); return { simpleGroups: simple, metaGroups: meta }; } }