Commit 6cc156a2 authored by Thomas Hamel's avatar Thomas Hamel
Browse files

first commit

parent b7e7b05f
Loading
Loading
Loading
Loading
Loading
+5 −39
Original line number Diff line number Diff line
# CHANGELOG
CHANGELOG
=========

## 4.0.0
0.1 (14/05/2025)
----------------

- Montée en version 4 des bibliothèques unicaen/* (PHP 7.4)

## 3.2.1

- Mise à jour des dépendances.
- Ajout de `post-install-cmd` et de `post-create-project-cmd` utiles dans le `composer.json`.

## 3.2.0

- Simplification des configs pour Docker.

## 3.1.0

- Dépendance avec les versions 3.0 des bib unicaen.
- Version avec une bdd postgres dans un service docker.
- Création du fichier de licence LICENSE.
- Création du script install.sh pour mimer ce qui est fait dans sygal.
- Nouvelle façon de mettre le numéro de version dans la config (cf. bin/bump-version).

## 3.0.0

- Dépendances: montée possible en ZF 3.
- Création d'un module démo avec bdd sqlite minimale.
- Docker: modif des ports utilisés et passage à PHP 7.3.
- Config pour tests unitaires.
- Désactivation du validateur de session HttpUserAgent car peut provoquer une erreur 'Session validation failed' sur android.



## 1.0.1

- Mise à jour des dépendances avec Composer.
- Ajout de la colonne user_role.accessible_exterieur pour gérer le blocages de rôles depuis l'extérieur.

## 1.0.0

- Embryon d'application.
- Installation du squelette d'application
 No newline at end of file
+27 −5
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ ARG PHP_VERSION

FROM unicaen-dev-php${PHP_VERSION}-apache

LABEL maintainer="Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>"
LABEL maintainer="Renaud BALOCHE <renaud.baloche at unicaen.fr>"

WORKDIR /var/www/html

@@ -17,15 +17,37 @@ RUN apt-get update -qq && \
# Nettoyage
RUN apt-get autoremove -y && apt-get clean && rm -rf /tmp/* /var/tmp/*

ENV PHP_CONF_LOCAL_DIR=docker/php \
    PHP_CONF_DIR=/etc/php/${PHP_VERSION}

# Configuration PHP et PHP-FPM
ADD ${PHP_CONF_LOCAL_DIR}/fpm/pool.d/www.conf.part /tmp/
RUN cat /tmp/www.conf.part >> ${PHP_CONF_DIR}/fpm/pool.d/www.conf && rm /tmp/www.conf.part
ADD ${PHP_CONF_LOCAL_DIR}/fpm/conf.d/99-app.ini ${PHP_CONF_DIR}/fpm/conf.d/
ADD ${PHP_CONF_LOCAL_DIR}/cli/conf.d/99-app.ini ${PHP_CONF_DIR}/cli/conf.d/

#RUN a2enconf php${PHP_VERSION}-fpm

# Symlink apache access and error logs to stdout/stderr so Docker logs shows them
RUN ln -sf /dev/stdout /var/log/apache2/access.log
RUN ln -sf /dev/stdout /var/log/apache2/other_vhosts_access.log
RUN ln -sf /dev/stderr /var/log/apache2/error.log

ENV APACHE_CONF_LOCAL_DIR=docker/apache \
    APACHE_CONF_DIR=/etc/apache2

# Configuration Apache et FPM
ADD docker/apache/000-default.conf ${APACHE_CONF_DIR}/sites-available/
ADD docker/php/fpm/conf.d/*.ini ${PHP_CONF_DIR}/fpm/conf.d/
ADD docker/php/cli/conf.d/*.ini ${PHP_CONF_DIR}/cli/conf.d/
ADD ${APACHE_CONF_LOCAL_DIR}/ports.conf            ${APACHE_CONF_DIR}/ports.conf
ADD ${APACHE_CONF_LOCAL_DIR}/site.conf             ${APACHE_CONF_DIR}/sites-available/000-default.conf
ADD ${APACHE_CONF_LOCAL_DIR}/site-ssl.conf         ${APACHE_CONF_DIR}/sites-available/default-ssl.conf

RUN a2enconf php${PHP_VERSION}-fpm.conf && \
RUN a2ensite 000-default default-ssl &&  \
    service php${PHP_VERSION}-fpm reload

# Copie des scripts complémentaires à lancer au démarrage du container
COPY docker/entrypoint.d/* /entrypoint.d/

# Git
RUN git config --global --add safe.directory /app

WORKDIR /app
+73 −65
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ application à la mode "Unicaen".

## Création d'une nouvelle appli à partir du squelette

Imaginons que nous voulons créer une nouvelle appli PHP 7.3 dans le répertoire `./newapp`.
Imaginons que nous voulons créer une nouvelle appli PHP 8.0 dans le répertoire `./newapp`.

### Préalable

@@ -16,57 +16,14 @@ environnement PHP dont on maîtrise la version. Pour obtenir puis construire cet

### Création des sources de l'application

- Pour obtenir le master des sources du squelette d'application :
- Pour obtenir la branche skeleton-app-update des sources du squelette d'application :

```bash
APP_DIR=newapp

git clone git@git.unicaen.fr:lib/unicaen/skeleton-application.git ${APP_DIR}
cd ${APP_DIR}
```

- Puis pour installer les dépendances PHP :

```bash
# si vous avez la joie d'être derrière un proxy :
#HTTP_PROXY=http://10.14.128.99:3128
#HTTPS_PROXY=${HTTP_PROXY}
#NO_PROXY=unicaen.fr,localhost

PHP_VERSION=7.3

docker run \
--rm \
-v $PWD:/app \
-w /app \
--env HTTP_PROXY \
--env HTTPS_PROXY \
--env NO_PROXY \
unicaen-dev-php${PHP_VERSION}-apache \
composer install
```

- Puis pour installer les fichiers de config exemples :

```bash
docker run \
--rm \
-v $PWD:/app \
-w /app \
--env HTTP_PROXY \
--env HTTPS_PROXY \
--env NO_PROXY \
unicaen-dev-php${PHP_VERSION}-apache \
composer run-script "post-create-project-cmd"
```

### Droits d'écriture

Comme les commandes lancées via Docker (comme ici, `composer`) sont exécutées en `root`, il faut reprendre la main 
sur les fichiers créés.

```bash
sudo chown -R ${USER}:${USER} .
git checkout skeleton-app-update
```

### Création du dépôt git
@@ -84,30 +41,34 @@ namespace gitlab spécifié.*

## Construction et lancement du container Docker

Il faut penser à modifier les fichiers composer.json et docker-compose.yml pour mettre les informations relatives à l'application (le nom de l'application, le nom du container attendu etc...)
unicaen-dev-php8.0-apache est nécéssaire pour cette étape en skeleton-app-update
```bash
docker-compose up --build
```

- Il faut ensuite accèder au container et récupérer les bibliothèques  :

## Module Demo
```bash
docker exec -it nomDuContainer /bin/bash
composer install
chown -R ${USER}:${USER} .
composer run-script "post-create-project-cmd"
```

Le squelette d'application possède un module "démo" qui utilise une base de données PostgreSQL de démonstration 
permettant d'avoir une authentification locale qui fonctionne. 
- Comme les commandes lancées via Docker (comme ici, `composer`) sont exécutées en `root`, il faut reprendre la main
sur les fichiers créés.

Cette base de données est fournie par le service `db` (fichier de config `docker-compose.yml`).
Il y a également un service `adminer` fournissant de quoi explorer la base de données avec l'outil 
["Adminer"](https://www.adminer.org) en vous rendant à l'adresse `http://localhost:9080` (sélectionner "PostgeSQL"
et utiliser les informations de connexion à la bdd présentes dans le `docker-compose.yml`).
Pour explorer/administrer la base de données *de l'extérieur du container* (avec PHPStorm par exemple), 
l'adresse de la base est cette fois `localhost:8432`.
```bash
chown -R ${USER}:${USER} .
```

NB :
- Grâce au montage `./data/db:/var/lib/postgresql/data` spécifié dans `docker-compose.yml`, la base de données est 
  persistée dans le répertoire `data/db` de l'appli (d'ailleurs, ne pas oublier de faire un `sudo chmod -R 777 data/db`).
- Les scripts de création de la base de données exécutés au lancement du container (si la base n'existe pas déjà)
  se trouvent dans le répertoire `./docker/db` de l'appli et sont fournis au container grâce au montage 
  `./docker/db/:/docker-entrypoint-initdb.d/`. 
- Lancer le script qui va déplacer les .dist dans le dossier autoload et les script sql dans un dossier nommé SQL.
Les scripts SQL ne seront pas exécuter automatiquement.

```bash
composer run-script "post-create-project-cmd"
```

## Configuration du projet

@@ -121,19 +82,66 @@ cp -r config/autoload/local.php.dist config/autoload/local.php
créez dans `config/autoload` les fichiers de configuration locaux et globaux des bibliothèques utilisées 
à partir des `.dist` :
```bash
cp -r vendor/unicaen/app/config/unicaen-app.global.php.dist   config/autoload/unicaen-app.global.php
cp -r vendor/unicaen/app/config/unicaen-app.local.php.dist    config/autoload/unicaen-app.local.php
cp -r vendor/unicaen/auth/config/unicaen-auth.global.php.dist config/autoload/unicaen-auth.global.php
cp -r vendor/unicaen/auth/config/unicaen-auth.local.php.dist  config/autoload/unicaen-auth.local.php
cp -R ./vendor/unicaen/app/config/unicaen-app.global.php.dist ./config/autoload/unicaen-app.global.php;
cp -R ./vendor/unicaen/app/config/unicaen-app.local.php.dist ./config/autoload/unicaen-app.local.php;
cp -R ./vendor/unicaen/authentification/config/unicaen-authentification.global.php.dist ./config/autoload/unicaen-authentification.global.php;
cp -R ./vendor/unicaen/authentification/config/unicaen-authentification.local.php.dist ./config/autoload/unicaen-authentification.local.php;
cp -R ./vendor/unicaen/ldap/config/unicaen-ldap.local.php.dist ./config/autoload/unicaen-ldap.local.php;
cp -R ./vendor/unicaen/mail/config/unicaen-mail.global.php.dist ./config/autoload/unicaen-mail.global.php;
cp -R ./vendor/unicaen/mail/config/unicaen-mail.local.php.dist ./config/autoload/unicaen-mail.local.php;
cp -R ./vendor/unicaen/privilege/config/unicaen-privilege.global.php.dist ./config/autoload/unicaen-privilege.global.php;
cp -R ./vendor/unicaen/utilisateur/config/unicaen-utilisateur.global.php.dist ./config/autoload/unicaen-utilisateur.global.php;
cp -R ./config/autoload/local.php.dist ./config/autoload/local.php;
```

- Le cas échéant, reportez-vous aux docs des modules concernés pour adapter ces fichiers de configuration 
à vos besoins :
  - [unicaen/app](https://git.unicaen.fr/lib/unicaen/app)
  - [unicaen/auth](https://git.unicaen.fr/lib/unicaen/auth)
  - [unicaen/privilege](https://git.unicaen.fr/lib/unicaen/privilege)
  - [unicaen/mail](https://git.unicaen.fr/lib/unicaen/mail)
  - [unicaen/ldap](https://git.unicaen.fr/lib/unicaen/ldap)

  
- Si cela n'a pas déjà été fait par une des `post-create-project-cmd` du `composer.json`, 
  récupérer les différentes requêtes sql pour instancier les premières données pour les bibliothèques :

```bash
mkdir -p SQL 
mkdir -p ./SQL/001-unicaen-utilisateur
cp -R ./vendor/unicaen/utilisateur/data/sql/schema_postgresql.sql ./SQL/001-unicaen-utilisateur/001-schema-unicaen-utilisateur.sql
cp -R ./vendor/unicaen/utilisateur/data/sql/data.sql ./SQL/001-unicaen-utilisateur/001-data-unicaen-utilisateur.sql
mkdir -p ./SQL/002-unicaen-privilege
cp -R ./vendor/unicaen/privilege/data/sql/schema_postgresql.sql ./SQL/002-unicaen-privilege/002-schema-unicaen-privilege.sql	
cp -R ./vendor/unicaen/privilege/data/sql/data.sql ./SQL/002-unicaen-privilege/002-data-unicaen-privilege.sql	
mkdir -p ./SQL/003-unicaen-mail
cp -R ./vendor/unicaen/mail/SQL/001_tables.sql ./SQL/003-unicaen-mail/003-schema-unicaen-mail.sql
cp -R ./vendor/unicaen/mail/SQL/002_privileges.sql ./SQL/003-unicaen-mail/003-data-unicaen-mail.sql
```

- Exécuter les requêtes dans l'ordre suivant dans la base de données du container :
```
./SQL/001-unicaen-utilisateur/001-schema-unicaen-utilisateur.sql
./SQL/002-unicaen-privilege/002-schema-unicaen-privilege.sql
./SQL/003-unicaen-mail/003-schema-unicaen-mail.sql;
./SQL/001-unicaen-utilisateur/001-data-unicaen-utilisateur.sql;
./SQL/001-unicaen-utilisateur/002-data-unicaen-privilege.sql;
./SQL/003-unicaen-mail/003-data-unicaen-mail.sql;	
```

## Test de l'application 

Théoriquement, l'application devrait être accessible à l'adresse [https://localhost:8443](https://localhost:8443).
Le port utilisé dépend des redirections configurées dans le fichier [docker-compose.yml](docker-compose.yml).

## Module Demo

Le squelette d'application possède un module "démo" qui utilise une base de données PostgreSQL de démonstration
permettant d'avoir une authentification locale qui fonctionne.

Cette base de données est fournie par le service `db` (fichier de config `docker-compose.yml`).
Il y a également un service `adminer` fournissant de quoi explorer la base de données avec l'outil
["Adminer"](https://www.adminer.org) en vous rendant à l'adresse `http://localhost:9080` (sélectionner "PostgeSQL"
et utiliser les informations de connexion à la bdd présentes dans le `docker-compose.yml`).
Pour explorer/administrer la base de données *de l'extérieur du container* (avec PHPStorm par exemple),
l'adresse de la base est cette fois `localhost:8432`.
+99 −0
Original line number Diff line number Diff line
-- -----------------------------------------------------
-- Table unicaen_role
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS unicaen_role (
  id                    SERIAL        PRIMARY KEY,
  role_id               VARCHAR(64)   NOT NULL,
  libelle               VARCHAR(255)  NOT NULL,
  description           TEXT          NOT NULL,
  is_default            BOOLEAN       DEFAULT false NOT NULL,
  is_auto               BOOLEAN       DEFAULT false NOT NULL,
  parent_id             INTEGER,
  ldap_filter           VARCHAR(255)  DEFAULT NULL::character varying,
  accessible_exterieur  BOOLEAN       DEFAULT true NOT NULL,
  displayed             BOOLEAN       DEFAULT true NOT NULL,
  CONSTRAINT fk_unicaen_role_parent FOREIGN KEY (parent_id) REFERENCES unicaen_role (id) DEFERRABLE INITIALLY IMMEDIATE
);

CREATE UNIQUE INDEX un_unicaen_role_role ON unicaen_role (role_id);
CREATE INDEX ix_unicaen_role_parent ON unicaen_role (parent_id);


-- -----------------------------------------------------
-- Table unicaen_utilisateur
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS unicaen_utilisateur (
  id                    SERIAL        PRIMARY KEY,
  username              VARCHAR(255)  NOT NULL,
  display_name          VARCHAR(255)  NOT NULL,
  email                 VARCHAR(255),
  password              VARCHAR(128)  DEFAULT 'application'::character varying NOT NULL,
  state                 BOOLEAN       DEFAULT true NOT NULL,
  password_reset_token  VARCHAR(256),
  last_role_id          INTEGER,
  CONSTRAINT fk_unicaen_utilisateur_last_role FOREIGN KEY (last_role_id) REFERENCES unicaen_role(id) DEFERRABLE INITIALLY IMMEDIATE
);

CREATE UNIQUE INDEX un_unicaen_utilisateur_username ON unicaen_utilisateur(username);
CREATE UNIQUE INDEX un_unicaen_utilisateur_password_reset_token ON unicaen_utilisateur(password_reset_token);
CREATE INDEX ix_unicaen_utilisateur_last_role ON unicaen_utilisateur(last_role_id);


-- -----------------------------------------------------
-- Table unicaen_utilisateur_role_linker
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS unicaen_utilisateur_role_linker (
  utilisateur_id   INTEGER NOT NULL,
  role_id          INTEGER NOT NULL,
  CONSTRAINT pk_unicaen_utilisateur_role_linker PRIMARY KEY (utilisateur_id,role_id),
  CONSTRAINT fk_unicaen_utilisateur_role_linker_utilisateur FOREIGN KEY (utilisateur_id) REFERENCES unicaen_utilisateur (id) DEFERRABLE INITIALLY IMMEDIATE,
  CONSTRAINT fk_unicaen_utilisateur_role_linker_role FOREIGN KEY (role_id) REFERENCES unicaen_role (id) DEFERRABLE INITIALLY IMMEDIATE
);

CREATE INDEX ix_unicaen_utilisateur_role_linker_user ON unicaen_utilisateur_role_linker (utilisateur_id);
CREATE INDEX ix_unicaen_utilisateur_role_linker_role ON unicaen_utilisateur_role_linker (role_id);


-- -----------------------------------------------------
-- Table unicaen_privilege_categorie
-- -----------------------------------------------------
CREATE TABLE UNICAEN_PRIVILEGE_CATEGORIE (
  ID        SERIAL        PRIMARY KEY,
  CODE      VARCHAR(150)  NOT NULL,
  LIBELLE   VARCHAR(200)  NOT NULL,
  NAMESPACE VARCHAR(255),
  ORDRE     INTEGER       DEFAULT 0
);

CREATE UNIQUE INDEX un_unicaen_privilege_categorie_code ON unicaen_privilege_categorie (code);


-- -----------------------------------------------------
-- Table unicaen_privilege_privilege
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS unicaen_privilege (
  id           SERIAL       PRIMARY KEY,
  categorie_id INTEGER      NOT NULL,
  code         VARCHAR(150) NOT NULL,
  libelle      VARCHAR(200) NOT NULL,
  ordre        INTEGER      DEFAULT 0,
  CONSTRAINT fk_unicaen_privilege_categorie FOREIGN KEY (categorie_id) REFERENCES unicaen_privilege_categorie (id) DEFERRABLE INITIALLY IMMEDIATE
);

CREATE UNIQUE INDEX un_unicaen_privilege_code ON unicaen_privilege (categorie_id, code);
CREATE INDEX ix_unicaen_privilege_categorie ON unicaen_privilege (categorie_id);


-- -----------------------------------------------------
-- TABLE UNICAEN_PRIVILEGE_ROLE_LINKER
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS unicaen_privilege_role_linker (
  privilege_id INTEGER  NOT NULL,
  role_id      INTEGER  NOT NULL,
  CONSTRAINT pk_unicaen_privilege_role_linker PRIMARY KEY (privilege_id, role_id),
  CONSTRAINT fk_unicaen_privilege_role_linker_privilege FOREIGN KEY (privilege_id) REFERENCES unicaen_privilege (id) DEFERRABLE INITIALLY IMMEDIATE,
  CONSTRAINT fk_unicaen_privilege_role_linker_role FOREIGN KEY (role_id) REFERENCES unicaen_role (id) DEFERRABLE INITIALLY IMMEDIATE
);

CREATE INDEX ix_unicaen_privilege_role_linker_privilege ON unicaen_privilege_role_linker (privilege_id);
CREATE INDEX ix_unicaen_privilege_role_linker_role ON unicaen_privilege_role_linker (role_id);
 No newline at end of file
+93 −0
Original line number Diff line number Diff line
INSERT INTO unicaen_utilisateur (id, username, email, display_name, password, state)
VALUES
  (0, 'app', 'dsi.applications@unicaen.fr', 'Application', 'ldap', false)
  ON CONFLICT (username) DO
  UPDATE SET
           email=excluded.email,
           display_name=excluded.display_name,
           password=excluded.password;


INSERT INTO unicaen_role (role_id, libelle, description, is_default, is_auto, parent_id, ldap_filter, accessible_exterieur)
values
  ('administrateur', 'Administrateur', 'Administrateur de l''application', false, true, null, null, true),
  ('superviseur', 'Superviseur', 'Superviseur', false, true, null, null, true)
ON CONFLICT (role_id) DO
  UPDATE SET
           libelle=excluded.libelle,
           description=excluded.description,
           is_default=excluded.is_default,
           is_auto=excluded.is_auto,
           parent_id=excluded.parent_id,
           ldap_filter=excluded.ldap_filter,
           accessible_exterieur=excluded.accessible_exterieur;


INSERT INTO unicaen_privilege_categorie (code, libelle, namespace, ordre)
VALUES
  ('utilisateur', 'Gestion des utilisateurs', 'UnicaenUtilisateur\Provider\Privilege',  1),
  ('role',        'Gestion des rôles',        'UnicaenUtilisateur\Provider\Privilege',  2),
  ('privilege',   'Gestion des privilèges',   'UnicaenPrivilege\Provider\Privilege',    3)
ON CONFLICT (code) DO
  UPDATE SET
           libelle=excluded.libelle,
           namespace=excluded.namespace,
           ordre=excluded.ordre;


WITH d(code, lib, ordre) AS (
  SELECT 'utilisateur_afficher',      'Consulter un utilisateur',                       1 UNION
  SELECT 'utilisateur_ajouter',       'Ajouter un utilisateur',                         2 UNION
  SELECT 'utilisateur_changerstatus', 'Changer le statut d''un utilisateur',            3 UNION
  SELECT 'utilisateur_modifierrole',  'Modifier les rôles attribués à un utilisateur',  4 UNION
  SELECT 'utilisateur_rechercher',    'Rechercher un utilisateur',                      5
)
INSERT INTO unicaen_privilege(categorie_id, code, libelle, ordre)
SELECT cp.id, d.code, d.lib, d.ordre
FROM d
  JOIN unicaen_privilege_categorie cp ON cp.code = 'utilisateur'
ON CONFLICT (categorie_id, code) DO
  UPDATE SET
           libelle=excluded.libelle,
           ordre=excluded.ordre;


WITH d(code, lib, ordre) AS (
  SELECT 'role_afficher', 'Consulter les rôles',  1 UNION
  SELECT 'role_modifier', 'Modifier un rôle',     2 UNION
  SELECT 'role_effacer',  'Supprimer un rôle',    3
)
INSERT INTO unicaen_privilege(categorie_id, code, libelle, ordre)
SELECT cp.id, d.code, d.lib, d.ordre
FROM d
  JOIN unicaen_privilege_categorie cp ON cp.code = 'role'
ON CONFLICT (categorie_id, code) DO
  UPDATE SET
           libelle=excluded.libelle,
           ordre=excluded.ordre;


WITH d(code, lib, ordre) AS (
  SELECT 'privilege_voir',      'Afficher les privilèges',  1 UNION
  SELECT 'privilege_ajouter' ,  'Ajouter un privilège',     2 UNION
  SELECT 'privilege_modifier' , 'Modifier un privilège',    3 UNION
  SELECT 'privilege_supprimer', 'Supprimer un privilège',   4 UNION
  SELECT 'privilege_affecter',  'Attribuer un privilège',   5
)
INSERT INTO unicaen_privilege(categorie_id, code, libelle, ordre)
SELECT cp.id, d.code, d.lib, d.ordre
FROM d
  JOIN unicaen_privilege_categorie cp ON cp.code = 'privilege'
ON CONFLICT (categorie_id, code) DO
  UPDATE SET
           libelle=excluded.libelle,
           ordre=excluded.ordre;


INSERT INTO unicaen_privilege_role_linker (role_id, privilege_id)
SELECT role.id, privilege.id
FROM unicaen_role role, unicaen_privilege privilege
  JOIN unicaen_privilege_categorie cp ON privilege.categorie_id = cp.id
WHERE role.role_id = 'administrateur'
  AND cp.code IN ('utilisateur', 'role', 'privilege')
ON CONFLICT DO NOTHING;
 No newline at end of file
Loading