[AngularJs + Php Mysql] Gérer l’identification et les droits.

angularjslogo-php

Introduction


Voici ma méthode la plus récente et la plus claire, pour créer un système d’identification et d’affectations de  droits dans une application ANGULARJS avec un Back End PHP-MYSQL.

Finalement, une fois que l’on a compris, ce n’est pas si dur. Bien sur, il existe d’autres techniques, mais celle ci à le mérite de fonctionner.

Pour l’étape 3, il est possible que cela soit sujet à hacking, vu que le contrôle est effectué en JS, il faudrait donc faire la partie discrimination en fonction du rôle dans la partie Back End, cependant, cela fonctionne déjà comme cela. j’ai déjà mon idée pour passer la restriction CRUD en Back end : Le rôle de l’utilisateur sera passé en variable de session PHP, puis le test sera fait sur chaque fonction CRUD Update ou Delete ou Create, dans le back end, du coup avec le copié collé, tout fonctionnera de suite.

Principe général


  • Une table SQL des utilisateurs contient l’id, le nom, le prénom, l’Email, le mot de passe, le rôle de chaque utilisateur. (On peut bien sur ajouter la photo et pleins d’autres trucs…)
  • Une requête AJAX envoi le couple email/mot de passe de la vue identification au back end Php-Mysql qui teste si la correspondance email/mot de passe est valide.
  • C’est le Back end Php-Mysql (En technologie PDO) qui apporte la réponse, celle ci est testée dans la fonction de rappel de la requête $http de AngularJS.
  • un service AngularJs stocke l’intégralité des variables de l’utilisateur(C’est un objet JSON), si la réponse du back end PhpMysql est valide.
  • Les droits sont vérifiés lors de chaque requêtes CRUD UPDATE et INSERT, si le rôle de l’utilisateur est ADMIN ou SUPERUTILISATEUR, alors la requête est acceptée, si les droits de l’utilisateur est UTILISATEURSIMPLE, alors la requête est rejetée et l’utilisateur ne peut ni updater ni écrire. (Note : Il est aussi possible de le faire avec un interceptor mais c’est plus compliqué.)
  • Il est également possible de restreindre l’accès à des vues en fonction du rôle de l’utilisateur  dans le routeur AngularJs ngRoute.

Principes non traités dans cette doc :

  • Ensuite, si on actualise l’application lors de l’appui sur la touche F5, le service perds l’objet utilisateur, il faut alors utiliser le web Storage pour éviter à l’utilisateur de se re-logger sans cesse, et créer un objet Json ‘utilisateur’ persistant dans la mémoire du navigateur.
  • Création CRUD des utilisateurs
  • Cryptage MD5 du mot de passe

Schéma :


schf.jpg

Lire la suite

Publicités

[AngularJs] insérer un Loader Ajax

angularjs
Introduction


Insérer un Loader Ajax qui s’affiche lors de chaque requête $http ajax sur les pages, en seulement 3 minutes.

Un loader est une image GIF animée qui signale à l’utilisateur de l’app qu’une requête AJAX est en cours.

On se sert d’un interceptor.

Note : dans mon cas, j’ajoute toujours app devant le nom des différents modules, exemple : app.factory, app.service etc … et jamais de points- virgules à la fin ! je n’ai jamais de problèmes de ce fait.

 

Comment faire :


http://stackoverflow.com/questions/17838708/implementing-loading-spinner-using-httpinterceptor-and-angularjs-1-1-5

La solution de Michael Hunziker à copier coller dans l’application AngularJs, ça a fonctionné immédiatement pour moi… Attention de bien nommer l’image du loader et son chemin.

Interceptor:


.factory('httpInterceptor', function ($q, $rootScope, $log) {

    var numLoadings = 0;

    return {
        request: function (config) {

            numLoadings++;

            // Show loader
            $rootScope.$broadcast("loader_show");
            return config || $q.when(config)

        },
        response: function (response) {

            if ((--numLoadings) === 0) {
                // Hide loader
                $rootScope.$broadcast("loader_hide");
            }

            return response || $q.when(response);

        },
        responseError: function (response) {

            if (!(--numLoadings)) {
                // Hide loader
                $rootScope.$broadcast("loader_hide");
            }

            return $q.reject(response);
        }
    };
})
.config(function ($httpProvider) {
    $httpProvider.interceptors.push('httpInterceptor');
});

