Refactor: merge SettingsController into ProfileController

Removed SettingsController and moved its logic into ProfileController, consolidating user profile, account, GDPR, network, and two-factor authentication actions. Updated routes, behaviors, and view files to reflect the new structure. Also updated composer.json to use pcrt/yii2-usuario and pcrt/yii2-select2, added 'surname' to Profile model, and added new attributes to User model. Improved user feedback by redirecting after key actions instead of rendering message views.
This commit is contained in:
2025-10-15 09:16:32 +02:00
parent 2a95a8d4d2
commit eba9671e1b
49 changed files with 1555 additions and 1690 deletions

View File

@ -1,5 +1,5 @@
{ {
"name": "2amigos/yii2-usuario", "name": "pcrt/yii2-usuario",
"description": "Highly customizable and extensible user management, authentication, and authorization Yii2 extension", "description": "Highly customizable and extensible user management, authentication, and authorization Yii2 extension",
"type": "yii2-extension", "type": "yii2-extension",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@ -41,7 +41,7 @@
"prefer-stable": true, "prefer-stable": true,
"require": { "require": {
"php": ">=5.5", "php": ">=5.5",
"2amigos/yii2-selectize-widget": "^1.1", "pcrt/yii2-select2": "^1.0.6",
"yiisoft/yii2-authclient": "^2.1", "yiisoft/yii2-authclient": "^2.1",
"yiisoft/yii2-httpclient": "^2.0", "yiisoft/yii2-httpclient": "^2.0",
"yiisoft/yii2-bootstrap": "^2.0", "yiisoft/yii2-bootstrap": "^2.0",

View File

@ -144,6 +144,8 @@ class AdminController extends Controller
$this->make(AjaxRequestModelValidator::class, [$user])->validate(); $this->make(AjaxRequestModelValidator::class, [$user])->validate();
if ($user->load(Yii::$app->request->post()) && $user->validate()) { if ($user->load(Yii::$app->request->post()) && $user->validate()) {
$user->created_by = Yii::$app->user->getId() ?? null;
$this->trigger(UserEvent::EVENT_BEFORE_CREATE, $event); $this->trigger(UserEvent::EVENT_BEFORE_CREATE, $event);
$mailService = MailFactory::makeWelcomeMailerService($user); $mailService = MailFactory::makeWelcomeMailerService($user);

View File

@ -11,18 +11,47 @@
namespace Da\User\Controller; namespace Da\User\Controller;
use Da\User\Contracts\MailChangeStrategyInterface;
use Da\User\Event\GdprEvent;
use Da\User\Event\ProfileEvent;
use Da\User\Event\SocialNetworkConnectEvent;
use Da\User\Event\UserEvent;
use Da\User\Form\GdprDeleteForm;
use Da\User\Form\SettingsForm;
use Da\User\Helper\SecurityHelper;
use Da\User\Model\Profile;
use Da\User\Model\SocialNetworkAccount;
use Da\User\Model\User; use Da\User\Model\User;
use Da\User\Module;
use Da\User\Query\ProfileQuery; use Da\User\Query\ProfileQuery;
use Da\User\Query\SocialNetworkAccountQuery;
use Da\User\Query\UserQuery;
use Da\User\Search\SessionHistorySearch;
use Da\User\Service\EmailChangeService;
use Da\User\Service\SessionHistory\TerminateUserSessionsService;
use Da\User\Service\TwoFactorEmailCodeGeneratorService;
use Da\User\Service\TwoFactorQrCodeUriGeneratorService;
use Da\User\Service\TwoFactorSmsCodeGeneratorService;
use Da\User\Traits\ContainerAwareTrait;
use Da\User\Traits\ModuleAwareTrait; use Da\User\Traits\ModuleAwareTrait;
use Da\User\Validator\AjaxRequestModelValidator;
use Da\User\Validator\TwoFactorCodeValidator;
use Da\User\Validator\TwoFactorEmailValidator;
use Da\User\Validator\TwoFactorTextMessageValidator;
use Yii; use Yii;
use yii\base\Module; use yii\base\DynamicModel;
use yii\base\InvalidParamException;
use yii\filters\AccessControl; use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\helpers\ArrayHelper;
use yii\web\Controller; use yii\web\Controller;
use yii\web\ForbiddenHttpException; use yii\web\ForbiddenHttpException;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\web\Response;
class ProfileController extends Controller class ProfileController extends Controller
{ {
use ContainerAwareTrait;
use ModuleAwareTrait; use ModuleAwareTrait;
/** @var int will allow only profile owner */ /** @var int will allow only profile owner */
@ -34,19 +63,36 @@ class ProfileController extends Controller
/** @var int will allow anyone, including guests */ /** @var int will allow anyone, including guests */
public const PROFILE_VISIBILITY_PUBLIC = 3; public const PROFILE_VISIBILITY_PUBLIC = 3;
/**
* {@inheritdoc}
*/
public $defaultAction = 'profile';
protected $profileQuery; protected $profileQuery;
protected $userQuery;
protected $socialNetworkAccountQuery;
/** /**
* ProfileController constructor. * SettingsController constructor.
* *
* @param string $id * @param string $id
* @param Module $module * @param Module $module
* @param ProfileQuery $profileQuery * @param ProfileQuery $profileQuery
* @param UserQuery $userQuery
* @param SocialNetworkAccountQuery $socialNetworkAccountQuery
* @param array $config * @param array $config
*/ */
public function __construct($id, Module $module, ProfileQuery $profileQuery, array $config = []) public function __construct(
{ $id,
Module $module,
ProfileQuery $profileQuery,
UserQuery $userQuery,
SocialNetworkAccountQuery $socialNetworkAccountQuery,
array $config = []
) {
$this->profileQuery = $profileQuery; $this->profileQuery = $profileQuery;
$this->userQuery = $userQuery;
$this->socialNetworkAccountQuery = $socialNetworkAccountQuery;
parent::__construct($id, $module, $config); parent::__construct($id, $module, $config);
} }
@ -56,71 +102,559 @@ class ProfileController extends Controller
public function behaviors() public function behaviors()
{ {
return [ return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'disconnect' => ['post'],
'delete' => ['post'],
'two-factor-disable' => ['post'],
'terminate-sessions' => ['post'],
],
],
'access' => [ 'access' => [
'class' => AccessControl::class, 'class' => AccessControl::class,
'rules' => [ 'rules' => [
[ [
'allow' => true, 'allow' => true,
'actions' => ['index'], 'actions' => [
'profile',
'account',
'export',
'networks',
'privacy',
'gdpr-consent',
'gdpr-delete',
'disconnect',
'delete',
'two-factor',
'two-factor-enable',
'two-factor-disable',
'two-factor-mobile-phone'
],
'roles' => ['@'], 'roles' => ['@'],
], ],
[ [
'allow' => true, 'allow' => true,
'actions' => ['show'], 'actions' => ['confirm'],
'roles' => ['?', '@'], 'roles' => ['?', '@'],
], ],
[
'allow' => $this->getModule()->enableSessionHistory,
'actions' => ['session-history', 'terminate-sessions'],
'roles' => ['@'],
],
], ],
], ],
]; ];
} }
public function actionIndex() /**
* @throws \yii\base\InvalidConfigException
* @return string|Response
*/
public function actionProfile()
{ {
return $this->redirect(['show', 'id' => Yii::$app->user->getId()]); $profile = $this->profileQuery->whereUserId(Yii::$app->user->identity->getId())->one();
}
public function actionShow($id)
{
$user = Yii::$app->user;
$id = (int) $id;
/** @var ?User $identity */
$identity = $user->getIdentity();
switch($this->module->profileVisibility) {
case static::PROFILE_VISIBILITY_OWNER:
if($identity === null || $id !== $user->getId()) {
throw new ForbiddenHttpException();
}
break;
case static::PROFILE_VISIBILITY_ADMIN:
if($id === $user->getId() || ($identity !== null && $identity->getIsAdmin())) {
break;
}
throw new ForbiddenHttpException();
case static::PROFILE_VISIBILITY_USERS:
if((!$user->getIsGuest())) {
break;
}
throw new ForbiddenHttpException();
case static::PROFILE_VISIBILITY_PUBLIC:
break;
default:
throw new ForbiddenHttpException();
}
$profile = $this->profileQuery->whereUserId($id)->one();
if ($profile === null) { if ($profile === null) {
throw new NotFoundHttpException(); $profile = $this->make(Profile::class);
$profile->link('user', Yii::$app->user->identity);
} }
/**
*
*
* @var ProfileEvent $event
*/
$event = $this->make(ProfileEvent::class, [$profile]);
$this->make(AjaxRequestModelValidator::class, [$profile])->validate();
if ($profile->load(Yii::$app->request->post())) {
$this->trigger(UserEvent::EVENT_BEFORE_PROFILE_UPDATE, $event);
if ($profile->save()) {
Yii::$app->getSession()->setFlash('success', Yii::t('usuario', 'Your profile has been updated'));
$this->trigger(UserEvent::EVENT_AFTER_PROFILE_UPDATE, $event);
return $this->refresh();
}
}
Yii::debug(get_class(Yii::$app->session));
return $this->render( return $this->render(
'show', 'profile',
[ [
'profile' => $profile, 'model' => $profile,
] ]
); );
} }
/**
* @throws NotFoundHttpException
* @return string
*/
public function actionPrivacy()
{
if (!$this->module->enableGdprCompliance) {
throw new NotFoundHttpException();
}
return $this->render(
'privacy',
[
'module' => $this->module
]
);
}
/**
* @throws NotFoundHttpException
* @throws \Throwable
* @throws \yii\base\Exception
* @throws \yii\base\InvalidConfigException
* @throws \yii\db\StaleObjectException
* @throws ForbiddenHttpException
* @return string|Response
*/
public function actionGdprDelete()
{
if (!$this->module->enableGdprCompliance) {
throw new NotFoundHttpException();
}
/**
*
*
* @var GdprDeleteForm $form
*/
$form = $this->make(GdprDeleteForm::class);
$user = $form->getUser();
/* @var $event GdprEvent */
$event = $this->make(GdprEvent::class, [$user]);
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
$this->trigger(GdprEvent::EVENT_BEFORE_DELETE, $event);
if ($event->isValid) {
Yii::$app->user->logout();
//Disconnect social networks
$networks = $this->socialNetworkAccountQuery->where(['user_id' => $user->id])->all();
foreach ($networks as $network) {
$this->disconnectSocialNetwork($network->id);
}
/* @var $security SecurityHelper */
$security = $this->make(SecurityHelper::class);
$anonymReplacement = $this->module->gdprAnonymizePrefix . $user->id;
$user->updateAttributes(
[
'email' => $anonymReplacement . "@example.com",
'username' => $anonymReplacement,
'gdpr_deleted' => 1,
'blocked_at' => time(),
'auth_key' => $security->generateRandomString()
]
);
$user->profile->updateAttributes(
[
'public_email' => $anonymReplacement . "@example.com",
'name' => $anonymReplacement,
'surname' => $anonymReplacement,
'gravatar_email' => $anonymReplacement . "@example.com",
'location' => $anonymReplacement,
'website' => $anonymReplacement . ".tld",
'bio' => Yii::t('usuario', 'Deleted by GDPR request')
]
);
}
$this->trigger(GdprEvent::EVENT_AFTER_DELETE, $event);
Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your personal information has been removed'));
return $this->goHome();
}
return $this->render(
'gdpr-delete',
[
'model' => $form,
]
);
}
public function actionGdprConsent()
{
/**
*
*
* @var User $user
*/
$user = Yii::$app->user->identity;
if ($user->gdpr_consent) {
return $this->redirect(['profile']);
}
$model = new DynamicModel(['gdpr_consent']);
$model->addRule('gdpr_consent', 'boolean');
$model->addRule('gdpr_consent', 'default', ['value' => 0, 'skipOnEmpty' => false]);
$model->addRule(
'gdpr_consent',
'compare',
[
'compareValue' => true,
'message' => Yii::t('usuario', 'Your consent is required to work with this site'),
'when' => function () {
return $this->module->enableGdprCompliance;
},
]
);
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$user->updateAttributes(
[
'gdpr_consent' => 1,
'gdpr_consent_date' => time(),
]
);
return $this->redirect(['profile']);
}
return $this->render(
'gdpr-consent',
[
'model' => $model,
'gdpr_consent_hint' => $this->module->getConsentMessage(),
]
);
}
/**
* Exports the data from the current user in a mechanical readable format (csv). Properties exported can be defined
* in the module configuration.
*
* @throws NotFoundHttpException if gdpr compliance is not enabled
* @throws \Exception
* @throws \Throwable
*/
public function actionExport()
{
if (!$this->module->enableGdprCompliance) {
throw new NotFoundHttpException();
}
try {
$properties = $this->module->gdprExportProperties;
$user = Yii::$app->user->identity;
$data = [$properties, []];
$formatter = Yii::$app->formatter;
// override the default html-specific format for nulls
$formatter->nullDisplay = "";
foreach ($properties as $property) {
$data[1][] = $formatter->asText(ArrayHelper::getValue($user, $property));
}
array_walk($data[0], function (&$value, $key) {
$splitted = explode('.', $value);
$value = array_pop($splitted);
});
Yii::$app->response->headers->removeAll();
Yii::$app->response->headers->add('Content-type', 'text/csv');
Yii::$app->response->headers->add('Content-Disposition', 'attachment;filename=gdpr-data.csv');
Yii::$app->response->send();
$f = fopen('php://output', 'w');
foreach ($data as $line) {
fputcsv($f, $line);
}
} catch (\Exception $e) {
throw $e;
} catch (\Throwable $e) {
throw $e;
}
}
public function actionAccount()
{
/**
*
*
* @var SettingsForm $form
*/
$form = $this->make(SettingsForm::class);
$event = $this->make(UserEvent::class, [$form->getUser()]);
$this->make(AjaxRequestModelValidator::class, [$form])->validate();
if ($form->load(Yii::$app->request->post())) {
$this->trigger(UserEvent::EVENT_BEFORE_ACCOUNT_UPDATE, $event);
if ($form->save()) {
Yii::$app->getSession()->setFlash(
'success',
Yii::t('usuario', 'Your account details have been updated')
);
$this->trigger(UserEvent::EVENT_AFTER_ACCOUNT_UPDATE, $event);
return $this->refresh();
}
}
return $this->render(
'account',
[
'model' => $form,
]
);
}
public function actionConfirm($id, $code)
{
$user = $this->userQuery->whereId($id)->one();
if ($user === null || MailChangeStrategyInterface::TYPE_INSECURE === $this->module->emailChangeStrategy) {
throw new NotFoundHttpException();
}
$event = $this->make(UserEvent::class, [$user]);
$this->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION, $event);
if ($this->make(EmailChangeService::class, [$code, $user])->run()) {
$this->trigger(UserEvent::EVENT_AFTER_CONFIRMATION, $event);
}
return $this->redirect(['account']);
}
public function actionNetworks()
{
return $this->render(
'networks',
[
'user' => Yii::$app->user->identity,
]
);
}
public function actionDisconnect($id)
{
$this->disconnectSocialNetwork($id);
return $this->redirect(['networks']);
}
public function actionDelete()
{
if (!$this->module->allowAccountDelete) {
throw new NotFoundHttpException(Yii::t('usuario', 'Not found'));
}
/**
*
*
* @var User $user
*/
$user = Yii::$app->user->identity;
$event = $this->make(UserEvent::class, [$user]);
Yii::$app->user->logout();
$this->trigger(UserEvent::EVENT_BEFORE_DELETE, $event);
$user->delete();
$this->trigger(UserEvent::EVENT_AFTER_DELETE, $event);
Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your account has been completely deleted'));
return $this->goHome();
}
public function actionTwoFactor($id)
{
if (!$this->module->enableTwoFactorAuthentication) {
throw new ForbiddenHttpException(Yii::t('usuario', 'Application not configured for two factor authentication.'));
}
if ($id != Yii::$app->user->id) {
throw new ForbiddenHttpException();
}
$choice = Yii::$app->request->post('choice');
/** @var User $user */
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
throw new NotFoundHttpException();
}
switch ($choice) {
case 'google-authenticator':
$uri = $this->make(TwoFactorQrCodeUriGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor', ['id' => $id, 'uri' => $uri, 'user' => $user]);
case 'email':
$emailCode = $this->make(TwoFactorEmailCodeGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor-email', ['id' => $id, 'code' => $emailCode]);
case 'sms':
// get mobile phone, if exists
$mobilePhone = $user->getAuthTfMobilePhone();
$smsCode = $this->make(TwoFactorSmsCodeGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor-sms', ['id' => $id, 'code' => $smsCode, 'mobilePhone' => $mobilePhone]);
default:
throw new InvalidParamException("Invalid 2FA choice");
}
}
public function actionTwoFactorEnable($id)
{
if (!$this->module->enableTwoFactorAuthentication) {
throw new ForbiddenHttpException(Yii::t('usuario', 'Application not configured for two factor authentication.'));
}
Yii::$app->response->format = Response::FORMAT_JSON;
/** @var User $user */
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
return [
'success' => false,
'message' => Yii::t('usuario', 'User not found.')
];
}
$code = Yii::$app->request->get('code');
$module = Yii::$app->getModule('user');
$validators = $module->twoFactorAuthenticationValidators;
$choice = Yii::$app->request->get('choice');
$codeDurationTime = ArrayHelper::getValue($validators, $choice.'.codeDurationTime', 300);
$class = ArrayHelper::getValue($validators, $choice.'.class');
$object = $this
->make($class, [$user, $code, $this->module->twoFactorAuthenticationCycles]);
$success = $object->validate();
$success = $success && $user->updateAttributes(['auth_tf_enabled' => '1','auth_tf_type' => $choice]);
$message = $success ? $object->getSuccessMessage() : $object->getUnsuccessMessage($codeDurationTime);
return [
'success' => $success,
'message' => $message
];
}
public function actionTwoFactorDisable($id)
{
if (!$this->module->enableTwoFactorAuthentication) {
throw new ForbiddenHttpException(Yii::t('usuario', 'Application not configured for two factor authentication.'));
}
if ($id != Yii::$app->user->id) {
throw new ForbiddenHttpException();
}
/**
* @var User $user
*/
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
throw new NotFoundHttpException();
}
if ($user->updateAttributes(['auth_tf_enabled' => '0', 'auth_tf_key' => null])) {
Yii::$app
->getSession()
->setFlash('success', Yii::t('usuario', 'Two factor authentication has been disabled.'));
} else {
Yii::$app
->getSession()
->setFlash('danger', Yii::t('usuario', 'Unable to disable Two factor authentication.'));
}
$this->redirect(['account']);
}
/**
* Display list session history.
*/
public function actionSessionHistory()
{
$searchModel = new SessionHistorySearch([
'user_id' => Yii::$app->user->id,
]);
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('session-history', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Terminate all session user
*/
public function actionTerminateSessions()
{
$this->make(TerminateUserSessionsService::class, [Yii::$app->user->id])->run();
return $this->redirect(['session-history']);
}
public function actionTwoFactorMobilePhone($id)
{
Yii::$app->response->format = Response::FORMAT_JSON;
/**
*
*
* @var User $user
*/
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
return [
'success' => false,
'message' => Yii::t('usuario', 'User not found.')
];
}
$mobilePhone = Yii::$app->request->get('mobilephone');
$currentMobilePhone = $user->getAuthTfMobilePhone();
$success = false;
if ($currentMobilePhone == $mobilePhone) {
$success = true;
} else {
$success = $user->updateAttributes(['auth_tf_mobile_phone' => $mobilePhone]);
$success = $success && $this->make(TwoFactorSmsCodeGeneratorService::class, [$user])->run();
}
return [
'success' => $success,
'message' => $success
? Yii::t('usuario', 'Mobile phone number successfully enabled.')
: Yii::t('usuario', 'Error while enabling SMS two factor authentication. Please reload the page.'),
];
}
/**
* @param $id
* @throws ForbiddenHttpException
* @throws NotFoundHttpException
* @throws \Exception
* @throws \Throwable
* @throws \yii\db\StaleObjectException
*/
protected function disconnectSocialNetwork($id)
{
/**
*
*
* @var SocialNetworkAccount $account
*/
$account = $this->socialNetworkAccountQuery->whereId($id)->one();
if ($account === null) {
throw new NotFoundHttpException();
}
if ($account->user_id !== Yii::$app->user->id) {
throw new ForbiddenHttpException();
}
$event = $this->make(SocialNetworkConnectEvent::class, [Yii::$app->user->identity, $account]);
$this->trigger(SocialNetworkConnectEvent::EVENT_BEFORE_DISCONNECT, $event);
$account->delete();
$this->trigger(SocialNetworkConnectEvent::EVENT_AFTER_DISCONNECT, $event);
}
} }

View File

@ -109,13 +109,16 @@ class RecoveryController extends Controller
$this->trigger(FormEvent::EVENT_AFTER_REQUEST, $event); $this->trigger(FormEvent::EVENT_AFTER_REQUEST, $event);
} }
return $this->render( Yii::$app->session->setFlash('info', Yii::t('usuario', 'Recovery message sent'));
'/shared/message', return $this->redirect(['/user/login']);
[
'title' => Yii::t('usuario', 'Recovery message sent'), // return $this->render(
'module' => $this->module, // '/shared/message',
] // [
); // 'title' => Yii::t('usuario', 'Recovery message sent'),
// 'module' => $this->module,
// ]
// );
} }
return $this->render('request', ['model' => $form]); return $this->render('request', ['model' => $form]);
@ -151,13 +154,14 @@ class RecoveryController extends Controller
Yii::t('usuario', 'Recovery link is invalid or expired. Please try requesting a new one.') Yii::t('usuario', 'Recovery link is invalid or expired. Please try requesting a new one.')
); );
return $this->render( // return $this->render(
'/shared/message', // '/shared/message',
[ // [
'title' => Yii::t('usuario', 'Invalid or expired link'), // 'title' => Yii::t('usuario', 'Invalid or expired link'),
'module' => $this->module, // 'module' => $this->module,
] // ]
); // );
return $this->redirect(['/user/recovery/request']);
} }
/** @var RecoveryForm $form */ /** @var RecoveryForm $form */
@ -172,13 +176,15 @@ class RecoveryController extends Controller
Yii::$app->session->setFlash('success', Yii::t('usuario', 'Password has been changed')); Yii::$app->session->setFlash('success', Yii::t('usuario', 'Password has been changed'));
return $this->render( // return $this->render(
'/shared/message', // '/shared/message',
[ // [
'title' => Yii::t('usuario', 'Password has been changed'), // 'title' => Yii::t('usuario', 'Password has been changed'),
'module' => $this->module, // 'module' => $this->module,
] // ]
); // );
return $this->redirect(['/user/login']);
} }
} }

