Lançado Adianti Framework 7.6!
Clique aqui para saber mais
Recuperação de senha através de link seguro! Pessoal boa noite, Estou utilizando o framework a quase um mês, e resolvi implantar uma lógica de recuperação de senha, utilizando o mesmo template da tela de login. A ideia é o seguinte: O usuário clica num link adicionado na tela de login de "Esqueceu a senha", é levado para uma tela onde ele digita o email cadastrado e o sistema envia um email com o link para reset, ao clicar nesse li...
HA
Recuperação de senha através de link seguro!  
Pessoal boa noite,

Estou utilizando o framework a quase um mês, e resolvi implantar uma lógica de recuperação de senha, utilizando o mesmo template da tela de login. A ideia é o seguinte: O usuário clica num link adicionado na tela de login de "Esqueceu a senha", é levado para uma tela onde ele digita o email cadastrado e o sistema envia um email com o link para reset, ao clicar nesse link, faço a checagem se é válido e o usuário digita a nova senha.

1º - Adicionar colunas na tabelas de usuários
ALTER TABLE `system_user` ADD `reset_pass` CHAR(1) NULL DEFAULT NULL AFTER `active`, ADD `data_pass` VARCHAR(50) NULL DEFAULT NULL AFTER `reset_pass`, ADD `uid_pass` VARCHAR(50) NULL DEFAULT NULL AFTER `data_pass`;


2º - Adicionar os campos acima no SystemUser para permitir edição
  1. <?php
  2. public function __construct($id NULL)
  3. {
  4.         //....
  5.         parent::addAttribute('reset_pass');
  6.         parent::addAttribute('data_pass');
  7.         parent::addAttribute('uid_pass');
  8. }
  9. ?>


3º - Alterei na SystemUserForm para não permitir o cadastro de email já existente, hoje o template valida apenas login
  1. <?php
  2. public static function onSave($param)
  3. {
  4.         //....
  5.         if (SystemUser::newFromLogin($object->login) instanceof SystemUser)
  6.         {
  7.                  throw new Exception(_t('An user with this login is already registered'));
  8.         }
  9.                 
  10.         if (SystemUser::newFromEmail($object->email) instanceof SystemUser)
  11.         {
  12.                  throw new Exception(_t('An user with this email is already registered'));
  13.         }
  14.         //...
  15. }
  16. ?>


4º - Controller SendEmailPasswordForm responsável por capturar o email do usuário e enviar o link para reset
  1. <?php
  2. class SendEmailPasswordForm extends TPage
  3. {
  4.     protected $form// form
  5.     
  6.     function __construct($param)
  7.     {
  8.         parent::__construct();
  9.         $table = new TTable;
  10.         $table->width '100%';
  11.         // creates the form
  12.         $this->form = new TForm('form_send_email_pass');
  13.         $this->form->class 'tform';
  14.         $this->form->style 'max-width: 450px; margin:auto; margin-top:120px;';
  15.         // add the notebook inside the form
  16.         $this->form->add($table);
  17.         // create the form fields
  18.         $email = new TEntry('email');
  19.         
  20.         // define the sizes
  21.         $email->setSize('70%'40);
  22.         $email->style 'height:35px; font-size:14px;float:left;border-bottom-left-radius: 0;border-top-left-radius: 0;';
  23.         $row=$table->addRow();
  24.         $row->addCell( new TLabel('Resetar senha') )->colspan 2;
  25.         $row->class='tformtitle';
  26.         $email->placeholder 'user@email.com';
  27.         $email->setLabel('Email');
  28.         
  29.         $email->addValidation('Email', new TEmailValidator);
  30.         $envelope '<span style="float:left;width:35px;margin-left:45px;height:35px;" class="input-group-addon"><span class="glyphicon glyphicon-envelope"></span></span>';
  31.         $container1 = new TElement('div');
  32.         $container1->add($envelope);
  33.         $container1->add($email);
  34.         $row=$table->addRow();
  35.         $row->addCell($container1)->colspan 2;
  36.         
  37.         // create an action button (save)
  38.         $recuperar_button=new TButton('recovery');
  39.         // define the button action
  40.         $recuperar_button->setAction(new TAction(array($this'onReset')), _t('Send'));
  41.         $recuperar_button->class 'btn btn-success';
  42.         $recuperar_button->style 'font-size:18px;width:90%;padding:10px';
  43.         $row=$table->addRow();
  44.         $row->class 'tformaction';
  45.         $cell $row->addCell$recuperar_button );
  46.         $cell->colspan 2;
  47.         $cell->style 'text-align:center';
  48.         
  49.         $login = new TActionLink('Login', new TAction(array($this'onLogin')) );
  50.         $login->style 'font-size:16px;width:90%;padding:10px';
  51.         
  52.         $row $table->addRow();
  53.         $cell $row->addCell$login );
  54.         
  55.         $this->form->setFields(array($email$recuperar_button));
  56.         // add the form to the page
  57.         parent::add($this->form);
  58.     }
  59.     
  60.     public function onLogin()
  61.     {
  62.         AdiantiCoreApplication::gotoPage('LoginForm');
  63.     }
  64.     public function onReset()
  65.     {
  66.         try
  67.         {
  68.             TTransaction::open('permission');
  69.             $data $this->form->getData('StdClass');
  70.             $this->form->validate();
  71.             $user SystemUser::newFromEmail$data->email );
  72.             TTransaction::close();
  73.             // valida se existe usuário com email digitado
  74.             if ($user)
  75.             {
  76.             
  77.                 try
  78.                 {
  79.                     TTransaction::open('permission');
  80.                     $object = new SystemUser($user->id);
  81.                     $object->reset_pass 'Y'//parâmetro que diz que há uma requisição de reset de senha
  82.                     $object->data_pass time(); //variável para validação de link
  83.                     $object->uid_pass uniqid(rand(), true); //variável para validação de link
  84.                     $object->store();
  85.                     
  86.                     // monta parâmetros GET com criptografia
  87.                     $url sprintf'id=%s&email=%s&uid=%s&key=%s',$object->idmd5($object->email), md5($object->uid_pass), md5($object->data_pass) );
  88.                     // monta link que será enviado para o email do usuário
  89.                     $link = ($_SERVER['HTTPS']=='on' "https" "http") . '://'$_SERVER['HTTP_HOST'] . '/index.php?class=ResetPasswordForm&'$url;
  90.                     
  91.                     // pega parâmetros para envio de email
  92.                     $prefs SystemPreference::getAllPreferences();
  93.                     TTransaction::close();
  94.                     
  95.                     $mail = new TMail;
  96.                     $mail->setFrom($prefs['mail_from'], 'Falko ERP');
  97.                     $mail->setSubject('Reset de senha');
  98.                     $mail->setHtmlBody("Você solicitou o reset de senha, por favor clique no link abaixo para cadastrar sua nova senha!<br><br>
  99.                                         Usuário: $object->login<br>
  100.                                         <a href='$link'>Resetar senha</a><br><br>
  101.                                         Atenciosamente,<br>
  102.                                         <b>Falko ERP</b>");
  103.                     $mail->addAddress($object->email);
  104.                     $mail->SetUseSmtp();
  105.                     $mail->SetSmtpHost($prefs['smtp_host'], $prefs['smtp_port']);
  106.                     $mail->SetSmtpUser($prefs['smtp_user'], $prefs['smtp_pass']);
  107.                     $mail->send();
  108.                     
  109.                     new TMessage('info''Você receberá um email com as instruções para redefinição de senha.');
  110.                 }
  111.                 catch (Exception $e)
  112.                 {
  113.                     // shows the exception error message
  114.                     new TMessage('error'$e->getMessage());
  115.                     
  116.                     // undo all pending operations
  117.                     TTransaction::rollback();
  118.                 }
  119.             }
  120.             else
  121.             {
  122.                 throw new Exception(_t('User not found'));
  123.             }
  124.         }
  125.         catch (Exception $e)
  126.         {
  127.             new TMessage('error',$e->getMessage());
  128.             TTransaction::rollback();
  129.         }
  130.     }
  131. }
  132. ?>