Directive:

.directive("loader", function ($rootScope) {
    return function ($scope, element, attrs) {
        $scope.$on("loader_show", function () {
            return element.show();
        });
        return $scope.$on("loader_hide", function () {
            return element.hide();
        });
    };
}
)

CSS:

#loaderDiv {
   position: fixed;
   top: 0;
   right: 0;
   bottom: 0;
   left: 0;
   
   background-color: white;
   opacity: .6;
}

.ajax-loader {
   position: absolute;
   left: 50%;
   top: 50%;
   margin-left: -32px; /* -1 * image width / 2 */
   margin-top: -32px; /* -1 * image height / 2 */
   display: block;
}

HTML:

<div id="loaderDiv" loader>
    <img src="img-app/loader.gif" class="ajax-loader"/></div>

Résultat :
Voir l’app http://nicolash.org/pompestation/#/accueil

#loaderdiv

[Divers] Une liste doit être minimisée, un objet peut être gros.

Introduction


Une chose que je perds de vue quelques fois lorsque je fais une app.

Description


  • Une liste d’objets provenant de AJAX doit être limitée en nombre de colonnes pour ne pas être couteuse en temps de chargement dans le front end.
    Autrement dit, il faut éviter les SELECT table.* FROM table dans la requête SQL qui va constituer la liste.

    Pourquoi ? Parce qu’une liste doit être rapide à afficher dans le navigateur, on ne peut pas se permettre de quérir toutes les caractéristiques des objets, une liste doit être synthétique.

  • Une liste d’objet comprends toujours l’id de chaque objet, lors du clic sur un objet dans une liste, une requête AJAX unique avec le critère ID doit être exécutée, qui pourra télécharger elle toutes les caractéristiques de l’objet et de ses éventuelles jointures…
    Pourquoi ? Parce qu’un utilisateur accepte d’attendre pour lire les caractéristiques de son objet, par contre il n’accepte pas d’attendre la constitution d’une liste d’objets.

La plupart des sites et apps fonctionnent comme cela, alors pourquoi tenter de modifier ce système ?

Souvent il m’arrive de quérir l’objet dans la liste JSON, par paresse( Et de créer une méga liste JSON avec pleins de colonnes puisque cela fonctionne, surtout en one time binding…), alors qu’il faut plutôt toujours réaliser une requête AJAX qui va quérir l’objet en fonction de son ID (et surtout ses jointures, cela peut devenir énorme et ne saurait être conservé dans le gros tableau json de la liste, bien sur) sur la BDD. C’est le fonctionnement logique que tout le monde comprends, il ne faut pas contrevenir à cette rêgle, malgré les aptitudes énomes d’AngularJs à faciliter le tout …

 

[Application 61 ] Journal de Dev

pompestation

 Liste actualisée des actions à mener :


Vue Stations :

  • cocher-la-case-avec-une-coche_318-32559.pngAjouter des photos dans les dropdowns de filtres
  • cocher-la-case-avec-une-coche_318-32559.pngControle front end du format de l’email et du téléphone
  • cocher-la-case-avec-une-coche_318-32559.pngAjouter l’adresse décomposée
  • Ajouter une cartographie des stations service, avec leur adresses avec google map
  • Ajouter un 0 dans les champs number, x,x0
  • Ajouter une case recherche + filtre par département
  • Eventuellement ajouter ici l’onglet avec tous les détails de la stations(intervenants, citernes, fournisseurs favoris, etc …)
  • cocher-la-case-avec-une-coche_318-32559.pngFaire un tableau moins fourni
  •  cocher-la-case-avec-une-coche_318-32559.pngUn filtre par département, Ville, Taille, Type + retour à initial

