diff --git a/README.md b/README.md
index 16a92272a1d0d7d9eb93d215adb02863633b7bb4..1b85b277cac47e63a0b894429997183da7b894e1 100644
--- a/README.md
+++ b/README.md
@@ -223,6 +223,16 @@ Il s'agit du même `/graphql` que l'_endpoint_ de l'API, mais le serveur est con
 
 [^doute]: euuuuh à vérifier...
 
+## Tests
+[^doute_tests]
+
+Sigma possède une suite de tests unitaires, déstinés à tester les resolvers graphql.
+
+Pour executer les tests, il suffit d'utiliser la commande `npm test`.
+
+Les tests effectués sont dans test/testData.js, sous la forme d'une liste. Chaque élément contient une requête graphql, et les données qu'elle doit renvoyer. Quand les seed sont modifiées, il faudra modifier les resultats attendus également. Les tests peuvent être créés ou mis à jour en entrant la requête dans graphiql, et en copiant le resultat.
+
+[^doute_tests]: cette fonctionnalité n'a pas été utilisée ni testée depuis beaucoup trop de commits pour que cette partie soit fiable actuellement (2018-12-04).
 
 ## Documentation
 
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/package-lock.json b/package-lock.json
index 1afc35330e24ddb34796d256b64734cb391dee76..4cbf45501c8205ecb29d0d5244aeb90c4786fb44 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3506,6 +3506,12 @@
       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
     },
+    "assertion-error": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+      "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+      "dev": true
+    },
     "assign-symbols": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
@@ -3884,6 +3890,12 @@
       "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
       "dev": true
     },
+    "browser-stdout": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+      "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+      "dev": true
+    },
     "browserify-aes": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
@@ -4175,6 +4187,20 @@
         "lazy-cache": "^1.0.3"
       }
     },
+    "chai": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
+      "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
+      "dev": true,
+      "requires": {
+        "assertion-error": "^1.1.0",
+        "check-error": "^1.0.2",
+        "deep-eql": "^3.0.1",
+        "get-func-name": "^2.0.0",
+        "pathval": "^1.1.0",
+        "type-detect": "^4.0.5"
+      }
+    },
     "chalk": {
       "version": "2.4.1",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
@@ -4231,6 +4257,12 @@
       "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
       "dev": true
     },
+    "check-error": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+      "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+      "dev": true
+    },
     "chokidar": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
@@ -4856,6 +4888,15 @@
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
       "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
     },
+    "deep-eql": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+      "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+      "dev": true,
+      "requires": {
+        "type-detect": "^4.0.0"
+      }
+    },
     "deep-extend": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -5022,6 +5063,12 @@
         }
       }
     },
+    "diff": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+      "dev": true
+    },
     "diffie-hellman": {
       "version": "5.0.3",
       "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@@ -6701,6 +6748,12 @@
       "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
       "dev": true
     },
+    "get-func-name": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+      "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+      "dev": true
+    },
     "get-stream": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
@@ -6919,6 +6972,12 @@
         "viz.js": "2.0.0"
       }
     },
+    "growl": {
+      "version": "1.10.5",
+      "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+      "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+      "dev": true
+    },
     "handlebars": {
       "version": "4.0.12",
       "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz",
@@ -7035,6 +7094,12 @@
         "minimalistic-assert": "^1.0.1"
       }
     },
+    "he": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+      "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+      "dev": true
+    },
     "header-case": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz",
@@ -8656,6 +8721,33 @@
       "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==",
       "dev": true
     },
+    "mocha": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
+      "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
+      "dev": true,
+      "requires": {
+        "browser-stdout": "1.3.1",
+        "commander": "2.15.1",
+        "debug": "3.1.0",
+        "diff": "3.5.0",
+        "escape-string-regexp": "1.0.5",
+        "glob": "7.1.2",
+        "growl": "1.10.5",
+        "he": "1.1.1",
+        "minimatch": "3.0.4",
+        "mkdirp": "0.5.1",
+        "supports-color": "5.4.0"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.15.1",
+          "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+          "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
+          "dev": true
+        }
+      }
+    },
     "moment": {
       "version": "2.21.0",
       "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz",
@@ -9392,6 +9484,12 @@
         "pify": "^3.0.0"
       }
     },
