Garradin

Centos7 - Installation de GARRADIN

Page mise à jour le 01/02/2019.

SOMMAIRE

A - Installation

B - Paramètrage

C - Adaptation du logiciel

D - Passer Garradin en HTTPS

E - Mise à jour de Garradin

F - Utilisation de SQLITE3

 

Garradin est une application Web qui permet de gérer la comptabilité d'une association. L'application Web gère la comptabilité et les adhérents. Elle dispose aussi d'un wiki et d'un petit éditeur de pages web. Le produit est utilisable en ligne sur internet mais il peut aussi être installé sur un serveur privé. C'est l'option prise pour ce tutoriel.

Garradin sera installé dans la home directory de l'utilisateur en tant que virtualhost. Voir le paragraphe : Apache : Espace web privé (userdir). L'application utilise une base de données sqlite3.

Version installée : garradin-0.9.2 du 28 janvier 2019
avec PHP : 7.1.23, SQLITE : 3.7.17, HTTPD : 2.4.6.

 

A - Installation

Téléchargement et décompression

On se positionne à la racine de l'espace web de l'utilisateur, on télécharge Garradin, on le décompresse puis on supprime le fichier téléchargé.

# cd /home/user1/public_html
# wget https://fossil.kd2.org/garradin/uv/garradin-0.9.2.tar.bz2
# tar xjf garradin-0.9.2.tar.bz2
# rm -f garradin-0.9.2.tar.bz2

Mise en place des fichiers

L'application sera installée dans la home directory de l'utilisateur, à la racine du site ( /home/user1/public_html/ ). Pour celà on déplace tous les fichiers qui figurent dans le répertoire garradin-0.9.2 créé par la décompression (tous les fichiers même les fichiers cachés -> .htaccess) à la racine du site web puis on supprime le répertoire garradin-0.9.2.

# mv garradin-0.9.2/* ./
# mv garradin-0.9.2/.h* ./
# rmdir garradin-0.9.2

Mise en place des droits sur les répertoires

Le répertoire "cache" doit être en "rwxrwxrwx" et Garradin doit pouvoir écrire via apache dans les autres répertoires et dans le fichier error.log.

# chmod 777 cache
# chmod 774 plugins
# chmod 770 www/squelettes
# touch error.log
# chmod ug=rw,o= error.log

Affectation au propriétaire de la home directory

Vu que Garradin est installé dans la home directory de l'utilisateur, il faut donner la propriété des fichiers à l'utilisateur (user1) puis ajouter apache au groupe user1.

# chown -R user1:user1 ./
# gpasswd -a apache user1

Paramètrage Selinux

"Chcon" modifie le contexte de façon temporaire. Pour fixer le contexte de façon permanente, il faudra utiliser "semanage". Ici, on donne le droit à apache de lire le contenu du répertoire de l'utilisateur, celui de lire et d'écrire sur le cache, sur le répertoire squelettes et sur le fichier error.log.

# chcon -R -t httpd_sys_content_t .
# chcon -R -t httpd_sys_rw_content_t cache
# chcon -R -t httpd_sys_rw_content_t www/squelettes
# chcon -t httpd_sys_rw_content_t error.log

Création du virtualhost
désactiver les options Indexes et Multiviews

Sur le serveur Web, il faut créer le fichier de configuration dans le répertoire /etc/httpd/conf.d/ et ajouter les lignes après "->" en adaptant l'adresse IP, l'utilisateur et le nom de domaine. Ne pas oublier de relancer le serveur apache.

# touch /etc/httpd/conf.d/garradin.conf
# vi /etc/httpd/conf.d/garradin.conf
->
# Garradin - Comptabilite - Production
# --------------------------------------------
<VirtualHost 192.168.1.233:80>
        ServerName www. garradin.vhost.fr
        ServerAlias garradin.vhost.fr

        DocumentRoot /home/user1/public_html/www/
        <Directory /home/user1/public_html/www/>
                Options FollowSymLinks
                AllowOverride All
                Require all granted
        </Directory>

        Errorlog /var/log/httpd/garradin.log
        LogLevel warn
</VirtualHost>

# systemctl restart httpd

Garradin est maintenant installé.

 

B - Paramètrage de Garradin

Répertoires et fichiers modifiés à l'installation

A la racine du site web, l'installation crée :
- le fichier de base de données : association.sqlite
- le fichier de configuration locale : config.local.php qui contient les paramètres locaux et notamment la clé de session
- le fichier d'erreur : error.log

Dans le répertoire cache,
- le répertoire compiled
- le répertoire static

Interface applicative d'installation

A partir d'un navigateur, http:// garradin.vhost.fr

Garradin - Installation - Section1

 

Garradin - Installation- Section2

 