View File

@ -135,13 +135,7 @@ class RegistrationController extends Controller
Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your account has been created')); Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your account has been created'));
} }
$this->trigger(FormEvent::EVENT_AFTER_REGISTER, $event); $this->trigger(FormEvent::EVENT_AFTER_REGISTER, $event);
return $this->render( return $this->redirect(['/user/login']);
'/shared/message',
[
'title' => Yii::t('usuario', 'Your account has been created'),
'module' => $this->module,
]
);
} }
Yii::$app->session->setFlash('danger', Yii::t('usuario', 'User could not be registered.')); Yii::$app->session->setFlash('danger', Yii::t('usuario', 'User could not be registered.'));
} else { } else {
@ -234,13 +228,14 @@ class RegistrationController extends Controller
); );
} }
return $this->render( // return $this->render(
'/shared/message', // '/shared/message',
[ // [
'title' => Yii::t('usuario', 'Account confirmation'), // 'title' => Yii::t('usuario', 'Account confirmation'),
'module' => $this->module, // 'module' => $this->module,
] // ]
); // );
return $this->redirect(['/user/profile']);
} }
/** /**
@ -285,15 +280,17 @@ class RegistrationController extends Controller
); );
} }
return $this->render( return $this->redirect(['/user/login']);
'/shared/message',
[ // return $this->render(
'title' => $success // '/shared/message',
? Yii::t('usuario', 'A new confirmation link has been sent') // [
: Yii::t('usuario', 'Unable to send confirmation link'), // 'title' => $success
'module' => $this->module, // ? Yii::t('usuario', 'A new confirmation link has been sent')
] // : Yii::t('usuario', 'Unable to send confirmation link'),
); // 'module' => $this->module,
// ]
// );
} }
return $this->render( return $this->render(

View File

@ -1,648 +0,0 @@
<?php
/*
* This file is part of the 2amigos/yii2-usuario project.
*
* (c) 2amigOS! <http://2amigos.us/>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Da\User\Controller;
use Da\User\Contracts\MailChangeStrategyInterface;
use Da\User\Event\GdprEvent;
use Da\User\Event\ProfileEvent;
use Da\User\Event\SocialNetworkConnectEvent;
use Da\User\Event\UserEvent;
use Da\User\Form\GdprDeleteForm;
use Da\User\Form\SettingsForm;
use Da\User\Helper\SecurityHelper;
use Da\User\Model\Profile;
use Da\User\Model\SocialNetworkAccount;
use Da\User\Model\User;
use Da\User\Module;
use Da\User\Query\ProfileQuery;
use Da\User\Query\SocialNetworkAccountQuery;
use Da\User\Query\UserQuery;
use Da\User\Search\SessionHistorySearch;
use Da\User\Service\EmailChangeService;
use Da\User\Service\SessionHistory\TerminateUserSessionsService;
use Da\User\Service\TwoFactorEmailCodeGeneratorService;
use Da\User\Service\TwoFactorQrCodeUriGeneratorService;
use Da\User\Service\TwoFactorSmsCodeGeneratorService;
use Da\User\Traits\ContainerAwareTrait;
use Da\User\Traits\ModuleAwareTrait;
use Da\User\Validator\AjaxRequestModelValidator;
use Da\User\Validator\TwoFactorCodeValidator;
use Da\User\Validator\TwoFactorEmailValidator;
use Da\User\Validator\TwoFactorTextMessageValidator;
use Yii;
use yii\base\DynamicModel;
use yii\base\InvalidParamException;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\helpers\ArrayHelper;
use yii\web\Controller;
use yii\web\ForbiddenHttpException;
use yii\web\NotFoundHttpException;
use yii\web\Response;
class SettingsController extends Controller
{
use ContainerAwareTrait;
use ModuleAwareTrait;
/**
* {@inheritdoc}
*/
public $defaultAction = 'profile';
protected $profileQuery;
protected $userQuery;
protected $socialNetworkAccountQuery;
/**
* SettingsController constructor.
*
* @param string $id
* @param Module $module
* @param ProfileQuery $profileQuery
* @param UserQuery $userQuery
* @param SocialNetworkAccountQuery $socialNetworkAccountQuery
* @param array $config
*/
public function __construct(
$id,
Module $module,
ProfileQuery $profileQuery,
UserQuery $userQuery,
SocialNetworkAccountQuery $socialNetworkAccountQuery,
array $config = []
) {
$this->profileQuery = $profileQuery;
$this->userQuery = $userQuery;
$this->socialNetworkAccountQuery = $socialNetworkAccountQuery;
parent::__construct($id, $module, $config);
}
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'disconnect' => ['post'],
'delete' => ['post'],
'two-factor-disable' => ['post'],
'terminate-sessions' => ['post'],
],
],
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'actions' => [
'profile',
'account',
'export',
'networks',
'privacy',
'gdpr-consent',
'gdpr-delete',
'disconnect',
'delete',
'two-factor',
'two-factor-enable',
'two-factor-disable',
'two-factor-mobile-phone'
],
'roles' => ['@'],
],
[
'allow' => true,
'actions' => ['confirm'],
'roles' => ['?', '@'],
],
[
'allow' => $this->getModule()->enableSessionHistory,
'actions' => ['session-history', 'terminate-sessions'],
'roles' => ['@'],
],
],
],
];
}
/**
* @throws \yii\base\InvalidConfigException
* @return string|Response
*/
public function actionProfile()
{
$profile = $this->profileQuery->whereUserId(Yii::$app->user->identity->getId())->one();
if ($profile === null) {
$profile = $this->make(Profile::class);
$profile->link('user', Yii::$app->user->identity);
}
/**
*
*
* @var ProfileEvent $event
*/
$event = $this->make(ProfileEvent::class, [$profile]);
$this->make(AjaxRequestModelValidator::class, [$profile])->validate();
if ($profile->load(Yii::$app->request->post())) {
$this->trigger(UserEvent::EVENT_BEFORE_PROFILE_UPDATE, $event);
if ($profile->save()) {
Yii::$app->getSession()->setFlash('success', Yii::t('usuario', 'Your profile has been updated'));
$this->trigger(UserEvent::EVENT_AFTER_PROFILE_UPDATE, $event);
return $this->refresh();
}
}
return $this->render(
'profile',
[
'model' => $profile,
]
);
}
/**
* @throws NotFoundHttpException
* @return string
*/
public function actionPrivacy()
{
if (!$this->module->enableGdprCompliance) {
throw new NotFoundHttpException();
}
return $this->render(
'privacy',
[
'module' => $this->module
]
);
}
/**
* @throws NotFoundHttpException
* @throws \Throwable
* @throws \yii\base\Exception
* @throws \yii\base\InvalidConfigException
* @throws \yii\db\StaleObjectException
* @throws ForbiddenHttpException
* @return string|Response
*/
public function actionGdprDelete()
{
if (!$this->module->enableGdprCompliance) {
throw new NotFoundHttpException();
}
/**
*
*
* @var GdprDeleteForm $form
*/
$form = $this->make(GdprDeleteForm::class);
$user = $form->getUser();
/* @var $event GdprEvent */
$event = $this->make(GdprEvent::class, [$user]);
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
$this->trigger(GdprEvent::EVENT_BEFORE_DELETE, $event);
if ($event->isValid) {
Yii::$app->user->logout();
//Disconnect social networks
$networks = $this->socialNetworkAccountQuery->where(['user_id' => $user->id])->all();
foreach ($networks as $network) {
$this->disconnectSocialNetwork($network->id);
}
/* @var $security SecurityHelper */
$security = $this->make(SecurityHelper::class);
$anonymReplacement = $this->module->gdprAnonymizePrefix . $user->id;
$user->updateAttributes(
[
'email' => $anonymReplacement . "@example.com",
'username' => $anonymReplacement,
'gdpr_deleted' => 1,
'blocked_at' => time(),
'auth_key' => $security->generateRandomString()
]
);
$user->profile->updateAttributes(
[
'public_email' => $anonymReplacement . "@example.com",
'name' => $anonymReplacement,
'gravatar_email' => $anonymReplacement . "@example.com",
'location' => $anonymReplacement,
'website' => $anonymReplacement . ".tld",
'bio' => Yii::t('usuario', 'Deleted by GDPR request')
]
);
}
$this->trigger(GdprEvent::EVENT_AFTER_DELETE, $event);
Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your personal information has been removed'));
return $this->goHome();
}
return $this->render(
'gdpr-delete',
[
'model' => $form,
]
);
}
public function actionGdprConsent()
{
/**
*
*
* @var User $user
*/
$user = Yii::$app->user->identity;
if ($user->gdpr_consent) {
return $this->redirect(['profile']);
}
$model = new DynamicModel(['gdpr_consent']);
$model->addRule('gdpr_consent', 'boolean');
$model->addRule('gdpr_consent', 'default', ['value' => 0, 'skipOnEmpty' => false]);
$model->addRule(
'gdpr_consent',
'compare',
[
'compareValue' => true,
'message' => Yii::t('usuario', 'Your consent is required to work with this site'),
'when' => function () {
return $this->module->enableGdprCompliance;
},
]
);
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$user->updateAttributes(
[
'gdpr_consent' => 1,
'gdpr_consent_date' => time(),
]
);
return $this->redirect(['profile']);
}
return $this->render(
'gdpr-consent',
[
'model' => $model,
'gdpr_consent_hint' => $this->module->getConsentMessage(),
]
);
}
/**
* Exports the data from the current user in a mechanical readable format (csv). Properties exported can be defined
* in the module configuration.
*
* @throws NotFoundHttpException if gdpr compliance is not enabled
* @throws \Exception
* @throws \Throwable
*/
public function actionExport()
{
if (!$this->module->enableGdprCompliance) {
throw new NotFoundHttpException();
}
try {
$properties = $this->module->gdprExportProperties;
$user = Yii::$app->user->identity;
$data = [$properties, []];
$formatter = Yii::$app->formatter;
// override the default html-specific format for nulls
$formatter->nullDisplay = "";
foreach ($properties as $property) {
$data[1][] = $formatter->asText(ArrayHelper::getValue($user, $property));
}
array_walk($data[0], function (&$value, $key) {
$splitted = explode('.', $value);
$value = array_pop($splitted);
});
Yii::$app->response->headers->removeAll();
Yii::$app->response->headers->add('Content-type', 'text/csv');
Yii::$app->response->headers->add('Content-Disposition', 'attachment;filename=gdpr-data.csv');
Yii::$app->response->send();
$f = fopen('php://output', 'w');
foreach ($data as $line) {
fputcsv($f, $line);
}
} catch (\Exception $e) {
throw $e;
} catch (\Throwable $e) {
throw $e;
}
}
public function actionAccount()
{
/**
*
*
* @var SettingsForm $form
*/
$form = $this->make(SettingsForm::class);
$event = $this->make(UserEvent::class, [$form->getUser()]);
$this->make(AjaxRequestModelValidator::class, [$form])->validate();
if ($form->load(Yii::$app->request->post())) {
$this->trigger(UserEvent::EVENT_BEFORE_ACCOUNT_UPDATE, $event);
if ($form->save()) {
Yii::$app->getSession()->setFlash(
'success',
Yii::t('usuario', 'Your account details have been updated')
);
$this->trigger(UserEvent::EVENT_AFTER_ACCOUNT_UPDATE, $event);
return $this->refresh();
}
}
return $this->render(
'account',
[
'model' => $form,
]
);
}
public function actionConfirm($id, $code)
{
$user = $this->userQuery->whereId($id)->one();
if ($user === null || MailChangeStrategyInterface::TYPE_INSECURE === $this->module->emailChangeStrategy) {
throw new NotFoundHttpException();
}
$event = $this->make(UserEvent::class, [$user]);
$this->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION, $event);
if ($this->make(EmailChangeService::class, [$code, $user])->run()) {
$this->trigger(UserEvent::EVENT_AFTER_CONFIRMATION, $event);
}
return $this->redirect(['account']);
}
public function actionNetworks()
{
return $this->render(
'networks',
[
'user' => Yii::$app->user->identity,
]
);
}
public function actionDisconnect($id)
{
$this->disconnectSocialNetwork($id);
return $this->redirect(['networks']);
}
public function actionDelete()
{
if (!$this->module->allowAccountDelete) {
throw new NotFoundHttpException(Yii::t('usuario', 'Not found'));
}
/**
*
*
* @var User $user
*/
$user = Yii::$app->user->identity;
$event = $this->make(UserEvent::class, [$user]);
Yii::$app->user->logout();
$this->trigger(UserEvent::EVENT_BEFORE_DELETE, $event);
$user->delete();
$this->trigger(UserEvent::EVENT_AFTER_DELETE, $event);
Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your account has been completely deleted'));
return $this->goHome();
}
public function actionTwoFactor($id)
{
if (!$this->module->enableTwoFactorAuthentication) {
throw new ForbiddenHttpException(Yii::t('usuario', 'Application not configured for two factor authentication.'));
}
if ($id != Yii::$app->user->id) {
throw new ForbiddenHttpException();
}
$choice = Yii::$app->request->post('choice');
/** @var User $user */
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
throw new NotFoundHttpException();
}
switch ($choice) {
case 'google-authenticator':
$uri = $this->make(TwoFactorQrCodeUriGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor', ['id' => $id, 'uri' => $uri, 'user' => $user]);
case 'email':
$emailCode = $this->make(TwoFactorEmailCodeGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor-email', ['id' => $id, 'code' => $emailCode]);
case 'sms':
// get mobile phone, if exists
$mobilePhone = $user->getAuthTfMobilePhone();
$smsCode = $this->make(TwoFactorSmsCodeGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor-sms', ['id' => $id, 'code' => $smsCode, 'mobilePhone' => $mobilePhone]);
default:
throw new InvalidParamException("Invalid 2FA choice");
}
}
public function actionTwoFactorEnable($id)
{
if (!$this->module->enableTwoFactorAuthentication) {
throw new ForbiddenHttpException(Yii::t('usuario', 'Application not configured for two factor authentication.'));
}
Yii::$app->response->format = Response::FORMAT_JSON;
/** @var User $user */
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
return [
'success' => false,
'message' => Yii::t('usuario', 'User not found.')
];
}
$code = Yii::$app->request->get('code');
$module = Yii::$app->getModule('user');
$validators = $module->twoFactorAuthenticationValidators;
$choice = Yii::$app->request->get('choice');
$codeDurationTime = ArrayHelper::getValue($validators, $choice.'.codeDurationTime', 300);
$class = ArrayHelper::getValue($validators, $choice.'.class');
$object = $this
->make($class, [$user, $code, $this->module->twoFactorAuthenticationCycles]);
$success = $object->validate();
$success = $success && $user->updateAttributes(['auth_tf_enabled' => '1','auth_tf_type' => $choice]);
$message = $success ? $object->getSuccessMessage() : $object->getUnsuccessMessage($codeDurationTime);
return [
'success' => $success,
'message' => $message
];
}
public function actionTwoFactorDisable($id)
{
if (!$this->module->enableTwoFactorAuthentication) {
throw new ForbiddenHttpException(Yii::t('usuario', 'Application not configured for two factor authentication.'));
}
if ($id != Yii::$app->user->id) {
throw new ForbiddenHttpException();
}
/**
* @var User $user
*/
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
throw new NotFoundHttpException();
}
if ($user->updateAttributes(['auth_tf_enabled' => '0', 'auth_tf_key' => null])) {
Yii::$app
->getSession()
->setFlash('success', Yii::t('usuario', 'Two factor authentication has been disabled.'));
} else {
Yii::$app
->getSession()
->setFlash('danger', Yii::t('usuario', 'Unable to disable Two factor authentication.'));
}
$this->redirect(['account']);
}
/**
* Display list session history.
*/
public function actionSessionHistory()
{
$searchModel = new SessionHistorySearch([
'user_id' => Yii::$app->user->id,
]);
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('session-history', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Terminate all session user
*/
public function actionTerminateSessions()
{
$this->make(TerminateUserSessionsService::class, [Yii::$app->user->id])->run();
return $this->redirect(['session-history']);
}
public function actionTwoFactorMobilePhone($id)
{
Yii::$app->response->format = Response::FORMAT_JSON;
/**
*
*
* @var User $user
*/
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
return [
'success' => false,
'message' => Yii::t('usuario', 'User not found.')
];
}
$mobilePhone = Yii::$app->request->get('mobilephone');
$currentMobilePhone = $user->getAuthTfMobilePhone();
$success = false;
if ($currentMobilePhone == $mobilePhone) {
$success = true;
} else {
$success = $user->updateAttributes(['auth_tf_mobile_phone' => $mobilePhone]);
$success = $success && $this->make(TwoFactorSmsCodeGeneratorService::class, [$user])->run();
}
return [
'success' => $success,
'message' => $success
? Yii::t('usuario', 'Mobile phone number successfully enabled.')
: Yii::t('usuario', 'Error while enabling SMS two factor authentication. Please reload the page.'),
];
}
/**
* @param $id
* @throws ForbiddenHttpException
* @throws NotFoundHttpException
* @throws \Exception
* @throws \Throwable
* @throws \yii\db\StaleObjectException
*/
protected function disconnectSocialNetwork($id)
{
/**
*
*
* @var SocialNetworkAccount $account
*/
$account = $this->socialNetworkAccountQuery->whereId($id)->one();
if ($account === null) {
throw new NotFoundHttpException();
}
if ($account->user_id !== Yii::$app->user->id) {
throw new ForbiddenHttpException();
}
$event = $this->make(SocialNetworkConnectEvent::class, [Yii::$app->user->identity, $account]);
$this->trigger(SocialNetworkConnectEvent::EVENT_BEFORE_DISCONNECT, $event);
$account->delete();
$this->trigger(SocialNetworkConnectEvent::EVENT_AFTER_DISCONNECT, $event);
}
}

