Browse Source

first working account controllers (login, register, remind_password & reset_password)

- updated languages (added infoRemindSuccess & infoResetSuccess)
- added en/Account language
- added Account/Remind_password & Account/Reset_password Controllers & Views
- updated Account/Login & Account/Register Controllers & Views
- renamed views Aauth/Reset & Aauth/ResetSuccess to Aauth/RemindPassword & Aauth/ResetPassword
- updated LoginTokenModel
- updated Libraries/Aauth
- updated Config/Aauth
v3-dev
REJack 7 years ago
parent
commit
0b040a8a9e
No known key found for this signature in database
GPG Key ID: 4A44B48700429F46
  1. 12
      application/Config/Aauth.php
  2. 6
      application/Controllers/Account/Login.php
  3. 4
      application/Controllers/Account/Register.php
  4. 71
      application/Controllers/Account/Remind_password.php
  5. 74
      application/Controllers/Account/Reset_password.php
  6. 4
      application/Language/de/Aauth.php
  7. 2
      application/Language/en/Aauth.php
  8. 57
      application/Language/en/Account.php
  9. 2
      application/Language/es/Aauth.php
  10. 2
      application/Language/fa/Aauth.php
  11. 2
      application/Language/fr/Aauth.php
  12. 2
      application/Language/id/Aauth.php
  13. 2
      application/Language/ru/Aauth.php
  14. 2
      application/Language/sv/Aauth.php
  15. 2
      application/Language/zh-CN/Aauth.php
  16. 2
      application/Language/zh-TW/Aauth.php
  17. 43
      application/Libraries/Aauth.php
  18. 1
      application/Models/Aauth/LoginTokenModel.php
  19. 0
      application/Views/Aauth/RemindPassword.php
  20. 0
      application/Views/Aauth/ResetPassword.php
  21. 14
      application/Views/Account/Login.php
  22. 18
      application/Views/Account/Register.php
  23. 33
      application/Views/Account/RemindPassword.php
  24. 33
      application/Views/Account/ResetPassword.php

12
application/Config/Aauth.php

@ -42,21 +42,21 @@ class Aauth extends BaseConfig
| 'linkResetPassword'
|
| Link for reset_password without site_url or base_url
| (default: '/account/reset_password')
| (default: '/account/reset_password/index')
|
| 'linkVerification'
|
| Link for verification without site_url or base_url
| (default: '/account/verification')
| (default: '/account/verification/index')
| 'linkVerification'
|
| Redirect path to TOTP Verification page
| (default: '/account/twofactor_verification')
| (default: '/account/twofactor_verification/index')
*/
public $linkNoPermission = false;
public $linkResetPassword = '/account/reset_password';
public $linkVerification = '/account/verification';
public $linkTotp = '/account/twofactor_verification';
public $linkResetPassword = '/account/reset_password/index';
public $linkVerification = '/account/verification/index';
public $linkTotp = '/account/twofactor_verification/index';
/*
|--------------------------------------------------------------------------

6
application/Controllers/Account/Login.php

@ -43,11 +43,11 @@ class Login extends Controller
/**
* Index
*
* @return redirect
* @return void
*/
public function index()
{
if ($input = $this->request->getVar())
if ($input = $this->request->getPost())
{
$identifier = ($this->config->loginUseUsername ? $input['username'] : $input['email']);
@ -57,7 +57,7 @@ class Login extends Controller
}
else
{
return redirect()->to('/account');
redirect()->to('/account');
}
}

4
application/Controllers/Account/Register.php