Vue Citernes :

  • cocher-la-case-avec-une-coche_318-32559.png Activer le calcul du taux de remplissage
  • cocher-la-case-avec-une-coche_318-32559.png Colorer en orange et rouge les ligne en fonction du besoin de reassort
  • cocher-la-case-avec-une-coche_318-32559.pngPlacer les filtres en haut
  • cocher-la-case-avec-une-coche_318-32559.pngEnlever des colonnes du tableau, mettre les volumes dans le détail
  • cocher-la-case-avec-une-coche_318-32559.pngActiver le tri par Taux de remplissage
  • Enlever le bug du css ligne rouge sur les Taux<200
  • Filtrer par type de carburant

Vue Pompes :

  • cocher-la-case-avec-une-coche_318-32559.png Faire la jointure pour obtenir le nom des citernes dans le tableau = OK
  • Montrer à quelle station appartient une pompe
  • Ajouter un filtre par station

Vue Produits :

  • cocher-la-case-avec-une-coche_318-32559.pngPlacer les filtres en haut
  • Enlever l’affectation à une station( Cet affectation proviendra de la commande de stock qui sera affectable par stations)
  • Faire fonctionner le tri par succés produit

Vue Intervenants :

  • cocher-la-case-avec-une-coche_318-32559.pngLier un intervenant à une station
  • cocher-la-case-avec-une-coche_318-32559.pngAjouter son salaire, son contrat sous format fichier, son évaluation
  • cocher-la-case-avec-une-coche_318-32559.pngPlacer les filtres en haut
  • Ajouter une cartographie des intervenants avec google map
  • NEW ajouter une fonctionnalité de fixation d’horaires de travail par semaine (Belle avec du drag n drop et des graphiques) (Gros travail)
  • Ajouter sa date de naissance
  • cocher-la-case-avec-une-coche_318-32559.pngCréer un système d’Emailing globalisé/Par groupe
  • cocher-la-case-avec-une-coche_318-32559.pngEssayer de trouver un moyen pour que l’on voit encore les boutons’ nouveau’ etc …

Vue Réassort carburant immédiat :

  • cocher-la-case-avec-une-coche_318-32559.pngCréer un article détaillant le fonctionnement de la gestion des stocks avec les triggers SQL (pas fini)
  • cocher-la-case-avec-une-coche_318-32559.pngImposer le choix d’une station avant de donner l’accès au formulaire
  • Interdire une valeur négative
  • cocher-la-case-avec-une-coche_318-32559.pngAjouter un filtre par station
  • cocher-la-case-avec-une-coche_318-32559.pngActiver le calcul du taux de remplissage
  • cocher-la-case-avec-une-coche_318-32559.pngColorer en orange et rouge les ligne en fonction du besoin de réassort
  • cocher-la-case-avec-une-coche_318-32559.pngPouvoir trier par taux de remplissage (automatique)

Vue Gestion/effectuer une commande de carburant :

  • Ajouter les taux de remplissage dans le form de commande + Empêcher de commander trop.
  • Créer un modèle de bon de commande, et activer l’envoi par email.
  • Activer l’envoi de la commande par email avec un bouton ‘ Envoyer la commande par Email’, l’email dur service client dans la vue fournisseurs doit être obligatoirement renseigné.
  • Activer l’application de commande avec un bouton ‘Appliquer la commande’ + Possibilité d’annuler avec les triggers … (Hard)
  • Export PDF d’un bon de commande, essayer de pouvoir le personnaliser.

Vue Rapports/ réassort Carburant :

  • Activer l’export en PDF
  • Calculer la somme des commandes par station

Vue Accueil ou dans une vue paramêtres :

  • Prix moyen du litre d’essence du jour ou de la semaine
  • Taux de tva réglable
  • Possibilité de requester les services commerciaux des fournisseurs avec un bouton pour demander leurs tarifs de la semaine (Message automatisé)

Sur toutes les vues :

  • cocher-la-case-avec-une-coche_318-32559.pngTransparence de la ligne du tableau choisi lors du clic sur nouveau = OK
  • cocher-la-case-avec-une-coche_318-32559.pngTester un nouveau design avec la liste sur la gauche et le détail sur la droite
  • cocher-la-case-avec-une-coche_318-32559.pngExport PDF et XLS de la liste (A continuer)

