diff --git a/.eslintrc.json b/.eslintrc.json
index ed55f719b7e472b089b05b9ae0c2b6eefe4e735f..6bc9af7e5870290ce9b10f5a7677cbd40d9db172 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -7,6 +7,7 @@
     "parserOptions": {
         "sourceType": "module"
     },
+    "parser": "babel-eslint",
     "rules": {
         "no-unused-vars": 0,
         "indent": ["error",4],
diff --git a/db/migrations/20180305111321_metaGroup_member_table.js b/db/migrations/20180305111321_metaGroup_member_table.js
new file mode 100644
index 0000000000000000000000000000000000000000..ab7268d3ee913ab518f8be69170f7c9006893411
--- /dev/null
+++ b/db/migrations/20180305111321_metaGroup_member_table.js
@@ -0,0 +1,13 @@
+
+exports.up = function(knex, Promise) {
+  return knex.schema.createTable('meta_group_membership', function (table){
+    table.timestamp(true, true);
+    table.string('member_uid').notNullable();
+    table.string('union_uid').notNullable();
+    table.enum('status', ['admin', 'speaker', 'basic']).notNullable();
+  });
+};
+
+exports.down = function(knex, Promise) {
+  return knex.schema.dropTable('meta_group_membership');
+};
diff --git a/db/seeds/01_create_groups.js b/db/seeds/01_create_groups.js
index ee9c1ce9463b9c3d697978667f06c15da9e955b1..fb2d49459c027fc55830236aced3132281aeb598 100644
--- a/db/seeds/01_create_groups.js
+++ b/db/seeds/01_create_groups.js
@@ -21,6 +21,14 @@ exports.seed = function(knex, Promise) {
           school: 'polytechnique',
           parentuid: 'kes',
           type : 'simple'
+        },{
+          name: 'Bôbar',
+          uid: 'bob',
+          description : "Viens. On est bien",
+          website: 'bôbar.binet.fr',
+          school: 'polytechnique',
+          parentuid: 'kes',
+          type : 'simple'
         },{
           name: 'Kès',
           uid: 'kes',
diff --git a/db/seeds/05_metagroup_membership.js b/db/seeds/05_metagroup_membership.js
new file mode 100644
index 0000000000000000000000000000000000000000..cd1587503a14bf8f86f50d8f3964f34113bae412
--- /dev/null
+++ b/db/seeds/05_metagroup_membership.js
@@ -0,0 +1,23 @@
+
+exports.seed = async function(knex, Promise) {
+    // Deletes ALL existing entries
+    await knex('meta_groups').del();
+    await knex('meta_group_membership').insert([
+      { 
+        member_uid : "br",
+        union_uid : "federez",
+        status : "admin"
+      },
+      { 
+        member_uid : "data",
+        union_uid : "federez",
+        status : "admin"
+      },
+      { 
+        member_uid : "bob",
+        union_uid : "bsckbl",
+        status : "admin"
+      }
+    ]);
+    return;
+};
diff --git a/package-lock.json b/package-lock.json
index 9f6530332ce026f63a160fc68c6b313652085a24..b802c1f4ee2898b0b22e4c9fddd4c487a1a4308a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,6 +4,120 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.40.tgz",
+      "integrity": "sha512-eVXQSbu/RimU6OKcK2/gDJVTFcxXJI4sHbIqw2mhwMZeQ2as/8AhS9DGkEDoHMBBNJZ5B0US63lF56x+KDcxiA==",
+      "requires": {
+        "@babel/highlight": "7.0.0-beta.40"
+      }
+    },
+    "@babel/generator": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.40.tgz",
+      "integrity": "sha512-c91BQcXyTq/5aFV4afgOionxZS1dxWt8OghEx5Q52SKssdGRFSiMKnk9tGkev1pYULPJBqjSDZU2Pcuc58ffZw==",
+      "requires": {
+        "@babel/types": "7.0.0-beta.40",
+        "jsesc": "2.5.1",
+        "lodash": "4.17.5",
+        "source-map": "0.5.7",
+        "trim-right": "1.0.1"
+      }
+    },
+    "@babel/helper-function-name": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.40.tgz",
+      "integrity": "sha512-cK9BVLtOfisSISTTHXKGvBc2OBh65tjEk4PgXhsSnnH0i8RP2v+5RCxoSlh2y/i+l2fxQqKqv++Qo5RMiwmRCA==",
+      "requires": {
+        "@babel/helper-get-function-arity": "7.0.0-beta.40",
+        "@babel/template": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40"
+      }
+    },
+    "@babel/helper-get-function-arity": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.40.tgz",
+      "integrity": "sha512-MwquaPznI4cUoZEgHC/XGkddOXtqKqD4DvZDOyJK2LR9Qi6TbMbAhc6IaFoRX7CRTFCmtGeu8gdXW2dBotBBTA==",
+      "requires": {
+        "@babel/types": "7.0.0-beta.40"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.40.tgz",
+      "integrity": "sha512-mOhhTrzieV6VO7odgzFGFapiwRK0ei8RZRhfzHhb6cpX3QM8XXuCLXWjN8qBB7JReDdUR80V3LFfFrGUYevhNg==",
+      "requires": {
+        "chalk": "2.3.1",
+        "esutils": "2.0.2",
+        "js-tokens": "3.0.2"
+      }
+    },
+    "@babel/template": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.40.tgz",
+      "integrity": "sha512-RlQiVB7eL7fxsKN6JvnCCwEwEL28CBYalXSgWWULuFlEHjtMoXBqQanSie3bNyhrANJx67sb+Sd/vuGivoMwLQ==",
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40",
+        "babylon": "7.0.0-beta.40",
+        "lodash": "4.17.5"
+      },
+      "dependencies": {
+        "babylon": {
+          "version": "7.0.0-beta.40",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.40.tgz",
+          "integrity": "sha512-AVxF2EcxvGD5hhOuLTOLAXBb0VhwWpEX0HyHdAI2zU+AAP4qEwtQj8voz1JR3uclGai0rfcE+dCTHnNMOnimFg=="
+        }
+      }
+    },
+    "@babel/traverse": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.40.tgz",
+      "integrity": "sha512-h96SQorjvdSuxQ6hHFIuAa3oxnad1TA5bU1Zz88+XqzwmM5QM0/k2D+heXGGy/76gT5ajl7xYLKGiPA/KTyVhQ==",
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.40",
+        "@babel/generator": "7.0.0-beta.40",
+        "@babel/helper-function-name": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40",
+        "babylon": "7.0.0-beta.40",
+        "debug": "3.1.0",
+        "globals": "11.3.0",
+        "invariant": "2.2.3",
+        "lodash": "4.17.5"
+      },
+      "dependencies": {
+        "babylon": {
+          "version": "7.0.0-beta.40",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.40.tgz",
+          "integrity": "sha512-AVxF2EcxvGD5hhOuLTOLAXBb0VhwWpEX0HyHdAI2zU+AAP4qEwtQj8voz1JR3uclGai0rfcE+dCTHnNMOnimFg=="
+        },
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "@babel/types": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.40.tgz",
+      "integrity": "sha512-uXCGCzTgMZxcSUzutCPtZmXbVC+cvENgS2e0tRuhn+Y1hZnMb8IHP0Trq7Q2MB/eFmG5pKrAeTIUfQIe5kA4Tg==",
+      "requires": {
+        "esutils": "2.0.2",
+        "lodash": "4.17.5",
+        "to-fast-properties": "2.0.0"
+      },
+      "dependencies": {
+        "to-fast-properties": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
+        }
+      }
+    },
     "@f/animate": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/@f/animate/-/animate-1.0.1.tgz",
