diff --git a/ldap_connexion_config.json b/ldap_connexion_config.json new file mode 100644 index 0000000000000000000000000000000000000000..a7a9108742c2c5d015db5784427bea9c73f9fa74 --- /dev/null +++ b/ldap_connexion_config.json @@ -0,0 +1,4 @@ +{ + "dn": "uid=anatole.romon,ou=eleves,dc=frankiz,dc=net", + "passwd": "moutoN0tablettE0rouE" +} \ No newline at end of file diff --git a/src/graphql/connectors/authentifiers.js b/src/graphql/connectors/authentifiers.ts similarity index 83% rename from src/graphql/connectors/authentifiers.js rename to src/graphql/connectors/authentifiers.ts index 4ad92cdbee0f0f693cd974452f7eb7d533274471..b453c639f0dfb280f9e50fbb833c093350ae57fe 100644 --- a/src/graphql/connectors/authentifiers.js +++ b/src/graphql/connectors/authentifiers.ts @@ -7,20 +7,29 @@ import knex from '../../../db/knex_router.js'; import * as connectors from './connectors.js'; import * as selectors from './selectors.js'; import * as list_selectors from './list_selectors.js'; -import {Open as LDAPOpen, User as LDAPUser} from '../../ldap/users'; -import {Admin as LDAPAdmin, Supervisor as LDAPSupervisor} from '../../ldap/admins'; /** * @summary Place-holder permettant de concaténer utilisateur et permissions dans un seul objet * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. - * @arg {Object} ldap_access - Représente les permissions de l'utilisateur en question. * @return {Object} Prototype de la fonction contenant la concaténation des deux arguments. */ -function User(user, ldap_access){ //hawkspar->akka ; ceci pourrait avantageusement être une classe - this.anonymous = Boolean(user.anonymous), - this.uid = user.uid, - this.password = user.password, - this.ldap_access = ldap_access; +// function OldUser(user, ldap_access){ //hawkspar->akka ; ceci pourrait avantageusement être une classe +// this.anonymous = Boolean(user.anonymous), +// this.uid = user.uid, +// this.password = user.password, +// this.ldap_access = ldap_access; +// } + +/** + * @summary un objet typé pour représenter la personne effectuant la requête. A ne pas confondre avec l'objet représentant un utilisateur + */ +class QUser{ + anonymous : boolean; + uid : string; + constructor(auth, uid){ + this.anonymous = !auth; + this.uid = uid; + } } /** @@ -31,18 +40,18 @@ function User(user, ldap_access){ //hawkspar->akka ; ceci pourrait avantageuseme * @rights user */ export function anonymous(user){ - return new User(user, new LDAPOpen()); + return new QUser(true, null); } /** - * @summary Authentifie un utilisateur comme viewer(groupUID) en appelant {@link User} et {@link LDAPUser} + * @summary Authentifie un utilisateur comme authentifié * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. * * @return {Promise(Object)} Un objet user si l'utilisateur possède les droits indiqués, * null sinon * @rights user */ -export function loggedIn(user, groupUID){ //hawkspar: WTF ? Pq garder son groupUID ? - return new User(user, new LDAPUser(user)); +export function loggedIn(user){ //hawkspar: WTF ? Pq garder son groupUID ? + return new QUser(false, user.uid); } /** diff --git a/src/graphql/connectors/connectors.js b/src/graphql/connectors/connectors.ts similarity index 77% rename from src/graphql/connectors/connectors.js rename to src/graphql/connectors/connectors.ts index f1d017e6d57f0670401dc01fdd2c16a8ef02ec4b..e995e40034289b0502f6b344a3cafad3868ee123 100644 --- a/src/graphql/connectors/connectors.js +++ b/src/graphql/connectors/connectors.ts @@ -5,21 +5,66 @@ import knex from '../../../db/knex_router'; import * as selectors from './selectors'; import * as list_selectors from './list_selectors'; -import {Open as LDAPOpen, User as LDAPUser} from '../../ldap/users'; +import {Group as groupLdap, groupData} from '../../ldap/group'; +import {User as userLdap, userData} from '../../ldap/user'; +import { isExportNamedDeclaration } from 'babel-types'; +import { admin } from './authentifiers'; + +class Group{ + gid : string; + type : string; // simple or meta - not to be confused with category + + name? : string; + category? : string; + members? : string[]; + admins? : string[]; + description? : string; + website?: string; + createdAt?: string; + UpdatedAt?: string; + + constructor(obj){ + this.gid = obj.uid; // until the database is mutated, the gid is called uid in the database + this.type = obj.type; + this.description = obj.description; + this.website = obj.website; + this.createdAt = obj.createdAt; + this.UpdatedAt = obj.updatedAt; + } -const utilisateur = new LDAPOpen(); + /** + * @summary effectue une requête au ldap pour avoir les donnees du groupe. + */ + async fetchData() : Promise<void>{ + const data : groupData = await groupLdap.peek(this.gid); + this.name = data.name; + this.category = data.type; // this fields needs to be renamed in groupData + this.members = data.members; + this.admins = data.admins; + this.description = data.description || this.description; + } +} -let result = utilisateur.getMembers("br").then(res => { - console.log("Got it"); - return res; -}); +class User{ + uid : string; -export { utilisateur }; -/* Ce n'est pas comme ça qu'on est censé fonctionner. Toute utilisation de utilisateur - a vocation à être temporaire, et sera remplacé par l'usage des fonctions - d'authentification correctes -*/ + constructor(obj){ + this.uid = obj.uid; + } + + async fetchData() : Promise<void>{ + const data : userData = await userLdap.peek(this.uid); + for(const field in data){ + this[field] = data[field]; + } + } +} + +class QUser{ + uid: string; + password : string; +} /* Le tag @rights est la gestion des autorisations. @@ -100,7 +145,7 @@ function getGroupTableName(wantedType){ } } -export function rasifyGroupUID(uid){ //hawkspar->akka ; je plussoie le nom mais pas très lisible +export function rasifyGID(uid){ //hawkspar->akka ; je plussoie le nom mais pas très lisible return String(uid).replace(' ', '_').replace(/\W/g, '').toLowerCase(); } @@ -109,19 +154,19 @@ export function rasifyGroupUID(uid){ //hawkspar->akka ; je plussoie le nom mais * @desc Pour l'instant, la fonction effectue la même requête que `getAllVisibleGroups` * et restreint au groupe demandé. Cette fonction peut être implémentée de manière * plus efficace et plus chiante. - * @arg {Object} user - Utilisateur effectuant la requête. - * @arg {String} uid - Identifiant du groupe voulu. + * @arg {String} gid - Identifiant du groupe voulu. * @arg {String} type - Type de groupe voulu. `"simple"`, `"meta"` ou `"all"`. * @return {Promise(group)} Retour de requête knex. Le groupe demandé, si l'utilisateur a le droit de la voire. * @rights user */ -export async function getGroupIfVisible(user, groupUID, type="all"){ +export async function getGroupIfVisible(quser : QUser, gid, type="all") : Promise<Group>{ let group_table_name = getGroupTableName(type); - let visible_groups = await selectors.visibleGroups(user); - return knex.with('visible_groups', visible_groups).select() + let visible_groups = await selectors.visibleGroups(quser); + const res = await knex.with('visible_groups', visible_groups).select() .from(group_table_name).innerJoin('visible_groups', function (){ this.on('visible_groups.uid', '=', group_table_name + '.uid'); - }).where(group_table_name + '.uid', groupUID).then(res => res[0]); + }).where(group_table_name + '.uid', gid); + return res[0]; } export const getSimpleGroupIfVisible = (user, groupUID) => getGroupIfVisible(user, groupUID, "simple"); @@ -135,9 +180,9 @@ export const getMetaGroupIfVisible = (user, groupUID) => getGroupIfVisible(user, * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire. * @rights user */ -export async function getAllVisibleSimpleGroups (user){ - let visible_groups = await selectors.visibleGroups(user); - return getSimpleGroupsFromCallbacks(user, visible_groups); +export async function getAllVisibleSimpleGroups(quser : QUser) : Promise<Group[]>{ + let visible_groups = await selectors.visibleGroups(quser); + return getSimpleGroupsFromCallbacks(quser, visible_groups); } /** @@ -148,54 +193,72 @@ export async function getAllVisibleSimpleGroups (user){ * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire. * @rights user */ -export async function getAllVisibleMetaGroups (user){ - let visible_groups = await selectors.visibleGroups(user); - return getMetaGroupsFromCallbacks(user, visible_groups); +export async function getAllVisibleMetaGroups(quser : QUser) : Promise<Group[]>{ + let visible_groups = await selectors.visibleGroups(quser); + return getMetaGroupsFromCallbacks(quser, visible_groups); } /** * @summary Renvoie tous les groupes visibles par l'utilisateur user * @desc Cette fonction effectue une requête knex. Elle gère l'arête de parenté. - * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. * @arg {String} wantedType - Type de groupe voulu : `"simple"`, `"meta"` ou `"all"`. * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire. * @rights user */ -export async function getAllVisibleGroups(user){ - let visible_groups = await selectors.visibleGroups(user); - return getGroupsFromCallbacks(user, visible_groups); +export async function getAllVisibleGroups(quser : QUser) : Promise<Group[]>{ + let visible_groups = await selectors.visibleGroups(quser); + return getGroupsFromCallbacks(quser, visible_groups); } /** * @summary Teste si un utilisateur est membre d'un groupe - * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. - * @arg {Object} groupUID - L'id du groupe dont on veu savoir si l'utilisateur est membre. * @return {Promise(Boolean)} Boolean indiquant si l'utilisateur est membre du groupe. * @rights user */ -export async function isMember(user, groupUID){ - let member_list = await getGroupMemberUsers(user, groupUID); - return member_list && (member_list.indexOf(groupUID) != -1); +export async function isMember(quser : QUser, group : Group) : Promise<boolean>{ + let member_set = await getGroupMemberUsersSet(quser, group); + if( member_set && member_set.has(quser.uid) ){ + return true; + }else{ + return isSpeaker(quser, group); + } +} + +export async function isSpeaker(quser : QUser, group : Group) : Promise<boolean>{ + return isAdmin(quser, group); +} + +export async function isAdmin(quser : QUser, group : Group) : Promise<boolean>{ + let admin_set = await getGroupAdminUsersSet(quser, group); + if( admin_set && admin_set.has(quser.uid) ){ + return true; + }else{ + return isSupervisor(quser, group); + } +} + +export async function isSupervisor(quser : QUser, group : Group) : Promise<boolean>{ + // TODO : implement + return true; } /** - * @summary Attribue un UID qui n'a pas encore été utilisé à un groupe + * @summary Attribue un GID qui n'a pas encore été utilisé à un groupe * @desc RASifie le string initialUID si necessaire (ramené à de l'ASCCI sans espace), puis si l'uid est deja pris rajoute un n a la fin et reteste * @arg {String} uid - L'uid du groupe dont on veut les administrateurs. * @return {Promise} Retour de requête knex. Promise qui renvera une liste de tous les utilisateurs ayant droit d'admin sur le groupe * @rights user * remarque : n'importe qui peut tester si un groupe existe en demandant a créer un groupe avec ce nom la et en regardant si - * son UID a été modifié. Je ne vois pas comment contourner ce problème, c'est donc une faille permanente de sigma. + * son GID a été modifié. Je ne vois pas comment contourner ce problème, c'est donc une faille permanente (mineure) de sigma. */ -export function getAvailablegroupUID(initialUID){ - let rasUID = rasifyGroupUID(initialUID); - return knex.from('groups').where('uid', rasUID).then(res => { - if (res.length == 0) { - return (rasUID); - } else { - return (getAvailablegroupUID(rasUID + 'n')); - } - }); +export async function getAvailableGID(initialGID : string) : Promise<string>{ + let rasGID = rasifyGID(initialGID); + const res = knex.from('groups').where('uid', rasGID) + if (res.length == 0) { + return (rasGID); + } else { + return (getAvailableGID(rasGID + 'n')); + } } /** @@ -210,13 +273,16 @@ export function getAvailablegroupUID(initialUID){ * @return {Promise} Retour de requête knex. Le groupe qui vient d'être créé. En cas d'echec, renvoie une erreur. * @rights admin (args.parent_uid) */ -export async function createSubgroup(user, args){ +export async function createSubgroup(quser : QUser, group : Group, args) : Promise<Group>{ + + // TODO : finish + if (typeof args.parent_uid != 'string') throw "Illegal argument : parent_uid must be a non null string"; if (typeof args.name != 'string') throw "Illegal argument : name must be a non null string"; - let rasUID = await getAvailablegroupUID(args.uid); + let rasUID = await getAvailableGID(args.uid); // TODO : appeller une fonction de LDAPUser pour y créer un groupe. await knex('simple_groups').insert({ @@ -231,7 +297,7 @@ export async function createSubgroup(user, args){ type : "simple" }); - return getGroupIfVisible(user, rasUID); + return getGroupIfVisible(quser, rasUID); } /** @@ -244,9 +310,9 @@ export async function createSubgroup(user, args){ * @return {Promise} Retour de requête knex. Le groupe qui vient d'être créé. En cas d'echec, renvoie une erreur. * @rights user */ -export async function createGroupIfLegal(user, args){ - if( await LDAPOpen.isGroupAdmin(utilisateur, args.parentuid) ){ - return createSubgroup(user, args); +export async function createGroupIfLegal(quser : QUser, group : Group, args) : Promise<Group>{ + if( await isAdmin(quser, group) ){ + return createSubgroup(quser, group, args); }else{ throw "illegal request : you must have admin rights over a group to create a subgroup of that group"; } @@ -261,15 +327,16 @@ export async function createGroupIfLegal(user, args){ * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe. * @rights admin(recipientUID) */ -export async function getUserJoinGroupRequests(user, recipientUID){ +export async function getUserJoinGroupRequests(quser : QUser, recipient : Group) : Promise<Object>{ let result = knex.select('id', 'useruid', 'message').from('user_join_group') - .where('recipient', recipientUID); + .where('recipient', recipient.gid); return result.map( obj => { obj.type = "UserJoinGroup"; return obj; }); } + /** * @summary Renvoie toues les requêtes de type GroupJoinEvent * @desc Une requête UserJoinGroup est envoyée par un groupe à un évènement (donc aux administrateurs de l'évènement), @@ -281,9 +348,9 @@ export async function getUserJoinGroupRequests(user, recipientUID){ * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe. * @rights speaker(recipientUID) */ -export async function getGroupJoinEventRequests(user, recipientUID){ +export async function getGroupJoinEventRequests(quser : QUser, recipient : Group) : Promise<Object>{ let result = await knex.select('id', 'senderuid', 'eventuid', 'message').from('group_join_event') - .where('recipient', recipientUID); + .where('recipient', recipient.gid); return result.map( obj => { obj.type = "GroupJoinEvent"; return obj; @@ -292,7 +359,7 @@ export async function getGroupJoinEventRequests(user, recipientUID){ /** - * @summary Renvoie toues les requêtes de type GroupJoinEvent + * @summary Renvoie toues les requêtes de type GroupHostEvent * @desc Une requête UserJoinGroup est envoyée par un groupe à un évènement (donc aux administrateurs de l'évènement), * pour demander à rejoindre cet évènement. * Remarque : toutes les requêtes ont pour le moment un attribut recipient, @@ -302,9 +369,9 @@ export async function getGroupJoinEventRequests(user, recipientUID){ * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe. * @rights speaker(recipientUID) */ -export async function getYourGroupHostEventRequests(user, recipientUID){ +export async function getYourGroupHostEventRequests(quser : QUser, recipient : Group) : Promise<Object>{ let result = await knex.select('id', 'senderuid', 'eventuid', 'message').from('your_group_host_event') - .where('recipient', recipientUID); + .where('recipient', recipient.gid); return result.map( obj => { obj.type = "YourGroupHostEvent"; return obj; @@ -312,33 +379,6 @@ export async function getYourGroupHostEventRequests(user, recipientUID){ } -//Don't forget the argument user is the guy who makes the request, not the user we want -export const getUser = (user, uid, db) => { - const refactorer = (data) => { - if (typeof data.brRoom == 'string') data.brRoom = [data.brRoom]; - - return { - uid: uid, - lastName: data.sn, - givenName: data.givenName, - nickname: data.displayName, - nationality: data.country, - birthdate: data.brBirthdate, - groups: data.brMemberOf, - mail: data.mail, - phone: data.telephoneNumber, - address: data.brRoom, - promotion: data.brPromo - }; - }; - - const result = utilisateur.getUser(uid).then(res => { - return refactorer(res[0]); - }); - - return result; -}; - // All these messages are returned if they are visible export async function getAnnouncement(user, messageID){ @@ -403,7 +443,7 @@ export async function getAnswer(user, messageID){ * @param {*} eventID - Identifiant unique de l'événement. * @rights super */ -export async function getMessage(user, messageID){ +export async function getMessage(user, messageID) : Promise<any>{ return getEvent(user, messageID) | getAnnouncement(user, messageID) | getPrivatePost(user, messageID) | @@ -606,42 +646,70 @@ export function releaseAdminRights(user, groupUID){ * @author akka vodol * @rights member(metaGroupUID) */ -export async function getGroupMemberUsers(user, GroupUID){ - let type = await list_selectors.getGroupType(user, GroupUID); - switch( type ){ - case "SimpleGroup": - return utilisateur.getMembers(GroupUID); - // return ["anatole.romon"]; - case "MetaGroup": - return getMetaGroupMemberUsers(user, GroupUID); - default: - return undefined; - } +export async function getGroupMemberUsers(quser : QUser, group : Group) : Promise<User[]>{ + const memberSet = await getGroupMemberUsersSet(quser, group); + return Array.from(memberSet.values()).map( uid => new User(uid) ); +} + +async function getGroupMemberUsersSet(quser : QUser, group : Group) : Promise<Set<string>>{ + switch( group.type ){ + case "simple": + if(!group.members){ + await group.fetchData(); + } + return new Set(group.members); + case "meta": + let member_group_list = await selectors.metaGroupMembers(quser, group).then(cb => cb(knex)); + let members = new Set; + for(const memberGroup of member_group_list){ + let res = await getGroupMemberUsers(quser, new Group(memberGroup)); + for(const member of res.values()){ + members.add(member); + } + } + return members; + default: + return undefined; + } } + + /** - * @summary Renvoie les membres d'un meta groupe. + * @summary Renvoie les membres d'un groupe quelquonque. * @param {Object} user - Utilisateur effectuant la requête. * @param {String} metaGroupUID - Identifiant unique du groupe. * @return {Promise(List)} Une liste des uid de tous les membres du groupe * @author akka vodol * @rights member(metaGroupUID) */ -export async function getMetaGroupMemberUsers(user, metaGroupUID){ - let member_group_list = await selectors.metaGroupMembers(user, metaGroupUID).then(cb => cb(knex)); - let members = []; - for(let memberGroup of await member_group_list){ - members = members.concat(getGroupMemberUsers(user, metaGroupUID)); - } +export async function getGroupAdminUsers(quser : QUser, group : Group) : Promise<User[]>{ + const memberSet = await getGroupAdminUsersSet(quser, group); + return Array.from(memberSet.values()).map( uid => new User(uid) ); +} + +async function getGroupAdminUsersSet(quser : QUser, group : Group) : Promise<Set<string>>{ + switch( group.type ){ + case "simple": + if(!group.members){ + await group.fetchData(); + } + return new Set(group.admins); + case "meta": + // TODO : Meta group administration not yet implemented + return new Set([]); + default: + return undefined; + } } -export async function getSimpleGroupsFromCallbacks (user, selection){ +async function getSimpleGroupsFromCallbacks (user, selection){ return knex.with('selection', selection).select("simple_groups.*").from("simple_groups") .innerJoin('selection', function (){ this.on('selection.uid', '=', 'simple_groups.uid'); }); } -export async function getMetaGroupsFromCallbacks (user, selection){ +async function getMetaGroupsFromCallbacks (user, selection){ return knex.with('selection', selection).select().from("meta_groups") .innerJoin('selection', function (){ this.on('selection.uid', '=', 'meta_groups.uid'); @@ -656,7 +724,7 @@ export async function getMetaGroupsFromCallbacks (user, selection){ * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire. * @rights user */ -export async function getGroupsFromCallbacks(user, cbList){ +async function getGroupsFromCallbacks(user, cbList){ // console.log(cbList); let all_simple_groups = await getSimpleGroupsFromCallbacks(user, cbList); let all_meta_groups = await getMetaGroupsFromCallbacks(user, cbList); diff --git a/src/graphql/new_connectors/authorisation.ts b/src/graphql/new_connectors/authorisation.ts new file mode 100644 index 0000000000000000000000000000000000000000..c8b47227275ea5f0134f7c0565e59b407fc0480a --- /dev/null +++ b/src/graphql/new_connectors/authorisation.ts @@ -0,0 +1,65 @@ +import { QueryBuilder } from "knex"; + + +interface QUser { + uid : string +}; + +export type GroupSet = Set<string>; + + +/** + * There are 6 levels of authorisation for a group + * none : can't even know the group exists + * viewer : can see the group + * memebr : part of the group + * speaker : allowed to speak for the group + * admin : admin of the group + * supervisor : allowed to take control of the group + * + * Levels 0 and 5 are a bit special. For levels 1 - 4, the functions are as follows + */ + +// These functions return the list of all groups that the query user (quser) has corresponding priviledge for + +export async function forViewer(quser : QUser) : Promise<GroupSet>{ + throw new Error("Not implemented"); +} + +export async function forMember(quser : QUser) : Promise<GroupSet>{ + throw new Error("Not implemented"); +} + +export async function forSpeaker(quser : QUser) : Promise<GroupSet>{ + throw new Error("Not implemented"); +} + +export async function forAdmin(quser : QUser) : Promise<GroupSet>{ + throw new Error("Not implemented"); +} + +// These functions test if the quser has corresponding priviledges for the given group + +export async function isViewer(quser : QUser, gid : string) : Promise<boolean>{ + let groupSet = await forViewer(quser); + return groupSet.has(gid); +} + +export async function isMember(quser : QUser, gid : string) : Promise<boolean>{ + let groupSet = await forMember(quser); + return groupSet.has(gid); +} + +export async function isSpeaker(quser : QUser, gid : string) : Promise<boolean>{ + let groupSet = await forSpeaker(quser); + return groupSet.has(gid); +} + +export async function isAdmin(quser : QUser, gid : string) : Promise<boolean>{ + let groupSet = await forAdmin(quser); + return groupSet.has(gid); +} + +export async function isSupervisor(quser : QUser, gid : string) : Promise<boolean>{ + throw new Error('Not implemented'); +}; \ No newline at end of file diff --git a/src/graphql/new_connectors/connection.ts b/src/graphql/new_connectors/connection.ts new file mode 100644 index 0000000000000000000000000000000000000000..86a06e1c31cef562eae119a5a7ff9973992369b4 --- /dev/null +++ b/src/graphql/new_connectors/connection.ts @@ -0,0 +1,613 @@ +/** + * @file Fonctions pour interagir avec la BDD sigma et le LDAP. + * @author akka vodol + */ +import knex from '../../../db/knex_router'; + +import {Group as groupLdap, groupData} from '../../ldap/group'; +import {User as userLdap, userData} from '../../ldap/user'; +import { isExportNamedDeclaration } from 'babel-types'; + +import {GroupSet} from './authorisation'; + +export class Group{ + gid : string; + type : string; // simple or meta - not to be confused with category + + name? : string; + category? : string; + members? : string[]; + admins? : string[]; + description? : string; + website?: string; + createdAt?: string; + UpdatedAt?: string; + + constructor(obj){ + this.gid = obj.uid; // until the database is mutated, the gid is called uid in the database + this.type = obj.type; + this.description = obj.description; + this.website = obj.website; + this.createdAt = obj.createdAt; + this.UpdatedAt = obj.updatedAt; + } + + /** + * @summary effectue une requête au ldap pour avoir les donnees du groupe. + */ + async fetchData() : Promise<void>{ + const data : groupData = await groupLdap.peek(this.gid); + this.name = data.name; + this.category = data.type; // this fields needs to be renamed in groupData + this.members = data.members; + this.admins = data.admins; + this.description = data.description || this.description; + } +} + +export class User{ + uid : string; + + constructor(obj){ + this.uid = obj.uid; + } + + async fetchData() : Promise<void>{ + const data : userData = await userLdap.peek(this.uid); + for(const field in data){ + this[field] = data[field]; + } + } +} + +class QUser{ + uid: string; + password : string; +} + +/* + Le tag @rights est la gestion des autorisations. + + Le système GraphQL est pensé comme l'interface par laquelle les utilisateurs + intéragissent avec sigma, les graphismes en moins. + Le client peut envoyer tout type de requête. C'est au niveau des resolvers + que les permissions sont gérées. D'où le @rights + + Commençons par un rappel sur le fonctionnement des droits. + Chaque utilisateur a un certain niveau de droit sur chaque groupe. Ce niveau de droit indique + ce qu'il a le droit de savoir et de faire. Chaque niveau est inclus dans les niveaus supérieur. + Les différents niveaux sont : + none - aucun droit + viewer : l'utilisateur a visibilité sur le groupe. Il sait que le groupe existe, et a accès à un certain nombre d'infos. + member : l'utilisateur est membre du groupe + speaker : l'utilisateur peut parler au nom du groupe. Il a le droit de publier des annonces et d'organiser des évènements + admin : l'utilisateur a tous les droits sur le groupe + + Certaines fonctions de connectors effectuent des vérifications d'authorisations avant + de renvoyer une réponse, d'autres non. Pour être sur qu'on ne renvoie jamais de réponse + sans avoir au préalable éffectué les bonnes vérifications, chaque fonction possède dans sa + description un attribut droit, qui décrit les droits que fournit cette fonction. + + La valeur de @rights peut être : + super - la fonction n'effectue aucune véri-fication, et renvoie le resultat demandé + admin( groupUID ) - la fonction ne fait que ce qu'un admin du groupe indiqué aurait le droit de faire + speaker( groupUID ), member( groupUID ), veiwer( groupUID ) - même chose + user - la fonction ne fait que ce que l'utiliateur a le droit de faire (vérifications via l'argument user) + + La procédure a suivre est la suivante : quand une fonction possède un certain niveau de droit, + elle ne peut appeler une fonction possédant un niveau de droit plus large que si + 1 ) on a au préalable vérifié que l'utilisateur possédait effectivement ces droits. + ou + 2 ) on s'est assuré que l'opération effectuée par cet appel particulier de la fonction était dans les droits + de l'utilisateur + + Les resolvers de base de mutation et query ont des droits user. + + Les fonctions qui ne modifient pas la BDD et ne renvoient pas de données sur la BDD n'ont pas de rights. +*/ + +export function rasifyGID(uid){ //hawkspar->akka ; je plussoie le nom mais pas très lisible + return String(uid).replace(' ', '_').replace(/\W/g, '').toLowerCase(); +} + +/** + * @summary Renvoie tous les groupes simples dont les id sont dans groupSet + */ +export async function getSimpleGroups(groupSet : GroupSet) : Promise<Group[]>{ + const res = await knex.select().from('simple_groups').whereIn('uid', groupSet.entries()); + return res.map( (data) => new Group(data) ); +} + +/** + * @summary Renvoie tous les groupes simples dont les id sont dans groupSet + */ +export async function getMetaGroups(groupSet : GroupSet) : Promise<Group[]>{ + const res = await knex.select().from('meta_groups').whereIn('uid', groupSet.entries()); + return res.map( (data) => new Group(data) ); +} + +/** + * @summary Renvoie tous les groupes simples dont les id sont dans groupSet + */ +export async function getGroups(groupSet : GroupSet) : Promise<Group[]>{ + const res = await knex.select().from('groups').whereIn('uid', groupSet.entries()); + return res.map( (data) => new Group(data) ); +} + +/** + * @summary Attribue un GID qui n'a pas encore été utilisé à un groupe + * @desc RASifie le string initialUID si necessaire (ramené à de l'ASCCI sans espace), puis si l'uid est deja pris rajoute un n a la fin et reteste + * @arg {String} uid - L'uid du groupe dont on veut les administrateurs. + * @return {Promise} Retour de requête knex. Promise qui renvera une liste de tous les utilisateurs ayant droit d'admin sur le groupe + * @rights user + * remarque : n'importe qui peut tester si un groupe existe en demandant a créer un groupe avec ce nom la et en regardant si + * son GID a été modifié. Je ne vois pas comment contourner ce problème, c'est donc une faille permanente (mineure) de sigma. + */ +export async function getAvailableGID(initialGID : string) : Promise<string>{ + let rasGID = rasifyGID(initialGID); + const res = knex.from('groups').where('uid', rasGID) + if (res.length == 0) { + return (rasGID); + } else { + return (getAvailableGID(rasGID + 'n')); + } +} + +/** + * @summary Créé un groupe si les arguments sont tous valides + * @desc Les arguments doivent être valides, sauf pour uid. Une clé uid valide sera générée dans tous les cas. + * Les authorisations de l'utilisateur ne sont pas vérifiées + * On teste si l'utilisateur qui envoie la requête a des droits d'admin sur le parent du groupe qui doit être créé, avec la fonction + * `getUsersWithAdminRights`. + * Si un argument est invalide ou si l'utilisateur n'a pas les droits, la fonction renvoie une erreur + * @arg {Object} user - L'utilisateur qui effectue la requête. + * @arg {Object} args - Les arguments envoyés à la mutation. Cf le schéma GraphQL + * @return {Promise} Retour de requête knex. Le groupe qui vient d'être créé. En cas d'echec, renvoie une erreur. + * @rights admin (args.parent_uid) + */ +export async function createSubgroup(quser : QUser, group : Group, args) : Promise<Group>{ + + // TODO : finish + + if (typeof args.parent_uid != 'string') + throw "Illegal argument : parent_uid must be a non null string"; + if (typeof args.name != 'string') + throw "Illegal argument : name must be a non null string"; + + let rasGID = await getAvailableGID(args.uid); + + // TODO : appeller une fonction de LDAPUser pour y créer un groupe. + await knex('simple_groups').insert({ + uid: rasGID, + parent_uid: args.parent_uid, + createdAt: knex.fn.now(), + updatedAt: this.createdAt, + name: args.name, + website: args.website, + description: args.description, + school: args.school, + type : "simple" + }); + + return getGroup(rasGID); +} + +export async function getUser(uid : string){ + return new User(uid); +} + +export async function searchUsers(args){ + const searchData = { + givenName: args.givenName, + lastName: args.lastName, + nickname: args.nickname, + nationality: args.nationality, + school: args.school, + promotion: args.promotion, + groups: args.groups, + studies: args.studies, + sport: args.sport, + phone: args.phone, + mail: args.mail, + adress: args.adress, + ip: args.ip + } + const userList = await userLdap.search(searchData); + return userList.map( (uid) => new User(uid) ); +} + +/** + * @summary Renvoie toues les requêtes de type UserJoinGroup + * @desc Une requête UserJoinGroup est envoyée par un utilisateur à un groupe, + * pour demander à rejoindre ce groupe + */ +export async function getUserJoinGroupRequests(recipient : Group){ + let result = knex.select('id', 'useruid', 'message').from('user_join_group') + .where('recipient', recipient.gid); + return result.map( obj => { + obj.type = "UserJoinGroup"; + return obj; + }); +} + +/** + * @summary Renvoie toues les requêtes de type GroupJoinEvent + * @desc Une requête UserJoinGroup est envoyée par un groupe à un évènement (donc aux administrateurs de l'évènement), + * pour demander à rejoindre cet évènement. + * Remarque : toutes les requêtes ont pour le moment un attribut recipient, + * mais ici il ne sera a terme pas utilisé. + */ +export async function getGroupJoinEventRequests(quser : QUser, recipient : Group){ + let result = await knex.select('id', 'senderuid', 'eventuid', 'message').from('group_join_event') + .where('recipient', recipient.gid); + return result.map( obj => { + obj.type = "GroupJoinEvent"; + return obj; + }); +} + +/** + * @summary Renvoie toues les requêtes de type GroupHostEvent + * @desc Une requête UserJoinGroup est envoyée par un groupe à un évènement (donc aux administrateurs de l'évènement), + * pour demander à rejoindre cet évènement. + * Remarque : toutes les requêtes ont pour le moment un attribut recipient, + * mais ici il ne sera a terme pas utilisé. + */ +export async function getYourGroupHostEventRequests(quser : QUser, recipient : Group){ + let result = await knex.select('id', 'senderuid', 'eventuid', 'message').from('your_group_host_event') + .where('recipient', recipient.gid); + return result.map( obj => { + obj.type = "YourGroupHostEvent"; + return obj; + }); +} + + +// All these messages are returned if they are visible + +// TODO : figure out which announcements are visible + +export async function getAnnouncement(messageID){ + let res = await knex.select().from('announcements').where('id', messageID); + if(res[0]){ + res[0].type = 'Announcement'; + return res[0]; + } + res = await knex.select().from('events').where('id', messageID); + if(res[0]){ + res[0].type = 'Announcement'; + return res[0]; + } + return undefined; +} + +export async function getEvent(messageID){ + let res = await knex.select().from('events').where('id', messageID); + if(res[0]){ + res[0].type = 'Event'; + return res[0]; + } + return undefined; +} + +export async function getPrivatePost(messageID){ + let res = await knex.select().from('private_posts').where('id', messageID); + if(res[0]){ + res[0].type = 'PrivatePost'; + return res[0]; + } + return undefined; +} + +export async function getQuestion(messageID){ + let res = await knex.select().from('questions').where('id', messageID); + if(res[0]){ + res[0].type = 'Question'; + return res[0]; + } + return undefined; +} + +export async function getAnswer(messageID){ + let res = await knex.select().from('answers').where('id', messageID); + if(res[0]){ + res[0].type = 'Answer'; + return res[0]; + } + return undefined; +} + +/** + * + * @param groupSet The set of all groups who's events we want to see. + */ +export async function allEvents(groupSet : GroupSet){ + let selection = []; + throw new Error('Not implemented'); + let result = await knex.select().from('events').whereIn('id', selection); + for(let r of result){ + r.type = 'Announcement'; + } + return result; +} + +export async function allAnnouncements(groupSet : GroupSet){ + let selection = []; + throw new Error('Not implemented'); + let result = await knex.select().from('announcements').whereIn('id', selection); + result = result.concat( + await knex.select().from('events').whereIn('id', selection) + ); + for(let r of result){ + r.type = 'Announcement'; + } + return result; +} + +export async function receivedPrivatePosts(group : Group){ + let selection = []; + throw new Error('Not implemented'); + // let result = await knex('private_posts').select().whereIn('id', received_messages); + // for(let entry of result){ + // entry.type = "PrivatePost"; + // } + // return result; +} + +export async function receivedQuestions(group : Group){ + let selection = []; + throw new Error('Not implemented'); + // let result = await knex('questions').select().whereIn('id', received_messages); + // for(let entry of result){ + // entry.type = "Question"; + // } + // return result; +} + +export async function receivedAnswers(group : Group){ + let selection = []; + throw new Error('Not implemented'); + // let received_messages = await selectors.recievedMessages(user, groupUID); + // let result = await knex('answers').select().whereIn('id', received_messages); + // for(let entry of result){ + // entry.type = "Answer"; + // } + // return result; +} + + +export async function visibleMessages(user, messageID){ + +} + +export async function getMessageGroupAuthors(user, messageID){ + return knex.select({uid: 'group'}).from('group_message_relationships') + .where('message', messageID).whereIn('status', ['host', 'publish']); + +} + +export async function getMessageGroupRecipients(user, messageID){ + return knex.select({uid: 'group'}).from('group_message_relationships') + .where('message', messageID).where('status', 'recieve'); +} + +/** + * @summary Renvoie simplement un groupe en fonction de son identifiant. + * @param {Object} user - Utilisateur effectuant la requête. + * @param {String} groupUID - Identifiant unique du groupe. + * @author manifold + * @rights super + */ +export async function getGroup(gid : string) : Promise<Group>{ + // Une sélection sur une table renvoie un tableau. + // Knex renvoie une promesse, qui se résout en le tableau sélectionné. + // On récupère son unique valeur, puisqu'on filtre sur l'identifiant unique. + return knex.select().from('groups').where('uid',gid).then(results => results[0]); +}; + +/** + * @summary Renvoie simplement un groupe simple en fonction de son identifiant. + * @param {Object} user - Utilisateur effectuant la requête. + * @param {String} groupUID - Identifiant unique du groupe. + * @author manifold + * @rights super + */ +export async function getSimpleGroup(gid : string) : Promise<Group>{ + return knex.select().from('simple_groups').where('uid', gid).then(results => results [0]); +}; + +/** + * @summary Renvoie simplement un meta groupe en fonction de son identifiant. + * @param {Object} user - Utilisateur effectuant la requête. + * @param {String} groupUID - Identifiant unique du groupe. + * @author manifold + * @rights super + */ +export async function getMetaGroup(gid : string) : Promise<Group>{ + return knex.select().from('meta_groups').where('uid', gid).then(results => results [0]); +}; + +/** + * @summary Refuse une requête d'un groupe voulant rejoindre un évènement + * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. + * @arg {Int} requestID - L'id de la requête à refuser. + * @return {Promise(Boolean)} Vrai si l'opération a réussie; + * @rights admin(request.recipient) + */ +export async function denyGroupJoinEventRequest(requestID){ + await knex('group_join_event').where('id', requestID).del(); + return true; +} + +/** + * @summary Refuse une requête d'un groupe voulant rejoindre un évènement + * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. + * @arg {Int} requestID - L'id de la requête à refuser. + * @return {Promise(Boolean)} Vrai si l'opération a réussie; + * @rights admin(request.recipient) + */ +export async function acceptGroupJoinEventRequest(user, requestID){ + let request = await knex('group_join_event').select().where('id', requestID); + if( !request) + return false; + await knex('group_join_event').where('id', requestID).del(); + let group = request[0].senderuid; + let event = request[0].eventuid; + await knex('group_participation').insert({ + group : group, + message : event, + status : "join" + }); + return; + +} + + +/** + * @summary Refuse une requête d'un groupe voulant rejoindre un évènement + * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. + * @arg {Int} requestID - L'id de la requête à refuser. + * @return {Promise(Boolean)} Vrai si l'opération a réussie; + * @rights admin(request.recipient) + */ +export async function denyYourGroupHostEventRequest(requestID : string) : Promise<boolean>{ + await knex('your_group_host_event').where('id', requestID).del(); + throw new Error('Not implemented'); +} + +/** + * @summary Refuse une requête d'un groupe voulant rejoindre un évènement + * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. + * @arg {Int} requestID - L'id de la requête à refuser. + * @return {Promise(Boolean)} Vrai si l'opération a réussie; + * @rights admin(request.recipient) + */ +export async function acceptYourGroupHostEventRequest(requestID : string) : Promise<Boolean>{ + let request = await knex('your_group_host_event').select().where('id', requestID); + if( !request) + return false; + await knex('group_join_event').where('id', requestID).del(); + let group = request[0].recipient; + let event = request[0].eventuid; + await knex('group_message_relationships').insert({ + group : group, + message : event, + status : "host" + }); + return; + +} + +export async function takeAdminRights(user, groupUID, justification) : Promise<boolean>{ + await knex('taken_rights').insert({ + user_uid : user.uid, + group_uid : groupUID, + justification : justification + }); + return true; +} + + +export function releaseAdminRights(user, groupUID){ + return knex('taken_rights').del().where('user_uid', user.uid).where('group_uid', groupUID); +} + +/** + * @summary Renvoie les membres d'un groupe quelquonque. + * @param {Object} user - Utilisateur effectuant la requête. + * @param {String} metaGroupUID - Identifiant unique du groupe. + * @return {Promise(List)} Une liste des uid de tous les membres du groupe + * @author akka vodol + * @rights member(metaGroupUID) + */ +export async function getGroupMemberUsers(quser : QUser, group : Group) : Promise<User[]>{ + const memberSet = await getGroupMemberUsersSet(quser, group); + return Array.from(memberSet.values()).map( uid => new User(uid) ); +} + +async function getGroupMemberUsersSet(quser : QUser, group : Group) : Promise<Set<string>>{ + switch( group.type ){ + case "simple": + if(!group.members){ + await group.fetchData(); + } + return new Set(group.members); + case "meta": + let member_group_list = await knex.distinct().select().from('groups') + .innerJoin('meta_group_membership', 'groups.uid', 'meta_group_membership.member_uid') + .where('meta_group_membership.union_uid', '=', group.gid); + let members = new Set; + for(const memberGroup of member_group_list){ + let res = await getGroupMemberUsers(quser, new Group(memberGroup)); + for(const member of res.values()){ + members.add(member); + } + } + return members; + default: + return undefined; + } +} + + +/** + * @summary Renvoie les membres d'un groupe quelquonque. + * @param {Object} user - Utilisateur effectuant la requête. + * @param {String} metaGroupUID - Identifiant unique du groupe. + * @return {Promise(List)} Une liste des uid de tous les membres du groupe + * @author akka vodol + * @rights member(metaGroupUID) + */ +export async function getGroupAdminUsers(quser : QUser, group : Group) : Promise<User[]>{ + const memberSet = await getGroupAdminUsersSet(quser, group); + return Array.from(memberSet.values()).map( uid => new User(uid) ); +} + +async function getGroupAdminUsersSet(quser : QUser, group : Group) : Promise<Set<string>>{ + switch( group.type ){ + case "simple": + if(!group.members){ + await group.fetchData(); + } + return new Set(group.admins); + case "meta": + // TODO : Meta group administration not yet implemented + return new Set([]); + default: + return undefined; + } +} + +/* + * réflexion sur une façon possible de gérer les utilisateurs sans en demander trop à LDAP + * Sans utilité pour le moment, ne faites pas attention + */ + +/* +function smartUserObject(user, uid){ + this.user = user; + this.uid = uid; + + this.resolution = {}; + let resolutionAlias = this.resolution; + + let attributeDictionnary = { + givenName : "givenName" + }; + + for(let attribute in attributeDictionnary){ + this[attribute] = function(){ + return new Promise((resolve, reject) => { + resolutionAlias[attributeDictionnary[attribute]] = resolve; + }); + }; + } + + this.resolve = async function(){ + let userObject = await renseignerSurUtilisateur(this.user, this.uid); + for(let attribute in this.resolution){ + this.resolution[attribute](userObject.attribute); + } + }; +} +*/ \ No newline at end of file diff --git a/src/graphql/resolvers.ts b/src/graphql/resolvers.ts index 0663d777eb31d24bcb9d7729dc7eaae74f4c5bbd..9baa12805c0502c75bb25731891f92a148c71f17 100644 --- a/src/graphql/resolvers.ts +++ b/src/graphql/resolvers.ts @@ -10,8 +10,9 @@ import '../config_passport'; import authenticator from './authenticator'; -import * as connectors from './connectors/connectors'; -import * as authentifiers from './connectors/authentifiers'; +import * as auth from './new_connectors/authorisation'; +import * as conn from './new_connectors/connection'; + import MessageResolvers from './resolvers/messages'; import GroupResolvers from './resolvers/groups'; @@ -41,104 +42,72 @@ export const resolvers = { // group queries - allGroups: async function(root, args, context){ - let user = await authentifiers.anonymous(context.user); - return user && connectors.getAllVisibleGroups(user); + allGroups: async function(root, args, context) : Promise<conn.Group[]>{ + const visibleGroupSet = await auth.forViewer(context.user); + return conn.getGroups(visibleGroupSet); }, - allSimpleGroups: async function (root, args, context){ - let user = await authentifiers.anonymous(context.user); - return user && connectors.getAllVisibleSimpleGroups(user); + allSimpleGroups: async function (root, args, context) : Promise<conn.Group[]>{ + const visibleGroupSet = await auth.forViewer(context.user); + return conn.getSimpleGroups(visibleGroupSet); }, - group: async function(root, args, context) { - let user = await authentifiers.anonymous(context.user); - return user && connectors.getGroupIfVisible(user, args.uid); + allMetaGroups: async function(root, args, context) : Promise<conn.Group[]>{ + const visibleGroupSet = await auth.forViewer(context.user); + return conn.getMetaGroups(visibleGroupSet); }, - simpleGroup: async function(obj, args, context){ - let user = await authentifiers.anonymous(context.user); - return user && connectors.getSimpleGroupIfVisible(user, args.uid); + group: async function(root, args, context) : Promise<conn.Group>{ + if(await auth.isViewer(context.user, args.gid)){ + return conn.getGroup(args.gid); + }else{ + return null; + } }, - metaGroup: async function(obj, args, context){ - let user = await authentifiers.anonymous(context.user); - return user && connectors.getMetaGroupIfVisible(user, args.uid); + + simpleGroup: async function(obj, args, context) : Promise<conn.Group>{ + if(await auth.isViewer(context.user, args.gid)){ + return conn.getSimpleGroup(args.gid); + }else{ + return null; + } + }, + + metaGroup: async function(obj, args, context) : Promise<conn.Group>{ + if(await auth.isViewer(context.user, args.gid)){ + return conn.getMetaGroup(args.gid); + }else{ + return null; + } }, /* * Message queries. */ - allAnnouncements: function(obj, args, context) { - return knex.select().from("announcements"); + allAnnouncements: async function(obj, args, context) : Promise<Object[]> { + const visibleGroupSet = await auth.forViewer(context.user); + return conn.allAnnouncements(visibleGroupSet); }, - allEvents(root, args, context) { - return knex.select().from("events"); - }, - - allMessages(root, args, context) { - const events = knex.select().from("events"); - const posts = knex.select().from("posts"); - return Promise.all([events, posts]).then(res => { - return _.flatten(res); - }); + allEvents: async function (root, args, context) : Promise<Object[]> { + const visibleGroupSet = await auth.forViewer(context.user); + return conn.allAnnouncements(visibleGroupSet); }, - // user queries - user: async function(obj, args, context){ - let user = await authentifiers.anonymous(context.user); - return user && connectors.getUser(user,args.uid); - }, - - searchTOL: (obj, args, context) => { - const result = connectors.utilisateur.repliquerTOLdesIds({ - givenName: args.givenName, - lastName: args.lastName, - nickname: args.nickname, - nationality: args.nationality, - school: args.school, - promotion: args.promotion, - groups: args.groups, - studies: args.studies, - sport: args.sport, - phone: args.phone, - mail: args.mail, - adress: args.adress, - ip: args.ip - }); - return result; + user: async function(root, args, context){ + return conn.getUser(args.uid); }, - // viewer queries - - // member queries - - allMembers : async function(obj, args, context){ - let user = await authentifiers.member(context.user, args.from); - return user && connectors.getGroupMemberUsers(context.user, obj.groupUID); + searchTOL: (root, args, context) => { + // TODO : filter + return conn.searchUsers(args); }, - // speaker queries - - allRequests: async function(obj, args, context){ - let res = []; - let user = authentifiers.admin(context.user, args.from); - if(user){ - res = res.concat(await connectors.getUserJoinGroupRequests(user, args.from)); - } - user = user || authentifiers.speaker(user, args.from); - if(user){ - res = res.concat(await connectors.getGroupJoinEventRequests(user, args.from)); - res = res.concat(await connectors.getYourGroupHostEventRequests(user, args.from)); - } - return res; - }, - - test: async function(obj, args, context){ - return connectors.getSimpleGroup(context.user, "br"); + test: async function(root, args, context){ + return conn.getSimpleGroup("br"); } }, @@ -152,37 +121,27 @@ export const resolvers = { // @rights admin(obj.groupUID) UserJoinGroup: { user : (obj, args, context) => { - return connectors.getUser(context.user, obj.useruid); - /*return connectors.getUser(context.user, "quentin.gendre"); - if(obj.useruid === "anatole.romon"){ - return connectors.getUser(context.user, "anatole.romon").then(res => { - return connectors.getUser(context.user, "quentin.gendre"); - }); - }else{ - return new Promise( (resolve, reject) => { - resolve({givenName : "patrick"}); - }); - }*/ + return conn.getUser(obj.useruid); } }, // @rights speaker(obj.groupUID) GroupJoinEvent : { event: (obj, args, context) => { - return connectors.getEvent(context.user, obj.eventuid); + return conn.getEvent(obj.eventuid); }, groupWantingToJoin: (obj, args, context) => { - return connectors.getGroup(context.user, obj.senderuid); + return conn.getGroup(obj.senderuid); } }, // @rights speaker(obj.groupUID) YourGroupHostEvent : { event: (obj, args, context) => { - return connectors.getEvent(context.user, obj.eventuid); + return conn.getEvent(obj.eventuid); }, sender: (obj, args, context) => { - return connectors.getGroup(context.user, obj.senderuid); + return conn.getGroup(obj.senderuid); } }, @@ -205,21 +164,23 @@ export const resolvers = { // Superviser mutations - takeAdminRights : async function(obj, args, context){ - let user = await authentifiers.superviser(context.user, args.from); - return user && await connectors.takeAdminRights(user, args.from, user.justification); + takeAdminRights : async function(obj, args, context) : Promise<boolean>{ + const justification = await auth.isSupervisor(context.user, args.from); + if(justification){ + return conn.takeAdminRights(context.user, args.from, justification); + }else{ + return false; + } }, releaseAdminRights : async function(obj, args, context){ - let user = await authentifiers.superviser(context.user, args.from); - return user && await connectors.releaseAdminRights(user, args.from, user.justification); + await conn.releaseAdminRights(context.user, args.from); }, // Admin mutations createSubgroup: async function (obj, args, context){ - let user = authentifiers.admin(context.user, args.from); - return user && connectors.createSubgroup(user, args); + throw new Error('Not implemented'); }, login: function (obj, args, context) { diff --git a/src/graphql/typeDefs/actions.graphql b/src/graphql/typeDefs/actions.graphql index 18fe6cf9786bb589aebfbda139ae4356142d5b97..136919d6fa02e1666af2e55bcd9b67a2bafa50fe 100644 --- a/src/graphql/typeDefs/actions.graphql +++ b/src/graphql/typeDefs/actions.graphql @@ -6,13 +6,12 @@ type Query { allGroups: [Group] allSimpleGroups: [SimpleGroup] - group(uid: ID!) : Group - simpleGroup(uid : ID!) : SimpleGroup - metaGroup(uid : ID!) : MetaGroup + group(gid: ID!) : Group + simpleGroup(gid : ID!) : SimpleGroup + metaGroup(gid : ID!) : MetaGroup # message queries - allMessages: [Message] message(id: ID!): Message allEvents: [Event] allAnnouncements: [Announcement] @@ -37,20 +36,6 @@ type Query { ip: String ): [String] - # Admin queries - - allRequests(from : String!) : [Request] - - # Speaker queries - - # allRequests(from : String!) : [Request] - - # Member Queries - - allMembers(from : String!) : [Group] - - # Viewer Queries - test : String }