Autres :

  • cocher-la-case-avec-une-coche_318-32559.png Fait partiellement :Créer un service ANGULARJS pour tous les CRUD (Test sur un = ok)
  • Bien les gérer les droits sur toutes les vues(normaliser)
  • A la fin, faire du lazy loading

A faire (Idées ):

Un menu paramêtre avec :

  • Taux de tva
  • Prix de l’essence moyen
  • Taux et délai avant dépréciation des stocks.
  • Valeur du stock déclanchant une Auto Commande par email
  • Date déclenchant une auto commande par email
  • Catégorie de produit ?
  • Evaporation du carburant
  • Délai moyen avant rappel de commande
  • Graphes d’évolutions des stocks dans le temps par citernes, par station
  • http://www.cat-logistique.com/stocks.htm
  • http://fiches-pratiques.chefdentreprise.com/Thematique/gestion-finance-1050/FichePratique/Comment-rationaliser-gestion-stocks-257182.htm
  • Dans la vue Fournisseur, ajouter un indice de satisfaction, le coup du transport, de la livraison, la qualité du contact et du service client, notation et classement.
  • Eventuellement ajouter une vue avec toutes les finances de l’organisation, le total des actifs, des fonds disponibles etc …
  • Calculer les taux d’utilisation d’une station, et faire de la loi de poisson aussi + ajouter les trop longues files d’attente + le cas des grêves (Distribution limitée à 20 litres) .
  • Se renseigner sur comment ‘raccorder’ les pompes physiques à l’application(surement du langage C).
  • Faire une vue qui récapitule toutes les infos d’une seule station avec des tonnes de jointures SQL.

JOURNAL DE DEVELOPPEMENT

Le 12-08 : 3h30

  • Ajout de la date, en format date Json, dans une colonne varChar dans la base de données. (Volontaire, possibilité de mettre en format date plus tard avec un convertisseur)
  • Ajout et activation de angularUi select sur la vue Produits, avec la case de recherche : ok.
  • Testing de clef étrangère sur la table Citerne : ok
  • Ajout de fetchAll(PDO::FETCH_ASSOC) dans crud.php pour éviter le doubling dans le retour Json (éliminer les index): ok

Lire la suite

[Application 61] Passage de l’ ancien Back End Php-Mysql à PDO Mysql.

logo-phppompestation

Introduction


Avec Php 7 , mysql_real_escape_string() est discontinué.

Je passe donc le back end au format PDO en 1h30 de temps.

Cela ne change rien à ma technique de copié-collé pour chaque CRUD ..

Note : On peut spécifier le typage de variables dans les insert et les update pour ajouter à la sécurité, mais là je ne le fais pas.

Note 2 : A la fin d’une action SQL,le back end peut renvoyer un message JSON au front end qui peut l’afficher directement dans le front end dans la fonction de rappel de AngularJs, c’est le json nommé « data » qui contiendra le message… J’ai mis un exemple :
print_r(json_encode(‘Procédure Back end Ok’));

Pourquoi utiliser PDO et les requêtes préparées ?


  • Les requêtes préparées empêchent les injections SQL (Pour tester, essayer de rentrer un quote ‘, cela ne passe pas, hi hi !)
  • PDO devient le standard avec mysqli, mais est mieux que mysqli

Schéma :


vues

Le nouveau code :


Présence de 2 fichiers :

  • 1 pour la connexion
  • 1 pour tout le back end qui récupère les datas du front end (AngularJs dans ce cas). tout le back end est centralisé dans un seul fichier.

Lire la suite

[Application 61] PompeStation .

pompestation

Introduction


PompeStation, gestion de station service.

Un Gros projet, la gestion du  crud est importante ici, avec un back end en Php-Mysql.

Les jointures seront omniprésentes, ainsi que les contraintes d’intégrité !

Qu’est que la contrainte d’intégrité ? Un exemple on ne peut plus simple , si je crée une station service, puis que je lui associe 2 citernes, il ne serait pas logique de pouvoir supprimer ensuite cette station service puis de laisser les 2 citernes orphelines. La contrainte d’intégrité, en l’occurence, 2 clefs étrangères, nous empéchera donc de supprimer cette station service.