View File

@ -27,6 +27,7 @@ use yii\db\ActiveRecord;
/** /**
* @property int $user_id * @property int $user_id
* @property string $name * @property string $name
* @property string $surname
* @property string $public_email * @property string $public_email
* @property string $gravatar_email * @property string $gravatar_email
* @property string $gravatar_id * @property string $gravatar_id
@ -88,6 +89,7 @@ class Profile extends ActiveRecord
'gravatarEmailPattern' => ['gravatar_email', 'email'], 'gravatarEmailPattern' => ['gravatar_email', 'email'],
'websiteUrl' => ['website', 'url'], 'websiteUrl' => ['website', 'url'],
'nameLength' => ['name', 'string', 'max' => 255], 'nameLength' => ['name', 'string', 'max' => 255],
'surnameLength' => ['surname', 'string', 'max' => 255],
'publicEmailLength' => ['public_email', 'string', 'max' => 255], 'publicEmailLength' => ['public_email', 'string', 'max' => 255],
'gravatarEmailLength' => ['gravatar_email', 'string', 'max' => 255], 'gravatarEmailLength' => ['gravatar_email', 'string', 'max' => 255],
'locationLength' => ['location', 'string', 'max' => 255], 'locationLength' => ['location', 'string', 'max' => 255],
@ -102,6 +104,7 @@ class Profile extends ActiveRecord
{ {
return [ return [
'name' => Yii::t('usuario', 'Name'), 'name' => Yii::t('usuario', 'Name'),
'surname' => Yii::t('usuario', 'Surname'),
'public_email' => Yii::t('usuario', 'Email (public)'), 'public_email' => Yii::t('usuario', 'Email (public)'),
'gravatar_email' => Yii::t('usuario', 'Gravatar email'), 'gravatar_email' => Yii::t('usuario', 'Gravatar email'),
'location' => Yii::t('usuario', 'Location'), 'location' => Yii::t('usuario', 'Location'),

View File

@ -57,6 +57,13 @@ use yii\web\IdentityInterface;
* @property string $last_login_ip * @property string $last_login_ip
* @property int $password_changed_at * @property int $password_changed_at
* @property int $password_age * @property int $password_age
* @property int $status
* @property string $password_reset_token
* @property string $language
* @property boolean $rememberMe
* @property int $state
* @property int $created_by
*
* Defined relations: * Defined relations:
* @property SocialNetworkAccount[] $socialNetworkAccounts * @property SocialNetworkAccount[] $socialNetworkAccounts
* @property Profile $profile * @property Profile $profile
@ -204,6 +211,12 @@ class User extends ActiveRecord implements IdentityInterface
'last_login_ip' => Yii::t('usuario', 'Last login IP'), 'last_login_ip' => Yii::t('usuario', 'Last login IP'),
'password_changed_at' => Yii::t('usuario', 'Last password change'), 'password_changed_at' => Yii::t('usuario', 'Last password change'),
'password_age' => Yii::t('usuario', 'Password age'), 'password_age' => Yii::t('usuario', 'Password age'),
'language' => Yii::t('usuario', 'Language'),
'status' => Yii::t('usuario', 'Status'),
'state' => Yii::t('usuario', 'State'),
'created_by' => Yii::t('usuario', 'Created by'),
'rememberMe' => Yii::t('usuario', 'Remember Me'),
'password_reset_token' => Yii::t('usuario', 'Password Reset Token'),
]; ];
} }
@ -393,4 +406,40 @@ class User extends ActiveRecord implements IdentityInterface
{ {
return $this->getAttribute('auth_tf_mobile_phone'); return $this->getAttribute('auth_tf_mobile_phone');
} }
/**
* Returns the user who created this user
* @return \yii\db\ActiveQuery
*/
public function getCreator()
{
return $this->hasOne(self::class, ['id' => 'created_by']);
}
/**
* Returns the user's name
* @return string|null
*/
public function getName()
{
return $this->profile ? $this->profile->name : null;
}
/**
* Returns the user's surname
* @return string|null
*/
public function getSurname()
{
return $this->profile ? $this->profile->surname : null;
}
/**
* Returns the user's full name
* @return string
*/
public function getFullName()
{
return $this->profile ? ($this->profile->name . ' ' . $this->profile->surname) : $this->username;
}
} }

