Bonjour,
J'ai besoin encore d'une petite aide pour la validation. Voci un extrait

'password'  => array(
            array(
                'rule' =>'notEmpty',
                'allowEmpty'=> false,
                'message'   => "Le mot de passe est obligatoire"
            ),
            array(
                'rule' => array('between', 6, 10),
                'message'   =>'Le mot de passe doit avoir entre 6 et 10 caractères'
            ),
            array(
                'rule' => '/^(?=.*\d)(?=.*[a-x])(?=.*[A-Z]).*$/', // Controle si au moin 1 chiffre et 1 mujuscule
                'message'   =>'Le mot de passe doit contenir au moins une majuscule et un chiffre.'
            )
        ),
        'newpassword'   => array(
            array(
                'rule' =>'notEmpty',
                'allowEmpty'=> false,
                'message'   => "Le nouveau mot de passe est obligatoire"
            ),
            array(
                'rule' => array('between', 6, 10),
                'message'   =>'Le nouveau mot de passe doit avoir entre 6 et 10 caractères'
            ),
            array(
                'rule' => '/^(?=.*\d)(?=.*[a-x])(?=.*[A-Z]).*$/', // Controle si au moin 1 chiffre et 1 mujuscule
                'message'   =>'Le nouveau mot de passe doit contenir au moins une majuscule et un chiffre.'
            )
        ),

J'ai évidemment plus de regle de validation dans mon modele user.php.
Ci-dessus, 'password' fonctionne très bien, mais 'new password' ne fonctionne pas.

Si mon champs 'newpassword' à la valeur "toto", et ben ca passe tout droit.

Il faut savoir que ma table 'users' ne contien pas de champs 'newpassword' . Il contient bien un champ 'password' mais pas 'newpassword'.

Je me demande si c'est a raison, car toutes mes regles de validation, aussi bien pour d'autres modèles, fonctionnent.

Comment puis faire pour parer cette issue, pour un champs qui n'est pas enregistré dans ma table?

Pour info, voici mon formulaire:

<?php $this->set('title_for_layout',__("Changer votre mot de passe temporaire")); ?>
<div class="page-header">
    <h2><?php echo __("Changer votre mot de passe temporaire"); ?></h2>
</div>
<?php echo $this->Session->flash(); ?>
<?php echo $this->Form->create('User',array('class'=>'navbar-form','novalidate')); ?>
<?php echo $this->Form->input('username',array('label'=>__("Nom d'utilisateur"),'class'=>'form-control')); ?>
<?php echo $this->Form->input('email',array('label'=>__("E-mail"),'class'=>'form-control')); ?>
<?php echo $this->Form->input('password',array('label'=>__("Mot de passe temporaire"),'class'=>'form-control')); ?>
<?php echo $this->Form->input('newpassword',array('label'=>__("Nouveau mot de passe"),'type'=>'password','class'=>'form-control')); ?>
<?php echo $this->Form->input('captcha',array('label'=>__($this->Html->image('/users/captcha/').' = '),'class'=>'form-control input-sm','style'=>'width:40px')); ?>
<?php echo $this->Form->end(array('label'=>__('Enregistrer'),'class'=>'btn btn-primary')); ?>

D'ailleur captcha, n'a pas de champs dans ma base de donnée, non plus, au passage, mais là c'est pas grave, il n'y a pas de validation, dans le modele.