@ -48,7 +48,7 @@ class Register extends Controller
*/
public function index()
{
if ($input = $this->request->getVar())
if ($input = $this->request->getPost())
{
if (! $this->aauth->createUser($input['email'], $input['password'], $input['username']))
{
@ -56,7 +56,7 @@ class Register extends Controller
}
else
{
$data['info'] = $this->aauth->printInfos('<br />', true);
$data['infos'] = $this->aauth->printInfos('<br />', true);
}
}

71
application/Controllers/Account/Remind_password.php

@ -0,0 +1,71 @@
<?php
/**
* CodeIgniter-Aauth
*
* Aauth is a User Authorization Library for CodeIgniter 4.x, which aims to make
* easy some essential jobs such as login, permissions and access operations.
* Despite ease of use, it has also very advanced features like groupping,
* access management, public access etc..
*
* @package CodeIgniter-Aauth
* @author Magefly Team
* @copyright 2014-2017 Emre Akay
* @copyright 2018 Magefly
* @license https://opensource.org/licenses/MIT MIT License
* @link https://github.com/magefly/CodeIgniter-Aauth
*/
namespace App\Controllers\Account;
use CodeIgniter\Controller;
use Config\Aauth as AauthConfig;
use App\Libraries\Aauth;
use App\Models\Aauth\UserVariableModel as UserVariableModel;
use Config\Services;
/**
* Aauth Accont/Remind_password Controller
*
* @package CodeIgniter-Aauth
*/
class Remind_password extends Controller
{
/**
* Constructor
*/
public function __construct()
{
$this->config = new AauthConfig();
$this->aauth = new Aauth();
$this->request = Services::request();
helper('form');
}
/**
* Index
*
* @return void
*/
public function index()
{
if ($input = $this->request->getPost())
{
if (! $this->aauth->remindPassword($input['email']))
{
$data['errors'] = $this->aauth->printErrors('<br />', true);
}
else
{
$data['infos'] = $this->aauth->printInfos('<br />', true);
}
}
$data['cssFiles'] = [
'/assets/css/login.css'
];
echo view('Templates/HeaderBlank', $data);
echo view('Account/RemindPassword', $data);
echo view('Templates/FooterBlank', $data);
}
}

74
application/Controllers/Account/Reset_password.php

@ -0,0 +1,74 @@
<?php
/**
* CodeIgniter-Aauth
*
* Aauth is a User Authorization Library for CodeIgniter 4.x, which aims to make
* easy some essential jobs such as login, permissions and access operations.
* Despite ease of use, it has also very advanced features like groupping,
* access management, public access etc..
*
* @package CodeIgniter-Aauth
* @author Magefly Team
* @copyright 2014-2017 Emre Akay
* @copyright 2018 Magefly
* @license https://opensource.org/licenses/MIT MIT License
* @link https://github.com/magefly/CodeIgniter-Aauth
*/
namespace App\Controllers\Account;
use CodeIgniter\Controller;
use Config\Aauth as AauthConfig;
use App\Libraries\Aauth;
use App\Models\Aauth\UserVariableModel as UserVariableModel;
use Config\Services;
/**
* Aauth Accont/Reset_password Controller
*
* @package CodeIgniter-Aauth
*/
class Reset_password extends Controller
{
/**
* Constructor
*/
public function __construct()
{
$this->config = new AauthConfig();
$this->aauth = new Aauth();
$this->request = Services::request();
helper('form');
}
/**
* Index
*
* @param string $verificationCode Verification Code
*
* @return void
*/
public function index(string $verificationCode = '')
{
if ($input = $this->request->getPost())
{
if (! $this->aauth->resetPassword($input['verification_code']))
{
$data['errors'] = $this->aauth->printErrors('<br />', true);
}
else
{
$data['infos'] = $this->aauth->printInfos('<br />', true);
}
}
$data['verificationCode'] = $verificationCode;
$data['cssFiles'] = [
'/assets/css/login.css'
];
echo view('Templates/HeaderBlank', $data);
echo view('Account/ResetPassword', $data);
echo view('Templates/FooterBlank', $data);
}
}

4
application/Language/de/Aauth.php

@ -34,7 +34,9 @@ return [
'textResetSuccess' => 'Du hast dein Passwort erfolgreich zurückgesetzt. Dein neues Passwort lautet: {password}',
'infoCreateSuccess' => 'Dein Benutzerkonto wurde erfolgreich erstellt. Du kannst dich jetzt einloggen.',
'infoCreateVerification' => 'Dein Benutzerkonto wurde erfolgreich erstellt. Eine E-Mail mit Informationen zur Bestätigung wurde versendet. ',
'infoCreateVerification' => 'Dein Benutzerkonto wurde erfolgreich erstellt. Eine E-Mail mit Informationen zur Bestätigung wurde an deine E-Mail-Adresse versendet. ',
'infoRemindSuccess' => 'Eine E-Mail mit Informationen zum zurückzusetzen wurde an deine E-Mail-Adresse versendet.',
'infoResetSuccess' => 'Eine E-Mail mit deinem neuem Passwort wurde an deine E-Mail-Adresse versendet.',
'noAccess' => 'Entschuldige, aber du hast kein Zugriffsrecht auf die angeforderte Seite.',
'notVerified' => 'Dein Account wurde bisher nicht bestätigt. Bitte prüfe deine E-Mails und bestätige deine Registrierung.',

2
application/Language/en/Aauth.php

@ -35,6 +35,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => 'Sorry, you do not have access to the resource you requested.',
'notVerified' => 'Your account has not been verified. Please check your email and verify your account.',

57
application/Language/en/Account.php

@ -0,0 +1,57 @@
<?php
/**
* CodeIgniter-Aauth
*
* Aauth is a User Authorization Library for CodeIgniter 4.x, which aims to make
* easy some essential jobs such as login, permissions and access operations.
* Despite ease of use, it has also very advanced features like groupping,
* access management, public access etc..
*
* @package CodeIgniter-Aauth
* @author Magefly Team
* @copyright 2014-2017 Emre Akay
* @copyright 2018 Magefly
* @license https://opensource.org/licenses/MIT MIT License
* @link https://github.com/magefly/CodeIgniter-Aauth
*/
/**
* Account language strings.
*
* Language English
*
* @package CodeIgniter-Aauth
*
* @codeCoverageIgnore
*/
return [
'linkBackToLogin' => 'Back to Login',
'linkLogin' => 'Login',
'linkRegister' => 'Register new Account',
'linkRemindPassword' => 'Forgot Password?',
'loginHeader' => 'Login',
'loginLabelUsername' => 'Username',
'loginLabelEmail' => 'Email address',
'loginLabelPassword' => 'Password',
'loginLabelRemember' => 'Remember me',
'loginLabelSubmit' => 'Login',
'registerHeader' => 'Create new Account',
'registerLabelUsername' => 'Username',
'registerLabelEmail' => 'Email address',
'registerLabelPassword' => 'Password',
'registerLabelRemember' => 'Remember me',
'registerLabelSubmit' => 'Create Account',
'registerRequired' => 'Required',
'remindPasswordHeader' => 'Remind Password',
'remindPasswordText' => 'Forgot your password? <br />You can reset your password here.',
'remindPasswordLabelEmail' => 'Email address',
'remindPasswordLabelSubmit' => 'Send reset instructions',
'resetPasswordHeader' => 'Reset Password',
'resetPasswordText' => 'You are only one step away from your new password.',
'resetPasswordLabelVerificationCode' => 'Verification Code',
'resetPasswordLabelSubmit' => 'Send new password',
];

2
application/Language/es/Aauth.php

@ -35,6 +35,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => 'Ups, lo siento, no tienes permiso para ver el recurso solicitado.',
'notVerified' => 'Tu cuenta aún no ha sido verificada, por favor revisa tu correo electrónico y verifica tu cuenta.',

2
application/Language/fa/Aauth.php

@ -35,6 +35,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => 'متاسفانه شما به منبع درخواست شده دسترسی ندارید.',
'notVerified' => 'حساب کاربری شما تایید نشده است. لطفا ایمیل خود را برای تایید حسا کاربری بررسی کنید.',

2
application/Language/fr/Aauth.php

@ -35,6 +35,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => 'Désolé, vous n\'avez pas accès à cette ressource.',
'notVerified' => 'Votre compte n\'a pas été confirmé. Merci de vérifier vos email et de confirmer votre compte.',

2
application/Language/id/Aauth.php

@ -35,6 +35,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => 'Maaf, Anda tidak memiliki akses ke sumber daya yang Anda minta.',
'notVerified' => 'Akun anda belum diverifikasi. Silakan cek email anda dan verifikasi akun anda.',

2
application/Language/ru/Aauth.php

@ -35,6 +35,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => 'Извините, у вас нет доступа к запрашиваемому ресурсу.',
'notVerified' => 'Ваш акккаунт не подтвержден. Проверьте ваш ящик e-mail и подтвердите аккаунт.',

2
application/Language/sv/Aauth.php

@ -35,6 +35,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => 'Du har tyvärr inte rättighet att visa den här resursen.',
'notVerified' => 'Ditt konto är inte bekräftat. Var vänlig kolla din e-post och bekräfta ditt konto.',

2
application/Language/zh-CN/Aauth.php

@ -37,6 +37,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => '对不起,您无法存取您需要的资源。',
'notVerified' => '您的帐户尚未验证,请检查信箱并验证帐户。',

2
application/Language/zh-TW/Aauth.php

@ -37,6 +37,8 @@ return [
'infoCreateSuccess' => 'Your account has successfully been created. You can now login.',
'infoCreateVerification' => 'Your account has successfully been created. A email has been sent to your email address with verification details..',
'infoRemindSuccess' => 'A email has been sent to your email address with reset instructions.',
'infoResetSuccess' => 'A email has been sent to your email address with your new password has been sent.',
'noAccess' => '對不起,您無法存取您需要的資源。',
'notVerified' => '您的帳號尚未驗證,請檢查信箱並驗證帳號。',

43
application/Libraries/Aauth.php

@ -273,7 +273,7 @@ class Aauth
$userVariableModel->save($userId, 'verification_code', $verificationCode, true);
$messageData['code'] = $verificationCode;
$messageData['link'] = site_url($this->config->linkVerification . '/' . $userId . '/' . $verificationCode);
$messageData['link'] = site_url($this->config->linkVerification . '/' . $verificationCode);
$emailService->initialize(isset($this->config->emailConfig) ? $this->config->emailConfig : []);
$emailService->setFrom($this->config->emailFrom, $this->config->emailFromName);
@ -455,21 +455,33 @@ class Aauth
$userVariableModel = new UserVariableModel();
$emailService = \Config\Services::email();
$resetCode = sha1(strtotime('now'));
$userVariableModel->save($user->id, 'verification_code', $resetCode, true);
$userVariableModel->save($user['id'], 'verification_code', $resetCode, true);
$messageData['code'] = $resetCode;
$messageData['link'] = site_url($this->config->linkResetPassword . '/' . $user->id . '/' . $resetCode);
$messageData['link'] = site_url($this->config->linkResetPassword . '/' . $resetCode);
$emailService->initialize(isset($this->config->emailConfig) ? $this->config->emailConfig : []);
$emailService->setFrom($this->config->emailFrom, $this->config->emailFromName);
$emailService->setTo($user->email);
$emailService->setTo($user['email']);
$emailService->setSubject(lang('Aauth.subjectReset'));
$emailService->setMessage(view('Aauth/Reset', $messageData));
$emailService->setMessage(view('Aauth/RemindPassword', $messageData));
return $emailService->send();
if ($email = $emailService->send())
{
$this->info(lang('Aauth.infoRemindSuccess'));
return $email;
}
else
{
$this->error(explode('<br />', $emailService->printDebugger([])));
return false;
}
}
$this->error(lang('Aauth.notFoundUser'));
return false;
}
/**
@ -517,9 +529,20 @@ class Aauth
$emailService->setFrom($this->config->emailFrom, $this->config->emailFromName);
$emailService->setTo($user['email']);
$emailService->setSubject(lang('Aauth.subjectResetSuccess'));
$emailService->setMessage(view('Aauth/ResetSuccess', $messageData));
$emailService->setMessage(view('Aauth/ResetPassword', $messageData));
return true;
if ($email = $emailService->send())
{
$this->info(lang('Aauth.infoResetSuccess'));
return $email;
}
else
{
$this->error(explode('<br />', $emailService->printDebugger([])));
return false;
}
}
}
@ -697,8 +720,8 @@ class Aauth
$tokenData['selector_hash'] = password_hash($selectorString, PASSWORD_DEFAULT);
$tokenData['expires_at'] = date('Y-m-d H:i:s', strtotime($expire));
$loginTokenModel->insert($tokenData);
set_cookie($cookieData);
$loginTokenModel->insert($tokenData);
}
$userModel->updateLastLogin($user['id']);

1
application/Models/Aauth/LoginTokenModel.php

@ -19,6 +19,7 @@ namespace App\Models\Aauth;
use Config\Aauth as AauthConfig;
use Config\Database;
use Config\Services;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\BaseConnection;
use CodeIgniter\Database\ConnectionInterface;

0
application/Views/Aauth/Reset.php → application/Views/Aauth/RemindPassword.php

0
application/Views/Aauth/ResetSuccess.php → application/Views/Aauth/ResetPassword.php

14
application/Views/Account/Login.php

@ -1,6 +1,6 @@
<div class="container">
<div class="card card-login mx-auto mt-5">
<div class="card-header"><?=lang('Account.loginText')?></div>
<div class="card-header"><?=lang('Account.loginHeader')?></div>
<div class="card-body">
<form method="POST">
<?if (isset($errors)):?>
@ -33,9 +33,15 @@
</div>
<button class="btn btn-primary btn-block" type="submit"><?=lang('Account.loginLabelSubmit')?></button>
</form>
<div class="text-center">
<a class="d-block small mt-3" href="<?=site_url('account/register')?>"><?=lang('Account.loginLinkRegister')?></a>
<a class="d-block small" href="<?=site_url('account/forgot_password')?>"><?=lang('Account.loginLinkForgotPassword')?></a>
</div>
<div class="card-footer">
<div class="row">
<div class="col-6">
<a class="d-block small" href="<?=site_url('account/remind_password')?>"><?=lang('Account.linkRemindPassword')?></a>
</div>
<div class="col-6 text-right">
<a class="d-block small" href="<?=site_url('account/register')?>"><?=lang('Account.linkRegister')?></a>
</div>
</div>
</div>
</div>

18
application/Views/Account/Register.php

@ -1,6 +1,6 @@
<div class="container">
<div class="card card-register mx-auto mt-5">
<div class="card-header"><?=lang('Account.registerText')?></div>
<div class="card-header"><?=lang('Account.registerHeader')?></div>
<div class="card-body">
<form method="POST">
<?if (isset($errors)):?>
@ -27,14 +27,18 @@
<label for="inputPassword"><?=lang('Account.registerLabelPassword')?>*</label>
</div>
</div>
<div class="form-group">
<p>* <?=lang('Account.registerRequired')?></p>
</div>
<p class="small">* <?=lang('Account.registerRequired')?></p>
<button class="btn btn-primary btn-block" type="submit"><?=lang('Account.registerLabelSubmit')?></button>
</form>
<div class="text-center">
<a class="d-block small mt-3" href="<?=site_url('account/login')?>"><?=lang('Account.registerLinkLogin')?></a>
<a class="d-block small" href="<?=site_url('account/forgot_password')?>"><?=lang('Account.registerLinkForgotPassword')?></a>
</div>
<div class="card-footer">
<div class="row">
<div class="col-6">
<a class="d-block small" href="<?=site_url('account/login')?>"><?=lang('Account.linkBackToLogin')?></a>
</div>
<div class="col-6 text-right">
<a class="d-block small" href="<?=site_url('account/remind_password')?>"><?=lang('Account.linkRemindPassword')?></a>
</div>
</div>
</div>
</div>

33
application/Views/Account/RemindPassword.php

@ -0,0 +1,33 @@
<div class="container">
<div class="card card-login mx-auto mt-5">
<div class="card-header"><?=lang('Account.remindPasswordHeader')?></div>
<div class="card-body">
<form method="POST">
<p><?=lang('Account.remindPasswordText')?></p>
<?if (isset($errors)):?>
<div class="alert alert-danger"><?=$errors?></div>
<?endif;?>
<?if (isset($infos)):?>
<div class="alert alert-info"><?=$infos?></div>
<?endif;?>
<div class="form-group">
<div class="form-label-group">
<input type="email" name="email" id="inputEmail" class="form-control" placeholder="<?=lang('Account.remindPasswordLabelEmail')?>" required autofocus>
<label for="inputEmail"><?=lang('Account.remindPasswordLabelEmail')?></label>
</div>
</div>
<button class="btn btn-primary btn-block" type="submit"><?=lang('Account.remindPasswordLabelSubmit')?></button>
</form>
</div>
<div class="card-footer">
<div class="row">
<div class="col-6">
<a class="d-block small" href="<?=site_url('account/login')?>"><?=lang('Account.linkBackToLogin')?></a>
</div>
<div class="col-6 text-right">
<a class="d-block small" href="<?=site_url('account/register')?>"><?=lang('Account.linkRegister')?></a>
</div>
</div>
</div>
</div>
</div>

33
application/Views/Account/ResetPassword.php

@ -0,0 +1,33 @@
<div class="container">
<div class="card card-login mx-auto mt-5">
<div class="card-header"><?=lang('Account.resetPasswordHeader')?></div>
<div class="card-body">
<form method="POST">
<p><?=lang('Account.resetPasswordText')?></p>
<?if (isset($errors)):?>
<div class="alert alert-danger"><?=$errors?></div>
<?endif;?>
<?if (isset($infos)):?>
<div class="alert alert-info"><?=$infos?></div>
<?endif;?>
<div class="form-group">
<div class="form-label-group">
<input type="test" name="verification_code" id="inputVerificationCode" class="form-control" placeholder="<?=lang('Account.resetPasswordLabelVerificationCode')?>" value="<?=$verificationCode?>" required autofocus>
<label for="inputVerificationCode"><?=lang('Account.resetPasswordLabelVerificationCode')?></label>
</div>
</div>
<button class="btn btn-primary btn-block" type="submit"><?=lang('Account.resetPasswordLabelSubmit')?></button>
</form>
</div>
<div class="card-footer">
<div class="row">
<div class="col-6">
<a class="d-block small" href="<?=site_url('account/login')?>"><?=lang('Account.linkBackToLogin')?></a>
</div>
<div class="col-6 text-right">
<a class="d-block small" href="<?=site_url('account/register')?>"><?=lang('Account.linkRegister')?></a>
</div>
</div>
</div>
</div>
</div>
Loading…
Cancel
Save