View File

@ -91,7 +91,7 @@ class Module extends BaseModule
* @see AccessRuleFilter * @see AccessRuleFilter
*/ */
public $gdprConsentExcludedUrls = [ public $gdprConsentExcludedUrls = [
'user/settings/*' 'user/profile/*'
]; ];
/** /**
* @var bool whether to enable two factor authentication or not * @var bool whether to enable two factor authentication or not

View File

@ -202,19 +202,24 @@ return [
'Rule name' => 'Nome regola', 'Rule name' => 'Nome regola',
'Rule {0} does not exists' => 'La regola {0} non esiste', 'Rule {0} does not exists' => 'La regola {0} non esiste',
'Rule {0} not found.' => 'Regola {0} non trovata.', 'Rule {0} not found.' => 'Regola {0} non trovata.',
'Rule' => 'ruolo', 'Rule' => 'Regola',
'Rules' => 'Regole', 'Rules' => 'Regole',
'Save' => 'Salva', 'Save' => 'Salva',
'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => 'Scansiona il codice QR con l\'applicazione Google Authenticator, poi inserisci il codice temporaneo nel riquadro ed invia.', 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => 'Scansiona il codice QR con l\'applicazione Google Authenticator, poi inserisci il codice temporaneo nel riquadro ed invia.',
'Select children...' => 'Seleziona figli...',
'Select items...' => 'Seleziona elementi...',
'Select role...' => 'Seleziona ruolo...',
'Select rule...' => 'Seleziona una regola...', 'Select rule...' => 'Seleziona una regola...',
'Send password recovery email' => 'Invia email di recupero password', 'Send password recovery email' => 'Invia email di recupero password',
'Session history' => 'Cronologia sessioni', 'Session history' => 'Cronologia sessioni',
'Session ID' => 'ID sessione', 'Session ID' => 'ID sessione',
'Settings' => 'Impostazioni',
'Sign in' => 'Accedi', 'Sign in' => 'Accedi',
'Sign up' => 'Registrati', 'Sign up' => 'Registrati',
'Something went wrong' => 'È successo qualcosa di strano', 'Something went wrong' => 'È successo qualcosa di strano',
'Status' => 'Stato', 'Status' => 'Stato',
'Submit' => 'Invia', 'Submit' => 'Invia',
'Surname' => 'Cognome',
'Switch identities is disabled.' => 'Il cambio identità è disabilitato', 'Switch identities is disabled.' => 'Il cambio identità è disabilitato',
'Terminate all sessions' => 'Termina tutte le sessioni', 'Terminate all sessions' => 'Termina tutte le sessioni',
'Text message' => 'Messaggio di testo tramite SMS', 'Text message' => 'Messaggio di testo tramite SMS',

View File

@ -9,7 +9,7 @@
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
use yii\bootstrap\ActiveForm; use yii\bootstrap4\ActiveForm;
use yii\helpers\Html; use yii\helpers\Html;
/** @var yii\web\View $this */ /** @var yii\web\View $this */
@ -22,21 +22,15 @@ use yii\helpers\Html;
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'layout' => 'horizontal',
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'enableClientValidation' => false, 'enableClientValidation' => false,
'fieldConfig' => [
'horizontalCssClasses' => [
'wrapper' => 'col-sm-9',
],
],
] ]
); ?> ); ?>
<?= $this->render('/admin/_user', ['form' => $form, 'user' => $user]) ?> <?= $this->render('/admin/_user', ['form' => $form, 'user' => $user]) ?>
<div class="form-group"> <div class="form-group d-flex justify-content-center">
<div class="col-lg-offset-3 col-lg-9"> <div class="w-75">
<?= Html::submitButton(Yii::t('usuario', 'Update'), ['class' => 'btn btn-block btn-success']) ?> <?= Html::submitButton(Yii::t('usuario', 'Update'), ['class' => 'btn btn-block btn-success']) ?>
</div> </div>
</div> </div>

View File