5º - Controller ResetPasswordForm responsável por checar se o link é válido e permitir o usuário digitar a nova senha
  1. <?php
  2. class ResetPasswordForm extends TPage
  3. {
  4.     protected $form// form
  5.     
  6.     /**
  7.      * Class constructor
  8.      * Creates the page and the registration form
  9.      */
  10.     function __construct($param)
  11.     {
  12.         parent::__construct();
  13.         
  14.         $valido TRUE;
  15.         if (isset($_GET['id']))
  16.         {
  17.             $id $_GET['id'];
  18.             $email $_GET['email'];
  19.             $uid $_GET['uid'];
  20.             $data $_GET['key'];
  21.             
  22.             // checa se id do usuário existe
  23.             TTransaction::open('permission');
  24.             $user = new SystemUser($id);
  25.             TTransaction::close();
  26.         
  27.             if ($user instanceof SystemUser)
  28.             {
  29.                 if ($user->active == 'N'//não permite que usuário inativo altera a senha
  30.                 {
  31.                     $valido FALSE;
  32.                 }
  33.                 else if ($user->reset_pass != 'Y'//valida se há uma requisição de reset de senha
  34.                 {
  35.                     $valido FALSE;
  36.                 }
  37.                 else if (md5($user->email) != $email//valida se email criptografado é igual ao do link acessado
  38.                 {
  39.                     $valido FALSE;
  40.                 }
  41.                 else if (md5($user->uid_pass) != $uid//valida se uid criptografado é igual ao do link acessado
  42.                 {
  43.                     $valido FALSE;
  44.                 }
  45.                 else if (md5($user->data_pass) != $data//valida se email criptografado é igual ao do link acessado
  46.                 {
  47.                     $valido FALSE;
  48.                 }
  49.             }
  50.             else
  51.             {
  52.                 $valido FALSE;
  53.             }
  54.         }
  55.         // se não é valido, leva usuário para tela de login
  56.         if (!$valido && isset($_GET['id']))
  57.         {
  58.             new TMessage('error'_t('User not found'), new TAction(array($this'onLogin')) );
  59.             return false;
  60.         }
  61.         $table = new TTable;
  62.         $table->width '100%';
  63.         // creates the form
  64.         $this->form = new TForm('form_reset_password');
  65.         $this->form->class 'tform';
  66.         $this->form->style 'max-width: 450px; margin:auto; margin-top:120px;';
  67.         // add the notebook inside the form
  68.         $this->form->add($table);
  69.         // create the form fields
  70.         $user_id = new THidden('user_id');
  71.         $user_id->setValue($user->id);
  72.         $senha = new TPassword('senha');
  73.         $senha_confirm = new TPassword('senha_confirm');
  74.         
  75.         $senha->placeholder 'Nova senha';
  76.         $senha_confirm->placeholder 'Digite novamente';
  77.         
  78.         // define the sizes
  79.         $senha->setSize('70%'40);
  80.         $senha_confirm->setSize('70%'40);
  81.         $senha->style 'height:35px; font-size:14px;float:left;border-bottom-left-radius: 0;border-top-left-radius: 0;';
  82.         $senha_confirm->style 'height:35px; font-size:14px;float:left;border-bottom-left-radius: 0;border-top-left-radius: 0;';
  83.         $row=$table->addRow();
  84.         $row->addCell( new TLabel('Nova senha') )->colspan 2;
  85.         $row->class='tformtitle';
  86.         
  87.         $senha->setLabel('Senha');
  88.         $senha_confirm->setLabel('Senha_confirm');
  89.         
  90.         $senha->addValidation('Senha', new TRequiredValidator);
  91.         $senha_confirm->addValidation('Senha_confirm', new TRequiredValidator);
  92.         $locker '<span style="float:left;width:35px;margin-left:45px;height:35px;" class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span>';
  93.         $container1 = new TElement('div');
  94.         $container1->add($locker);
  95.         $container1->add($senha);
  96.         $container1->add($user_id);
  97.         
  98.         $container2 = new TElement('div');
  99.         $container2->add($locker);
  100.         $container2->add($senha_confirm);
  101.         $row=$table->addRow();
  102.         $row->addCell($container1)->colspan 2;
  103.         $row=$table->addRow();
  104.         $row->addCell($container2)->colspan 2;
  105.         
  106.         // create an action button (save)
  107.         $recuperar_button=new TButton('recovery');
  108.         // define the button action
  109.         $recuperar_button->setAction(new TAction(array($this'onReset')), _t('Save'));
  110.         $recuperar_button->class 'btn btn-success';
  111.         $recuperar_button->style 'font-size:18px;width:90%;padding:10px';
  112.         $row=$table->addRow();
  113.         $row->class 'tformaction';
  114.         $cell $row->addCell$recuperar_button );
  115.         $cell->colspan 2;
  116.         $cell->style 'text-align:center';
  117.         
  118.         $this->form->setFields(array($senha$senha_confirm$user_id$recuperar_button));
  119.         // add the form to the page
  120.         parent::add($this->form);
  121.     }
  122.     
  123.     public function onLogin()
  124.     {
  125.         TApplication::loadPage('LoginForm'''$_REQUEST);
  126.     }
  127.     /**
  128.      * Reset password
  129.      */
  130.     public function onReset()
  131.     {
  132.         try
  133.         {
  134.             $data $this->form->getData('StdClass');
  135.             $this->form->validate();
  136.             //valida se senha e senha de confirmação foram digitadas iguais
  137.             if ($data->senha != $data->senha_confirm)
  138.             {
  139.                 new TMessage('error''Senhas não conferem, por favor digite as senhas iguais.');
  140.             }
  141.             else
  142.             {
  143.                 // se passou pelas validações, instancia o usuário
  144.                 TTransaction::open('permission');
  145.                 $object = new SystemUser($data->user_id);
  146.                 if ($object)
  147.                 {
  148.                     // grava nova senha e limpa os outros campos, assim é garantido que o link é válido para apenas uma utilização
  149.                     $object->password password_hash($data->senhaPASSWORD_DEFAULT);
  150.                     $object->reset_pass NULL;
  151.                     $object->data_pass NULL;
  152.                     $object->uid_pass NULL;
  153.                     $object->store();
  154.                     
  155.                     new TMessage('info''Senha alterada com sucesso!', new TAction(array($this'onLogin')) );
  156.                 }
  157.                 else
  158.                 {
  159.                     new TMessage('error'_t('User not found'), new TAction(array($this'onLogin')) );
  160.                 }
  161.                 TTransaction::close();
  162.             }
  163.         }
  164.         catch (Exception $e)
  165.         {
  166.             new TMessage('error',$e->getMessage());
  167.             TTransaction::rollback();
  168.         }
  169.     }
  170. }
  171. ?>

Curso completo Meu Negócio Pronto
Use para si, ou transforme em um negócio: Inclui aulas e códigos-fontes
Gestor de conteúdo (SITE) + Loja Virtual (E-Commerce) + Emissor de Notas para infoprodutos


Meu negócio pronto Quero me inscrever agora!

Comentários (38)


HA

Pessoal, qualquer melhoria ou sugestão, podem infomar.
Apenas para pontuar no último arquivo, salvei a senha usando password_hash, pois estou utilizando PHP superior a 5.5. Alterei toda a forma de encriptação no sistema.

Futuramente farei a parte de cadastro de usuário, utilizando uma lógica parecida, com confirmação por link enviado por email.

Abraços!
JA

Muito legal, acho que deveria integrar ao templete, facilita nos próximos updates. Parabéns!
AL

Parabéns pela iniciativa Henrique. Será muito útil para todos.
AL

Alguem pode ajudar, informando de que forma devo chamar o formulario para digitar o email para recuperação de senha. Coloquei o seguinte codigo na pagina Login.html


<a href="index.php?class=LoginForm&method=onRecovery">[Esqueceu sua Senha?]</a></div>

<!-- /#wrapper -->

Esse metodo =onRecovery, faz ligação onde?
HA

Amos ao invés de editar diretamente o Login.html, coloque um link na controladora de LoginForm logo depois do código do botão de entrar.

  1. <?php
  2. $recupera = new TActionLink(_t('Forgot your password?'), new TAction(array($this'onRecovery')) );
  3. $recupera->style 'font-size:16px;width:90%;padding:10px';
  4.         
  5. $row $table->addRow();
  6. $cell $row->addCell$recupera ); ?>


Esse método onRecovery está no próprio LoginForm

  1. <?php
  2. public function onRecovery()
  3. {
  4.     AdiantiCoreApplication::gotoPage('SendEmailPasswordForm');
  5. ?>
CF

Henrique, boa noite. Muito legal a sua iniciativa, e funcionou perfeitamente, mas somente se eu acessar o sistema e chamar as telas manualmente. O link está na tela de login chamado o evento OnRecovery, que chama a tela SendEmailPasswordForm conforme abaixo:

  1. <?php
  2. public static function OnRecovery()
  3.     {
  4.        AdiantiCoreApplication::gotoPage('SendEmailPasswordForm');
  5.     }
  6. ?>


Ao clicar no link, ele não abre a tela para digitar o e-mail e volta para a tela de login. O que esqueci de fazer?

Abs
Cleber Fosse
HA

Cleber boa noite,

Fico feliz em ter ajudado. Esqueci de informar uma coisa no tutorial, pode ser o seu caso, é preciso adicionar as controladoras como páginas públicas no application.ini, pois as páginas podem estar caindo na checagem de permissão do framework. Veja se isso resolve.

[permission] ; Public classes, anyone (logged or not) has access public_classes[] = PublicForm public_classes[] = PublicView public_classes[] = SendEmailPasswordForm public_classes[] = ResetPasswordForm


Abraços!
CF

Exatamente Henrique, era o que falta.

Muito obrigado pela ajuda.

Abraço e sucesso!!!
CF

Henrique, boa noite.
Voltei a trabalhar no meu sistema e deparei com um problema ao recuperar a senha. Eu recebo o e-mail, faz a atualização no usuário corretamente, mas ao clicar no link não está indo para o formulário solicitar a nova senha e sim para a tela de login normal.

o meu link está da seguinte maneira:
index.php?class=LoginForm&method=&id=1&email=12d23a1861905a1801f13c61da3229fc&uid=71bf7b51c38c2f420b39742fd24cadc0&key=209f532ecce01b409ebf588c325c5f04&_ga=GA1.3.1374476325.1502645928&_gid=GA1.3.334907752.1506130288&PHPSESSID=6bm1gcs0b2gfasjampu8dttpo6


Será que está correto?

Abs,
Cleber
CF

Henrique, corrigindo link:

index.php?class=ResetPasswordForm&id=1&email=12d23a1861905a1801f13c61da3229fc&uid=71bf7b51c38c2f420b39742fd24cadc0&key=209f532ecce01b409ebf588c325c5f04&_ga=GA1.3.1374476325.1502645928&_gid=GA1.3.334907752.1506130288&PHPSESSID=em1b87kfjh95nmoi9p2ichpou1
HA

Cleber tudo bem?
Percebi que você está passando mais algumas outras variáveis GET no link, realizou alguma modificação? Me passa por gentileza qual deveria ser o link inteiro, não só a parte do index.php. Sugiro depurar o código no arquivo ResetPasswordForm e ver onde ele está caindo na variável $valido = false;
CF

Henrique, boa noite.

Fiz uns testes e até comparei a versão do ResetPasswordForm com a sua e está igual. Vou colocar alguns TMessage para ver o resultado das variáveis.
CF

Henrique, na url abaixo tem a mudança que eu fiz para testar se a classe estaria recebe-se ao menos o ID do usuário.

www.s2s.com.br/sid/index.php?class=ResetPasswordForm&id=1

TC

Poxa Vida Cara, Muiiito Show de bola obrigado pela colaboração
HA

Cléber desculpa a demora! Ainda não consegui pegar o problema exato que vc está tendo, o ideal seria a depuração mesmo. Mas tem uma coisa que eu adianto, acabei realizando uma melhoria na montagem do link de reset de senha. Usar a variável $_SERVER['HTTP_HOST'] implica num problema de não conseguirmos pegar o endereço correto quando o sistema está em subpastas. Pra isso, criei mais um campo de preferências para setar a url_base do sistema. Ficando assim:

  1. <?php
  2.   // pega parâmetros para envio de email
  3.   $prefs SystemPreference::getAllPreferences();
  4.  // monta link que será enviado para o email do usuário
  5.  $link $prefs['url_base'] . '/index.php?class=ResetPasswordForm&'$url;
  6. ?>


No seu exemplo, essa url_base você salvaria no banco como s2s.com.br/sid ou com HTTPS se for o caso. Recomendo bastante realizar essa alteração, isso ajuda a configurar URLs para diferentes ambientes e clientes.
CF

Henrique, boa noite.

Fiz o ajuste para a montagem da URL e da maneira que fez acima (sem nenhuma alteração) e fez a montagem abaixo:
http://s2s.com.br/sid/index.php?class=ResetPasswordForm&id=1


Estranho o porque a tela não é apresentada.

Obrigado pela ajuda. Vou tentar debugar amanhã,
CF

Henrique, aproveitando: eu coloquei os dois fontes PHP na pasta app/control/public, está certo?

Outra coisa que identifiquei foi que o PublicView eu consigo carregar esse arquivo ao logar no sistema e digitando o nome do programa na URL. Fiz a mesma coisa para o ResetPasswordForm e ele dá erro de permissão de acesso.

Talvez essa informação possa ajudar.

Abs
Cleber Fosse
HA

Cléber você pode estar com o mesmo problema que passou antes. Os arquivos não precisam necessariamente estar na pasta Control/public, mas precisam serem adicionadas no application.ini no public_classes
CF

Henrique, boa noite.

O application.ini está OK.
CF

Henrique,
[permission]
; Public classes, anyone (logged or not) has access
public_classes[] = PublicForm
public_classes[] = PublicView
public_classes[] = SendEmailPasswordForm
public_classes[] = ResetPasswordForm
NR

Henrrique esto com problema ao eviar o email na tela de resetar a senha ao enviar o email me da este erro "Método SystemUser::newFromEmail() não encontrado"

O que sera que etou fazendo errado..

Segui todos os passos.
Pode me ajudar
NR

Henrrique esto com problema ao eviar o email na tela de resetar a senha ao enviar o email me da este erro "Método SystemUser::newFromEmail() não encontrado"

O que sera que etou fazendo errado..

Segui todos os passos.
Pode me ajudar
HA

Nilton é preciso implementar o método no modelo SystemUset.
  1. <?php
  2. static public function newFromEmail($email)
  3.     {
  4.         $repos = new TRepository('SystemUser');
  5.         $criteria = new TCriteria;
  6.         $criteria->add(new TFilter('email''='$email));
  7.         $objects $repos->load($criteria);
  8.         if (isset($objects[0]))
  9.         {
  10.             return $objects[0];
  11.         }
  12.     }
  13. ?>
RB

Henrique,

Estou implementando a opção de recuperá com a sua dica, porém na hora de enviar o email -, da um erro de conexão,

error: connection failed;

MC

Ficou muito bom, show de bola, testando o código acrescentei uma linha para redirecionar para a página de login depois de enviar o email.

na linha 115 alterei para:

  1. <?php
  2. new TMessage('info''Você receberá um email com as instruções para redefinição de senha.', new TAction(array('LoginForm''onClear')) );
  3. ?>


e no arquivo LoginForm.php acrescentei

  1. <?php
  2.  public function onClear$param )
  3.     {
  4.          $this->form->clear(TRUE);  
  5.     }
  6. ?>


Amanhã vou tentar implementar um bloqueio de tela no form SendEmailPasswordForm enquanto estiver enviando o email. para o usuário não ficar clicando no botão " enviar ". Parabéns!
RB

Miuller,

Tem como postar a solução, pois segui passo a passo, mas na hora que clico em emviar email da o sguinte erro :


Notice: Undefined index: url_base in /var/www/html/centinel/app/control/public/SendEmailPasswordForm.class.php on line 99

Fatal error: Uncaught Error: Class 'PHPMailerPHPMailerPHPMailer' not found in /var/www/html/centinel/app/lib/util/TMail.class.php:23 Stack trace: #0 /var/www/html/centinel/app/control/public/SendEmailPasswordForm.class.php(103): TMail->__construct() #1 [internal function]: SendEmailPasswordForm->onReset(Array) #2 /var/www/html/centinel/lib/adianti/control/TPage.php(51): call_user_func(Array, Array) #3 /var/www/html/centinel/lib/adianti/control/TPage.php(205): AdiantiControlTPage->run() #4 /var/www/html/centinel/lib/adianti/core/AdiantiCoreApplication.php(62): AdiantiControlTPage->show(Array) #5 /var/www/html/centinel/engine.php(34): AdiantiCoreAdiantiCoreApplication::run(true) #6 /var/www/html/centinel/engine.php(43): TApplication::run(true) #7 {main} thrown in /var/www/html/centinel/app/lib/util/TMail.class.php on line 23
MC

Boa tarde Rubens, o email está enviando?, se a resposta for sim, na sua caixa de email, clicando no link teria que redirecionar para o seu projeto, tente substituir a variável urlbase.

  1. <?php;
  2.   // monta link que será enviado para o email do usuário                    
  3.     $prefs['url_base'] = sprintf( 'http%s://%s%s' , isset( $_SERVER[ 'HTTPS' ] ) ? 's' : null , $_SERVER[ 'HTTP_HOST' ] , dirname( $_SERVER[ 'REQUEST_URI' ] ) );
  4.   $link = $prefs['url_base'] . '/index.php?class=ResetPasswordForm&'. $url;
  5. ?>


Qualquer coisa posta ai

RB

Miuller,

Então, fiz como indicado, porém agora da a mensagem que não esta encontrando a classe PHPMailer;

Observação isto esta acontecendo após atualizar para versão 5.0



Fatal error: Uncaught Error: Class 'PHPMailerPHPMailerPHPMailer' not found in /var/www/html/centinel/app/lib/util/TMail.class.php:23 Stack trace: #0 /var/www/html/centinel/app/control/public/SendEmailPasswordForm.class.php(104): TMail->__construct() #1 [internal function]: SendEmailPasswordForm->onReset(Array) #2 /var/www/html/centinel/lib/adianti/control/TPage.php(51): call_user_func(Array, Array) #3 /var/www/html/centinel/lib/adianti/control/TPage.php(205): AdiantiControlTPage->run() #4 /var/www/html/centinel/lib/adianti/core/AdiantiCoreApplication.php(62): AdiantiControlTPage->show(Array) #5 /var/www/html/centinel/engine.php(34): AdiantiCoreAdiantiCoreApplication::run(true) #6 /var/www/html/centinel/engine.php(43): TApplication::run(true) #7 {main} thrown in /var/www/html/centinel/app/lib/util/TMail.class.php on line 23
MC

Boa tarde, observando a mensagem de erro observei que tem um problema na classe "/var/www/html/centinel/app/lib/util/TMail.class.php:23 ", tenho uma sugestão, faça um backup da classe TMail de seu projeto e crie um novo projeto, dai nesse novo projeto copia a classe TMail e substitui pela de seu projeto (a que vc fez o backup), e vê se soluciona o problema.
RB

Miuller,

Não funcionou funcionou, já tinha feito isto antes.
MC

Rubens, tente criar um novo projeto e adicione as p áginas deste exemplo no novo projeto, só para testar mesmo, dando uma olhada no projeto, notei que o envio em localhost tava funcionando mas quando coloquei o projeto no servidor estava dando um erro no envio, talvez seja o seu caso, vou postar as modificações que realizei.

  1. <?php
  2. if ($user)
  3.             {
  4.             
  5.                 try
  6.                 {
  7.                     TTransaction::open('permission');
  8.                     
  9.                     $preferences SystemPreference::getAllPreferences(); //mais ou menos na linha 81
  10.                     
  11.                     $object = new SystemUser($user->id);
  12.                     $object->reset_pass 'Y'//parâmetro que diz que há uma requisição de reset de senha
  13.                     $object->data_pass time(); //variável para validação de link
  14.                     $object->uid_pass uniqid(rand(), true); //variável para validação de link
  15.                     $object->store();
  16.                     
  17.                     // monta parâmetros GET com criptografia
  18.                     $url sprintf'id=%s&email=%s&uid=%s&key=%s',$object->idmd5($object->email), md5($object->uid_pass), md5($object->data_pass) );
  19.                     
  20.                     // monta link que será enviado para o email do usuário                    
  21.                     $prefs['url_base'] = sprintf'http%s://%s%s' , isset( $_SERVER'HTTPS' ] ) ? 's' null $_SERVER'HTTP_HOST' ] , dirname$_SERVER'REQUEST_URI' ] ) );
  22.                     $link $prefs['url_base'] . '/index.php?class=ResetPasswordForm&'$url;
  23.                                                           
  24.                     $mail = new TMail;
  25.                     $mail->setFrom(trim($preferences['mail_from']), 'Seu nome');                  
  26.                     $mail->addAddress(trim($object->email));  
  27.                     $mail->setSubject('Cadastrar nova senha do seu projeto');                   
  28.                     if ($preferences['smtp_auth'])
  29.                     {
  30.                         $mail->SetUseSmtp();
  31.                         $mail->SetSmtpHost($preferences['smtp_host'], $preferences['smtp_port']);
  32.                         $mail->SetSmtpUser($preferences['smtp_user'], $preferences['smtp_pass']);
  33.                     }                  
  34.                     
  35.                     $mail->setHtmlBody("Você solicitou uma nova senha, por favor clique no link abaixo para cadastrar a nova senha!<br><br>
  36.                                         Usuário: $object->login<br>
  37.                                         <a href='$link'>Cadastrar nova senha</a><br><br>
  38.                                         Atenciosamente,<br>
  39.                                         <b>Seu nome</b>");
  40.                     $mail->addAddress($object->email);
  41.                     //$mail->SetUseSmtp();
  42.                     //$mail->SetSmtpHost($preferences['smtp_host'], $preferences['smtp_port']);
  43.                     //$mail->SetSmtpUser($preferences['smtp_user'], $preferences['smtp_pass']);
  44.                     $mail->send();                    
  45.                     new TMessage('info''Tudo certo, Você receberá um email com as instruções para redefinição de senha em: '.$object->email.'', new TAction(array('LoginForm''onClear')) );//redireciona para a página login no metódo onClear
  46.                   
  47.                    TTransaction::close();            
  48.                 
  49.                 }
  50.                 catch (Exception $e)
  51.                 {
  52.                     // shows the exception error message
  53.                     new TMessage('error'$e->getMessage());
  54.                     
  55.                     // undo all pending operations
  56.                     TTransaction::rollback();
  57.                 }
  58. ?>