+    "pathval": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+      "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+      "dev": true
+    },
     "pause": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
@@ -11569,6 +11667,12 @@
         "prelude-ls": "~1.1.2"
       }
     },
+    "type-detect": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+      "dev": true
+    },
     "type-is": {
       "version": "1.6.16",
       "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
diff --git a/package.json b/package.json
index 3400d426f969b0a54173e6de6964f8d2d500f00a..e901a3974339b7d6f21f8b53dcca4b3d721724df 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,8 @@
     "start": "nodemon --watch build ./build/bundle.js",
     "start_prod": "node ./build/bundle.js",
     "doc": "jsdoc --configure configfile_doc.json",
-    "lint": "eslint --ext .js --ext .ts src/ "
+    "lint": "eslint --ext .js --ext .ts src/",
+    "test": "mocha --exit"
   },
   "repository": {
     "type": "git",
@@ -67,6 +68,7 @@
     "@types/node": "^10.12.10",
     "@types/passport": "^0.4.7",
     "babel-eslint": "^8.2.6",
+    "chai": "^4.2.0",
     "eslint": "^4.19.1",
     "eslint-config-standard": "^11.0.0",
     "eslint-loader": "^2.1.1",
@@ -74,10 +76,12 @@
     "eslint-plugin-node": "^6.0.1",
     "eslint-plugin-promise": "^3.8.0",
     "eslint-plugin-standard": "^3.1.0",
+    "graphql-request": "^1.8.2",
     "jsdoc": "^3.5.5",
     "jsdoc-babel": "^0.5.0",
     "jsdoc-to-markdown": "^4.0.1",
     "nodemon": "^1.18.7",
+    "mocha": "^5.2.0",
     "ts-loader": "^5.3.1",
     "typescript": "^3.2.1",
     "webpack": "^4.26.1",
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 8d44672f7bde4c5803aec19077e1d8c8d94f4b07..f392dc7f2ac930bfddcc4bf3b9d27b133131860c 100644
--- a/src/graphql/resolvers.ts
+++ b/src/graphql/resolvers.ts
@@ -8,8 +8,9 @@ import knex from '../../db/knex_router';
 
 import '../config_passport';
 
-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';
 
@@ -39,104 +40,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;
-        },
-
-        // 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);
+        user: async function(root, args, context){
+            return conn.getUser(args.uid);
         },
 
-        // 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;
+        searchTOL: (root, args, context) => {
+            // TODO : filter
+            return conn.searchUsers(args);
         },
 
-        test: async function(obj, args, context){
-            return connectors.getSimpleGroup(context.user, "br");
+        test: async function(root, args, context){
+            return conn.getSimpleGroup("br");
         }
     },
 
@@ -150,37 +119,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);
         }
     },
 