@ -20,7 +20,7 @@ use Da\User\Widget\AssignmentsWidget;
<?php $this->beginContent($module->viewPath. '/admin/update.php', ['user' => $user]) ?> <?php $this->beginContent($module->viewPath. '/admin/update.php', ['user' => $user]) ?>
<?= yii\bootstrap\Alert::widget( <?= yii\bootstrap4\Alert::widget(
[ [
'options' => [ 'options' => [
'class' => 'alert-info alert-dismissible', 'class' => 'alert-info alert-dismissible',

View File

@ -9,7 +9,7 @@
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
use yii\bootstrap\ActiveForm; use yii\bootstrap4\ActiveForm;
use yii\helpers\Html; use yii\helpers\Html;
/** /**
@ -25,18 +25,13 @@ use yii\helpers\Html;
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'layout' => 'horizontal',
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'enableClientValidation' => false, 'enableClientValidation' => false,
'fieldConfig' => [
'horizontalCssClasses' => [
'wrapper' => 'col-sm-9',
],
],
] ]
); ?> ); ?>
<?= $form->field($profile, 'name') ?> <?= $form->field($profile, 'name') ?>
<?= $form->field($profile, 'surname') ?>
<?= $form->field($profile, 'public_email') ?> <?= $form->field($profile, 'public_email') ?>
<?= $form->field($profile, 'website') ?> <?= $form->field($profile, 'website') ?>
<?= $form->field($profile, 'location') ?> <?= $form->field($profile, 'location') ?>
@ -44,8 +39,8 @@ use yii\helpers\Html;
<?= $form->field($profile, 'bio')->textarea() ?> <?= $form->field($profile, 'bio')->textarea() ?>
<div class="form-group"> <div class="form-group d-flex justify-content-center">
<div class="col-lg-offset-3 col-lg-9"> <div class="w-75">
<?= Html::submitButton(Yii::t('usuario', 'Update'), ['class' => 'btn btn-block btn-success']) ?> <?= Html::submitButton(Yii::t('usuario', 'Update'), ['class' => 'btn btn-block btn-success']) ?>
</div> </div>
</div> </div>

View File

@ -27,20 +27,18 @@ use yii\data\ActiveDataProvider;
*/ */
?> ?>
<?php $this->beginContent($module->viewPath. '/admin/update.php', ['user' => $user]) ?> <?php $this->beginContent($module->viewPath . '/admin/update.php', ['user' => $user]) ?>
<div class="row"> <div class="d-flex justify-content-end">
<div class="col-xs-12">
<?= Html::a( <?= Html::a(
Yii::t('usuario', 'Terminate all sessions'), Yii::t('usuario', 'Terminate all sessions'),
['/user/admin/terminate-sessions', 'id' => $user->id], ['/user/admin/terminate-sessions', 'id' => $user->id],
[ [
'class' => 'btn btn-danger btn-xs pull-right', 'class' => 'btn btn-danger btn-xs',
'data-method' => 'post' 'data-method' => 'post'
] ]
) ?> ) ?>
</div> </div>
</div> <hr />
<hr>
<?php Pjax::begin(); ?> <?php Pjax::begin(); ?>

View File

@ -9,8 +9,8 @@
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
use yii\bootstrap\ActiveForm; use yii\bootstrap4\ActiveForm;
use yii\bootstrap\Nav; use yii\bootstrap4\Nav;
use yii\helpers\Html; use yii\helpers\Html;
/** /**
@ -18,9 +18,12 @@ use yii\helpers\Html;
* @var \Da\User\Model\User $user * @var \Da\User\Model\User $user
*/ */
use yii\helpers\Url;
$this->title = Yii::t('usuario', 'Create a user account'); $this->title = Yii::t('usuario', 'Create a user account');
$this->params['breadcrumbs'][] = ['label' => Yii::t('usuario', 'Users'), 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => Yii::t('usuario', 'Users'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
$currentRoute = Yii::$app->controller->getRoute();
?> ?>
<div class="clearfix"></div> <div class="clearfix"></div>
@ -31,41 +34,36 @@ $this->params['breadcrumbs'][] = $this->title;
] ]
) ?> ) ?>
<div class="row"> <div class="container-fluid px-0">
<div class="col-md-12"> <div class="tab-wrapper">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="panel-body">
<?= $this->render('/shared/_menu') ?> <?= $this->render('/shared/_menu') ?>
<div class="row"> <div class="row p-3">
<div class="col-md-3"> <div class="col-12 col-md-4 col-lg-3">
<div class="panel panel-default"> <div class="card">
<div class="panel-body"> <div class="card-body">
<?= Nav::widget( <?= Nav::widget(
[ [
'options' => [ 'options' => [
'class' => 'nav-pills nav-stacked', 'class' => 'nav nav-pills flex-column',
], ],
'items' => [ 'items' => [
[ [
'label' => Yii::t('usuario', 'Account details'), 'label' => Yii::t('usuario', 'Account details'),
'url' => ['/user/admin/create'], 'url' => ['/user/admin/create'],
'linkOptions' => ['class' => 'nav-link'],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Profile details'), 'label' => Yii::t('usuario', 'Profile details'),
'options' => [ 'url' => '#',
'class' => 'disabled', 'linkOptions' => ['class' => 'nav-link disabled', 'onclick' => 'return false;'],
'onclick' => 'return false;', 'options' => ['class' => 'nav-item'],
],
], ],
[ [
'label' => Yii::t('usuario', 'Information'), 'label' => Yii::t('usuario', 'Information'),
'options' => [ 'url' => '#',
'class' => 'disabled', 'linkOptions' => ['class' => 'nav-link disabled', 'onclick' => 'return false;'],
'onclick' => 'return false;', 'options' => ['class' => 'nav-item'],
],
], ],
], ],
] ]
@ -73,9 +71,9 @@ $this->params['breadcrumbs'][] = $this->title;
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-9"> <div class="col-12 col-md-8 col-lg-9">
<div class="panel panel-default"> <div class="card">
<div class="panel-body"> <div class="card-body">
<div class="alert alert-info"> <div class="alert alert-info">
<?= Yii::t('usuario', 'Credentials will be sent to the user by email') ?>. <?= Yii::t('usuario', 'Credentials will be sent to the user by email') ?>.
<?= Yii::t( <?= Yii::t(
@ -85,21 +83,15 @@ $this->params['breadcrumbs'][] = $this->title;
</div> </div>
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'layout' => 'horizontal',
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'enableClientValidation' => false, 'enableClientValidation' => false,
'fieldConfig' => [
'horizontalCssClasses' => [
'wrapper' => 'col-sm-9',
],
],
] ]
); ?> ); ?>
<?= $this->render('/admin/_user', ['form' => $form, 'user' => $user]) ?> <?= $this->render('/admin/_user', ['form' => $form, 'user' => $user]) ?>
<div class="form-group"> <div class="form-group d-flex justify-content-center">
<div class="col-lg-offset-3 col-lg-9"> <div class="w-75">
<?= Html::submitButton( <?= Html::submitButton(
Yii::t('usuario', 'Save'), Yii::t('usuario', 'Save'),
['class' => 'btn btn-block btn-success'] ['class' => 'btn btn-block btn-success']
@ -113,7 +105,4 @@ $this->params['breadcrumbs'][] = $this->title;
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</div> </div>

View File

@ -29,9 +29,10 @@ $this->params['breadcrumbs'][] = $this->title;
<?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?> <?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?>
<?php Pjax::begin() ?> <?php Pjax::begin() ?>
<div class="table-responsive"> <div class="table-responsive d-flex p-3">
<?= GridView::widget( <?= GridView::widget(
[ [
'options' => ['class' => 'flex-grow-1'],
'dataProvider' => $dataProvider, 'dataProvider' => $dataProvider,
'filterModel' => $searchModel, 'filterModel' => $searchModel,
'layout' => "{items}\n{pager}", 'layout' => "{items}\n{pager}",
@ -153,7 +154,7 @@ $this->params['breadcrumbs'][] = $this->title;
return null; return null;
}, },
'reset' => function ($url, $model) use ($module) { 'reset' => function ($url, $model) use ($module) {
if($module->allowAdminPasswordRecovery) { if ($module->allowAdminPasswordRecovery) {
return Html::a( return Html::a(
'<span class="glyphicon glyphicon-flash"></span>', '<span class="glyphicon glyphicon-flash"></span>',
['/user/admin/password-reset', 'id' => $model->id], ['/user/admin/password-reset', 'id' => $model->id],
@ -191,7 +192,7 @@ $this->params['breadcrumbs'][] = $this->title;
], ],
], ],
] ]
); ?> ); ?>
</div> </div>
<?php Pjax::end() ?> <?php Pjax::end() ?>

View File

@ -10,7 +10,7 @@
*/ */
use Da\User\Model\User; use Da\User\Model\User;
use yii\bootstrap\Nav; use yii\bootstrap4\Nav;
use yii\helpers\Html; use yii\helpers\Html;
use yii\web\View; use yii\web\View;
use Da\User\Module as UserModule; use Da\User\Module as UserModule;
@ -36,112 +36,104 @@ $module = Yii::$app->getModule('user');
] ]
) ?> ) ?>
<div class="row"> <div class="container-fluid px-0">
<div class="col-md-12"> <div class="tab-wrapper">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="panel-body">
<?= $this->render('/shared/_menu') ?> <?= $this->render('/shared/_menu') ?>
<div class="row"> <div class="row p-3">
<div class="col-md-3"> <div class="col-12 col-md-4 col-lg-3">
<div class="panel panel-default"> <div class="card">
<div class="panel-body"> <div class="card-body">
<?= Nav::widget( <?= Nav::widget([
[
'options' => [ 'options' => [
'class' => 'nav-pills nav-stacked', 'class' => 'nav nav-pills flex-column',
], ],
'items' => [ 'items' => [
[ [
'label' => Yii::t('usuario', 'Account details'), 'label' => Yii::t('usuario', 'Account details'),
'url' => ['/user/admin/update', 'id' => $user->id], 'url' => ['/user/admin/update', 'id' => $user->id],
'linkOptions' => ['class' => 'nav-link'],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Profile details'), 'label' => Yii::t('usuario', 'Profile details'),
'url' => ['/user/admin/update-profile', 'id' => $user->id], 'url' => ['/user/admin/update-profile', 'id' => $user->id],
'linkOptions' => ['class' => 'nav-link'],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Information'), 'label' => Yii::t('usuario', 'Information'),
'url' => ['/user/admin/info', 'id' => $user->id], 'url' => ['/user/admin/info', 'id' => $user->id],
'linkOptions' => ['class' => 'nav-link'],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Assignments'), 'label' => Yii::t('usuario', 'Assignments'),
'url' => ['/user/admin/assignments', 'id' => $user->id], 'url' => ['/user/admin/assignments', 'id' => $user->id],
'linkOptions' => ['class' => 'nav-link'],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Session history'), 'label' => Yii::t('usuario', 'Session history'),
'url' => ['/user/admin/session-history', 'id' => $user->id], 'url' => ['/user/admin/session-history', 'id' => $user->id],
'visible' => $module->enableSessionHistory, 'visible' => $module->enableSessionHistory,
'linkOptions' => ['class' => 'nav-link'],
'options' => ['class' => 'nav-item'],
], ],
'<hr>',
[ [
'label' => Yii::t('usuario', 'Confirm'), 'label' => Yii::t('usuario', 'Confirm'),
'url' => ['/user/admin/confirm', 'id' => $user->id], 'url' => ['/user/admin/confirm', 'id' => $user->id],
'visible' => !$user->isConfirmed, 'visible' => !$user->isConfirmed,
'linkOptions' => [ 'linkOptions' => [
'class' => 'text-success', 'class' => 'nav-link text-success',
'data-method' => 'post', 'data-method' => 'post',
'data-confirm' => Yii::t( 'data-confirm' => Yii::t('usuario', 'Are you sure you want to confirm this user?'),
'usuario',
'Are you sure you want to confirm this user?'
),
], ],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Block'), 'label' => Yii::t('usuario', 'Block'),
'url' => ['/user/admin/block', 'id' => $user->id], 'url' => ['/user/admin/block', 'id' => $user->id],
'visible' => !$user->isBlocked, 'visible' => !$user->isBlocked,
'linkOptions' => [ 'linkOptions' => [
'class' => 'text-danger', 'class' => 'nav-link text-danger',
'data-method' => 'post', 'data-method' => 'post',
'data-confirm' => Yii::t( 'data-confirm' => Yii::t('usuario', 'Are you sure you want to block this user?'),
'usuario',
'Are you sure you want to block this user?'
),
], ],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Unblock'), 'label' => Yii::t('usuario', 'Unblock'),
'url' => ['/user/admin/block', 'id' => $user->id], 'url' => ['/user/admin/block', 'id' => $user->id],
'visible' => $user->isBlocked, 'visible' => $user->isBlocked,
'linkOptions' => [ 'linkOptions' => [
'class' => 'text-success', 'class' => 'nav-link text-success',
'data-method' => 'post', 'data-method' => 'post',
'data-confirm' => Yii::t( 'data-confirm' => Yii::t('usuario', 'Are you sure you want to unblock this user?'),
'usuario',
'Are you sure you want to unblock this user?'
),
], ],
'options' => ['class' => 'nav-item'],
], ],
[ [
'label' => Yii::t('usuario', 'Delete'), 'label' => Yii::t('usuario', 'Delete'),
'url' => ['/user/admin/delete', 'id' => $user->id], 'url' => ['/user/admin/delete', 'id' => $user->id],
'linkOptions' => [ 'linkOptions' => [
'class' => 'text-danger', 'class' => 'nav-link text-danger',
'data-method' => 'post', 'data-method' => 'post',
'data-confirm' => Yii::t( 'data-confirm' => Yii::t('usuario', 'Are you sure you want to delete this user?'),
'usuario', ],
'Are you sure you want to delete this user?' 'options' => ['class' => 'nav-item'],
),
], ],
], ],
], ]) ?>
]
) ?>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-9"> <div class="col-12 col-md-8 col-lg-9">
<div class="panel panel-default"> <div class="card">
<div class="panel-body"> <div class="card-body">
<?= $content ?> <?= $content ?>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</div> </div>

View File

@ -9,7 +9,7 @@
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
use dosamigos\selectize\SelectizeDropDownList; use pcrt\widgets\select2\Select2;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
@ -26,6 +26,7 @@ use yii\widgets\ActiveForm;
[ [
'enableClientValidation' => false, 'enableClientValidation' => false,
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'options' => ['class' => 'p-3'],
] ]
) ?> ) ?>
@ -33,24 +34,29 @@ use yii\widgets\ActiveForm;
<?= $form->field($model, 'description') ?> <?= $form->field($model, 'description') ?>
<?= $form->field($model, 'rule')->widget(SelectizeDropDownList::class, [ <?= $form->field($model, 'rule')->widget(Select2::class, [
'items' => ArrayHelper::map(Yii::$app->getAuthManager()->getRules(), 'name', 'name'), 'items' => ArrayHelper::map(Yii::$app->getAuthManager()->getRules(), 'name', 'name'),
'options' => [ 'options' => [
'prompt' => Yii::t('usuario', 'Select rule...'), 'placeholder' => Yii::t('usuario', 'Select rule...'),
] 'multiple' => false,
],
'clientOptions' => [
'allowClear' => true,
'width' => '100%',
],
]) ?> ]) ?>
<?= $form->field($model, 'children')->widget(Select2::class, [
<?= $form->field($model, 'children')->widget(
SelectizeDropDownList::class,
[
'items' => $unassignedItems, 'items' => $unassignedItems,
'options' => [ 'options' => [
'id' => 'children', 'placeholder' => Yii::t('usuario', 'Select children...'),
'multiple' => true, 'multiple' => true
], ],
] 'clientOptions' => [
) ?> 'allowClear' => true,
'width' => '100%',
],
]) ?>
<?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-success btn-block']) ?> <?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-success btn-block']) ?>