Garradin - Page de connexion

C - Adaptation du logiciel

Une fois le logiciel installé, il convient :

1°) de mettre en place les catégories de membres

Garradin - Catégories de membres

2°) de mettre en place la cotisation annuelle

Garradin - Cotisation annuelle

3°) de saisir les éléments bancaires

Garradin - Référence bancaires

4°) de configurer la fiche de membres

Garradin - Fiche de membre - section 1

 

e-mail : désactiver champ obligatoire

Téléphone : modifier l'intitulé -> Téléphone fixe
Ajouter le champs tel_portable et repositionner ce champs derrière téléphone fixe
Ajouter le champs prédéfini note et le rendre modifiable par les membres

5°) de saisir les données des membres ou d'importer la liste des membres (si disponible au format excel)

Si vous disposez d'une ancienne version de Microsoft Excel (2003/2007/2010 ?), l'import des données pose problème pour les caractères accentués. En effet, Garradin ignore les cellules qui en comportent. Pour remédier à ce problème, il est préférable d'utiliser LibreOffice qui permet de formater les données selon le codage UTF-8.

D - Passer Garradin en HTTPS

Prés-requis :
Disposer d'un certificat installé sur le serveur Web pour le domaine considéré (pour moi, le domaine = garradin.vhost.fr).
Activer le flux HTTPS via le reverse proxy Apache.

Dans cette configuration, les flux sont chiffrés entre l'utilisateur et le reverse proxy, ce qui est suffisant pour sécuriser les accès via Internet. Derrière le reverse proxy, les flux transitent en clair sur le réseau local.

1°) Modifier le fichier de configuration

Se placer à la racine du site, dans le répertoire root du serveur web où est installé Garradin et ajouter les 2 lignes suivantes au fichier de configuration local.

# vi /home/user1/public_html/config.local.php
->
const PREFER_HTTPS = 3;
const WWW_URL = 'https://garradin.vhost.fr/';

Ajouter les 2 lignes suivantes au fichier .htaccess

# vi /home/user1/public_html/.htaccess
->
  SetEnv HTTPS "on"
  SetEnv HTTP_X_FORWARDED_PROTO "https"

Test du bon fonctionnement.