Milles mercis pour votre aide.
(Suis presqu'au bout) :o)

11 réponses


Salut,
ok je vois ou tu veux en venir. J'a regardé le lien mais ca ne correspond pas à 100% à mon problem car je n'utilise pas save()
car dans mon controller je ne sauve pas les données. Voici le contenu de l'action appelé du controller par le formulaire

/**
    * When user click on the received mail to reset it password
    **/
    function resetpassword($username,$token){
        // Check if the username and the password match to a row
        $d'user'] = $this->User->find('first',array(
            'conditions'=>array(
                'username'=>$username,
                'token'=>$token
                )
            ));
        // We are going to use the user ID from $user
        $user = current($d);

        if(!empty($user)){
            // If yes
            // GET Post
            if($this->request->is('post')){
                if($this->Session->read('Captcha') != $this->request->data'User']'captcha']){
                    $this->Session->setFlash(__("Le calcul est faux"),'notif',array('type'=>'danger'));
                }else{
                    // Save in a var
                    $data = $this->request->data'User'];
                    // User fill up a form with temp password and new password. He has to enter his username, email and password
                    // Now, it check if username, email and password match to the user id field
                    $ok = $this->User->find('first',array(
                    'conditions'=>array(
                        'User.id'=>$user'User']'id'], // Compare ID
                        'username'=>$data'username'],
                        'email'=>$data'email'],
                        'password'=>AuthComponent::password($data'password']) // Compare password
                        )
                    ));
                    $ok = current($ok);
                    // IF result matches
                    if(!empty($ok)){
                        // Select the row DB
                        $this->User->id = $ok'id'];
                        // Replace the Temp passsword with the new
                        $this->User->saveField('password',$data'newpassword']);
                        // Change the passwordrst field status
                        $this->User->saveField('passwordrst',0);
                        // Notify User
                        $this->Session->setFlash(__("Le mot de passe a été changé"),'notif');
                    }else{

                        $this->Session->setFlash(__("Les informations fournies ne correspondent à aucun compte"),'notif',array('type'=>'danger'));
                    }
                }
            }
        }else{
            $this->Session->setFlash(__("Il n'est plus possible d'initier le mot de passe"),'notif',array('type'=>'danger'));
        }
    }

Je me demande si c'est pas au niveau du formulaire que je dois faire ca, a ce niveau là, non? ou je me trompe complétement

<?php echo $this->Form->create(null,array('class'=>'navbar-form','novalidate')); ?>

Tente ceci dans ta conditions if(!empty($ok)) .

Ca permettra de controller:
Si envoi Post
Creation d'un enregistrement avec données
Si validation OK
Enregistre newpassword encodé et passwordrst a 0

PS: Je ne sais meme pas si je suis HS sur ton probleme. :p

$this->User->create($this->request->data);
    $this->User->id = $ok'id'];
    if($this->User->validates()) {
        $this->User->save(array(
            'id' => $ok'id'],
            'password' => $this->Auth->password($this->request->data'User']'newpassword']),
            'passwordrst' => 0
    ));
        $this->Session->setFlash(__("Le mot de passe a été changé"),'notif');
    } else {
        $this->Session->setFlash(__("Les informations fournies ne correspondent à aucun compte"),'notif',array('type'=>'danger'));
    }

Je crois que tu n'as pas compris ce que je t'ai donné. Analyse le code de save() et saveField(), tu verras qu'il lance une fonction validates() avant d'enregistrer. Le soucis c'est que tu ne lui passe que le champ password à enregistrer donc il ne fait le validates() que sur ce champ. Il va te falloir lancer manuellement la validation.

$this->User->validates()

Je suis vraiment désolé, mais j'arrive pas comprendre.
J'ai aussi modifié mon code qui me semble plus juste. Je reprend alors mon exlication avec la correction.
Ici j'ai mon formulaire, que je commente

<?php $this->set('title_for_layout',__("Changer votre mot de passe temporaire")); ?>
<div class="page-header">
    <h2><?php echo __("Changer votre mot de passe temporaire"); ?></h2>