View File

@ -25,9 +25,10 @@ $this->params['breadcrumbs'][] = $this->title;
?> ?>
<?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?> <?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?>
<div class="table-responsive"> <div class="table-responsive d-flex p-3">
<?= GridView::widget( <?= GridView::widget(
[ [
'options' => ['class' => 'flex-grow-1'],
'dataProvider' => $dataProvider, 'dataProvider' => $dataProvider,
'filterModel' => $searchModel, 'filterModel' => $searchModel,
'layout' => "{items}\n{pager}", 'layout' => "{items}\n{pager}",

View File

@ -0,0 +1,78 @@
<?php
/*
* This file is part of the 2amigos/yii2-usuario project.
*
* (c) 2amigOS! <http://2amigos.us/>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use yii\helpers\Html;
use Da\User\Module as UserModule;
use Da\User\Model\User;
use yii\bootstrap4\Nav;
/** @var User $user */
$user = Yii::$app->user->identity;
/** @var UserModule $module */
$module = Yii::$app->getModule('user');
$networksVisible = count(Yii::$app->authClientCollection->clients) > 0;
?>
<div class="card">
<div class="card-header">
<h3 class="card-title m-0">
<?= Html::img(
$user->profile->getAvatarUrl(48),
[
'class' => 'rounded-lg',
'alt' => $user->username,
]
) ?>
<?= $user->username ?>
</h3>
</div>
<div class="card-body">
<?= Nav::widget([
'options' => ['class' => 'nav nav-pills flex-column'], // nav verticale
'items' => [
[
'label' => Yii::t('usuario', 'Profile'),
'url' => ['/user/profile/profile'],
'linkOptions' => ['class' => 'nav-link'],
'active' => Yii::$app->controller->action->id === 'profile',
],
[
'label' => Yii::t('usuario', 'Account'),
'url' => ['/user/profile/account'],
'linkOptions' => ['class' => 'nav-link'],
'active' => Yii::$app->controller->action->id === 'account',
],
[
'label' => Yii::t('usuario', 'Session history'),
'url' => ['/user/profile/session-history'],
'visible' => $module->enableSessionHistory,
'linkOptions' => ['class' => 'nav-link'],
'active' => Yii::$app->controller->action->id === 'session-history',
],
[
'label' => Yii::t('usuario', 'Privacy'),
'url' => ['/user/profile/privacy'],
'visible' => $module->enableGdprCompliance,
'linkOptions' => ['class' => 'nav-link'],
'active' => Yii::$app->controller->action->id === 'privacy',
],
[
'label' => Yii::t('usuario', 'Networks'),
'url' => ['/user/profile/networks'],
'visible' => $networksVisible,
'linkOptions' => ['class' => 'nav-link'],
'active' => Yii::$app->controller->action->id === 'networks',
],
],
]) ?>
</div>
</div>

View File

@ -31,23 +31,20 @@ $module = Yii::$app->getModule('user');
<?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?> <?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?>
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-12 col-md-4 col-lg-3">
<?= $this->render('/settings/_menu') ?> <?= $this->render('/profile/_menu') ?>
</div> </div>
<div class="col-md-9"> <div class="col-12 col-md-8 col-lg-9">
<div class="panel panel-default"> <div class="card">
<div class="panel-heading"> <div class="card-body">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="panel-body">
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'id' => $model->formName(), 'id' => $model->formName(),
'options' => ['class' => 'form-horizontal'], // 'options' => ['class' => 'form-horizontal'],
'fieldConfig' => [ // 'fieldConfig' => [
'template' => "{label}\n<div class=\"col-lg-9\">{input}</div>\n<div class=\"col-sm-offset-3 col-lg-9\">{error}\n{hint}</div>", // 'template' => "{label}\n<div class=\"col-lg-9\">{input}</div>\n<div class=\"col-sm-offset-3 col-lg-9\">{error}\n{hint}</div>",
'labelOptions' => ['class' => 'col-lg-3 control-label'], // 'labelOptions' => ['class' => 'col-lg-3 control-label'],
], // ],
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'enableClientValidation' => false, 'enableClientValidation' => false,
] ]
@ -63,8 +60,8 @@ $module = Yii::$app->getModule('user');
<?= $form->field($model, 'current_password')->passwordInput() ?> <?= $form->field($model, 'current_password')->passwordInput() ?>
<div class="form-group"> <div class="form-group d-flex justify-content-center">
<div class="col-lg-offset-3 col-lg-9"> <div class="w-75">
<?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-block btn-success']) ?> <?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-block btn-success']) ?>
<br> <br>
</div> </div>

View File

@ -26,7 +26,7 @@ use yii\widgets\ActiveForm;
</div> </div>
<div class="panel-footer"> <div class="panel-footer">
<?= Html::submitButton(Yii::t('usuario', 'Submit'), ['class' => 'btn btn-success']) ?> <?= Html::submitButton(Yii::t('usuario', 'Submit'), ['class' => 'btn btn-success']) ?>
<p class="pull-right small"><?= Html::a(Yii::t('usuario', 'Account details'), ['/user/settings']) ?></p> <p class="pull-right small"><?= Html::a(Yii::t('usuario', 'Account details'), ['/user/profile']) ?></p>
</div> </div>
</div> </div>
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>

View File

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the 2amigos/yii2-usuario project.
*
* (c) 2amigOS! <http://2amigos.us/>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use yii\widgets\ActiveForm;
use yii\helpers\Html;
/** @var \Da\User\Form\GdprDeleteForm $model */
$this->title = Yii::t('usuario', 'Delete personal data');
?>
<div class="d-flex justify-content-center align-items-center">
<div class="card">
<div class="card-body">
<p><?= Yii::t('usuario', 'You are about to delete all your personal data from this site.') ?></p>
<p class="text-danger">
<?= Yii::t(
'usuario',
'Once you have deleted your data, you will not longer be able to sign in with this account.'
) ?>
</p>
<hr />
<?php
$form = ActiveForm::begin([])
?>
<div class="d-flex justify-content-center align-items-center">
<div class="w-75">
<?= $form->field($model, 'password')->passwordInput() ?>
</div>
</div>
<div class="d-flex justify-content-center align-items-center">
<?= Html::submitButton(Yii::t('usuario', 'Delete'), ['class' => 'btn btn-danger']) ?>
</div>
<hr />
<div class="d-flex justify-content-center align-items-center">
<?= Html::a(Yii::t('usuario', 'Back to privacy settings'), ['/user/profile/privacy'], ['class' => 'btn btn-info']) ?>
</div>
<?php
ActiveForm::end();
?>
</div>
</div>
</div>

View File

@ -28,7 +28,7 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<?= $this->render('/settings/_menu') ?> <?= $this->render('/profile/_menu') ?>
</div> </div>
<div class="col-md-9"> <div class="col-md-9">
<div class="panel panel-default"> <div class="panel panel-default">

View File

@ -0,0 +1,71 @@
<?php
use yii\helpers\Html;
/** @var \yii\web\View $this */
/** @var \Da\User\Module $module */
$this->title = Yii::t('usuario', 'Privacy settings');
?>
<div class="row">
<div class="col-12 col-md-4 col-lg-3">
<?= $this->render('_menu') ?>
</div>
<div class="col-12 col-md-8 col-lg-9">
<div class="card h-100">
<div class="card-body">
<div class="container-fluid mb-3">
<h3><?= Yii::t('usuario', 'Export my data') ?></h3>
<p><?= Yii::t(
'usuario',
'Here you can download your personal data in a comma separated values format.'
) ?>
</p>
<?= Html::a(
Yii::t('usuario', 'Download my data'),
['/user/profile/export'],
[
'class' => 'btn btn-info',
'target' => '_blank'
]
)
?>
</div>
<hr />
<div class="container-fluid">
<h3><?= Yii::t('usuario', 'Delete my account') ?></h3>
<p><?= Yii::t(
'usuario',
'This will remove your personal data from this site. You will no longer be able to sign in.'
) ?>
</p>
<?php if ($module->allowAccountDelete): ?>
<?= Html::a(
Yii::t('usuario', 'Delete account'),
['delete'],
[
'id' => 'gdpr-del-button',
'class' => 'btn btn-danger',
'data-method' => 'post',
'data-confirm' => Yii::t('usuario', 'Are you sure? There is no going back'),
]
) ?>
<?php else:
echo Html::a(
Yii::t('usuario', 'Delete'),
['/user/profile/gdpr-delete'],
[
'class' => 'btn btn-danger',
'id' => 'gdpr-del-button',
]
)
?>
<?php endif ?>
</div>
</div>
</div>
</div>
</div>

View File

@ -31,23 +31,20 @@ $timezoneHelper = $model->make(TimezoneHelper::class);
<?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?> <?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?>
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-12 col-md-4 col-lg-3">
<?= $this->render('_menu') ?> <?= $this->render('_menu') ?>
</div> </div>
<div class="col-md-9"> <div class="col-12 col-md-8 col-lg-9">
<div class="panel panel-default"> <div class="card">
<div class="panel-heading"> <div class="card-body">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="panel-body">
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'id' => $model->formName(), 'id' => $model->formName(),
'options' => ['class' => 'form-horizontal'], // 'options' => ['class' => 'form-horizontal'],
'fieldConfig' => [ // 'fieldConfig' => [
'template' => "{label}\n<div class=\"col-lg-9\">{input}</div>\n<div class=\"col-sm-offset-3 col-lg-9\">{error}\n{hint}</div>", // 'template' => "{label}\n<div class=\"col-lg-9\">{input}</div>\n<div class=\"col-sm-offset-3 col-lg-9\">{error}\n{hint}</div>",
'labelOptions' => ['class' => 'col-lg-3 control-label'], // 'labelOptions' => ['class' => 'col-lg-3 control-label'],
], // ],
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'enableClientValidation' => false, 'enableClientValidation' => false,
'validateOnBlur' => false, 'validateOnBlur' => false,
@ -56,6 +53,8 @@ $timezoneHelper = $model->make(TimezoneHelper::class);
<?= $form->field($model, 'name') ?> <?= $form->field($model, 'name') ?>
<?= $form->field($model, 'surname') ?>
<?= $form->field($model, 'public_email') ?> <?= $form->field($model, 'public_email') ?>
<?= $form->field($model, 'website') ?> <?= $form->field($model, 'website') ?>
@ -78,8 +77,8 @@ $timezoneHelper = $model->make(TimezoneHelper::class);
<?= $form->field($model, 'bio')->textarea() ?> <?= $form->field($model, 'bio')->textarea() ?>
<div class="form-group"> <div class="form-group d-flex justify-content-center">
<div class="col-lg-offset-3 col-lg-9"> <div class="w-75">
<?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-block btn-success']) ?> <?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-block btn-success']) ?>
<br> <br>
</div> </div>