@@ -503,6 +617,26 @@
         }
       }
     },
+    "babel-eslint": {
+      "version": "8.2.2",
+      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.2.tgz",
+      "integrity": "sha512-Qt2lz2egBxNYWqN9JIO2z4NOOf8i4b5JS6CFoYrOZZTDssueiV1jH/jsefyg+86SeNY3rB361/mi3kE1WK2WYQ==",
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.40",
+        "@babel/traverse": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40",
+        "babylon": "7.0.0-beta.40",
+        "eslint-scope": "3.7.1",
+        "eslint-visitor-keys": "1.0.0"
+      },
+      "dependencies": {
+        "babylon": {
+          "version": "7.0.0-beta.40",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.40.tgz",
+          "integrity": "sha512-AVxF2EcxvGD5hhOuLTOLAXBb0VhwWpEX0HyHdAI2zU+AAP4qEwtQj8voz1JR3uclGai0rfcE+dCTHnNMOnimFg=="
+        }
+      }
+    },
     "babel-runtime": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@@ -873,7 +1007,6 @@
       "version": "2.3.1",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz",
       "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==",
-      "dev": true,
       "requires": {
         "ansi-styles": "3.2.0",
         "escape-string-regexp": "1.0.5",
@@ -1825,7 +1958,6 @@
       "version": "3.7.1",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
       "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
-      "dev": true,
       "requires": {
         "esrecurse": "4.2.0",
         "estraverse": "4.2.0"
@@ -1834,8 +1966,7 @@
     "eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
-      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
-      "dev": true
+      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ=="
     },
     "espree": {
       "version": "3.5.3",
@@ -3367,8 +3498,7 @@
     "globals": {
       "version": "11.3.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz",
-      "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==",
-      "dev": true
+      "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw=="
     },
     "globby": {
       "version": "5.0.0",
@@ -3523,8 +3653,7 @@
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
     },
     "has-value": {
       "version": "1.0.0",
@@ -4088,6 +4217,11 @@
         "underscore": "1.8.3"
       }
     },
+    "jsesc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz",
+      "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4="
+    },
     "json-loader": {
       "version": "0.5.7",
       "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
@@ -6629,7 +6763,6 @@
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz",
       "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==",
-      "dev": true,
       "requires": {
         "has-flag": "3.0.0"
       }
@@ -6860,6 +6993,11 @@
         "nopt": "1.0.10"
       }
     },