Inspiré par la rapidité de la génération automatique de code de Hibernate avec Java et Hibernate Code Génération, je décide d’aller plus vite avec le CRUD en PHP. 

Les phases de conception de la Base de données :
. Création du modèle conceptuel avec Merise (Création des Entités, Création des attributs, Création des relations, Création des cardinalités.) (MCD)
. Création du modèle relationnel avec Mysql Workbench (Mise en Place de l’auto incrémentation sur les IDS, Création des clefs étrangères pour la contrainte d’intégrité, création des triggers.) (MPD)
. Phase de recettes avec les utilisateurs.

Voici un schéma du mpd au jour 1, par contre je placerais les clefs étrangères dans un second temps . (Dans mySql Workbench, cliquer sur Database/reverce Engineering pour générer le Mpd, ici, on peut voir que je n’ai créé qu’une clef étrangère entre station et citernes qui empêche la suppression d’une station si une citerne est encore associée à celle ci, la cardinalité étant 1(station)->n(citernes), la relation Merise étant « appartient » .

Par contre, pour les produits, la cardinalité vis à vis d’une station sera M,N, étant donné qu’un même produit pourra être stocké dans plusieurs stations, la relation étant le Stock, et qu’il exite plusieurs produits.

Je n’ai pas encore intégré les tables de la gestion des stocks et le trigger concerné… Générer le Mpd est bien utile pour détecter des erreurs de conception, par exemple, là on peut constater que la colonne idstation de la table produits n’a pas le bon type(varchar au lieux de int):

aaaaaaaa.png

J’ai donc élaboré une méthode pour normaliser et aller le plus vite possible pour créer une application AngularJs avec un Back End Php-Mysql : Toutes les vues sont copiées collées, ainsi que tous les controleurs ainsi que le code PHP-Mysql , ensuite, à la création de la nouvelle vue, je ne fais qu’un control+H, puis je change seulement le nom du modèle de données(Au singulier) dans le contrôleur et dans la vue et dans le code PHP-MYSQL Tout est pratiquement immédiat… Du coup j’ai pu faire un CRUD complet sur 8 vues en 1 heure et demi !
C’est un tout petit peu plus long lorsqu’il faut faire des jointures, mais on a la main sur tout le code facilement et le code est  hyper clair et facile à comprendre contrairement à ce que je faisais avant. Il est également facilement maintenable, étant donné que si il faut ajouter un champs dans une vue, il n’y a rien à faire hormis remanier la table SQL, la vue et un peu le back end…

Je n’utilise pas de générateur de CRUD, parce qu’avec ce Crud perso, je vais pouvoir ajouter des photos et pleins d’autres personnalisations …

Photo de l’application au jour 1 :


pompestationlogi

Principe du code :


Chaque vue est associée à un controleur AngularJs qui lance des appels Crud au Back End.

Le code PHP (Back End)

Lire la suite

[Java] Utiliser hibernate sans Jsp, Partie 1 : Multi-insertion (Français).

Java_logo

Introduction


Toujours à la recherche des solutions les plus rapides pour mes futures Apps, je suis maintenant avec le back-end Hibernate.

Hibernate permet de créer automatiquement les tables SQL, à partir du code JAVA.

C’est bien plus rapide. il fait le mapping Objet(Java)/Relationnel automatiquement.

Outre le fait d’être incroyablement rapide, il est également plus aisé de collaborer sur des projets de ce type.

Par comparaison, j’ai tapé le back end PHP de mon exo 60 à la main. , même si c’est rapide, cela ne l’est pas autant que Hibernate.

Mon code est copié de http://www.simplecodestuffs.com/auto-generate-primary-key-in-hibernate/ de   (Excellent!)

Par contre, c’est plus difficile à utiliser avec les JSP, et je voudrais aussi pouvoir l’utiliser avec AngularJs(Donc faudra utiliser la lib Gson en plus… c’est un peu lourd).

Egalement, attention, parce que dès que l’on aborde les jointures entre tables,cela devient plus compliqué !

Lire la suite