View File

@ -31,23 +31,22 @@ $this->params['breadcrumbs'][] = $this->title;
<?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?> <?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?>
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-12 col-md-4 col-lg-3">
<?= $this->render('/settings/_menu') ?> <?= $this->render('/profile/_menu') ?>
</div> </div>
<div class="col-md-9"> <div class="col-12 col-md-8 col-lg-9">
<div class="panel panel-default"> <div class="card">
<div class="panel-heading"> <div class="card-header text-right">
<?= Html::encode($this->title) ?>
<?= Html::a( <?= Html::a(
Yii::t('usuario', 'Terminate all sessions'), Yii::t('usuario', 'Terminate all sessions'),
['/user/settings/terminate-sessions'], ['/user/profile/terminate-sessions'],
[ [
'class' => 'btn btn-danger btn-xs pull-right', 'class' => 'btn btn-danger btn-xs',
'data-method' => 'post' 'data-method' => 'post'
] ]
) ?> ) ?>
</div> </div>
<div class="panel-body"> <div class="card-body">
<?php Pjax::begin(); ?> <?php Pjax::begin(); ?>

View File

@ -1,71 +0,0 @@
<?php
/*
* This file is part of the 2amigos/yii2-usuario project.
*
* (c) 2amigOS! <http://2amigos.us/>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use yii\helpers\Html;
/**
* @var \yii\web\View $this
* @var \Da\User\Model\Profile $profile
*/
$this->title = empty($profile->name) ? Html::encode($profile->user->username) : Html::encode($profile->name);
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="row">
<div class="col-sm-6 col-md-4">
<?= Html::img(
$profile->getAvatarUrl(230),
[
'class' => 'img-rounded img-responsive',
'alt' => $profile->user->username,
]
) ?>
</div>
<div class="col-sm-6 col-md-8">
<h4><?= $this->title ?></h4>
<ul style="padding: 0; list-style: none outside none;">
<?php if (!empty($profile->location)): ?>
<li>
<i class="glyphicon glyphicon-map-marker text-muted"></i>
<?= Html::encode($profile->location) ?>
</li>
<?php endif; ?>
<?php if (!empty($profile->website)): ?>
<li>
<i class="glyphicon glyphicon-globe text-muted"></i>
<?= Html::a(Html::encode($profile->website), Html::encode($profile->website)) ?>
</li>
<?php endif; ?>
<?php if (!empty($profile->public_email)): ?>
<li>
<i class="glyphicon glyphicon-envelope text-muted"></i>
<?= Html::a(
Html::encode($profile->public_email),
'mailto:' .
Html::encode($profile->public_email)
)
?>
</li>
<?php endif; ?>
<li>
<i class="glyphicon glyphicon-time text-muted"></i>
<?= Yii::t('usuario', 'Joined on {0, date}', $profile->user->created_at) ?>
</li>
</ul>
<?php if (!empty($profile->bio)): ?>
<p><?= Html::encode($profile->bio) ?></p>
<?php endif; ?>
</div>
</div>
</div>
</div>

View File

@ -21,13 +21,18 @@ use yii\widgets\ActiveForm;
$this->title = Yii::t('usuario', 'Recover your password'); $this->title = Yii::t('usuario', 'Recover your password');
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3"> <div class="site-login">
<div class="panel panel-default"> <a href="/site/login" class="d-flex align-items-center justify-content-center mb-4">
<div class="panel-heading"> <img src="/img/logotipo.png" class="pcrt-logo" style="max-width:42px;" />
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3> <div class="site-title">
<div class="type"><?= Yii::$app->params['name_first'] ?></div>
<div class="name"><?= Yii::$app->params['name_last'] ?></div>
</div> </div>
<div class="panel-body"> </a>
<div class="card" style="max-width: 32.5rem;width: 100%;">
<div class="card-body">
<div class="title"><?= Html::encode($this->title) ?></div>
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'id' => $model->formName(), 'id' => $model->formName(),

View File

@ -21,13 +21,17 @@ use yii\widgets\ActiveForm;
$this->title = Yii::t('usuario', 'Reset your password'); $this->title = Yii::t('usuario', 'Reset your password');
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<div class="row"> <div class="site-login">
<div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3"> <a href="/site/login" class="d-flex align-items-center justify-content-center mb-4">
<div class="panel panel-default"> <img src="/img/logotipo.png" class="pcrt-logo" style="max-width:42px;" />
<div class="panel-heading"> <div class="site-title">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3> <div class="type"><?= Yii::$app->params['name_first'] ?></div>
<div class="name"><?= Yii::$app->params['name_last'] ?></div>
</div> </div>
<div class="panel-body"> </a>
<div class="card" style="max-width: 32.5rem;width: 100%;">
<div class="card-body">
<div class="title"><?= Html::encode($this->title) ?></div>
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'id' => $model->formName(), 'id' => $model->formName(),
@ -43,5 +47,4 @@ $this->params['breadcrumbs'][] = $this->title;
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>
</div> </div>
</div> </div>
</div>
</div> </div>

View File

@ -58,7 +58,7 @@ $this->params['breadcrumbs'][] = $this->title;
'usuario', 'usuario',
'If you already registered, sign in and connect this account on settings page' 'If you already registered, sign in and connect this account on settings page'
), ),
['/user/settings/networks'] ['/user/profile/networks']
) ?>. ) ?>.
</p> </p>
</div> </div>

View File

@ -22,13 +22,18 @@ use yii\widgets\ActiveForm;
$this->title = Yii::t('usuario', 'Sign up'); $this->title = Yii::t('usuario', 'Sign up');
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3"> <div class="site-login">
<div class="panel panel-default"> <a href="/site/login" class="d-flex align-items-center justify-content-center mb-4">
<div class="panel-heading"> <img src="/img/logotipo.png" class="pcrt-logo" style="max-width:42px;" />
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3> <div class="site-title">
<div class="type"><?= Yii::$app->params['name_first'] ?></div>
<div class="name"><?= Yii::$app->params['name_last'] ?></div>
</div> </div>
<div class="panel-body"> </a>
<div class="card" style="max-width: 32.5rem;width: 100%;">
<div class="card-body">
<div class="title"><?= Html::encode($this->title) ?></div>
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'id' => $model->formName(), 'id' => $model->formName(),
@ -49,11 +54,10 @@ $this->params['breadcrumbs'][] = $this->title;
<?= $form->field($model, 'gdpr_consent')->checkbox(['value' => 1]) ?> <?= $form->field($model, 'gdpr_consent')->checkbox(['value' => 1]) ?>
<?php endif ?> <?php endif ?>
<?= Html::submitButton(Yii::t('usuario', 'Sign up'), ['class' => 'btn btn-success btn-block']) ?> <?= Html::submitButton(Yii::t('usuario', 'Sign up'), ['class' => 'btn btn-primary btn-block']) ?>
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>
</div> </div>
</div>
<p class="text-center"> <p class="text-center">
<?= Html::a(Yii::t('usuario', 'Already registered? Sign in!'), ['/user/security/login']) ?> <?= Html::a(Yii::t('usuario', 'Already registered? Sign in!'), ['/user/security/login']) ?>
</p> </p>

View File

@ -20,13 +20,17 @@ use yii\widgets\ActiveForm;
$this->title = Yii::t('usuario', 'Request new confirmation message'); $this->title = Yii::t('usuario', 'Request new confirmation message');
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<div class="row"> <div class="site-login">
<div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3"> <a href="/site/login" class="d-flex align-items-center justify-content-center mb-4">
<div class="panel panel-default"> <img src="/img/logotipo.png" class="pcrt-logo" style="max-width:42px;" />
<div class="panel-heading"> <div class="site-title">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3> <div class="type"><?= Yii::$app->params['name_first'] ?></div>
<div class="name"><?= Yii::$app->params['name_last'] ?></div>
</div> </div>
<div class="panel-body"> </a>
<div class="card" style="max-width: 32.5rem;width: 100%;">
<div class="card-body">
<div class="title"><?= Html::encode($this->title) ?></div>
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'id' => $model->formName(), 'id' => $model->formName(),
@ -42,5 +46,4 @@ $this->params['breadcrumbs'][] = $this->title;
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>
</div> </div>
</div> </div>
</div>
</div> </div>

View File

@ -15,7 +15,7 @@
*/ */
use Da\User\Helper\AuthHelper; use Da\User\Helper\AuthHelper;
use dosamigos\selectize\SelectizeDropDownList; use pcrt\widgets\select2\Select2;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
@ -27,6 +27,7 @@ $unassignedItems = Yii::$container->get(AuthHelper::class)->getUnassignedItems($
[ [
'enableClientValidation' => false, 'enableClientValidation' => false,
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'options' => ['class' => 'p-3'],
] ]
) ?> ) ?>
@ -34,23 +35,29 @@ $unassignedItems = Yii::$container->get(AuthHelper::class)->getUnassignedItems($
<?= $form->field($model, 'description') ?> <?= $form->field($model, 'description') ?>
<?= $form->field($model, 'rule')->widget(SelectizeDropDownList::class, [ <?= $form->field($model, 'rule')->widget(Select2::class, [
'items' => ArrayHelper::map(Yii::$app->getAuthManager()->getRules(), 'name', 'name'), 'items' => ArrayHelper::map(Yii::$app->getAuthManager()->getRules(), 'name', 'name'),
'options' => [ 'options' => [
'prompt' => 'Select rule...' 'placeholder' => Yii::t('usuario', 'Select rule...'),
] 'multiple' => false,
],
'clientOptions' => [
'allowClear' => true,
'width' => '100%',
],
]) ?> ]) ?>
<?= $form->field($model, 'children')->widget( <?= $form->field($model, 'children')->widget(Select2::class, [
SelectizeDropDownList::class,
[
'items' => $unassignedItems, 'items' => $unassignedItems,
'options' => [ 'options' => [
'id' => 'children', 'placeholder' => Yii::t('usuario', 'Select children...'),
'multiple' => true, 'multiple' => true
], ],
] 'clientOptions' => [
) ?> 'allowClear' => true,
'width' => '100%',
],
]) ?>
<?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-success btn-block']) ?> <?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-success btn-block']) ?>

View File

@ -26,9 +26,10 @@ $this->params['breadcrumbs'][] = $this->title;
?> ?>
<?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?> <?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?>
<div class="table-responsive"> <div class="table-responsive p-3">
<?= GridView::widget( <?= GridView::widget(
[ [
'options' => ['class' => 'flex-grow-1'],
'dataProvider' => $dataProvider, 'dataProvider' => $dataProvider,
'filterModel' => $searchModel, 'filterModel' => $searchModel,
'layout' => "{items}\n{pager}", 'layout' => "{items}\n{pager}",
@ -66,6 +67,6 @@ $this->params['breadcrumbs'][] = $this->title;
], ],
], ],
] ]
) ?> ) ?>
</div> </div>
<?php $this->endContent() ?> <?php $this->endContent() ?>

View File

@ -15,6 +15,7 @@ use yii\widgets\ActiveForm;
[ [
'enableClientValidation' => false, 'enableClientValidation' => false,
'enableAjaxValidation' => true, 'enableAjaxValidation' => true,
'options' => ['class' => 'p-3'],
] ]
) ?> ) ?>
@ -22,6 +23,13 @@ use yii\widgets\ActiveForm;
<?= $form->field($model, 'className') ?> <?= $form->field($model, 'className') ?>
<?= Html::submitButton(Yii::t('usuario', 'Save'), ['class' => 'btn btn-success btn-block']) ?> <div class="form-group d-flex justify-content-center">
<div class="w-75">
<?= Html::submitButton(
Yii::t('usuario', 'Save'),
['class' => 'btn btn-block btn-success']
) ?>
</div>
</div>
<?php ActiveForm::end() ?> <?php ActiveForm::end() ?>

View File