+    "trim-right": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
+    },
     "tty-browserify": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
diff --git a/package.json b/package.json
index 3fb5e2449494c39592716faed3543c5ace252152..03650a7b435f0fcad1fe75e84fb914b6cfe58350 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
   "description": "Backend of sigma, the new Frankiz",
   "main": "index.js",
   "dependencies": {
+    "babel-eslint": "^8.2.2",
     "body-parser": "^1.18.2",
     "colors": "^1.1.2",
     "connect-ensure-login": "^0.1.1",
diff --git a/src/graphql/connectors/connectors.js b/src/graphql/connectors/connectors.js
index 0aea999c8b86c9b16380d9ecc67a98c28dbe84b5..6b431f7322b76a167affb16fd27e738b756b80aa 100644
--- a/src/graphql/connectors/connectors.js
+++ b/src/graphql/connectors/connectors.js
@@ -10,6 +10,51 @@ import { exportAllDeclaration } from 'babel-types';
 
 export { renseignerSurUtilisateur, repliquerTOLdesIds, listerMembres };
 
+/*
+Le tag @rights et la gestion des authorisations
+
+Le système GraphQL est pensé comme l'interface par laquelle les utilisateurs 
+intéragissent avec sigma, les graphismes en moins.
+Pour cette raison, et pour des questions de sécurité, il faut partir du principe que
+l'utilisateir peut rédiger n'importe quelle requête, et que c'est au niveau des resolvers
+que la sécurité ce déroule. C'est dans cette optique que j'utilise le tag @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 inclu dans les niveaus supérieur.
+Les différends 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érification, 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.
+*/
+
+
+
+
 /**
  * @summary Génère une promise.
  * @function
@@ -37,6 +82,7 @@ const quickPromise = (val) => {
  * @arg {Object} groupUID - L'id du groupe dont on veut connaître le type.
  * @return {Promise(String)} Un string représentant le type du groupe.
  * Peut être "SimpleGroup" ou "MetaGroup". Renvoie `Undefined` si le groupe n'existe pas
+ * @rights super
  */
 export const getGroupType = (user, groupUID) => {
     return knex('simple_groups').select('uid').where('uid', groupUID).then( sg_res => {
@@ -60,6 +106,7 @@ export const getGroupType = (user, groupUID) => {
  * @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 member(groupUID)
  */
 export const getUsersWithAdminRights = (user, groupUID) => {
     return getGroupType(user, groupUID).then( groupType => {
@@ -98,6 +145,7 @@ export const getUsersWithAdminRights = (user, groupUID) => {
  * @arg {Object} user - Objet contenant un attribut `uid` de type `string`. 
  * User représente l'utilisateur qui a effectué la requête. 
  * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
+ * rights user
  */
 export const hasAdminRights = (user, groupUID) => {
     if(user.uid == "anatole.romon")
@@ -114,6 +162,7 @@ export const hasAdminRights = (user, groupUID) => {
  * @arg {Object} user - Objet contenant un attribut `uid` de type `string`. 
  * User représente l'utilisateur qui a effectué la requête. 
  * @return {Promise(Callback)} callback contruisant une requête knex pour une table de tous les id visibles.
+ * @rights user
  */
 export const getVisibleGroupCallback = (user) => {
     return listerGroupes(user, user.uid).then(group_ids => {
@@ -166,6 +215,7 @@ function getGroupTableName(wantedType){
  * @arg {String} uid - 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"){
     let group_table_name = getGroupTableName(type);
@@ -174,34 +224,45 @@ export async function getGroupIfVisible(user, groupUID, type="all"){
         .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]);
-};
+}
 
 export const getSimpleGroupIfVisible = (user, groupUID) => getGroupIfVisible(user, groupUID, "simple");
 export const getMetaGroupIfVisible = (user, groupUID) => getGroupIfVisible(user, groupUID, "meta");
 
+export async function getAllVisibleSimpleGroups (user){
+    let visible_groups = await getVisibleGroupCallback(user);
+    return knex.with('visible_groups', visible_groups).select().from("simple_groups").innerJoin('visible_groups', function (){
+        this.on('visible_groups.uid', '=', 'simple_groups.uid');
+    });
+};
+
+export async function getAllVisibleMetaGroups (user){
+    let visible_groups = await getVisibleGroupCallback(user);
+    return knex.with('visible_groups', visible_groups).select().from("meta_groups").innerJoin('visible_groups', function (){
+        this.on('visible_groups.uid', '=', 'meta_groups.uid');
+    });
+};
+
 /**
  * @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, wantedType="all"){
-    let group_table_name = getGroupTableName(wantedType);
-    let visible_groups = await getVisibleGroupCallback(user);
-    return knex.with('visible_groups', visible_groups).select().from(group_table_name).innerJoin('visible_groups', function (){
-        this.on('visible_groups.uid', '=', group_table_name + '.uid');
-    });
-};
-
-export const getAllVisibleSimpleGroups = (user) => getAllVisibleGroups(user,"simple");
-export const getAllVisibleMetaGroups = (user) => getAllVisibleGroups(user,"meta");
+export async function getAllVisibleGroups(user){
+    let all_simple_groups = await getAllVisibleSimpleGroups(user);
+    let all_meta_groups = await getAllVisibleMetaGroups(user);
+    return all_simple_groups.concat(all_meta_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 const isMember = (user, groupUID) => {
     return listerGroupes(user, user.uid).then(group_ids => group_ids && group_ids.indexOf(groupUID) != -1);
@@ -212,6 +273,9 @@ export const isMember = (user, groupUID) => {
  * @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.
  */
 export function getAvailablegroupUID(initialUID){
     let rasUID = initialUID.replace(' ', '_').replace(/\W/g, '').toLowerCase();
@@ -222,7 +286,7 @@ export function getAvailablegroupUID(initialUID){
             return (getAvailablegroupUID(rasUID + 'n'));
         }
     });
-};
+}
 
 /**
  * @summary Créé un groupe si les arguments sont tous valides
@@ -234,6 +298,7 @@ export function getAvailablegroupUID(initialUID){
  * @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.parentuid)
  */
 export async function createSubgroup(user, args){
     if (typeof args.parentuid != 'string')
@@ -257,7 +322,7 @@ export async function createSubgroup(user, args){
     });
 
     return getGroupIfVisible(user, rasUID);
-};
+}
 
 /**
  * @summary Créé un groupe si les arguments sont tous valides et l'utilisateur est authorisé
@@ -267,6 +332,7 @@ export async function createSubgroup(user, args){
  * @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 user
  */
 export async function createGroupIfLegal(user, args){
     if( await hasAdminRights(user, args.parentuid) ){
@@ -274,7 +340,7 @@ export async function createGroupIfLegal(user, args){
     }else{
         throw "illegal request : you must have admin rights over a group to create a subgroup of that group";
     }
-};
+}
 
 /**
  * @summary Renvoie toues les requêtes de type UserJoinGroup 
@@ -283,11 +349,12 @@ export async function createGroupIfLegal(user, args){
  * @arg {Object} user - L'utilisateur qui effectue la requête. 
  * @arg {String} args - L'identifiant du groupe qui reçoit la requête. 
  * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe.
+ * @rights admin(recipientUID)
  */
 export function getUserJoinGroupRequests(user, recipientUID){
     return knex.select('id', 'useruid', 'message').from('user_join_group')
         .where('recipient', recipientUID);
-};
+}
 
 /**
  * @summary Renvoie toues les requêtes de type GroupJoinEvent 
@@ -298,11 +365,12 @@ export function getUserJoinGroupRequests(user, recipientUID){
  * @arg {Object} user - L'utilisateur qui effectue la requête. 
  * @arg {String} args - L'identifiant du groupe qui reçoit la requête. 
  * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe.
+ * @rights speaker(recipientUID)
  */
 export function getGroupJoinEventRequests(user, recipientUID){
     return knex.select('id', 'senderuid', 'eventuid', 'message').from('group_join_event')
         .where('recipient', recipientUID);
-};
+}
 
 
 /**
@@ -314,6 +382,7 @@ export function getGroupJoinEventRequests(user, recipientUID){
  * @arg {Object} user - L'utilisateur qui effectue la requête. 
  * @arg {String} args - L'identifiant du groupe qui reçoit la requête. 
  * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe.
+ * @rights speaker(recipientUID)
  */
 export const getYourGroupHostEventRequests = (user, recipientUID) => {
     return knex.select('id', 'senderuid', 'eventuid', 'message').from('your_group_host_event')
@@ -353,10 +422,11 @@ export const getEvent = (user, eventID) => {
 };
 
 /**
- * @function Renvoie simplement un groupe en fonction de son identifiant.
+ * @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 const getGroup = (user, groupUID) => {
     // Une sélection sur une table renvoie un tableau.
@@ -365,14 +435,47 @@ export const getGroup = (user, groupUID) => {
     return knex.select().from('groups').where('uid',groupUID).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 const getSimpleGroup = (user, groupUID) => {
     return knex.select().from('simple_groups').where('uid',groupUID).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 const getMetaGroup = (user, groupUID) => {
     return knex.select().from('meta_groups').where('uid',groupUID).then(results => results [0]);
 };
 
 export const getMetaGroupAdminMembers = (user, metaGroupUID) => {
     return quickPromise([]);
+};
+
+/**
+ * @function getMetaGroupMembers
+ * @summary Renvoie tous les membres d'un meta-groupe.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} metaGroupUID - Identifiant unique du groupe.
+ * @return {Promise(callback)} a callback to build a query for the members of a group
+ * It doesn't need to be a promise, but I figure having all of my functions return promises is 
+ * easier than keeping track of which functions do and do not return promises.
+ * @author akka vodol 
+ * @rights member(metaGroupUID)
+ */
+export async function getMetaGroupMembersCallback(user, metaGroupUID){
+    return function(query_builder){
+        return query_builder.distinct().select().from('groups')
+            .innerJoin('meta_group_membership', 'groups.uid', 'meta_group_membership.member_uid')
+            .where('meta_group_membership.union_uid', '=', metaGroupUID);
+    };
 };
\ No newline at end of file
diff --git a/src/graphql/resolvers.js b/src/graphql/resolvers.js
index 24c05c153eccf64fa35833b5466292eb07aff507..d7b681cd619ad33549c7016c9bfdff526486346d 100644
--- a/src/graphql/resolvers.js
+++ b/src/graphql/resolvers.js
@@ -16,13 +16,15 @@ import { connect } from 'http2';
 export const resolvers = {
     Query: {
 
-        asAdmin: (obj, args, context) => {
-            return connectors.hasAdminRights(context.user, args.groupUID).then(res => {
-                if(res)
-                    return {groupUID : args.groupUID};
-                else
-                    throw "You do not have admin rights over this group";
-            });
+        asAdmin: async function (obj, args, context){
+            if(await connectors.hasAdminRights(context.user, args.groupUID))
+                return {groupUID : args.groupUID};
+            else
+                throw "You do not have admin rights over this group";
+        },
+
+        asMember: function (obj, args, context){
+            return {groupUID : args.groupUID};
         },
 
         accessGroups: (obj, args, context) => {
@@ -42,6 +44,10 @@ export const resolvers = {
         allGroups: (obj, args, context) => {
             return connectors.getAllVisibleGroups(context.user);
         },
+        allSimpleGroups: (obj, args, context) => {
+            return connectors.getAllVisibleSimpleGroups(context.user);
+        },
+
         group: (obj, args, context) => {
             return connectors.getGroupIfVisible(context.user, args.uid);
         },
@@ -100,6 +106,17 @@ export const resolvers = {
         }
     },
 
+    MemberQuery: {
+        isMember: (obj, args, context) => {
+            return true;
+        },
+
+        allMembers: async function (obj, args, context){
+            let cb = await connectors.getMetaGroupMembersCallback(context.user, obj.groupUID);
+            return cb(knex);
+        }
+    },
+
     AllRequests: {
         userJoinGroup : (obj, args, context) => {
             return connectors.getUserJoinGroupRequests(context.user, obj.groupUID);
@@ -243,8 +260,6 @@ export const resolvers = {
     SimpleGroup: {
 
         members: (obj, args, context) => {
-            console.log("Current group is",obj.uid);
-            console.log("\tMembers of the group are:",obj);
             return connectors.listerMembres(context.user,obj.uid);
         }
     },
diff --git a/src/graphql/typeDefs.js b/src/graphql/typeDefs.js
index b77e9ea4bd531601dfba749d4aed7d7056145596..f226961c163cf0bf7a2c96ee935dd1f9c69d45de 100644
--- a/src/graphql/typeDefs.js
+++ b/src/graphql/typeDefs.js
@@ -7,7 +7,7 @@ const RootTypes = `
 
         asAdmin(groupUID: ID): AdminQuery
         asSpeaker(groupUID: ID): AdminQuery
-        asMember(groupUID: ID): AdminQuery
+        asMember(groupUID: ID): MemberQuery
         asViewer(groupUID: ID): AdminQuery
         
     }
@@ -51,7 +51,7 @@ const subMutations = `
 
     type SpeakerMutation{
         postEvent(name: String, date: String): Event
-        answerRequest(request: ID, accept : Boolean): Request
+        answerEventRequest(request: ID, accept : Boolean): Request
     }
 
     type MemberMutation {
@@ -72,6 +72,8 @@ const subQueries = `
     """
     type GroupQuery{
         allGroups: [Group]
+        allSimpleGroups: [SimpleGroup]
+
         group(uid: ID) : Group
         simpleGroup(uid : ID) : SimpleGroup
         metaGroup(uid : ID) : MetaGroup
@@ -122,6 +124,7 @@ const subQueries = `
 
     type MemberQuery{
         isMember: Boolean
+        allMembers : [Group]
     }
 
     type ViewerQuery{