French Power Platform User Group

Please login or click SIGN UP FOR FREE to create your PowerPlatformUG account to join this user group.
 View Only
Expand all | Collapse all

Récupérer une variable pour un écran de mot de passe

  • 1.  Récupérer une variable pour un écran de mot de passe

    Posted Oct 14, 2021 07:25 AM
    Edited by Jonas De Brabanter Oct 14, 2021 07:33 AM
    bonjour à tous,

    Je reviens vers vous car je bloque sur un nouveau problème.

    Comme je l'indiquais dans un post précédent, je travaille dans un centre de soins et les données de l'application que je crée sont sensibles en termes de confidentialité.
    J'ai donc créé un écran pour entrer un code pin à l'ouverture. Il s'appelle LoginScreen. Si l'utilisateur met le bon code, il est renvoyé sur la page BrowseScreenResidents. S'il met un mauvais mot de passe, il est renvoyé vers un écran "Jail" ou il doit attendre x secondes avant de pouvoir se reconnecter. Après 3 tentatives infructueuses, il est renvoyé vers un autre écran "JailAdmin" et s'adresser à un Admin pour débloquer l'appli.
    Jusque là, tout va bien, j'y suis parvenu.

    Le soucis, c'est que si l'utilisateur arrive sur JailAdmin, qu'il ferme l'application et la rouvre, il a de nouveau 3 essais.

    Je vais tenter d'être le plus précis possible dans les éléments mis en place qui ont un lien avec mon problème : 

    Sur la page LoginScreen : 

    Une zone Entrée de texte nommée "TextInput2" ou l'utilisateur entre le code pin

    Un bouton nommé "Button3" sur lequel il clique pour se connecter. 

    Voici le code OnSelect de Button3 : 

    If(TextInput2.Text = "1234";
    
    Navigate(BrowseScreenResidents;None);;
    Reset(TextInput2)
    ;
    Navigate(Jail;None);;
    Reset(TextInput2);;
    UpdateContext({
        BadPasswordCount: Sum(Value(BadPasswordCount);1)
        })
    );;
    
    If(BadPasswordCount = 3;
    
    Navigate(JailAdmin;None);;
    
    Collect( MyItems; { Item: BadPasswordCount} ) ;;
    
    SaveData( MyItems; "LocalSavedItems" )
    
    )​

    Mon idée était donc de compter le nombre d'erreurs (Via le BadpasswordCount, qui est donc une variable contextuelle). Puis de stocker cette variable dans une collection. J'ai repris l'idée sur la documentation microsoft. Et j'imaginais la stocker en local sur le téléphone de l'utilisateur puisque si un utilisateur bloque son accès, ça doit être juste pour lui.

    Ensuite, à l'ouverture de l'application, j'ai créé un timer sur le LoginScreen d'une durée de 0,1 seconde.
    Sur OnTimerEnd, j'ai mis le code suivant : 

    LoadData(MyItems; "LocalSavedItems" );;
    
    If(BadPasswordCount = 3;
    Navigate(JailAdmin;None))


    J'ai testé ça sur mon tél android mais manifestement, le souci vient du fait qu'il ne parvient pas à récupérer la valeur de la variable "BadPasswordCount" sauvée précédemment.

    Quelqu'un pourrait m'aider ?

    J'ai une autre question plus basique. Sur la zone d'entrée de texte "TextInput2" ou l'utilisateur entre le code pin, est-il possible de changer un paramètre pour qu'android ouvre un clavier de chiffres et pas le clavier azerty ?

    J'espère vous avoir transmis tous les éléments utiles...

    Merci d'avance :)

    Jonas



    ------------------------------
    Jonas De Brabanter
    ------------------------------


  • 2.  RE: Récupérer une variable pour un écran de mot de passe

    Gold Contributor
    Posted Oct 16, 2021 06:34 PM
    Salut Jonas,
    Avant de tester ta variable il faut que tu l'alimentes avec la valeur qui se trouve dans la collection. Corrige ton code comme ceci :
    LoadData(MyItems; "LocalSavedItems" );;
    Set(BadPasswordCount; First(MyItems).Item);;
    If(BadPasswordCount = 3;
    Navigate(JailAdmin;None))​


    ------------------------------
    EMMANUEL GALLIS
    Power Platform Consultant
    France
    ------------------------------



  • 3.  RE: Récupérer une variable pour un écran de mot de passe

    Posted Oct 18, 2021 02:25 PM
    Bonsoir Emmanuel,

    Je te remercie d'avoir regardé pour mon problème. J'ai testé ta solution mais malheureusement ça ne fonctionne pas. 
    Quand je regarde dans l'éditeur d'application, je vois que la variable s'enregistre bien dans la collection, mais quand j'essaie sur mon portable, il ne récupère pas la valeur de la variable malgré le code que tu m'as donné. 
    As-tu une idée de quoi ça pourrait venir ?

    ------------------------------
    Jonas De Brabanter
    ------------------------------



  • 4.  RE: Récupérer une variable pour un écran de mot de passe

    Gold Contributor
    Posted Oct 18, 2021 04:05 PM
    Bizarre, ça devrait marcher. Y'a pas de raison...
    Par contre, attention, les fonctions SaveData() et LoadData() ne fonctionnent pas sur PC. Elles ne marchent que sur téléphone ou tablette. Donc, impossible à tester dans l'éditeur d'application.
    Je vais faire un test de mon côté pour voir si ça fonctionne bien avec un numérique...

    ------------------------------
    EMMANUEL GALLIS
    Power Platform Consultant
    France
    ------------------------------



  • 5.  RE: Récupérer une variable pour un écran de mot de passe

    Gold Contributor
    Posted Oct 19, 2021 05:46 AM
    Je viens de tester de mon côté et tout fonctionne bien. Donc ça dépends peut-être de l'endroit où tu as mis le code...
    Est-ce que tu as mis un libellé sur ton écran pour afficher le BadPasswordCount qui est chargé au lancement de l'application et voir sa valeur ?

    ------------------------------
    EMMANUEL GALLIS
    Power Platform Consultant
    France
    ------------------------------



  • 6.  RE: Récupérer une variable pour un écran de mot de passe

    Posted Oct 19, 2021 09:58 AM
    Hello,

    Je ne comprends vraiment pas ce qui se passe. J'ai effectivement mis un label pour afficher le BadPasswordCount mais il reste toujours à zéro

    Voici une image de mon LoginScreen suivi des codes des contrôles : 

    LoginScreen Picture
    Voici les différentes lignes de codes associées : 

    Timer1 : 

    Duration : 100
    AutoStart : true

    OnTimerEnd : 

    LoadData(MyItems; "LocalSavedItems" );;
    Set(BadPasswordCount; First(MyItems).Item);;
    If(BadPasswordCount = 3;
    Navigate(JailAdmin;None))​​


    Button 3 : OnSelect : 

    If(TextInput2.Text = "1234" ;
        Navigate(Accueil;None);
    
        TextInput2.Text = "6789" ;
        Navigate(Accueil;None);
    
        Navigate(Jail;None);;
        Reset(TextInput2);;
        UpdateContext({
        BadPasswordCount: Sum(Value(BadPasswordCount);1)
        })
    );;
    
    If(BadPasswordCount = 3;
    
        Navigate(JailAdmin;None);;
    
        Collect( MyItems; { Item: BadPasswordCount} ) ;;
    
        SaveData( MyItems; "LocalSavedItems" )
    
    )​
    Label5 : Text : 

    "BadPasswordCount "&Value(BadPasswordCount)​



    Voici ce que je vois en mode édition pour la fonctionnalité OnTimerEnd : 


    Est-il normal que le .Item (dans la 2ème ligne de code) soit en noir?
    Sinon pourrais-tu me dire où tu as mis le code ?

    Merci d'avance

    ------------------------------
    Jonas De Brabanter
    ------------------------------



  • 7.  RE: Récupérer une variable pour un écran de mot de passe

    Gold Contributor
    Posted Oct 20, 2021 04:04 AM
    Hello,
    Merci bcp pour ces explications bien détaillées. Très facile pour moi d'aider du coup... 😊
    Alors oui c'est normal que le .Item soit en noir puisque c'est le nom de la colonne de ta collection MyItems.
    Par contre, avant même d'aller plus loin je vois que t'as une croix rouge au dessus de ton timer. Pourquoi ? Quel est le message affiché lorsque tu le survole ?

    ------------------------------
    EMMANUEL GALLIS
    Power Platform Consultant
    France
    ------------------------------



  • 8.  RE: Récupérer une variable pour un écran de mot de passe

    Posted Oct 20, 2021 07:54 AM
    Oui désolé, j'aurais dû le faire dès le début 😅

    J'ai regardé pour la croix rouge mais elle a disparu, il n'y a donc plus d'avertissement non plus. 

    Si elle revient, je regarderai le message



    ------------------------------
    Jonas De Brabanter
    ------------------------------



  • 9.  RE: Récupérer une variable pour un écran de mot de passe

    Gold Contributor
    Posted Oct 20, 2021 08:56 AM
    Essaie de changer le code ainsi et dis-moi ce que ça donne :
    If(
        TextInput2.Text = "1234" || TextInput2.Text = "6789";
        Navigate(Accueil;None);
        Reset(TextInput2);;
        Set(gloBadPasswordCount: gloBadPasswordCount+1);;
        Navigate(Jail)
    );;
    
    If(gloBadPasswordCount = 3;
        Collect(MyItems; {Item: gloBadPasswordCount});;
        SaveData(MyItems; "LocalSavedItems");;
        Navigate(JailAdmin;None)
    )​​
    Par principe je ne mets pas de code après un Navigate() vu qu'on quitte l'écran et qu'il ne devrait plus y avoir de code qui s'exécute (même si ça marche quand même). Donc je le mets après le reste du code.. 😉

    Ensuite, modifies le code de ton TimerEnd comme ceci :
    LoadData(MyItems; "LocalSavedItems" );;
    Set(gloBadPasswordCount; First(MyItems).Item);;
    If(
        gloBadPasswordCount = 3;
        Navigate(JailAdmin)
    )​​​

    Après relecture de ton code initial et quelques tests, j'ai découvert d'où cela venait et c'est assez incroyable parce-que je crois qu'il va falloir que je le remonte à l'équipe support Power Apps parce-que ça pourrait poser des soucis à d'autres développeurs.
    En fait, dans ton TimerEnd tu utilises Set() pour manipuler BadPasswordCount et dans le bouton tu utilises UpdateContext(). Du coup tu ne manipules par les mêmes variables même si elles ont le même nom.
    Pourquoi ? Parce-que Set() définit une variable GLOBALE tandis que UpdateContext() définit une variable LOCALE. Et visiblement si tu manipules une même variable à la fois avec le Set() et le UpdateContext() non seulement Power Apps ne râle pas mais à priori c'est la variable locale qui a priorité sur la globale. Et du coup dans ton cas, lorsque tu relances l'application tu auras toujours zéro dans BadPasswordCount !!!

    Cela montre à quel point il faut être très attentif à la manière dont on manipule les variables et surtout quelles fonctions on utilise pour faire quoi. Et en profiter aussi pour caractériser les typologie de variables dans leur nom.
    Ainsi, toutes mes variables locales s'appellent locQuelqueChose et toutes mes variables globales s'appellent gloQuelqueChose. Et donc, j'aurais toujours Set(glo...) et jamais Set(loc...) et de la même manière j'aurais toujours UpdateContext({loc... }) et jamais UpdateContext({glo...})... 😉

    Dis-moi si tout fonctionne bien avec le nouveau code...

    ------------------------------
    EMMANUEL GALLIS
    Power Platform Consultant
    France
    ------------------------------



  • 10.  RE: Récupérer une variable pour un écran de mot de passe

    Posted Oct 20, 2021 01:47 PM
    Edited by Jonas De Brabanter Oct 20, 2021 02:19 PM
    Merci beaucoup de te casser la tête comme ça pour moi et pour toutes tes explications qui me seront bien utiles maintenant et pour la suite. Je pense d'ailleurs que je vais renommer convenablement mes contrôles.

    Et je ne pensais pas que je mettrais au jour un problème structurel de PowerApps  😅

    J'ai testé le code mais malheureusement ça ne fonctionne pas encore. 

    J'ai une croix rouge sur mon OnTimerEnd qui dit "La fonction "LoadData" contient des arguments non-valides. (J'imagine que c'est parce que de base la variable n'a pas de valeur, mais je ne vois pas comment solutionner ça).

    J'ai une autre croix rouge sur le OnSelect de mon bouton qui dit "Type d'argument non valide. L'une des valeurs suivantes est attendue : Number, Text, Boolean." (PS : j'avais mis le format de TextInput2 sur "nombre" en espérant que ça ouvrirait le clavier numérique, même si ça n'a pas marché. Mais même en le remettant sur "texte", l'erreur reste).

    J'ai essayé d'enlever les guillements autour des valeurs que peux prendre TexteInput2 (donc mettre TexteInput2 = 1234 II TextInput2 = 6789 plutôt que TexteInput2 = "1234" II TextInput2 = "6789"). Il me met alors une erreur avec un signe attention qui dit "Types incompatibles pour la comparaison. Il est possible de comparer ces types : Text, Number

    Peux-tu me dire quoi faire ?

    ------------------------------
    Jonas De Brabanter
    ------------------------------



  • 11.  RE: Récupérer une variable pour un écran de mot de passe

    Gold Contributor
    Posted Oct 21, 2021 08:02 AM
    Le LoadData() ne déclenche pas d'erreur avec une croix rouge s'il ne trouve pas la données parce-qu'elle n'existe pas encore. Par contre tu auras toujours une erreur sur le LoadData() en testant ton application dans le Studio parce-que les fonctions LoadData(), SaveData() et ClearData() ne fonctionne pas en mode web mais uniquement sur mobile.
    Enfin... jusqu'à tout récemment puisque désormais c'est le cas, moyennant l'activation d'une option dans les paramètres de l'app : https://www.linkedin.com/posts/egallis_loaddata-savedata-cleardata-activity-6856606490363490304-MkeW.
    Essaye déjà de voir si tu peux activer cette option si ce n'est déjà fait pour qu'on moins on puisse tester l'appli directement dans le Studio sans avoir à passer par un mobile.

    Ensuite, juste par acquis de conscience, change le SaveData() ainsi : Collect(MyItems; {Item: Value(gloBadPasswordCount)})
    Et le Set() du gloBadPasswordCount ainsi : Set(gloBadPasswordCount; Value(First(MyItems).Item))

    Pour ce qui est du TextInput2, faut juste être cohérent : soit tu mets le paramètre à Text et tu mets les guillemets pour le test, soit tu mets Number et tu mets pas les guillemets.

    Si ça marche toujours pas, accepte ma demande de contact sur le présent site et j'aurais ton adresse mail et on se fera une p'tite session Teams avec partage d'écran pour régler ce pb...

    ------------------------------
    EMMANUEL GALLIS
    Power Platform Consultant
    France
    ------------------------------



  • 12.  RE: Récupérer une variable pour un écran de mot de passe
    Best Answer

    Posted Oct 23, 2021 03:21 PM
    Edited by Jonas De Brabanter Oct 25, 2021 04:40 AM
    Salut à tous,

    Je suis parvenu exactement au résultat attendu grâce aux conseils d'Emmanuel ci-dessus et de quelques heures de casse-tête. Je vous propose donc l'ensemble des codes pour y parvenir. Je m'en tiendrai au nécessaire pour que ça fonctionne, je vous épargne les labels personnalisés pour laisser des messages aux utilisateurs que vous pouvez rajouter. 

    Pour rappel, je voulais créer un écran de mot de passe (de code pin à 4 chiffres en fait). Si l'utilisateur se trompe, il est bloqué pendant 15 secondes (sur l'écran Jail). Si l'utilisateur se trompe 3 fois, il est bloqué sur l'écran JailAdmin et il faut le mot de passe d'un administrateur pour débloquer l'application (l'idée étant de mettre un mot de passe administrateur bien plus complexe). Je voulais aussi qu'en cas de fermeture de l'application, on reprenne le compte existant des éventuels mots de passe erronés, et que l'application reste bien bloquée jusqu'à l'introduction du mot de passe administrateur.

    J'avais donc besoin : 

    D'un écran LoginScreen avec : 
    • Un Timer (Timer1)
    • Une zone d'entrée de texte (TextInput2)
    • Un bouton (Button3)
    • Un label avec le nombre d'essais (Label1)
    D'un écran Jail avec : 
    • Un Timer (Timer2)
    D'un écran JailAdmin avec :
    • Une zone d'entrée de texte (TextInput1)
    • Un bouton (Button1)
    D'un écran Accueil qui est le 1er écran de l'application sur lequel est renvoyé l'utilisateur qui a le bon mot de passe.

    On passe maintenant au code des différents contrôles : 

    LoginScreen :

    Timer1 : 


    OnTimerEnd : 

    LoadData(colLocalCache; "LocalSavedItems");;
    Set(gloBadPasswordCount; Value(First(colLocalCache).Item));;
    If(gloBadPasswordCount = 3; Navigate(JailAdmin))

     AutoStart : true

    Duration : 100

    AutoPause : false

    Visible : false


    TextInput2 : 

    Format : TextFormat.Number

    Button3 : 

    OnSelect : 

    If(
        TextInput2.Text = "1234" || TextInput2.Text = "6789";
        Set(gloBadPasswordCount; 0);;
        ClearCollect(colLocalCache; {Item: Value(gloBadPasswordCount)});;
        SaveData(colLocalCache; "LocalSavedItems");;
        Navigate(Accueil;None);
        
        Reset(TextInput2);;
        Set(gloBadPasswordCount; Value(gloBadPasswordCount)+1);;
        ClearCollect(colLocalCache; {Item: Value(gloBadPasswordCount)});;
        SaveData(colLocalCache; "LocalSavedItems");;
        Navigate(Jail;None)
    )​


    Label5 : 

    Text : "Nb d'essais : "&Value(gloBadPasswordCount)


    Sur l'écran Jail : 

    Timer2 : 

    OnTimerEnd : 

    Navigate(LoginScreen;ScreenTransition.Fade)​


    AutoStart : true

    Duration : 15000

    AutoPause : false

    Visible : true

    Text : Text(Time(0; 0; Self.Value/1000); "ss")

    Sur l'écran JailAdmin : 

    Button1 :

    OnSelect : 

    If(TextInput1.Text= "MotDePasseAdministrateurComplexe";
    Set(gloBadPasswordCount; 0);;
    ClearCollect(colLocalCache; {Item: Value(gloBadPasswordCount)});;
    SaveData(colLocalCache; "LocalSavedItems");;
    Navigate(LoginScreen;None)
    )

    Et voilà, je pense avoir été complet. Sinon n'hésitez pas au besoin :)

    Merci encore une fois à Emmanuel pour son aide précieuse.

    Je remercie aussi Shane Young qui m'a inspiré mon écran de mot de passe dans son tuto youtube (https://www.youtube.com/watch?v=GiN47Is_634) même s'il n'en a absolument pas conscience ;)

    Jonas

    ------------------------------
    Jonas De Brabanter
    ------------------------------



  • 13.  RE: Récupérer une variable pour un écran de mot de passe

    Gold Contributor
    Posted Oct 24, 2021 07:14 AM
    Ouaouh... Merci @Jonas De Brabanter pour toutes ces explications 🙏. Ca pourra servir à d'autres qui voudraient mettre en place le même système dans leurs applications... 👍

    Une remarque : j'allais écrire "c'est étrange que tu sois obligé d'utiliser le Last() pour récupérer le bon item de ta collection MyItems" mais en relisant ton code j'ai compris pourquoi. En fait, il ne faut pas faire un Collect() mais un ClearCollect() sinon les enregistrements s'ajoutent les uns aux autres plutôt que d'en avoir un seul... 😉 Et du coup tu pourras remettre un First() à la place du Last().

    Autre remarque, sur la nomenclature... Je porte une attention particulière au nom que je donne à mes variables pour être parfaitement sûr de bien comprendre à quoi elles servent. Par exemple, ta gloBadPasswordCount est parfaite. Mais d'un autre côté, ta collection MyItems a un nom qui est, selon moi, beaucoup trop générique. Les données que je gère localement avec les fonctions LoadData(), SaveData(), ClearData(), je les mets dans une variable qui s'appelle colAppCache ou colLocalCache. La notion de cache traduit bien qu'il s'agit de données "temporaires" stockées localement.
    Voilou... 😉

    ------------------------------
    EMMANUEL GALLIS
    Power Platform Consultant
    France
    ------------------------------



  • 14.  RE: Récupérer une variable pour un écran de mot de passe

    Posted Oct 25, 2021 04:33 AM
    Merci beaucoup pour ces nouveaux conseils.

    J'ai implémenté tout ça et tout fonctionne nickel.

    Je vais faire les changements dans ma réponse précédente pour que chacun ait le code le plus à jour en un seul endroit 🙂

    ------------------------------
    Jonas De Brabanter
    ------------------------------