Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gestion des zones de compétences des organisations #571

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ public class PreRequestFilter implements ContainerRequestFilter {
public void filter(ContainerRequestContext requestContext) throws IOException {

String rolesList = requestContext.getHeaderString("sec-roles");
String org = requestContext.getHeaderString("sec-org");
String userName = requestContext.getHeaderString("sec-username");
MDC.put("user", userName);
MDC.put("org", org);
MDC.put("roles", rolesList);
MDC.put("uri", requestContext.getUriInfo().getPath());

Expand All @@ -34,4 +36,4 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
}

}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.georchestra.cadastrapp.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -146,39 +147,47 @@ protected String addAuthorizationFiltering(HttpHeaders headers) {
*/
protected String addAuthorizationFiltering(HttpHeaders headers, String tableAlias) {

logger.debug("Check user geographical limitation ");

List<Map<String, Object>> limitations;
List<String> communes = new ArrayList<String>();
List<String> deps = new ArrayList<String>();

StringBuilder queryFilter = new StringBuilder();

// get roles list in header
// Example 'ROLE_MOD_LDAPADMIN,ROLE_EL_CMS,ROLE_SV_ADMIN'
String usernameString = headers.getHeaderString("sec-username");
if (usernameString == null){
logger.debug("Not checking geographical limitation, anonymous user");
return queryFilter.toString();
}
// get org in header
String orgString = headers.getHeaderString("sec-org");
// get roles in heade
String roleListString = headers.getHeaderString("sec-roles");

logger.debug("user roleList : "+ roleListString);
// merge org+roles to get groups list
List<String> groupsList = new ArrayList<String>();
if(orgString!=null && !orgString.isEmpty()){
groupsList.add(orgString);
}
if(roleListString!=null && !roleListString.isEmpty()){

// set separator by default if not set
if(roleSeparator.isEmpty()){
roleSeparator = ";";
}

// Force to add the array of value in first place of a new Array
String[] roleList = roleListString.split(roleSeparator);

// get commune list in database corresponding to this header
groupsList.addAll(Arrays.asList(roleListString.split(roleSeparator)));
}

logger.debug("Check user '" + usernameString + "' with groups '"+ groupsList.toString() + "' geographical limitation ");
jusabatier marked this conversation as resolved.
Show resolved Hide resolved
if(!groupsList.isEmpty()){
// get commune list in database corresponding to those groups
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("select distinct cgocommune, ccodep from ");
queryBuilder.append(databaseSchema);
queryBuilder.append(".groupe_autorisation ");
queryBuilder.append(createWhereInQuery(roleList.length, "idgroup"));
queryBuilder.append(createWhereInQuery(groupsList.size(), "idgroup"));
queryBuilder.append(";");

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
limitations = jdbcTemplate.queryForList(queryBuilder.toString(), roleList);
limitations = jdbcTemplate.queryForList(queryBuilder.toString(), groupsList);

// filter request on commune
if (limitations != null && !limitations.isEmpty()) {
Expand Down Expand Up @@ -234,6 +243,7 @@ protected String addAuthorizationFiltering(HttpHeaders headers, String tableAlia
}
else{
logger.warn("No filter, no sec-roles was found");
logger.warn("User authenticated as '" + usernameString + "' but no sec-org header, something is wrong");
jusabatier marked this conversation as resolved.
Show resolved Hide resolved
}

return queryFilter.toString();
Expand Down
141 changes: 134 additions & 7 deletions database/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

Ceci est la documentation des traitements qui mettent à jour la base de données applicative de cadastrapp.


## Principe de fonctionnement

Avant de configurer et jouer ce script, vous devez disposez d'une base de données PostgreSQL / PostGIS contenant des données cadastrales créées en utilisant le greffon **QGIS [cadastre](https://plugins.qgis.org/plugins/cadastre/)**
Expand All @@ -13,7 +12,6 @@ Le fichier de configuration du script vous permet de définir si les données ca

L'utilisation des vues matérialisées permet de gagner du temps lors de la mise de vos données car un simple REFRESH ```MATERIALIZED VIEW table_name``` suffit à relire la base de données source.


## Prérequis

### Versions PostgreSQL et PostGIS
Expand All @@ -22,7 +20,6 @@ L'utilisation des vues matérialisées permet de gagner du temps lors de la mise
* PostgreSQL > 9.6
* PostGIS > 2.1 mais < 3.0


### Si toutes les données sont dans la même base de données

C'est le cas le plus simple.
Expand All @@ -31,7 +28,6 @@ Dans ce cas il faut 2 schémas. Exemples :
* `cadastre_gis` : il contiendra les données cadastre produites par le plugin cadastre de QGIS
* `cadastrapp` : il contiendra les données applicatives pour cadastrapp et créées par notre script


### Si les données sont dans 2 bases de données distinctes

Dans ce cas on aura 2 bases de données différentes (sur la même machine ou pas) et donc 2 schémas différents. Exemples :
Expand All @@ -40,6 +36,42 @@ Dans ce cas on aura 2 bases de données différentes (sur la même machine ou pa

La base de données cible qui contiendra les données de cadastrapp devra comporter l'extension **[dblink](http://www.postgresql.org/docs/current//dblink.html)**.

### Si on souhaite remonter les autorisations geographiques depuis les groupes georchestra

Il faudra que le [fichier de correspondance fourni à la console](https://github.com/georchestra/georchestra/tree/master/console#custom-areas) comporte les codes INSEE des communes.

La base de données cible qui contiendra les données de cadastrapp devra :
* Comporter l'extension **[multicorn](https://multicorn.org/)**
* Avoir accès au serveur LDAP de l'instance geOrchestra

#### Installation de multicorn (Debian)

Dans Debian 10, multicorn est disponible via un paquet :

`$ sudo apt install postgresql-11-python3-multicorn`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A ajouter dans le playbook ansible

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

y'a t'il vraiment des gens qui utilisent le déploiement d'un deb de cadastrapp via ansible ? j'en doute très fortement :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Même si cette fonctionnalité est optionnelle car dépendante d'un LDAP ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'était juste une note pour moi :)


Cette commande est à adapter en fonction de votre version de PostgreSQL.

#### Création du Foreign Data Wrapper pour LDAP

Afin de récupérer les emprises géographiques définies pour l'organisation des utilisateurs, il est necessaire de configurer une connexion de la base de données vers le LDAP de Georchestra.

Commencer par installer l'extension multicorn sur la BDD précedemment créée :

```
CREATE EXTENSION multicorn;
```

Puis, créer le lien vers le serveur LDAP :

```
CREATE SERVER ldap_srv foreign data wrapper multicorn options (
wrapper 'multicorn.ldapfdw.LdapFdw'
);
ALTER SERVER ldap_srv
OWNER TO #user_cadastrapp;
```
> **Note:** Remplacer `#user_cadastrapp` par l'utilisateur utilisé par cadastrapp

## Configuration du script

Expand All @@ -49,7 +81,7 @@ Sous linux :
* le renommer en `config.sh`
* l'ouvrir et compléter les informations de connection aux bases de données
* si les données cadastre QGIS et cadastrapp sont dans la même base de données, laisser `uniqueDB=True` sinon mettre `uniqueDB=False`

* si vous souhaitez remonter les autorisations cartographiques de puis les organisations geOrchestra (LDAP), mettre `orgsAutorisations=True` sinon laisser `orgsAutorisations=False`

## Utilisation du script

Expand All @@ -59,11 +91,106 @@ Sous linux :

Note : il est possible de l'utiliser en mode silencieux avec l'option `-s` ou `--silent`. Si précisé, le script n'attendra pas de validation de la part de l'utilisateur.


## Mise à jour des données

Sous linux :
* aller dans le répertoire `database`
* exécuter le script `cadastrapp_update_data.sh`

Note : il est possible de l'utiliser en mode silencieux avec l'option `-s` ou `--silent`. Si précisé, le script n'attendra pas de validation de la part de l'utilisateur.
Note : il est possible de l'utiliser en mode silencieux avec l'option `-s` ou `--silent`. Si précisé, le script n'attendra pas de validation de la part de l'utilisateur.

## Mise en place d'un CRON pour rafraichir les autorisations liées aux organisations

Si vous avez mis en place la gestion des autorisations geographiques depuis les groupes georchestra, le script a créé une vue materialisée contenant les codes INSEE pour chaque groupe qui ont été remontés depuis le LDAP.
Ceci permet de ne pas surcharger ce dernier avec des requêtes à chaque sollicitation de cadastrapp.

Néanmoins, pour que les changements sur les périmètres des organisations faits dans la console geOrchestra soient pris en compte, cette vue materialisée devra être rafraichie.

Pour ce faire, il est conseillé de mettre en place un CRON qui permettra de la rafraichir à interval régulier.

### Mise en place d'un 'cron job' dans debian

Créez un fichier de script `cadastrapp_refresh_ldap_view.sh` sur le serveur contenant la base de données cadastrapp avec le contenu suivant :

```
#!/bin/sh
PGPASSWORD=#cadastrapp_password psql -h #cadastrapp_db_host -p $cadastrapp_db_port -d $cadastrapp_db_name -U $cadastrapp_user -c 'refresh materialized view #cadastrapp_schema.org_autorisation'
```
> **Note:** Remplacez les variables précédées d'un `#` par la valeur appropriée
Déplacez le fichier dans le répertoire cron correspondant à la fréquence souhaitée :

* /etc/cron.hourly => toutes les heures
* /etc/cron.daily => tous les jours
* /etc/cron.weekly => toutes les semaines
* /etc/cron.monthly => tous les mois

Ou bien si vous souhaitez un parametrage plus poussé, référez vous à la [documentation de crontab](https://debian-facile.org/doc:systeme:crontab)

Enfin pensez-bien à rendre le fichier executable :

```
chmod +x cadastrapp_refresh_ldap_view.sh
```

### Mise en place d'un 'cron job' via pg_cron

Commencez par installer l'extension `cron` de postgresql :

```
sudo apt install postgresql-11-cron
```

Une fois installée, partie OS, il faudra modifier les paramètres base de données dans PostgreSQL afin de pouvoir utiliser cette extension.

Le fichier “postgresql.conf” devra indiquer les éléments suivants pour permettre la création de cette extension en base :

* share_preload_libraries
* cron.database_name

```
sudo nano /etc/postgesql/11/main/postgresql.conf
```

Ajoutez à la fin du fichier :

```
shared_preload_libraries = 'pg_cron'
cron.database_name = '#cadastrappDBName'
```

> **Note:** Remplacez `#cadastrappDBName` par le nom de la base de donnée hébergeant cadastrapp

Autorisez la connexion de l'utilisateur en local via trust pour permettre l'accès à la tache CRON,
pour cela dans le fichier `/etc/postgresql/11/main/pg_hba.conf` modifiez la ligne :

```
host #cadastrappDBName #user_cadastrapp 127.0.0.1/32 trust
host all all 127.0.0.1/32 md5
```
> **Note:** Remplacez les variables précédées d'un `#` par la valeur appropriée
Relancez postgresql :

```
sudo service postgresql restart
```

Activez l'extention dans la base de donnée hebergeant cadastrapp :

```
CREATE EXTENSION pg_cron;
```

Autorisez l'utilisation pour l'utilisateur cadastrapp :

```
GRANT USAGE ON SCHEMA cron TO #user_cadastrapp;
GRANT INSERT ON TABLE cron.job TO #user_cadastrapp;
GRANT USAGE ON SEQUENCE cron.jobid_seq TO #user_cadastrapp;
```
> **Note:** Remplacer `#user_cadastrapp` par l'utilisateur utilisé par cadastrapp
Enfin lancez le script de definition la tache CRON :

```
./create_ldap_cronjob.sh
```
> **Note:** Par défaut, le script défini le rafraichissement de la vue mateiralisée toutes les heures, si cela ne vous convient pas, vous pouvez modifier cette configuration dans le fichier `sql/ldap/cronjob.sql`.
31 changes: 31 additions & 0 deletions database/cadastrapp_load_data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,33 @@ else
exit 1
fi

if [ "$orgsAutorisations" = True ] ; then
invalidLdapParam=False
if [ -z "$ldapUri" ] ; then
echo "Paramètre ldapUri manquant !"
invalidLdapParam=True
fi

if [ -z "$ldapPath" ] ; then
echo "Paramètre ldapPath manquant !"
invalidLdapParam=True
fi

if [ -z "$ldapBindDn" ] ; then
echo "Paramètre ldapBindDn manquant !"
invalidLdapParam=True
fi

if [ -z "$ldapBindPwd" ] ; then
echo "Paramètre ldapBindPwd manquant !"
invalidLdapParam=True
fi
if [ "$invalidLdapParam" = True ] ; then
echo " pb de configuration : stop"
exit 1
fi
fi

if [ "$silentMode" = True ] ; then
echo ""
read -p " Si ces infos sont exactes : appuyer sur la touche [Entrée] sinon faire ctrl + C pour arrêter."
Expand Down Expand Up @@ -76,6 +103,10 @@ replaceAndLaunch (){
s/#DBSchema_qgis/$qgisDBSchema/g
s/#DBUser_qgis/$qgisDBUser/g
s/#DBpasswd_qgis/$qgisDBPassword/g
s|#ldap_uri|$ldapUri|g
s/#ldap_path/$ldapPath/g
s/#ldap_binddn/$ldapBindDn/g
s/#ldap_bindpwd/$ldapBindPwd/g
}" |\
PGPASSWORD=$cadastrappDBPassword psql -h $cadastrappDBHost -p $cadastrappDBPort -d $cadastrappDBName -U $cadastrappDBUser

Expand Down
9 changes: 9 additions & 0 deletions database/config_sample.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ cadastrappDBPassword=cadastrapp_mdp
# True / False
uniqueDB=True

# Récupération des autorisations geographiques configurées pour les organisations dans la console geOrchestra
# True / False
orgsAutorisations=False

# Obligatoires si orgsAutorisations=True
#ldapUri=ldaps://ldap.georchestra.org
#ldapPath=ou=orgs,dc=georchestra,dc=org
#ldapBindDn=uid=cadastrapp,ou=users,dc=lepuyenvelay,dc=fr
#ldapBindPwd=secret
43 changes: 43 additions & 0 deletions database/create_ldap_cronjob.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash

clear
git_version=$(git rev-parse HEAD)

echo "--------------------------------------------------------------"
echo " Cadastrapp : script de création du cron job pour rafraichier la vue des organisations LDAP"
echo "--------------------------------------------------------------"
echo ""
echo " version : $git_version"
echo ""
echo "--------------------------------------------------------------"
echo " Lecture du fichier de configuration"
echo "--------------------------------------------------------------"
echo ""

# lecture du fichier de configuration des connexions
. config.sh

replaceAndLaunch (){
if [ -z "$1" ] || [ ! -e $1 ] ; then
echo "Le fichier SQL $1 n'existe pas."
exit 1
else
echo " Exécution du fichier : $1"
fi

cat $1 | sed "{
s/#schema_cadastrapp/$cadastrappDBSchema/g
s/#cadastrapp_db_host/$cadastrappDBHost/g
s/#cadastrapp_db_port/$cadastrappDBPort/g
s/#cadastrapp_db_name/$cadastrappDBName/g
s/#user_cadastrapp/$cadastrappDBUser/g
}" |\
PGPASSWORD=$cadastrappDBPassword psql -h $cadastrappDBHost -p $cadastrappDBPort -d $cadastrappDBName -U $cadastrappDBUser
}

replaceAndLaunch sql/ldap/cronjob.sql

echo ""
echo "--------------------------------------------------------------"
echo " FIN "
echo "--------------------------------------------------------------"
Loading