Dans la barre de navigation de votre navigateur saisissez : https://garradin.vhost.fr
Votre navigation devrait maintenant être protégée (apparition du cadena vert devant l'URL du site et sur la page administration, en regard du champ "Mot de passe".

 

E - Mise à jour de Garradin

Prérequis :
Créer un nouveau virtualHost au niveau du reverse proxy
Télécharger la dernière version stable.

# wget https://fossil.kd2.org/garradin/uv/garradin-0.9.2.tar.bz2

Effectuer une installation classique dans un nouveau virtualhost en suivant la procédure "A-installation" ci-dessus. L'utilisation d'un nouveau virtualhost permet de conserver intacte l'ancienne version, ce qui a pour avantage d'être en capacité de revenir à l'ancienne version si la migration à la nouvelle version se passe mal. Pour ma part, j'utilise 2 virtualHosts (le premier pour la production et le second pour effectuer des tests, former de nouveux utilisateurs, etc). A chaque mise à jour, je bascule de l'un sur l'autre.

Copier la base de données de la version précédente.

# cp /home/user1/public_html/association.sqlite /home/user2/public_html/
# chown user2:user2 association.sqlite

Restreindre l'accès à la base de données

# chmod o=-r association.sqlite

Copier les fichiers du site web si vous utilisez cette fonctionnalité

# cp /home/user1/public_html/www/squelettes/* /home/user2/public_html/www/squelettes/
# chown -R user2:user2 /home/user2/public_html/www/squelettes/*

Au niveau du reverse proxy, modifier le pointeur de sous-domaine pour qu'il corresponde au nouveau sous-domaine

 

Lancer l'interface web de Garradin pour qu'il convertisse la base de données

Dans votre navigateur, saisissez https://garradin.vhost.fr

Lorsque la base est convertie, il est possible de supprimer le fichier "association.pre-upgrade-0.9.2.sqlite" qui a été créé par garradin.

# rm -f  association.pre-upgrade-0.9.2.sqlite

Testez le bon fonctionnement de la mise à jour.

Si necessaire, supprimer l'ancien répertoire lorsque tous les tests sont corrects. L'idéal étant étant de disposer d'un virtualhost pour la version qui sera mise en production et un autre pour celle qui sera plutôt réservée aux tests d'utilisation et d'intégration.

 

Utilisation de Sqlite3

En mode console :

Se positionner dans le répertoire où est installé Garradin et lancer l'interprèteur SQL en chargeant la base de données utilisée par Garradin

# cd /home/user1/public_html/
# sqlite3 association.sqlite
->
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
# sqlite>

Pour quitter l'interpréteur SQLITE

# sqlite> .quit

Pour afficher les tables de la base de données association.sqlite

# sqlite> .table
compta_categories         fichiers                  rappels
compta_comptes            fichiers_compta_journal   rappels_envoyes
compta_comptes_bancaires  fichiers_contenu          recherches
compta_exercices          fichiers_membres          wiki_pages
compta_journal            fichiers_wiki_pages       wiki_recherche
compta_moyens_paiement    membres                   wiki_recherche_content
compta_projets            membres_categories        wiki_recherche_docsize
compta_rapprochement      membres_operations        wiki_recherche_segdir
config                    membres_sessions          wiki_recherche_segments
cotisations               plugins                   wiki_recherche_stat
cotisations_membres       plugins_signaux           wiki_revisions

Pour afficher le schema de la base de données

Dans l'extrait ci-dessous, j'ai supprimé certaines tables peu utiles pour la gestion des données.

# sqlite> .schema
CREATE TABLE membres_operations
-- Liaison des enregistrement des paiements en compta
(
    id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE,
    id_operation INTEGER NOT NULL REFERENCES compta_journal (id) ON DELETE CASCADE,
    id_cotisation INTEGER NULL REFERENCES cotisations_membres (id) ON DELETE SET NULL,

    PRIMARY KEY (id_membre, id_operation)
);

CREATE TABLE compta_exercices
-- Exercices
(
    id INTEGER NOT NULL PRIMARY KEY,

    libelle TEXT NOT NULL,

    debut TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(debut) IS NOT NULL AND date(debut) = debut),
    fin TEXT NULL DEFAULT NULL CHECK (fin IS NULL OR (date(fin) IS NOT NULL AND date(fin) = fin)),

    cloture INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE compta_comptes
-- Plan comptable
(
    id TEXT NOT NULL PRIMARY KEY, -- peut contenir des lettres, eg. 53A, 53B, etc.
    parent TEXT NOT NULL DEFAULT 0,

    libelle TEXT NOT NULL,

    position INTEGER NOT NULL, -- position actif/passif/charge/produit
    plan_comptable INTEGER NOT NULL DEFAULT 1, -- 1 = fait partie du plan comptable, 0 = a été ajouté par l'utilisateur
    desactive INTEGER NOT NULL DEFAULT 0 -- 1 = compte historique désactivé
);
CREATE INDEX compta_comptes_parent ON compta_comptes (parent);

CREATE TABLE compta_comptes_bancaires
-- Comptes bancaires
(
    id TEXT NOT NULL PRIMARY KEY,

    banque TEXT NOT NULL,

    iban TEXT NULL,
    bic TEXT NULL,

    FOREIGN KEY(id) REFERENCES compta_comptes(id) ON DELETE CASCADE
);

CREATE TABLE compta_projets
-- Projets (compta analytique)
(
    id INTEGER PRIMARY KEY NOT NULL,

    libelle TEXT NOT NULL
);

CREATE TABLE compta_journal
-- Journal des opérations comptables
(
    id INTEGER PRIMARY KEY NOT NULL,

    libelle TEXT NOT NULL,
    remarques TEXT NULL,
    numero_piece TEXT NULL, -- N° de pièce comptable

    montant REAL NOT NULL,

    date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date),
    moyen_paiement TEXT NULL,
    numero_cheque TEXT NULL,

    compte_debit TEXT NULL, -- N° du compte dans le plan, NULL est utilisé pour une opération qui vient d'un exercice précédent
    compte_credit TEXT NULL, -- N° du compte dans le plan

    id_exercice INTEGER NULL DEFAULT NULL, -- En cas de compta simple, l'exercice est permanent (NULL)
    id_auteur INTEGER NULL,
    id_categorie INTEGER NULL, -- Numéro de catégorie (en mode simple)
    id_projet INTEGER NULL,

    FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code),
    FOREIGN KEY(compte_debit) REFERENCES compta_comptes(id),
    FOREIGN KEY(compte_credit) REFERENCES compta_comptes(id),
    FOREIGN KEY(id_exercice) REFERENCES compta_exercices(id),
    FOREIGN KEY(id_auteur) REFERENCES membres(id) ON DELETE SET NULL,
    FOREIGN KEY(id_categorie) REFERENCES compta_categories(id) ON DELETE SET NULL,
    FOREIGN KEY(id_projet) REFERENCES compta_projets(id) ON DELETE SET NULL
);
CREATE INDEX compta_operations_exercice ON compta_journal (id_exercice);
CREATE INDEX compta_operations_date ON compta_journal (date);
CREATE INDEX compta_operations_comptes ON compta_journal (compte_debit, compte_credit);
CREATE INDEX compta_operations_auteur ON compta_journal (id_auteur);