@ -18,9 +18,10 @@ $this->params['breadcrumbs'][] = $this->title;
?> ?>
<?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?> <?php $this->beginContent($module->viewPath . '/shared/admin_layout.php') ?>
<div class="table-responsive"> <div class="table-responsive d-flex p-3">
<?= GridView::widget( <?= GridView::widget(
[ [
'options' => ['class' => 'flex-grow-1'],
'dataProvider' => $dataProvider, 'dataProvider' => $dataProvider,
'filterModel' => $searchModel, 'filterModel' => $searchModel,
'layout' => "{items}\n{pager}", 'layout' => "{items}\n{pager}",

View File

@ -23,15 +23,20 @@ $this->title = Yii::t('usuario', 'Sign in');
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?> <div class="site-login">
<a href="/site/login" class="d-flex align-items-center justify-content-center mb-4">
<div class="row"> <img src="/img/logotipo.png" class="pcrt-logo" style="max-width:42px;" />
<div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3"> <div class="site-title">
<div class="panel panel-default"> <div class="type"><?= Yii::$app->params['name_first'] ?></div>
<div class="panel-heading"> <div class="name"><?= Yii::$app->params['name_last'] ?></div>
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3>
</div> </div>
<div class="panel-body"> </a>
<div class="container px-0" style="max-width: 32.5rem;width: 100%;">
<?= $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?>
</div>
<div class="card" style="max-width: 32.5rem;width: 100%;">
<div class="card-body">
<div class="title"><?= Html::encode($this->title) ?></div>
<?php $form = ActiveForm::begin( <?php $form = ActiveForm::begin(
[ [
'id' => $model->formName(), 'id' => $model->formName(),
@ -62,13 +67,11 @@ $this->params['breadcrumbs'][] = $this->title;
' (' . Html::a( ' (' . Html::a(
Yii::t('usuario', 'Forgot password?'), Yii::t('usuario', 'Forgot password?'),
['/user/recovery/request'], ['/user/recovery/request'],
['tabindex' => '5'] ['tabindex' => '4']
) )
. ')' : '') . ')' : '')
) ?> ) ?>
<?= $form->field($model, 'rememberMe')->checkbox(['tabindex' => '4']) ?>
<?= Html::submitButton( <?= Html::submitButton(
Yii::t('usuario', 'Sign in'), Yii::t('usuario', 'Sign in'),
['class' => 'btn btn-primary btn-block', 'tabindex' => '3'] ['class' => 'btn btn-primary btn-block', 'tabindex' => '3']
@ -76,7 +79,6 @@ $this->params['breadcrumbs'][] = $this->title;
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>
</div> </div>
</div>
<?php if ($module->enableEmailConfirmation): ?> <?php if ($module->enableEmailConfirmation): ?>
<p class="text-center"> <p class="text-center">
<?= Html::a( <?= Html::a(

View File

@ -1,65 +0,0 @@
<?php
/*
* This file is part of the 2amigos/yii2-usuario project.
*
* (c) 2amigOS! <http://2amigos.us/>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use yii\helpers\Html;
use yii\widgets\Menu;
use Da\User\Module as UserModule;
use Da\User\Model\User;
/** @var User $user */
$user = Yii::$app->user->identity;
/** @var UserModule $module */
$module = Yii::$app->getModule('user');
$networksVisible = count(Yii::$app->authClientCollection->clients) > 0;
?>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<?= Html::img(
$user->profile->getAvatarUrl(24),
[
'class' => 'img-rounded',
'alt' => $user->username,
]
) ?>
<?= $user->username ?>
</h3>
</div>
<div class="panel-body">
<?= Menu::widget(
[
'options' => [
'class' => 'nav nav-pills nav-stacked',
],
'items' => [
['label' => Yii::t('usuario', 'Profile'), 'url' => ['/user/settings/profile']],
['label' => Yii::t('usuario', 'Account'), 'url' => ['/user/settings/account']],
[
'label' => Yii::t('usuario', 'Session history'),
'url' => ['/user/settings/session-history'],
'visible' => $module->enableSessionHistory,
],
['label' => Yii::t('usuario', 'Privacy'),
'url' => ['/user/settings/privacy'],
'visible' => $module->enableGdprCompliance
],
[
'label' => Yii::t('usuario', 'Networks'),
'url' => ['/user/settings/networks'],
'visible' => $networksVisible,
],
],
]
) ?>
</div>
</div>

View File

@ -1,60 +0,0 @@
<?php
/*
* This file is part of the 2amigos/yii2-usuario project.
*
* (c) 2amigOS! <http://2amigos.us/>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use yii\widgets\ActiveForm;
use yii\helpers\Html;
/** @var \Da\User\Form\GdprDeleteForm $model */
?>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">
<?= Yii::t('usuario', 'Delete personal data') ?>
</h3>
</div>
<div class="panel-body">
<p><?= Yii::t('usuario', 'You are about to delete all your personal data from this site.') ?></p>
<p class="text-danger">
<?= Yii::t(
'usuario',
'Once you have deleted your data, you will not longer be able to sign in with this account.'
) ?>
</p>
<hr>
<?php
$form = ActiveForm::begin([])
?>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<?= $form->field($model, 'password')->passwordInput() ?>
</div>
</div>
<div class="row">
<div class="col-md-12 text-center">
<?= Html::submitButton(Yii::t('usuario', 'Delete'), ['class' => 'btn btn-danger']) ?>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-12 text-center">
<?= Html::a(Yii::t('usuario', 'Back to privacy settings'), ['/user/settings/privacy'], ['class' => 'btn btn-info']) ?>
</div>
</div>
<?php
ActiveForm::end();
?>
</div>
</div>
</div>
</div>

View File

@ -1,71 +0,0 @@
<?php
use yii\helpers\Html;
/** @var \yii\web\View $this */
/** @var \Da\User\Module $module */
$this->title = Yii::t('usuario', 'Privacy settings');
?>
<div class="row">
<div class="col-md-3">
<?= $this->render('_menu') ?>
</div>
<div class="col-md-9">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<h3><?= Yii::t('usuario', 'Export my data') ?></h3>
<p><?= Yii::t(
'usuario',
'Here you can download your personal data in a comma separated values format.'
) ?>
</p>
<?= Html::a(Yii::t('usuario', 'Download my data'),
['/user/settings/export'],
[
'class' => 'btn btn-info',
'target' => '_blank'
])
?>
</div>
<div class="col-md-6">
<h3><?= Yii::t('usuario', 'Delete my account') ?></h3>
<p><?= Yii::t(
'usuario',
'This will remove your personal data from this site. You will no longer be able to sign in.'
) ?>
</p>
<?php if ($module->allowAccountDelete): ?>
<?= Html::a(
Yii::t('usuario', 'Delete account'),
['delete'],
[
'id' => 'gdpr-del-button',
'class' => 'btn btn-danger',
'data-method' => 'post',
'data-confirm' => Yii::t('usuario', 'Are you sure? There is no going back'),
]
) ?>
<?php else:
echo Html::a(Yii::t('usuario', 'Delete'),
['/user/settings/gdpr-delete'],
[
'class' => 'btn btn-danger',
'id' => 'gdpr-del-button',
])
?>
<?php endif ?>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -9,15 +9,14 @@
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
use yii\bootstrap\Alert; use yii\bootstrap4\Alert;
/** @var \Da\User\Module $module */ /** @var \Da\User\Module $module */
?> ?>
<?php if ($module->enableFlashMessages): ?> <?php if ($module->enableFlashMessages): ?>
<div class="row"> <div class="container-fluid px-0">
<div class="col-xs-12">
<?php foreach (Yii::$app->session->getAllFlashes(true) as $type => $message): ?> <?php foreach (Yii::$app->session->getAllFlashes(true) as $type => $message): ?>
<?php if (in_array($type, ['success', 'danger', 'warning', 'info'], true)): ?> <?php if (in_array($type, ['success', 'danger', 'warning', 'info'], true)): ?>
<?= Alert::widget( <?= Alert::widget(
@ -29,5 +28,4 @@ use yii\bootstrap\Alert;
<?php endif ?> <?php endif ?>
<?php endforeach ?> <?php endforeach ?>
</div> </div>
</div>
<?php endif ?> <?php endif ?>

View File

@ -9,54 +9,42 @@
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
use yii\bootstrap\Nav; use yii\bootstrap4\Nav;
$currentRoute = Yii::$app->controller->getRoute();
?> ?>
<?= Nav::widget( <nav>
[ <div class="nav nav-tabs" id="nav-tab" role="tablist">
'options' => [ <a class="nav-item nav-link <?= $currentRoute == 'user/admin/index' ? 'active' : '' ?>" href="<?= \yii\helpers\Url::to(['/user/admin/index']) ?>">
'class' => 'nav-tabs', <?= Yii::t('usuario', 'Users') ?>
'style' => 'margin-bottom: 15px', </a>
], <a class="nav-item nav-link <?= $currentRoute == 'user/role/index' ? 'active' : '' ?>" href="<?= \yii\helpers\Url::to(['/user/role/index']) ?>">
'items' => [ <?= Yii::t('usuario', 'Roles') ?>
[ </a>
'label' => Yii::t('usuario', 'Users'), <a class="nav-item nav-link <?= $currentRoute == 'user/permission/index' ? 'active' : '' ?>" href="<?= \yii\helpers\Url::to(['/user/permission/index']) ?>">
'url' => ['/user/admin/index'], <?= Yii::t('usuario', 'Permissions') ?>
], </a>
[ <a class="nav-item nav-link <?= $currentRoute == 'user/rule/index' ? 'active' : '' ?>" href="<?= \yii\helpers\Url::to(['/user/rule/index']) ?>">
'label' => Yii::t('usuario', 'Roles'), <?= Yii::t('usuario', 'Rules') ?>
'url' => ['/user/role/index'], </a>
], <div class="nav-item dropdown">
[ <a class="nav-link dropdown-toggle <?= (substr($currentRoute, strrpos($currentRoute, '/') + 1) === 'create') ? 'active' : '' ?>" id="create-tab" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
'label' => Yii::t('usuario', 'Permissions'), <?= Yii::t('usuario', 'Create') ?>
'url' => ['/user/permission/index'], </a>
], <div class="dropdown-menu" aria-labelledby="create-tab">
[ <a class="dropdown-item" href="<?= \yii\helpers\Url::to(['/user/admin/create']) ?>">
'label' => Yii::t('usuario', 'Rules'), <?= Yii::t('usuario', 'New user') ?>
'url' => ['/user/rule/index'], </a>
], <a class="dropdown-item" href="<?= \yii\helpers\Url::to(['/user/role/create']) ?>">
[ <?= Yii::t('usuario', 'New role') ?>
'label' => Yii::t('usuario', 'Create'), </a>
'items' => [ <a class="dropdown-item" href="<?= \yii\helpers\Url::to(['/user/permission/create']) ?>">
[ <?= Yii::t('usuario', 'New permission') ?>
'label' => Yii::t('usuario', 'New user'), </a>
'url' => ['/user/admin/create'], <a class="dropdown-item" href="<?= \yii\helpers\Url::to(['/user/rule/create']) ?>">
], <?= Yii::t('usuario', 'New rule') ?>
[ </a>
'label' => Yii::t('usuario', 'New role'), </div>
'url' => ['/user/role/create'], </div>
], </div>
[ </nav>
'label' => Yii::t('usuario', 'New permission'),
'url' => ['/user/permission/create'],
],
[
'label' => Yii::t('usuario', 'New rule'),
'url' => ['/user/rule/create'],
],
],
],
],
]
) ?>

View File

@ -24,16 +24,9 @@ use yii\helpers\Html;
] ]
) ?> ) ?>
<div class="row"> <div class="container-fluid px-0">
<div class="col-md-12"> <div class="tab-wrapper">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="panel-body">
<?= $this->render('/shared/_menu') ?> <?= $this->render('/shared/_menu') ?>
<?= $content ?> <?= $content ?>
</div> </div>
</div>
</div>
</div> </div>

View File

@ -9,8 +9,8 @@
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
use dosamigos\selectize\SelectizeDropDownList; use pcrt\widgets\select2\Select2;
use yii\bootstrap\Alert; use yii\bootstrap4\Alert;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
@ -43,16 +43,17 @@ use yii\widgets\ActiveForm;
<?= Html::activeHiddenInput($model, 'user_id') ?> <?= Html::activeHiddenInput($model, 'user_id') ?>
<?= $form->field($model, 'items')->widget( <?= $form->field($model, 'items')->widget(Select2::class, [
SelectizeDropDownList::class,
[
'items' => $availableItems, 'items' => $availableItems,
'options' => [ 'options' => [
'id' => 'children', 'placeholder' => Yii::t('usuario', 'Select items...'),
'multiple' => true, 'multiple' => true
], ],
] 'clientOptions' => [
) ?> 'allowClear' => true,
'width' => '100%',
],
]) ?>
<?= Html::submitButton(Yii::t('usuario', 'Update assignments'), ['class' => 'btn btn-success btn-block']) ?> <?= Html::submitButton(Yii::t('usuario', 'Update assignments'), ['class' => 'btn btn-success btn-block']) ?>