@@ -203,21 +162,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');
         },
     },
 
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
 }
 
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000000000000000000000000000000000000..15eb334306f0c1ec4be59c9578c67b8818a0bc3a
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,80 @@
+require('dotenv').config()
+
+const { credentialsConfig } =  require('../src/ldap/config');
+
+process.env.PORT = process.env.TEST_PORT || 3001;
+// The port is changed so that the test suite can be ran without interfering with a running server
+
+require('../build/bundle');
+
+const chai = require('chai');
+
+const expect = chai.expect;
+
+const { GraphQLClient } = require('graphql-request')
+
+const apiEndpoint = `http://localhost:${process.env.PORT || 3001}/graphql`;
+
+const auth = {
+  username : credentialsConfig.dn.split("=")[1].split(",")[0], 
+  password : credentialsConfig.passwd
+};
+
+const testList = require('./testData').testList;
+
+describe('test server API', function () {
+  
+  let client;
+
+  it('Should authentify and initialize the client', async function (){
+
+    const tempClient = new GraphQLClient(apiEndpoint);
+    const query = `
+    mutation {
+      login(username : "${auth.username}", password: "${auth.password}" ) 
+    }
+    `;
+
+    const res = await tempClient.request(query);
+    
+    expect(res).to.have.property('login');
+
+    const token = res.login;
+
+    client = new GraphQLClient(apiEndpoint, {
+      headers: {
+        mode : 'cors',  // Don't know what that does, isn't necessary. Worth looking into
+        credentials : 'include',  // Same
+        authorization: `Bearer ${token}`
+      }
+    });
+
+  });
+
+  it('Should query all groups to test the client', async function (){
+    const query = `
+    query {
+      allGroups {
+        name
+      }
+    }
+    `;
+
+    const res = await client.request(query);
+
+
+    expect(res).to.have.property('allGroups');
+    expect(res.allGroups).to.be.an('array');
+    expect(res.allGroups).to.have.lengthOf.above(3);
+  });
+
+  for(const test of testList){
+
+    it(test.description, async function (){
+      const res = await client.request(test.query);
+      expect(res).to.be.deep.equal(test.result);
+    });
+
+  }
+
+});
diff --git a/test/testData.js b/test/testData.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5a32126ab5754bd0c519edec0c7aa56f1ff720b
--- /dev/null
+++ b/test/testData.js
@@ -0,0 +1,83 @@
+/*
+* This is the list of unit tests which will be ran by the npm test command.
+* To add new unit tests, just write the query you want to test in GraphiQL,
+* then add new entries to the list with the following format :
+*   query : the query you wrote
+*   result : the output returned by GraphiQL
+*   description : what the test does
+*
+*   Tests should be written to work on the current seed
+*   If the seed is modified, the expected result for the tests will have to be changed as well
+*/
+
+exports.testList = [
+    {
+      query : `query{allGroups{name}}`,
+      result: {
+        "allGroups": [
+          { "name": "BR" },
+          { "name": "JTX" },
+          { "name": "Faërix" },
+          { "name": "Bôbar" },
+          { "name": "Kès" },
+          { "name": "Subaïsse" },
+          { "name": "X-Broadway" },
+          { "name": "Å’nologie" },
+          { "name": "Tribunes de l'X" },
+          { "name": "X-Finance" },
+          { "name": "ASK" }
+        ]
+      },
+      description : "Should query all groups"
+    },
+    {
+      query : `
+      query{group(uid : "br"){
+        uid,
+        name,
+        website
+      }}`,
+      result : {
+        "group": {
+          "uid": "br",
+          "name": "BR",
+          "website": "br.binets.fr"
+        }
+      },
+      description : "Should query a single group"
+    },
+    {
+      query : `query{
+        allMessages{
+          id,
+          title,
+          content
+        }
+      }`,
+      result : {
+        "allMessages": [
+          {
+            "id": "11",
+            "title": "Fête de la lune",
+            "content": "La fête de la lune, c'est bientôt dans le grand hall !"
+          },
+          {
+            "id": "12",
+            "title": "Perm BR du mardi soir",
+            "content": "La perm' BR c'est maintenant!"
+          },
+          {
+            "id": "13",
+            "title": "Formation Git",
+            "content": "Aujourd'hui, on va parler du système de contrôle de versions Git, qui est particulièrement utile pour travailler à plusieurs sur des projets informatiques: PSC, code de PI ou de projet de MAP, site binet, quoi que ce soit!"
+          },
+          {
+            "id": "14",
+            "title": "Formation Web",
+            "content": "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !"
+          }
+        ]
+      },
+      description : "Should fetch all messages"
+    }
+  ];
\ No newline at end of file