Testei e deu tudo certo, se vc não conseguir me fala no miuller.de.faria@gmail.com e te dou uma mão, flw
MC

Essa modificação acima é no arquivo SendEmailPassordForm, agora fiz outra modificação no arquivo ResetPaswordForm, conforme abaixo, atentar para a linha 29, pois ele verifica se o parâmetro email é igual ao da base de dados, essa é uma segurança a mais.

  1. <?php
  1. <?php
  2. class ResetPasswordForm extends TPage
  3. {
  4.     protected $form// form
  5.     
  6.     /**
  7.      * Class constructor
  8.      * Creates the page and the registration form
  9.      */
  10.     function __construct($param)
  11.     {
  12.         parent::__construct();
  13.         
  14.         $this->form = new TForm('form_reset_password');
  15.         $this->form->class 'tform';
  16.         
  17.         
  18.         $valido TRUE;
  19.         if (isset($param['id']))
  20.         {
  21.             $id $param['id'];            
  22.             $email $param['email'];
  23.             $uid $param['uid'];
  24.             $data $param['key'];
  25.             
  26.             // checa se id do usuário existe
  27.             TTransaction::open('permission');
  28.             $user = new SystemUser($id);
  29.             //verifica se o parametro email é igual ao da base de dados            
  30.             if( md5($user->email) !== $email)
  31.             {              
  32.                throw new Exception(_t('User not found'));
  33.             }
  34.             
  35.             TTransaction::close();
  36.         
  37.             if ($user instanceof SystemUser)
  38.             {
  39.                 if ($user->active == 'N'//não permite que usuário inativo altera a senha
  40.                 {
  41.                     $valido FALSE;
  42.                 }
  43.                 else if ($user->reset_pass != 'Y'//valida se há uma requisição de reset de senha
  44.                 {
  45.                     $valido FALSE;
  46.                 }
  47.                 else if (md5($user->email) != $email//valida se email criptografado é igual ao do link acessado
  48.                 {
  49.                     $valido FALSE;
  50.                 }
  51.                 else if (md5($user->uid_pass) != $uid//valida se uid criptografado é igual ao do link acessado
  52.                 {
  53.                     $valido FALSE;
  54.                 }
  55.                 else if (md5($user->data_pass) != $data//valida se email criptografado é igual ao do link acessado
  56.                 {
  57.                     $valido FALSE;
  58.                 }
  59.             }
  60.             else
  61.             {
  62.                 $valido TRUE;
  63.             }
  64.         }
  65.         // se não é valido, leva usuário para tela de login
  66.                    // echo 'o parametro 222 id é:'. $id;
  67.         if ( $valido FALSE)
  68.         {
  69.             new TMessage('error'_t('User not found'), new TAction(array($this'onLogin')) );
  70.             return false;
  71.         }
  72.         else
  73.         {
  74.         $table = new TTable;
  75.         $table->width '100%';
  76.         // creates the form
  77.         $this->form->style 'max-width: 450px; margin:auto; margin-top:120px;';
  78.         $this->form->add($table);
  79.         // create the form fields
  80.         $usuario = new THidden('usuario');                
  81.         $usuario->setValue($user->id);
  82.         
  83.         $senha = new TPassword('senha');
  84.         $senha_confirm = new TPassword('senha_confirm');
  85.    
  86.         $senha->placeholder 'Nova senha';
  87.         $senha_confirm->placeholder 'Digite novamente';
  88.         
  89.         // define the sizes
  90.         $senha->setSize('70%'40);
  91.         $senha_confirm->setSize('70%'40);
  92.         $senha->style 'height:35px; font-size:14px;float:left;border-bottom-left-radius: 0;border-top-left-radius: 0;';
  93.         $senha_confirm->style 'height:35px; font-size:14px;float:left;border-bottom-left-radius: 0;border-top-left-radius: 0;';
  94.         $row=$table->addRow();
  95.         $row->addCell( new TLabel('Nova senha') )->colspan 2;
  96.         $row->class='tformtitle';
  97.         
  98.         $senha->setLabel('Senha');
  99.         $senha_confirm->setLabel('Senha_confirm');
  100.         
  101.         $senha->addValidation('Senha', new TRequiredValidator);
  102.         $senha_confirm->addValidation('Senha_confirm', new TRequiredValidator);
  103.         $locker '<span style="float:left;width:35px;margin-left:45px;height:35px;" class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span>';
  104.         $container1 = new TElement('div');
  105.         $container1->add($locker);
  106.         $container1->add($senha);
  107.         $container1->add($usuario);
  108.         
  109.         $container2 = new TElement('div');
  110.         $container2->add($locker);
  111.         $container2->add($senha_confirm);
  112.         $row=$table->addRow();
  113.         $row->addCell($container1)->colspan 2;
  114.         $row=$table->addRow();
  115.         $row->addCell($container2)->colspan 2;
  116.         
  117.         // create an action button (save)
  118.         $recuperar_button=new TButton('recovery');
  119.         // define the button action
  120.         $recuperar_button->setAction(new TAction(array($this'onReset')), _t('Save'));
  121.         $recuperar_button->class 'btn btn-success';
  122.         $recuperar_button->style 'font-size:18px;width:90%;padding:10px';
  123.         $row=$table->addRow();
  124.         $row->class 'tformaction';
  125.         $cell $row->addCell$recuperar_button );
  126.         $cell->colspan 2;
  127.         $cell->style 'text-align:center';
  128.         
  129.         $this->form->setFields(array($senha$senha_confirm$usuario$recuperar_button));
  130.         
  131.         }
  132.         // add the form to the page
  133.         parent::add($this->form);
  134.     }
  135.     
  136.     public function onLogin()
  137.     {
  138.         TApplication::loadPage('LoginForm'''$_REQUEST);
  139.     }
  140.     /**
  141.      * Reset password
  142.      */
  143.     public function onReset()
  144.     {
  145.         try
  146.         {
  147.             $data $this->form->getData('StdClass');
  148.             $this->form->validate();
  149.             //valida se senha e senha de confirmação foram digitadas iguais
  150.             if ($data->senha != $data->senha_confirm)
  151.             {
  152.                 new TMessage('error''Senhas não conferem, por favor digite as senhas iguais.');
  153.             }
  154.             else
  155.             {
  156.                 // se passou pelas validações, instancia o usuário
  157.                 TTransaction::open('permission');
  158.                 $object = new SystemUser($data->usuario);
  159.                 if ($object)
  160.                 {
  161.                     // grava nova senha e limpa os outros campos, assim é garantido que o link é válido para apenas uma utilização
  162.                     $object->password md5($data->senha);
  163.                     $object->reset_pass 'SIM';
  164.                     $object->data_pass NULL//não entendi a necessidade deste campo
  165.                     $object->uid_pass date("Y-m-d H:i:s"); //acho que este campo seria para salvar a data da password modificada
  166.                     $object->store();
  167.                     
  168.                     new TMessage('info''Senha alterada com sucesso!', new TAction(array('LoginForm''onClear')) );
  169.                 }
  170.                 else
  171.                 {
  172.                     new TMessage('error',  _t('User not found'), new TAction(array($this'onLogin')) );
  173.                 }
  174.                 TTransaction::close();
  175.             }
  176.         }
  177.         catch (Exception $e)
  178.         {
  179.             new TMessage('error',$e->getMessage());
  180.             TTransaction::rollback();
  181.         }
  182.     }
  183. }
  184. ?>


DC

Muito obrigado!!! Muito útil, também não entendi porque não vem no admin padrão do framework!

Funcionou perfeitamente, vale ressaltar alguns detalhes óbvios para alguns porém não para todos:

É necessário configurar corretamente o formulário de preferencias do sistema, e para tanto, deve-se ter uma conta de email valida na hospedagem. não consegui colocar pra funcionar com o gmail...

Na classe ResetPasswordForm Alterar o salvamento da nova senha para md5 pois como o amigo citou, ele reformulou o sistema de login dele e o login padrão do framework utiliza md5 para geração e verificação das senhas.
linha : 149
$object->password = password_hash($data->senha, PASSWORD_DEFAULT);
para :
$object->password = md5($data->senha);


feito isso tudo funcionou perfeitamente!
CF

Henrique, boa noite.
Como ficaria a parte abaixo do código usando a versão 5 do framework?

// $recupera = new TActionLink( _t('Forgot your password?'), new TAction(array($this, 'onRecovery')) );
// $recupera->style = 'font-size:16px;width:90%;padding:10px';
// $row = $table->addRow();
// $cell = $row->addCell( $recupera );

Abs
Cleber
MC

No meu caso, eu coloquei tudo em um panel, e abaixo coloquei o link para o método onRecovery

  1. <?php
  2.         $login->placeholder _t('User');
  3.         $password->placeholder _t('Password');
  4.         $unidade->placeholder 'Unidade';
  5.         $regiao->placeholder 'Região';
  6.         $user '<span style="float:left;margin-left:44px;height:35px;" class="login-avatar"><span class="glyphicon glyphicon-user"></span></span>';
  7.         $locker '<span style="float:left;margin-left:44px;height:35px;" class="login-avatar"><span class="glyphicon glyphicon-lock"></span></span>';
  8.         $unit '<span style="float:left;margin-left:44px;height:35px;" class="login-avatar"><span class="fa fa-university"></span></span>';
  9.         $reg '<span style="float:left;margin-left:44px;height:35px;" class="login-avatar"><span class="fa fa-university"></span></span>';
  10.        
  11.         $logo '<img class="img-responsive" style="margin-left:170px" width="100" height="100" src="tim.php?src=app/images/logo.png&w=100&h=100&zc=2" >'//adicionei um logo acima do panel 
  12.                 
  13.         $panel = new TPanelGroup;
  14.         $panel->style 'height:120px;max-width:460px;margin:auto';
  15.         $panel->id ='imagem';
  16.         $panel->add($logo); //adicionei o logo no panel para personalisar
  17.         $recupera = new TActionLink('Esqueceu a senha?', new TAction(array($this'onRecovery')) );
  18.         $recupera->style 'font-size:12px;width:100%;padding:2px;text-align: center; float:left';  
  19.         $this->form->addFields( [$user$login] );
  20.         $this->form->addFields( [$locker$password] );
  21.         $this->form->addFields( [$unit$regiao] );
  22.         $this->form->addFields( [$reg$unidade] );    
  23.         
  24.         if (!empty($ini['general']['multiunit']) and $ini['general']['multiunit'] == '1')
  25.         {
  26.             $unit_id = new TCombo('unit_id');
  27.             $unit_id->setSize('70%');
  28.             $unit_id->style 'height:35px;font-size:14px;float:left;border-bottom-left-radius: 0;border-top-left-radius: 0;';
  29.             $this->form->addFields( [$unit$unit_id] );
  30.             $login->setExitAction(new TAction( [$this'onExitUser'] ) );
  31.         }
  32.         
  33.                
  34.         $btn $this->form->addAction(_t('Log in'), new TAction(array($this'onLogin')), '');
  35.         $btn->class 'btn btn-primary';
  36.         $btn->style 'height: 40px;width: 90%;display: block;margin: auto;font-size:17px;';
  37.                    
  38.         
  39.         $wrapper = new TElement('div');
  40.         $wrapper->style 'margin:auto; margin-top:20px;max-width:460px;';
  41.         $wrapper->id    'login-wrapper';
  42.         $wrapper->add$panel);
  43.         $wrapper->add($this->form);
  44.         $wrapper->add($recupera);
  45.                                 
  46.         // add the form to the page
  47.         parent::add($wrapper);
  48.     }
  49.     
  50.     
  51.     public function onRecovery()
  52.     {
  53.        AdiantiCoreApplication::gotoPage('SendEmailPasswordForm');
  54.     } 
  55. ?>
DC

Caso alguém precise dessa solução funcionando, dentro das minhas limitações de tempo eu passo todo o código funcionando em conjunto com o Admin padrão do adianti, já que estou muito grato por ter pego a solução aqui que me poupou muito trabalho e estudo, ajudarei com prazer outros usuários!
RB

Davidson,

Se puder disponibilizar ó código, serei muito grato.

Segue meu e-mail :rubensbispo29@gmail.com
DC

Vou mandar por e-mail e colocar aqui até amanhã de manhã! Mas adianto que a única modificação necessária foi a que postei acima na geração da nova senha em md5 , até lá, tente seguir o tutorial desde o início do post, caso não consiga, terá de estudar um pouco mais o framework.