</div>
<?php echo $this->Session->flash(); ?>
<!-- Creation du formulaire -->
<?php echo $this->Form->create(null,array('class'=>'navbar-form','novalidate')); ?>
<!-- Creation du champs username, qui sera utiliser pour le vérifier avec la valeur dans la table -->
<?php echo $this->Form->input('username',array('label'=>__("Nom d'utilisateur"),'class'=>'form-control')); ?>
<!-- Creation du champs email, qui sera utiliser pour le vérifier avec la valeur dans la table -->
<?php echo $this->Form->input('email',array('label'=>__("E-mail"),'class'=>'form-control')); ?>
<!-- Creation du champs temppassword, qui sera utiliser pour le vérifier avec la valeur du chapm 'password' de la table -->
<?php echo $this->Form->input('temppassword',array('label'=>__("Mot de passe temporaire"),'class'=>'form-control')); ?>
<!-- Creation du champs password, qui sera utiliser pour le replacer la valeur du champs 'password' dans la table -->
<?php echo $this->Form->input('password',array('label'=>__("Nouveau mot de passe"),'type'=>'password','class'=>'form-control')); ?>
<!-- Creation du champs captcha, qui n'interviendra pas avec ma table -->
<?php echo $this->Form->input('captcha',array('label'=>__($this->Html->image('/users/captcha/').' = '),'class'=>'form-control input-sm','style'=>'width:40px')); ?>

<?php echo $this->Form->end(array('label'=>__('Enregistrer'),'class'=>'btn btn-primary')); ?>

Ma validation est ainsi dans mon modele user.php

'password'  => array(
            array(
                'rule' =>'notEmpty',
                'allowEmpty'=> false,
                'message'   => "Le mot de passe est obligatoire"
            ),
            array(
                'rule' => array('between', 6, 10),
                'message'   =>'Le mot de passe doit avoir entre 6 et 10 caractères'
            ),
            array(
                'rule' => '/^(?=.*\d)(?=.*[a-x])(?=.*[A-Z]).*$/', // Controle si au moin 1 chiffre et 1 mujuscule
                'message'   =>'Le mot de passe doit contenir au moins une majuscule et un chiffre.'
            )
        ),
        'temppassword'  => array(
                'rule' =>'notEmpty',
                'allowEmpty'=> false,
                'message'   => "Le nouveau mot de passe est obligatoire"
        ),

Ici j'ai mon action qui est applée par le formulaire,
que je commente

if($this->request->is('post')){
// Contorle le champs captcha s'i, correspond avec la Session
                if($this->Session->read('Captcha') != $this->request->data'User']'captcha']){
                    $this->Session->setFlash(__("Le calcul est faux"),'notif',array('type'=>'danger'));
                }else{
                    // Je sauve le contenu de mon formulaire dans une variable
                    $data = $this->request->data'User'];
                    // User fill up a form with temp password and new password. He has to enter his username, email and password
                    // Je controle si id, username, email et le mot de passe temporaire, corresponde a une ligne, donc celle de l'utilisateur
                    $ok = $this->User->find('first',array(
                    'conditions'=>array(
                        'User.id'=>$user'User']'id'], // Compare ID
                        'username'=>$data'username'],
                        'email'=>$data'email'],
                        'password'=>AuthComponent::password($data'temppassword']) // Compare password
                        )// Avant j'utilisais la valeur du champ 'password' de mon formulaire
                    ));
                    $ok = current($ok);
                    // Si oui reste le mot de passe
                    if(!empty($ok)){
                        // Select la bonne ligne
                        $this->User->id = $ok'id'];
                        // Replace la valeur du champ temppassword dans le chamsp password de la table
                                                // Avant j'utilisais le champs 'newpassword' de mon formulaire, qui n'existe plus
                                                // Je force la validation, mais ca ne marceh toujours pas. Es-ce juste
                        $this->User->saveField('password',$data'password'],array('validate'=>true));
                        // Je change la valeur du champs de ma table à 0
                        $this->User->saveField('passwordrst',0);
                        // Notify User
                        $this->Session->setFlash(__("Le mot de passe a été changé"),'notif');
                    }else{

                        $this->Session->setFlash(__("Les informations fournies ne correspondent à aucun compte"),'notif',array('type'=>'danger'));
                    }
                }
            }

@prbaron: N'ai-je pas forcer la validation ainsi?

$this->User->saveField('password',$data'password'],array('validate'=>true));

Alors peut etr devrais-je remplacer ceci

$this->User->saveField('password',$data'password'],array('validate'=>true));
$this->User->saveField('passwordrst',0);

par ceci

$this->User->save($id,true,array('password'));
$this->User->saveField('passwordrst',0);

?
Mais ca me parrais bizard de sauver de deux maniere différente dans la meme table

Ok ca marche j'ai trouvé.
Pourrais-je vous demander vos commentaires?

/**
    * When user click on the received mail to reset it password
    **/
    function resetpassword($username,$token){
        /*
        The user get an e-mail with a link. He click on the link and check if the user name and token match to a row
        */
        $d'user'] = $this->User->find('first',array(
            'conditions'=>array(
                'username'=>$username,
                'token'=>$token
                )
            ));
        // This var will be used for the user id, later
        $user = current($d);
        // If not empty, if contain a row...
        if(!empty($user)){
            // If yes
            // GET Post
            if($this->request->is('post')){
                // Check Captcha
                if($this->Session->read('Captcha') != $this->request->data'User']'captcha']){
                    $this->Session->setFlash(__("Le calcul est faux"),'notif',array('type'=>'danger'));
                }else{
                    // Save into a var
                    $data = $this->request->data;
                    // User fill up a form with temp password and new password. He has to enter his username, email and password
                    // Now, it check again, if the form filed username, email and password match to the user id field
                    $ok = $this->User->find('first',array(
                    'conditions'=>array(
                        'User.id'=>$user'User']'id'], // Compare ID
                        'username'=>$data'User']'username'],
                        'email'=>$data'User']'email'],
                        'password'=>AuthComponent::password($data'User']'temppassword']) // Compare temppassword, with temporary password record in 'password' field
                        )
                    ));
                    $ok = current($ok);
                    // IF result matches, if OK
                    if(!empty($ok)){
                            // $data does not contain id, because the form do not have an input ID. Then we add
                            // an id collected at the begining of that action
                            $data'User']'id'] = $user'User']'id'];
                            // Replace the Temp passsword with the new. We only save password value/field
                            if($this->User->save($data,true,array('password'))){
                            // Change status of psswordrst field
                            $this->User->saveField('passwordrst',0);
                            // Notify User
                            $this->Session->setFlash(__("Le mot de passe a été changé"),'notif');
                        }else{
                            $this->Session->setFlash(__("Le nouveau mot de passe n'a pas pu être changer"),'notif',array('type'=>'danger    '));
                        }
                    }else{

                        $this->Session->setFlash(__("Les informations fournies ne correspondent à aucun compte"),'notif',array('type'=>'danger'));
                    }
                }
            }
        }else{
            $this->Session->setFlash(__("Il n'est plus possible d'initier le mot de passe"),'notif',array('type'=>'danger'));
        }
    }

J'ai encore un ultiem question.
Dans mon formulaire

<?php echo $this->Form->create(null,array('class'=>'navbar-form','novalidate')); ?>

Es-ce que je peux laisser 'null' ou je dois mettre User.
Avec null ca marche, comme meme, mais ca semble plus logique de mettre 'User', non?
J'ai encore un doute avec ca

C'est dommage tu as perdu 4 heures dans tes recherches pour une solution alors que je t'ai donné une solution relativement égale a la tienne tout en simplifiant tes 2 save en un seul....

En effet, j'ai été idot :o), Mais autant pour moi. Merci en tout cas

Tu lui as donné la réponse mais je doute qu'il comprenne d'où vient vraiment le problème.

Le soucis vient du fait que tu n'aies pas lancé de validation pour ton champ. Lorsque tu fais un save() ou un saveField() CakePHP lance un validates() en amont. Comme tu ne cherchais pas à enregistrer ton ton champ et que tu n'avais pas lancé la validation manuellement, CakePHP n'a pas chercher à regarder les règles de validation que tu lui avais donné.

Bonjour,

C'est pour cela que dans mon cas, je fais toujours un

if ($this->User->validates()) {
    //savegarde des données
}else{
    //retour au formulaire
}

Maintenant, je me pose une question, en faisant comme je fait, ce n'est pas une perte de temps puisque le save vas aussi vérifier les données? Il fait donc deux fois la validation nan?