CREATE TABLE compta_moyens_paiement
-- Moyens de paiement
(
    code TEXT NOT NULL PRIMARY KEY,
    nom TEXT NOT NULL
);

CREATE TABLE compta_categories
-- Catégories pour simplifier le plan comptable
(
    id INTEGER NOT NULL PRIMARY KEY,
    type INTEGER NOT NULL DEFAULT 1, -- 1 = recette, -1 = dépense, 0 = autre (utilisé uniquement pour l'interface)

    intitule TEXT NOT NULL,
    description TEXT NULL,

    compte TEXT NOT NULL, -- Compte affecté par cette catégorie

    FOREIGN KEY(compte) REFERENCES compta_comptes(id) ON DELETE CASCADE
);

CREATE TABLE "membres" (
        id INTEGER PRIMARY KEY, -- Numéro attribué automatiquement
        id_categorie INTEGER NOT NULL, -- Numéro de catégorie
        date_connexion TEXT NULL, -- Date de dernière connexion
        date_inscription TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d'inscription
        secret_otp TEXT NULL, -- Code secret pour TOTP
        clef_pgp TEXT NULL, -- Clé publique PGP
        numero INTEGER, -- Numéro
        nom TEXT, -- Nom & prénom
        email TEXT, -- Adresse E-Mail
        adresse TEXT, -- Adresse postale
        code_postal TEXT, -- Code postal
        ville TEXT, -- Ville
        pays TEXT, -- Pays
        telephone TEXT, -- Téléphone fixe
        tel_portable TEXT, -- Téléphone portable
        bureau INTEGER, -- Bureau & CA
        adh_ext INTEGER, -- Adhérent extérieur
        notes TEXT, -- Notes
        passe TEXT,
        FOREIGN KEY (id_categorie) REFERENCES membres_categories (id)
);
CREATE INDEX membres_id_categorie ON membres (id_categorie);
CREATE UNIQUE INDEX membres_identifiant ON membres (email);
CREATE UNIQUE INDEX membres_numero ON membres (numero);
CREATE INDEX membres_liste_numero ON membres (numero);
CREATE INDEX membres_liste_nom ON membres (nom);
CREATE INDEX membres_liste_adresse ON membres (adresse);
CREATE INDEX membres_liste_ville ON membres (ville);
CREATE INDEX membres_liste_bureau ON membres (bureau);
CREATE INDEX membres_liste_adh_ext ON membres (adh_ext);
CREATE INDEX membres_liste_notes ON membres (notes);

CREATE TABLE cotisations_membres
-- Enregistrement des cotisations et activités
(
    id INTEGER NOT NULL PRIMARY KEY,
    id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE,
    id_cotisation INTEGER NOT NULL REFERENCES cotisations (id) ON DELETE CASCADE,

    date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date)
);

CREATE TABLE membres_categories
-- Catégories de membres
(
    id INTEGER PRIMARY KEY NOT NULL,
    nom TEXT NOT NULL,

    droit_wiki INTEGER NOT NULL DEFAULT 1,
    droit_membres INTEGER NOT NULL DEFAULT 1,
    droit_compta INTEGER NOT NULL DEFAULT 1,
    droit_inscription INTEGER NOT NULL DEFAULT 0,
    droit_connexion INTEGER NOT NULL DEFAULT 1,
    droit_config INTEGER NOT NULL DEFAULT 0,
    cacher INTEGER NOT NULL DEFAULT 0,

    id_cotisation_obligatoire INTEGER NULL REFERENCES cotisations (id) ON DELETE SET NULL
);
CREATE UNIQUE INDEX cm_unique ON cotisations_membres (id_membre, id_cotisation, date);

CREATE TABLE cotisations
-- Types de cotisations et activités
(
    id INTEGER PRIMARY KEY NOT NULL,
    id_categorie_compta INTEGER NULL REFERENCES compta_categories (id) ON DELETE SET NULL, -- NULL si le type n'est pas associé automatiquement à la compta

    intitule TEXT NOT NULL,
    description TEXT NULL,
    montant REAL NOT NULL,

    duree INTEGER NULL, -- En jours
    debut TEXT NULL, -- timestamp
    fin TEXT NULL
);

Pour afficher le contenu d'une table

# sqlite> select * from compta_categories;

Quelques requêtes SQL

# sqlite> SELECT DISTINCT <Champ_à_rechercher> FROM <Table_n1>
      -> WHERE <Champ_à_rechercher> IN (
      -> SELECT <Champ_à_rechercher> FROM <Table_n2>;

° - °° - °