Skip to content
Snippets Groups Projects
Commit 753d05b9 authored by Wilson JALLET's avatar Wilson JALLET :money_with_wings:
Browse files

Merge branch 'master' into fix_resolver_dev

This was terrible
parents eff9386e 4a24cb7a
No related branches found
No related tags found
No related merge requests found
Showing
with 4956 additions and 3856 deletions
src/
ldap_connexion_config.json
\ No newline at end of file
# Official framework image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/node/tags/
image: node:latest
image: node:10-stretch
# Only needed when using a docker container to run your tests in.
# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
......@@ -26,44 +26,41 @@ stages:
install-dependencies:
stage: install
script:
- npm install -q
- npm ci
artifacts:
paths:
- node_modules/
tags:
- build
build:
stage: build
script:
- npm run build
- knex migrate:latest
- knex seed:run
before_script:
- export NODE_ENV=staging
- echo $LDAP_CONN_CONFIG > ldap_connexion_config.json
script: npm run build
artifacts:
paths:
- build/
tags:
- build
- database
deploy-staging:
stage: deploy
only:
- stable
before_script:
- export NODE_ENV=staging
- eval $(ssh-agent -s)
- ssh-add <(echo "$STAGING_PRIVATE_KEY")
- mkdir -p ~/.ssh
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
script:
- ssh -p22 sigma-dev@roued "mkdir -p /opt/sigma-back-dev"
- ssh -p22 sigma-dev@roued "rm -rf /opt/sigma-back-dev/build"
- ssh -p22 sigma-dev@roued "rm -rf /opt/sigma-back-dev/assets"
- scp -p22 -r build/ sigma-dev@roued:/opt/sigma-back-dev/build
- scp -p22 -r assets/ sigma-dev@roued:/opt/sigma-back-dev/assets
- scp -p22 package.json "package-lock.json" ldap_config.json ldap_connexion_config.json sigma-back-dev.service sigma-dev@roued:/opt/sigma-back-dev/
- ssh -p22 sigma-dev@129.104.201.10 "mkdir -p /opt/sigma-back-dev"
- ssh -p22 sigma-dev@129.104.201.10 "rm -rf /opt/sigma-back-dev/build"
- ssh -p22 sigma-dev@129.104.201.10 "rm -rf /opt/sigma-back-dev/assets"
- scp -p22 -r build/ sigma-dev@129.104.201.10:/opt/sigma-back-dev/build
- scp -p22 -r assets/ sigma-dev@129.104.201.10:/opt/sigma-back-dev/assets
- scp -p22 -r db/ sigma-dev@129.104.201.10:/opt/sigma-back-dev/db
- scp -p22 knexfile.js sigma-dev@129.104.201.10:/opt/sigma-back-dev/knexfile.js
- ssh -p22 sigma-dev@129.104.201.10 "cd /opt/sigma-back-dev && knex migrate:latest && knex seed:run"
- scp -p22 package.json "package-lock.json" ldap_config.json ldap_connexion_config.json sigma-back-dev.service sigma-dev@129.104.201.10:/opt/sigma-back-dev/
environment:
name: staging
url: http://129.104.210.10:3000
tags:
- deployment
\ No newline at end of file
url: http://129.104.201.10:3000
# Contribuer
## Description et actualité des branches
### _stable_
- déploiement de l'API pour les développeurs du front
### _master_
- une branche où on fait des petits commits pour merge dans stable
### _schema_kadabra_
- la branche sur laquelle kadabra commitait sa wish-list, maintenant c'est fait (on devrait supprimer cette branche d'ailleurs)
### *resolver_dev*
- branche sur laquelle akka vodol fais tout mon travail. Comme ça, il peut faire d'éventuelles modifications du schéma sans faire chier les autres, et ensuite on valide ensemble pour merge
### _orienteobjet_
- branche sur laquelle hawkspar développait la version "orienté objet" de ldap_data.js
## Structure
La structure générale du projet est détaillée ci-dessous ; pas d'inquiétude, la plupart des fichiers .js sont aussi extensivement documentés plus bas.
- Racine du projet : fichiers de configuration ;
- config.json : données "sensibles" spécifique au projet à priori non partageable (adresse du LDAP, mots de passe),
- configfile_doc.json : JSDoc, l'outil de génération automatique de documentation,
- autres fichiers relatifs à des modules particuliers ou à la gestion de paquets,
- [`assets`](../assets) : ressources ;
- images et divers (dont l'essentiel flavicon)
- [`build`](../build) : dépendances gérées automatiquement ;
- bundle.js est un monstrueux fichier généré automatiquement qui gère nos dépendances.
- [`db`](../db) : base de donnée sigma ;
- knex_router.js charge la configuration précisée dans knexfile.js,
- [`migrations`](../db/migrations) stocke l'ensemble des migrations knex ; c'est un équivalent d'un répertoire git pour la BDD sigma (du coup seulement les groupes pas les individus),
- [`seeds`](../db/seeds) : stocke les éléments de générations des BDD ; c'est un ensemble de scripts.
- [`doc`](.) : documentation ;
- ensemble de pages html et fichiers associés ; index.html permet de naviguer sereinement sur toute la doc JSDoc.
- [`node_modules`](../node_modules) : gestion automatique des modules.
- [`src`](../src) : code source
- [`admin_view`](../src/admin_view) : gestion d'une interface administrateur de la base de donnée, s'appuie sur *css* et *views*
- [`ldap`](../src/ldap) : gestion des requêtes LDAP
La syntaxe adoptée est JavaScript ES6, un standard moderne (2015) de JavaScript. Il permet d'importer des dépendances en utilisant le mot-clé `import`, ce que le serveur Node.js ne comprend pas puisque la version 8 de Node ne comprend que le standard ES5 (2009), qui gère les imports avec `require()`.
## Base de données
Sigma s'appuie sur deux bases de données :
- La BDD frankiz accessible par LDAP hébergée sur un serveur de l'école, qui contient identifiants, mots de passe, et toutes les informations sur les utilisateurs et groupes spécifiques X.
- On y accède par des requêtes LDAP, d'où la nécessité de ldap.js.
- La BDD de sigma propre est en [PostgreSQL](https://www.postgresql.fr/), hébergée en propre BR, qui contient les groupes et leurs niveaux de visibilité mais peu d'information sur les utilisateurs (seulement son école).
- Les requêtes à cette base de données sont gérées par [Knex.js](http://knexjs.org).
Cette structure peut sembler lourde et redondante mais s'explique par plusieurs raisons :
- Volonté d'intégrer d'autres écoles simplement
- Rajouter leurs groupes sur la BDD sigma
- Pas les obliger à rejoindre notre LDAP avec notre structure
- Garder le LDAP X et le mettre à jour ; il est utilisé par beaucoup d'autres sites X
- Enjeu de sécurité
- La BDD de sigma est public et ne comporte rien de compromettant
- La BDD accessible par LDAP de l'X qui contient des informations plus sensibles et qui doit être plus protégée
Les deux sections suivantes détaillent les opérations possibles grâce au back directement sur les bases de données via sigma.
### Guide: Knex.js
L'interface en ligne de commande de [Knex.js](http://knexjs.org) contient les commandes suivantes :
- `knex migrate:make migration_name` crée une migration dans `db/migrations/`
- `knex migrate:latest` met à jour le schéma de la BDD
- `knex seed:make filename` crée un _seed_ `seeds/filename`
- `knex seed:run` insère les _seeds_ dans la BDD
Un fichier _seed_ permet d'insérer des données dans la BDD. Ils sont stockés dans [`seeds`](../db/seeds).
#### Comment faire une migration
On utilisera l'interface en ligne de commande de Knex.js.
Les migrations servent à **mettre à jour le schéma de la base de données**. Pour créer une migration, on lance la commande `knex migrate:make <nom_migration>`, qui crée un fichier `db/migrations/[hash]_nom_migration.js` où le hash est la date et l'heure.
Maintenant, on édite le fichier de migration. Il fait deux exports, `exports.up` et `exports.down`, qui définissent respectivement comment mettre à jour le schéma de la BDD et comment annuler la modification si `knex migrate:rollback` est invoqué.
Il faut se référer à la documentation de Knex.js pour comprendre comment écrire les requêtes. Voici un [cheatsheet](https://devhints.io/knex).
### Fonctions LDAP
On peut facilement explorer et modifier des éléments du LDAP de l'école depuis le réseau de l'X avec [JXplorer](http://jxplorer.org/) en entrant `frankiz` dans nouvelle connexion et en allant dans `net`.
### Accéder à la BDD de sigma propre
Pour accéder à la "vraie" BDD, sur roued (le serveur qui héberge sigma), il faut
- se connecter dessus en `ssh roued`
- passer en `sudo`
- faire un `su postgres` pour se faire passer pour l'utilisateur unix postgres
- se connecter à la BDD via la commande `psql`
- faire les requetes en SQL par l'interface de postgreSQL.
## Panneau d'administration
### Authentification
L'authentification se fait contre le LDAP en envoyant un requête HTTP POST à '/adminview/avlogin'. C'est une page distincte de '/login' qui est utilisé pour les requetes d'authentification à partir du client front, pour pouvoir facilement distinguer les deux comportements :
- login depuis le panneau d'administration (POST à '/adminview/avlogin') : `passport.authenticate(...)` puis redirection vers GET '/adminview/admin'
- login depuis le client front (requête POST à '/login']) : `passport.authenticate(...)` puis renvoyer une reponse au client
### Accès direct à la BDD via knex
Le panneau d'administration sert (ou plutôt, servira à terme) à accéder directement à la BDD propre de sigma. On accède à la table `table_name` par une requête GET à '/adminview/db/`table_name`' et aux colonnes `columns` de cette table par une requête GET à '/adminview/db/`table_name`?columns=`columns`.
Ces pages sont protégées pour n'être accessibles qu'en étant authentifé.
### GraphiQL et Voyager
A partir du panneau d'admin, en faisant des requêtes GET à '/graphiql' et '/voyager' respectivement, on accède à GraphiQL et à GraphQL Voyager. Ces pages sont protégées pour n'être accessibles qu'en étant authentifé.
## Appendixes
### ESLint
On utilisera ESLint pour standardiser le code : un ensemble de règles de style pour le code sont appliquées, et quelques-unes d'entre elles sont dans le fichier `.eslintrc.json`. Pour l'instant, la config ESLint impose d'utiliser quatre espaces pour les indentations et d'utiliser des points-virgule en fin de ligne.
Il est préférable de l'installer **globalement** avec `npm install -g eslint`. Pour faire valider les fichiers source par ESLint, utilisez `npm run lint`.
qui fait appel au script `eslint src/` défini dans le [`package.json`](../package.json). L'option `--fix` permet de corriger les fichiers.
Sinon, si vous utilisez Atom ou Visual Studio Code pour éditer votre code, il existe des plugins qui font tourner ESLint en _live_ sur le code et vérifient que tout est en ordre.
Pour mieux comprendre ESLint, référez-vous à la [doc](https://eslint.org/docs/user-guide/getting-started).
## Contact
le BR 2016
FROM node:10.9-alpine
CMD [ "node", "build/bundle.js" ]
......@@ -8,9 +8,9 @@ Pour obtenir une copie de ce dépôt, clonez-le avec
git clone git@gitlab.binets.fr:br/sigma-backend.git
ou `git clone https://gitlab.binets.fr/br/sigma-backend.git`, puis installez les dépendences JavaScript avec `npm install`.
ou `git clone https://gitlab.binets.fr/br/sigma-backend.git`, puis installez les dépendances JavaScript avec `npm install`.
A terme, ce projet doit tourné sur un serveur de l'école polytechnique et fournir à un serveur front *au code séparé et documenté séparément* toute les données nécessaires à son bon fonctionnement (authentification, appartenance à un groupe, droits de visibilité...).
À terme, ce projet doit tourner sur un serveur du BR et servir d'API à un _frontend_ React *au code séparé et documenté séparément* toute les données nécessaires à son bon fonctionnement (authentification, appartenance à un groupe, droits de visibilité...). Le dépôt pour le serveur front se trouve ici : <https://gitlab.binets.fr/br/sigma-frontend> (on l'appellera indifféremment serveur front, front ou frontend...)
Ce document détaille les différentes dépendances du projet, sa structure générale, détaille un peu plus des éléments sur la base de données et la documentation ; le code est également commenté en détail.
......@@ -31,80 +31,49 @@ npm install -g webpack
npm install -g eslint
```
Les dépendances les plus importantes sont knex.js, notre outil de gestion de BDD locale, GraphQL qui sert à communiquer entre serveurs, ldap.js qui interroge le LDAP avec la plupart des données, webpack qui sert à la gestion du serveur. ESlint est un outil de vérification synthaxique.
Les dépendances les plus importantes sont knex.js, notre outil de gestion de BDD locale, GraphQL qui sert à communiquer entre serveurs, ldap.js qui interroge le LDAP avec la plupart des données, webpack qui sert à la gestion du serveur. ESlint est un outil de vérification syntaxique.
Le serveur utilisé est [express.js](https://expressjs.com/) ; il est configuré dans [`server.js`](../src/server.js) puis lancé sur le port 8888 dans [`index.js`](../src/index.js).
Le serveur utilisé est [express.js](https://expressjs.com/) ; il est configuré dans [`server.js`](../src/server.js) puis lancé sur le port 3000 dans [`index.js`](../src/index.js).
## Structure
## Configuration LDAP
La structure générale du projet est détaillée ci-dessous ; pas d'inquiétude, la plupart des fichiers .js sont aussi extensivement documentés plus bas.
L'API de Sigma nécessite de se connecter au LDAP Frankiz, à la fois pour obtenir des données et pour l'authentification des utilisateurs. Cela est fait à l'aide de la librairie [ldapjs](http://ldapjs.org) pour faire les requêtes au LDAP et [passportJS](http://www.passportjs.org/) pour l'auth.
* Racine du projet : fichiers de configuration ;
* config.json : données "sensibles" spécifique au projet à priori non partageable (adresse du LDAP, mots de passe),
* configfile_doc.json : JSDoc, l'outil de génération automatique de documentation,
* autres fichiers relatifs à des modules particuliers ou à la gestion de paquets,
* [`assets`](../assets) : ressources ;
* images et divers (dont l'essentiel flavicon)
* [`build`](../build) : dépendances gérées automatiquement ;
* bundle.js est un monstrueux fichier généré automatiquement qui gère nos dépendances.
* [`db`](../db) : base de donnée sigma ;
* knex_router.js charge la configuration précisée dans knexfile.js,
* [`migrations`](../db/migrations) stocke l'ensemble des migrations knex ; c'est un équivalent d'un répertoire git pour la BDD sigma (du coup seulement les groupes pas les individus),
* [`seeds`](../db/seeds) : stocke les éléments de générations des BDD ; c'est un ensemble de scripts.
* [`doc`](.) : documentation ;
* ensemble de pages html et fichiers associés ; index.html permet de naviguer sereinement sur toute la doc JSDoc.
* [`node_modules`](../node_modules) : gestion automatique des modules.
* [`src`](../src) : code source
* [`admin_view`](../src/admin_view) : gestion d'une interface administrateur de la base de donnée, s'appuie sur *css* et *views*
* [`ldap`](../src/ldap) : gestion des requêtes LDAP
* La configuration LDAP de base se situe dans [ldap_config.json](ldap_config.json).
* Elle est importée dans l'application depuis [src/ldap/config.js](src/ldap/config.js). Ce fichier écrase la config de base selon les options suivantes :
La syntaxe adoptée est JavaScript ES6, un standard moderne (2015) de JavaScript. Il permet d'importer des dépendances en utilisant le mot-clé `import`, ce que le serveur Node.js ne comprend pas puisque la version 8 de Node ne comprend que le standard ES5 (2009), qui gère les imports avec `require()`.
| **Variable** | **Description** | **Défaut** (`ldap_config.json`) |
| ------ | ------ | ----- |
| LDAP_URI | URI vers le serveur LDAP. | <ldap://frankiz.eleves.polytechnique.fr:389> |
## Base de données
### Exemple
Sigma s'appuie sur deux bases de données :
Si on développe en dehors du plâtal et qu'on ouvre un proxy SSH _port forwarding_ du LDAP de Frankiz (<frankiz.polytechnique.fr:389>) vers <localhost:8389>, on s'y connecte en définissant
* La BDD frankiz accessible par LDAP hébergée sur un serveur de l'école, qui contient identifiants, mots de passe, et toutes les informations sur les utilisateurs et groupes spécifiques X.
* On y accède par des requêtes LDAP, d'où la nécessité de ldap.js.
* La BDD de sigma propre est en [PostgreSQL](https://www.postgresql.fr/), hébergée en propre BR, qui contient les groupes et leurs niveaux de visibilité mais peu d'information sur les utilisateurs (seulement son école).
* Les requêtes à cette base de données sont gérées par [Knex.js](http://knexjs.org).
Cette structure peut sembler lourde et redondante mais s'explique par plusieurs raisons :
* Volonté d'intégrer d'autres écoles simplement
* Rajouter leurs groupes sur la BDD sigma
* Pas les obliger à rejoindre notre LDAP avec notre structure
* Garder le LDAP X et le mettre à jour ; il est utilisé par beaucoup d'autres sites X
* Enjeu de sécurité
* La BDD de sigma est public et ne comporte rien de compromettant
* La BDD accessible par LDAP de l'X qui contient des informations plus sensibles et qui doit être plus protégée
Les deux sections suivantes détaillent les opérations possibles grâce au back directement sur les bases de données via sigma.
### Guide: Knex.js
```bash
export LDAP_URI=ldap://localhost:8389
```
L'interface en ligne de commande de [Knex.js](http://knexjs.org) contient les commandes suivantes :
et le fichier `config.js` s'occupe du reste.
* `knex migrate:make migration_name` crée une migration dans `db/migrations/`
* `knex migrate:latest` met à jour le schéma de la BDD
* `knex seed:make filename` crée un _seed_ `seeds/filename`
* `knex seed:run` insère les _seeds_ dans la BDD
## Panneau d'administration
Un fichier _seed_ permet d'insérer des données dans la BDD. Ils sont stockés dans [`seeds`](../db/seeds).
Il est accessible au path `/adminview/admin` ; n'importe quel path devrait rediriger dessus, ou alors vers `/adminview/login`. Les identifiants à utiliser sont ceux de Frankiz. L'authentification se fait par le LDAP Frankiz.
#### Comment faire une migration
### Accès direct à la BDD via knex
On utilisera l'interface en ligne de commande de Knex.js.
Le panneau d'administration sert (ou plutôt, servira à terme) à accéder directement à la BDD propre de sigma. On accède à la table `table_name` par une requête GET à `/adminview/db/table_name`' et aux colonnes `columns` de cette table par une requête GET à `/adminview/db/table_name`?columns=`columns`.
Ces pages sont protégées pour n'être accessibles qu'en étant authentifié.
Les migrations servent à **mettre à jour le schéma de la base de données**. Pour créer une migration, on lance la commande `knex migrate:make <nom_migration>`, qui crée un fichier `db/migrations/[hash]_nom_migration.js` où le hash est la date et l'heure.
### GraphQL Playground et Voyager
Maintenant, on édite le fichier de migration. Il fait deux exports, `exports.up` et `exports.down`, qui définissent respectivement comment mettre à jour le schéma de la BDD et comment annuler la modification si `knex migrate:rollback` est invoqué.
Accéder via un navigateur à `/graphql` et `/voyager` respectivement renvoie les apps GraphQL Playground et GraphQL Voyager.
Il faut se référer à la documentation de Knex.js pour comprendre comment écrire les requêtes. Voici un [cheatsheet](https://devhints.io/knex).
Il s'agit du même `/graphql` que l'_endpoint_ de l'API, mais le serveur est configuré de sorte à renvoyer Playground lorsqu'il détecte un accès via navigateur. Les requêtes dans le Playground sont donc soumises au mêmes permissions que dans l'API.
### Fonctions LDAP
L'app Voyager permet de visualiser le « graphe » sous-jacent à la structure de l'API. Cet _endpoint_ devrait être protégé **en prod**.
On peut facilement explorer et modifier des éléments du LDAP de l'école depuis le réseau de l'X avec [JXplorer](http://jxplorer.org/) en entrant `frankiz` dans nouvelle connexion et en allant dans `net`.
**En production**,
## Scripts
......@@ -117,14 +86,17 @@ On utilisera Webpack pour transpiler le fichier source [`src/index.js`](../src/i
* `npm run build` qui exécute la commande `webpack` avec le fichier de configuration `webpack.config.js`, ou
* `npm run watch` qui recompile automatiquement dès que le code est modifié.
Pour faire tourner le serveur, il y a deux options :
### Démarrer le serveur
Pour faire tourner le serveur, lancer
npm start
* `npm start` fait tourner le serveur `bundle.js` en mode prod sur le port 3000 (donc il faut consulter https://localhost:3000)
* `npm test` le démarre avec [nodemon](https://nodemon.io/), outil dév qui redémarre automatiquement le serveur dans `bundle.js` dès que celui-ci est modifié.
démarre le serveur compilé [`build/bundle.js`](build/bundle.js) avec [nodemon](https://nodemon.io/), outil dév, et le redémarre automatiquement après modification.
Donc, lancer `npm run watch` dans un terminal et `npm test` dans un autre permet de recompiler le serveur __et__ le redémarrer automatiquement dès qu'il y a une modification.
Donc, lancer `npm run watch` dans un terminal et `npm start` dans un autre permet de recompiler le serveur __et__ le relance automatiquement.
Le script pour faire tourner [JSDoc](http://usejsdoc.org/index.html) et régénérrer la documentation est : `npm run doc`
Le script pour faire tourner [JSDoc](http://usejsdoc.org/index.html) et régénérer la documentation est : `npm run doc`
## Documentation
......@@ -132,18 +104,4 @@ La documentation détaillée du projet est [ici](./doc/index.html). Elle a été
Les fichiers compilés se situent dans [`doc`](.) avec leurs fichiers image. Par nature de l'outil JSDoc il est facile de documenter en détail des fonctions .js mais plus compliqué de documenter un fichier.
A la fin de ce fichier JSDoc rajjoute les commentaires placés dans chacun des fichiers et des hyperliens pour y accéder.
## Appendixes
### ESLint
On utilisera ESLint pour standardiser le code : un ensemble de règles de style pour le code sont appliquées, et quelques-unes d'entre elles sont dans le fichier `.eslintrc.json`. Pour l'instant, la config ESLint impose d'utiliser quatre espaces pour les indentations et d'utiliser des points-virgule en fin de ligne.
Il est préférable de l'installer **globalement** avec `npm install -g eslint`. Pour faire valider les fichiers source par ESLint, utilisez `npm run lint`.
qui fait appel au script `eslint src/` défini dans le [`package.json`](../package.json). L'option `--fix` permet de corriger les fichiers.
Sinon, si vous utilisez Atom ou Visual Studio Code pour éditer votre code, il existe des plugins qui font tourner ESLint en _live_ sur le code et vérifient que tout est en ordre.
Pour mieux comprendre ESLint, référez-vous à la [doc](https://eslint.org/docs/user-guide/getting-started).
\ No newline at end of file
A la fin de ce fichier JSDoc rajoute les commentaires placés dans chacun des fichiers et des hyperliens pour y accéder.
......@@ -7,8 +7,7 @@ exports.up = function(knex, Promise) {
exports.down = function(knex, Promise) {
return knex.schema.table('requests', function (table) {
table.renameColumn('recipient', 'recepient').then(() => {
return knex.schema.rable('requests','request');
});
table.renameColumn('recipient', 'recepient');
table.renameColumn('requests','request');
});
};
/*
Une mutation pour rajouter dans la BDD les types SimpleGroup et MetaGroup
(cf la documentation de l'interface GraphQL)
(cf la documentation de l'API GraphQL)
Les objets qui étaient jusqu''à présent stoqués dans la table groups
sont déplacés dans la table simple_groups
En cas de rollback, le déplacement se fait dans l'autre sens
......
......@@ -17,6 +17,7 @@ exports.seed = function(knex, Promise) {
},{
name: 'JTX',
uid: 'jtx',
description: "Le Journal Télévisé de l'X te fait revivre les évènements promo en images et expose régulièrement ses créations.",
website: 'binet-jtx.com',
school: 'polytechnique',
parentuid: 'kes',
......@@ -25,20 +26,22 @@ exports.seed = function(knex, Promise) {
name: 'Faërix',
uid: 'faerix',
website: 'faerix.net',
description: "Faërix est le binet de jeux de l'école : jeux de cartes, de plateau, de rôles... Le binet organise chaque année, sur un week-end, une convention de jeux de rôles, les Rencontres Rôlistes de l'X.",
school: 'polytechnique',
parentuid: 'kes',
type : 'simple'
},{
name: 'Bôbar',
uid: 'bob',
description : "Viens. On est bien",
website: 'bôbar.binet.fr',
description: "Le bar de l'École polytechnique, tenu par et pour les X. Le BôBar t'enkhûle avec affection",
website: 'http://tdb.bobar.pro/',
school: 'polytechnique',
parentuid: 'kes',
type : 'simple'
},{
name: 'Kès',
uid: 'kes',
description: "La Kès est le bureau des élèves de l'école, constitué de 16 kessiers élus par la promotion. Son local est ouvert de 12h30 à 22h30 tous les jours de la semaine (vendredi jusqu'à 18h15), et se trouve à l'entrée Est du Bataclan. Pour plus d'infos : consultez le Wikix ou téléphonez au 2726 pour faire un gros bisou à Mina et Zaza",
website: 'kes.binets.fr',
school: 'polytechnique',
type : 'simple'
......@@ -55,8 +58,7 @@ exports.seed = function(knex, Promise) {
website: 'laserwave.fr',
school: 'supoptique',
type : 'simple'
},
{
},{
name: 'WikiX',
uid: 'wikix',
website: 'https://wikix.polytechnique.org/',
......@@ -69,23 +71,59 @@ exports.seed = function(knex, Promise) {
website: 'http://bde.ensta-paristech.fr/',
school: 'ensta',
type : 'simple'
},
{
},{
name: "X-Chine",
uid: "x-chine",
website: "",
school: "polytechnique",
description: `X-Chine est le binet qui rassemble les amoureux et les curieux de l'Empire du Milieu, qu'ils soient chinois ou non !`,
type: "simple"
},
{
},{
name: 'Subaïsse',
uid: 'subaisse',
description: 'Le Binet de ceux qui subissent',
school: 'polytechnique',
parentuid: 'kes',
type : 'simple'
},
},{
name: 'X-Broadway',
uid: 'xbroadway',
website: 'https://xbroadway.binets.fr/',
description: "Créé par la promotion 2012, le binet X-Broadway prépare pendant une année une comédie musicale qu'il joue durant le tronc commun de la promo suivante. Chaque année, le bureau est composé de multiples pôles : comédie, danse, manute, musique, et prez'. Une fois le bureau constitué, il recrute sa troupe parmi les étudiants du plateau de Saclay.",
school: "polytechnique",
parentuid: 'kes',
type: 'simple'
},{
name: 'Œnologie',
uid: 'oenologie',
website: 'oenologie.binets.fr',
description: "Le binet de la Finesse et du Bon Goût par excellence. Cours d'initiation, dégustations, soirées Vins & Fromages, voyages chez les producteurs : le Binet Œnologie est là pour partager la passion du vin avec tous, néophytes ou connaisseurs.",
school: "polytechnique",
parentuid: "kes",
type: "simple"
},{
name: "Tribunes de l'X",
uid: 'politix',
website: 'https://www.facebook.com/Tribunes-de-lX-250533552110256/',
description: "Le binet Tribunes de l'X a pour but d'intéresser les élèves à la \"vie de la cité\" en organisant des conférences ou débats, autour de grandes sujets d'actualité et d'enjeux fondamentaux pour le débat public, avec des personnalités diverses, hommes politiques ou intellectuels. Cette association est la tribune étudiante de l'X.",
school: "polytechnique",
parentuid: "kes",
type: 'simple'
},{
name: "X-Finance",
uid: 'x-finance',
description: "X Finance gère un fonds d'investissement étudiant au profit de la FX en partenariat avec Edmond de Rothschild. Nous développons également des modèles algorithmiques pour gérer le risque. Le binet organise également des événements de networking en partenariat avec des écoles françaises et européeennes.",
school: "polytechnique",
parentuid: "kes",
type: "simple"
},{
name: "ASK",
uid: "ask",
description: "L'Action Sociale de la Kès regroupe les activités à caractère social et solidaire du platâl, comme le soutien scolaire, la bibliothèque de rue, les maraudes, le don du sang, les journées handicap ou encore le parrainage d'enfants. Chacun y trouvera son compte et pourra s'y investir à sa guise! Si tu as l'âme de l'Abbé Pierre ou le sex appeal d'Adriana Karembeu, chauffe toi et viens donner un peu de ton temps aux autres! Promis, on est gentils. Des bisous bisous!",
school: "polytechnique",
parentuid: "kes",
type: "simple"
}
];
return knex('simple_groups').insert(simple_groups);
......
File moved
......@@ -18,6 +18,11 @@ exports.seed = async function(knex, Promise) {
id: 3,
title: "Formation Web",
content: "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !"
},{
id: 4,
title: "Journées FedeRez",
content: "Cette année, nous parlerons de vie privée, protection des données et sécurité",
authors: ['federez']
}]);
await knex('events').del()
......
exports.seed = function(knex, Promise) {
// Deletes ALL existing entries
return knex('events').del()
.then(function () {
// Inserts seed entries
return knex('events').insert([
{
title : "Fête de la lune",
content : "La fête de la lune, c'est bientôt dans le grand hall !",
start_time : knex.fn.now(),
end_time : knex.fn.now(),
authors : ["x-chine"],
is_announcement : false
},{
title: "Perm BR du mardi soir",
content: "La perm' BR c'est maintenant!",
location: "Amphi Sauvy",
start_time: knex.fn.now(),
end_time: knex.fn.now(),
authors : ["br"],
is_announcement : true
},{
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!",
start_time: knex.fn.now(),
end_time: knex.fn.now(),
location: "Amphi Painlevé",
authors: ["br"],
is_announcement: false
},{
title: "Formation Web",
content: "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !",
authors: ['br'],
start_time: knex.fn.now(),
end_time: knex.fn.now(),
authors: ['br'],
is_announcement: false
}
]);
});
};
......@@ -13,7 +13,7 @@ module.exports = {
client: 'pg',
connection: {
host: 'localhost',
user: 'will',
user: 'sigma',
password: 'password',
database: 'sigma_dev',
charset: 'utf8'
......@@ -30,10 +30,10 @@ module.exports = {
directory: path.resolve('./db/seeds')
}
},
production: {
staging: {
client: 'pg',
connection: {
host: 'localhost',
host: '129.201.104.10',
user: 'will',
password: 'password',
database: 'sigma_dev',
......
......@@ -71,5 +71,5 @@
"sa": {
"attributs": "memberUid"
},
"sessionSecret":"change this"
"sessionSecret":"ozyNMHdT,WFTu|t"
}
\ No newline at end of file
This diff is collapsed.
......@@ -2,62 +2,73 @@
"name": "sigma-backend",
"version": "0.0.1",
"description": "Backend of sigma, the new Frankiz",
"main": "index.js",
"scripts": {
"build": "webpack --mode production",
"dev": "webpack --mode development",
"watch": "webpack --watch --mode development",
"start": "nodemon --watch build build/bundle.js",
"doc": "jsdoc -c configfile_doc.json",
"lint": "eslint src/"
},
"repository": {
"type": "git",
"url": "https://gitlab.binets.fr/br/sigma-backend"
},
"author": "Binet Réseau",
"license": "ISC",
"dependencies": {
"babel-eslint": "^8.2.2",
"body-parser": "^1.18.2",
"colors": "^1.1.2",
"apollo-server-express": "^2.0.4",
"body-parser": "^1.18.3",
"colors": "^1.3.2",
"connect-ensure-login": "^0.1.1",
"connect-flash": "^0.1.1",
"copy-webpack-plugin": "^4.5.0",
"cookie-parser": "^1.4.3",
"copy-webpack-plugin": "^4.5.2",
"cors": "^2.8.4",
"express": "^4.16.2",
"express-jwt": "^5.3.1",
"express-session": "^1.15.6",
"file-loader": "^1.1.11",
"fs": "0.0.1-security",
"fuse.js": "^3.2.0",
"graphql": "^0.13.1",
"graphql-server-express": "^1.3.2",
"graphql-tools": "^2.21.0",
"graphql-voyager": "^1.0.0-rc.15",
"knex": "^0.14.4",
"fuse.js": "^3.2.1",
"graphql": "^14.0.0",
"graphql-tools": "^3.1.1",
"graphql-voyager": "^1.0.0-rc.19",
"jsonwebtoken": "^8.3.0",
"knex": "^0.15.2",
"ldap-escape": "^1.1.5",
"ldapjs": "^1.0.2",
"lodash": "^4.17.5",
"lodash": "^4.17.10",
"morgan": "^1.9.0",
"passport": "^0.4.0",
"passport-ldapauth": "^2.0.0",
"pg": "^7.4.1",
"pug": "^2.0.0-rc.4",
"serve-favicon": "^2.4.5",
"pg": "^7.4.3",
"pug": "^2.0.3",
"serve-favicon": "^2.5.0",
"url-loader": "^0.6.2"
},
"devDependencies": {
"eslint": "^4.18.2",
"@types/connect-ensure-login": "^0.1.4",
"@types/connect-flash": "0.0.34",
"@types/graphql": "^0.13.4",
"@types/knex": "^0.14.23",
"@types/node": "^10.9.3",
"@types/passport": "^0.4.6",
"babel-eslint": "^8.2.6",
"eslint": "^4.19.1",
"eslint-config-standard": "^11.0.0",
"eslint-loader": "^2.0.0",
"eslint-plugin-import": "^2.9.0",
"eslint-loader": "^2.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^6.0.1",
"eslint-plugin-promise": "^3.6.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-promise": "^3.8.0",
"eslint-plugin-standard": "^3.1.0",
"jsdoc": "^3.5.5",
"nodemon": "^1.17.1",
"webpack": "^4.1.0",
"webpack-cli": "^2.0.10",
"webpack-node-externals": "^1.6.0"
},
"scripts": {
"start": "node build/bundle.js",
"lint": "eslint src/",
"build": "webpack --mode development",
"watch": "webpack --watch --mode development",
"doc": "jsdoc -c configfile_doc.json",
"test": "nodemon --watch build build/bundle.js"
},
"repository": {
"type": "git",
"url": "git@gitlab.binets.fr:br/sigma-backend"
},
"author": "Binet Réseau",
"license": "ISC"
"nodemon": "^1.18.3",
"ts-loader": "^4.5.0",
"typescript": "^3.0.3",
"webpack": "^4.17.1",
"webpack-cli": "^2.1.5",
"webpack-graphql-loader": "^1.0.0",
"webpack-node-externals": "^1.7.2"
}
}
/**
* @description Configuration de passport pour utiliser l'authentification LDAP
* @author kadabra
*
* on a besoin d'authentification pour 2 trucs :
* - l'accès a l'interface admin (admin_view) du back, définie dans admin_router.js
* - le contexte graphQL
*
* serializeUser permet d'obtenir une cle identifiant chaque user
* deserializeUser fait une requête vers une BDD de users en utilisant cette cle, et met dans l'objet JS req.user toutes les infos issues de la BDD
* Cette repartition permet de ne stocker dans la session (i.e. en mémoire sur le serveur) que la cle des utilisateurs connectes et de ne "charger en mémoire" toutes les infos de la BDD que lorsque nécessaire
* cf https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize#27637668
* et http://toon.io/understanding-passportjs-authentication-flow/
*
* Mais en fait dans notre cas c'est graphql qui communique avec la BDD, donc on s'en fiche! On peut se contenter de dire a serializeUser et deserializeUser de ne s'occuper que du champ uid)
* (on pourrait penser que passer par deserializeUser permettrait de réduire le nombre d'interactions avec la BDD, mais en fait non car deserializeUser est appelé *a chaque requete*)
*/
import passport from 'passport';
import LdapStrategy from 'passport-ldapauth';
import { ldapConfig } from './ldap/config';
// specifies options for 'ldapauth' strategy, to customize the behaviour of subsequent passport.authenticate('ldapauth') calls
passport.use(new LdapStrategy({
server: {
url: ldapConfig.ldap.server,
//bindDn: '.............',
//bindCredentials: '..........',
searchBase: ldapConfig.ldap.searchBase,
searchFilter: ldapConfig.ldap.searchFilter,
//searchAttributes: ['givenName', 'sn'],
//tlsOptions: '..........',
},
//usernameField: 'username', // Field name where the username is found, defaults to username
//passwordField: 'password', // Field name where the password is found, defaults to password
// given how LdapStrategy is coded, it is not necessary to do a verify callback
// https://github.com/vesse/passport-ldapauth/blob/master/lib/passport-ldapauth/strategy.js#L230
// (note that LdapStrategy has no default verify callback, the "verify" function (L105) is actually the "done" function that is called by the verify callback if we choose to make one)
// we leave this commented out as a template for future use
/*
function (user, done) {
// "verify callback", called after each passport.authenticate(...),
// unless missing credentials (in which case a 400 Error is returned)
// "The purpose of a verify callback is to find the user that possesses a set of credentials" (from passport doc)
// i.e. we query the database (in our case the LDAP) to get user's data
console.log("Entering passport's verify callback");
if (user){
//if user exists
console.log("Successfully authenticated " + user.uid);
}
}
*/
}));
//toujours bon a savoir pour faire des tests:
//The result of the serializeUser method is attached to the session as req.session.passport.user
passport.serializeUser(function (user, done) {
console.log(`passport.serializeUser(): serializing user ${user.uid}`); // DEBUG
done(null, user.uid);
});
//The first argument of deserializeUser corresponds to the key of the user object that was given to the done function in serializeUser
//The fetched object is attached to the request object as req.user (available in all subsequent middleware)
passport.deserializeUser(function (userUid, done) {
// console.log(`passport.deserializeUser(): deserializing user ${userUid}`); // DEBUG
done(null, { uid: userUid });
});
\ No newline at end of file
import passport from 'passport';
import '../config_passport';
import jwt from 'jsonwebtoken';
// JSON web token secret key
const SECRET_KEY = "boom shakalaka";
// Returns a promise wherein we try to authenticate the user
// against the LDAP using passportjs
// The promise will fail if no user is returned in the passport.authenticate
// callback.
const loginResolverFunc = ({ username, password, req }) => {
return new Promise((resolve, reject) => {
passport.authenticate('ldapauth', (err, user, info) => {
if (err) { reject(err); }
if (!user) { reject('Invalid credentials.'); }
// Sign a new JSON web token with the user's uid against the secret key
const token = jwt.sign({ uid: user.uid }, SECRET_KEY);
resolve(token);
})({ body: { username, password } });
});
};
export default loginResolverFunc;
\ No newline at end of file
......@@ -7,8 +7,6 @@ import * as selectors from './selectors';
import * as list_selectors from './list_selectors';
import ldap from '../../ldap/ldap_data';
// dn et mot de passe du bind user du LDAP
import ldap_bind_user from '../../../ldap_connexion_config.json';
const utilisateur = new ldap.UtilisateurAnonyme();
......@@ -29,7 +27,7 @@ export { utilisateur };
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érends niveaux sont :
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
......@@ -59,24 +57,6 @@ export { utilisateur };
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
* @desc Les fonctions ici sont toutes supposées renvoyer une promise.
* Si on veut renvoyer une valeur directement, cette fonction permet de construire
* une Promise qui renvoie cette valeur facilement.
* @arg {Object} val - La valeur qu'on veut renvoyer.
* @return {Promise(Object)} Une promise qui renvoi val
*/
const quickPromise = (val) => {
return new Promise( (resolve, reject) => {
resolve(val);
});
};
/**
* @summary Renvoie le nom de la table dans laquelle il faut chercher en fonction de ce qu'on veut
* @desc Ceci est obsolète, et devra être supprimé quand le code sera RAS
......
......@@ -2,14 +2,20 @@
* @file Implémentation des requêtes GraphQL.
* @author akka vodol
*/
import { request } from 'https';
import _ from 'lodash';
import { assertBinaryExpression } from 'babel-types';
import knex from '../../db/knex_router';
import passport from 'passport';
import './../config_passport';
import authenticator from '../graphql/authenticator';
import * as connectors from './connectors/connectors';
import * as list_selectors from './connectors/list_selectors';
import * as authentifiers from './connectors/authentifiers';
import MessageResolvers from './resolvers/messages';
import GroupResolvers from './resolvers/groups';
// nouveau test
......@@ -32,26 +38,26 @@ export const resolvers = {
// group queries
allGroups: async function(obj, args, context){
let user = await authentifiers.anonymous(context.user);
let user = await authentifiers.anonymous(context.bindUser);
return user && connectors.getAllVisibleGroups(user);
},
allSimpleGroups: async function (obj, args, context){
let user = await authentifiers.anonymous(context.user);
let user = await authentifiers.anonymous(context.bindUser);
return user && connectors.getAllVisibleSimpleGroups(user);
},
group: async function(obj, args, context){
let user = await authentifiers.anonymous(context.user);
let user = await authentifiers.anonymous(context.bindUser);
return user && connectors.getGroupIfVisible(user, args.uid);
},
simpleGroup: async function(obj, args, context){
let user = await authentifiers.anonymous(context.user);
let user = await authentifiers.anonymous(context.bindUser);
return user && connectors.getSimpleGroupIfVisible(user, args.uid);
},
metaGroup: async function(obj, args, context){
let user = await authentifiers.anonymous(context.user);
let user = await authentifiers.anonymous(context.bindUser);
return user && connectors.getMetaGroupIfVisible(user, args.uid);
},
......@@ -63,20 +69,27 @@ export const resolvers = {
return knex.select().from("announcements");
},
allEvents: function(obj, args, context) {
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);
});
},
// user queries
user: async function(obj, args, context){
let user = await authentifiers.anonymous(context.user);
let user = await authentifiers.anonymous(context.bindUser);
return user && connectors.getUser(user,args.uid);
},
searchTOL: (obj, args, context) => {
console.log("Searching TOL for",args);
const result = connectors.utilisateur.repliquerTOLdesIds({
givenName: args.givenName,
lastName: args.lastName,
......@@ -100,15 +113,15 @@ export const resolvers = {
// 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);
let user = await authentifiers.member(context.bindUser, args.from);
return user && connectors.getGroupMemberUsers(context.bindUser, obj.groupUID);
},
// speaker queries
allRequests: async function(obj, args, context){
let res = [];
let user = authentifiers.admin(context.user, args.from);
let user = authentifiers.admin(context.bindUser, args.from);
if(user){
res = res.concat(await connectors.getUserJoinGroupRequests(user, args.from));
}
......@@ -135,11 +148,11 @@ 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");
return connectors.getUser(context.bindUser, obj.useruid);
/*return connectors.getUser(context.bindUser, "quentin.gendre");
if(obj.useruid === "anatole.romon"){
return connectors.getUser(context.user, "anatole.romon").then(res => {
return connectors.getUser(context.user, "quentin.gendre");
return connectors.getUser(context.bindUser, "anatole.romon").then(res => {
return connectors.getUser(context.bindUser, "quentin.gendre");
});
}else{
return new Promise( (resolve, reject) => {
......@@ -152,20 +165,20 @@ export const resolvers = {
// @rights speaker(obj.groupUID)
GroupJoinEvent : {
event: (obj, args, context) => {
return connectors.getEvent(context.user, obj.eventuid);
return connectors.getEvent(context.bindUser, obj.eventuid);
},
groupWantingToJoin: (obj, args, context) => {
return connectors.getGroup(context.user, obj.senderuid);
return connectors.getGroup(context.bindUser, obj.senderuid);
}
},
// @rights speaker(obj.groupUID)
YourGroupHostEvent : {
event: (obj, args, context) => {
return connectors.getEvent(context.user, obj.eventuid);
return connectors.getEvent(context.bindUser, obj.eventuid);
},
sender: (obj, args, context) => {
return connectors.getGroup(context.user, obj.senderuid);
return connectors.getGroup(context.bindUser, obj.senderuid);
}
},
......@@ -173,7 +186,7 @@ export const resolvers = {
User : {
groups : (obj, args, context) => {
let result = Promise.all(obj.groups.map((grid) => {
return connectors.getSimpleGroup(context.user,grid);
return connectors.getSimpleGroup(context.bindUser,grid);
}));
return result.then(groups => {
......@@ -201,175 +214,24 @@ export const resolvers = {
// Admin mutations
createSubgroup: async function (obj, args, context){
let user = authentifiers.admin(context.user, args.from);
let user = authentifiers.admin(context.bindUser, args.from);
return user && connectors.createSubgroup(user, args);
},
login: function (obj, args, context) {
},
Message: {
__resolveType: function(obj) {
return obj.type;
}
},
Announcement: {
forEvent : function(obj, args, context){
// le champ is_announcement n'existe que sur les Events
// une ligne de la bdd events peut résoudre comme évènement ou comme annonce
if(obj.is_announcement)
return obj;
else
return null;
},
authors: async function (obj, args, context){
return connectors.getMessageGroupAuthors(context.user, obj.id);
},
recipients: async function (obj, args, context){
return connectors.getMessageGroupRecipients(context.user, obj.id);
}
},
Event: {
startTime : function(obj){
return obj.start_time;
},
endTime : function(obj){
return obj.end_time;
},
asAnnouncement : function(obj, args, context){
// le champ is_announcement indique si il existe une annonce qui va avec l'évènement
// une ligne de la bdd events peut résoudre comme évènement ou comme annonce
if(obj.is_announcement)
return obj;
else
return null;
},
authors: async function (obj, args, context){
return connectors.getMessageGroupAuthors(context.user, obj.id);
},
recipients: async function (obj, args, context){
return connectors.getMessageGroupRecipients(context.user, obj.id);
}
},
PrivatePost : {
authors: async function(obj, args, context){
return connectors.getUser(context.user, obj.author_uid, obj.author_db);
},
recipients: async function(obj, args, context){
return connectors.getGroup(context.user, obj.recipient_uid);
}
},
Question : {
authors: async function(obj, args, context){
return connectors.getUser(context.user, obj.author_uid, obj.author_db);
},
recipients: async function(obj, args, context){
return connectors.getGroup(context.user, obj.recipient_uid);
},
forAnswer: function(obj, args, context){
return obj.for_answer;
}
},
Answer : {
authors: async function(obj, args, context){
return connectors.getGroup(context.user, obj.author_uid);
},
const { username, password } = args;
const req = context.request;
recipients: async function(obj, args, context){
return connectors.getGroup(context.user, obj.recipient_uid);
},
forQuestion: function(obj, args, context){
return obj.for_question;
}
},
// @rights viewer(obj.uid)
Group: {
__resolveType: async (obj) => {
switch(obj.type) {
case "simple":
return "SimpleGroup";
case "meta":
return "MetaGroup";
}
}
},
// @rights viewer(obj.uid)
SimpleGroup: {
admins: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return await user.ldap_access.listMembers(context.user,obj.uid);
},
members: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return user.ldap_access.listMembers(context.user,obj.uid);
const result = authenticator({ username, password, req });
result.then(value => {
console.log(`Token: ${value}`);
});
return result;
},
likers: async function(obj, args, context){
return connectors.utilisateur.listMembers(context.user,obj.uid);
},
privatePosts: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedPrivatePosts(user, obj.uid);
},
questions: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedQuestions(user, obj.uid);
},
answers: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedAnswers(user, obj.uid);
}
},
// @rights viewer(obj.uid)
MetaGroup: {
members: (obj, args, context) => {
},
privatePosts: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedPrivatePosts(user, obj.uid);
},
...MessageResolvers,
questions: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedQuestions(user, obj.uid);
},
answers: async function(obj, args, context){
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedAnswers(user, obj.uid);
}
}
...GroupResolvers,
};
import knex from '../../../db/knex_router';
import * as connectors from '../connectors/connectors';
import * as authentifiers from '../connectors/authentifiers';
const GroupResolvers = {
// @rights viewer(obj.uid)
Group: {
__resolveType: async (obj) => {
switch (obj.type) {
case "simple":
return "SimpleGroup";
case "meta":
return "MetaGroup";
}
}
},
// @rights viewer(obj.uid)
SimpleGroup: {
admins: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return await user.ldap_access.listMembers(context.user, obj.uid);
},
members: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return user.ldap_access.listMembers(context.user, obj.uid);
},
likers: async function (obj, args, context) {
return connectors.utilisateur.listMembers(context.user, obj.uid);
},
privatePosts: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedPrivatePosts(user, obj.uid);
},
questions: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedQuestions(user, obj.uid);
},
answers: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedAnswers(user, obj.uid);
}
},
// @rights viewer(obj.uid)
MetaGroup: {
members: (obj, args, context) => {
},
privatePosts: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedPrivatePosts(user, obj.uid);
},
questions: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedQuestions(user, obj.uid);
},
answers: async function (obj, args, context) {
let user = await authentifiers.member(context.user, obj.uid);
return user && connectors.receivedAnswers(user, obj.uid);
}
}
};
export default GroupResolvers;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment