├── .gitignore ├── Bootstrap.php ├── CHANGELOG.md ├── Module.php ├── README.md ├── composer.json ├── controllers ├── AdminController.php ├── CrudController.php ├── DefaultController.php ├── GuestController.php └── UserController.php ├── helpers └── Security.php ├── mails ├── layouts │ └── html.php └── views │ ├── email.php │ ├── recovery.php │ ├── ru │ ├── email.php │ ├── recovery.php │ └── signup.php │ └── signup.php ├── messages ├── config.php ├── en │ └── users.php ├── ru │ └── users.php └── uk │ └── users.php ├── migrations └── m140418_204054_create_module_tbl.php ├── models ├── LoginForm.php ├── Profile.php ├── User.php ├── UserQuery.php ├── backend │ ├── User.php │ └── UserSearch.php └── frontend │ ├── ActivationForm.php │ ├── Email.php │ ├── PasswordForm.php │ ├── RecoveryConfirmationForm.php │ ├── RecoveryForm.php │ ├── ResendForm.php │ └── User.php ├── traits └── ModuleTrait.php └── views ├── admin └── login.php ├── crud ├── _form.php ├── create.php ├── index.php ├── update.php └── view.php ├── default ├── _index_item.php ├── _index_loop.php ├── index.php └── view.php ├── guest ├── login.php ├── recovery-confirmation.php ├── recovery.php ├── resend.php └── signup.php └── user ├── email.php ├── password.php └── update.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /Bootstrap.php: -------------------------------------------------------------------------------- 1 | urlManager->addRules( 19 | [ 20 | '<_m:users>' => '<_m>/default/index', 21 | '<_a:(login|signup|activation|recovery|recovery-confirmation|resend)>' => 'users/guest/<_a>', 22 | '<_a:logout>' => 'users/user/<_a>', 23 | '<_a:email>' => 'users/default/<_a>', 24 | '<_m:users>/' => '<_m>/default/view', 25 | 'my/settings/<_a:[\w\-]+>' => 'users/user/<_a>', 26 | ], 27 | false 28 | ); 29 | 30 | // Add module I18N category. 31 | if (!isset($app->i18n->translations['users']) && !isset($app->i18n->translations['users*'])) { 32 | $app->i18n->translations['users'] = [ 33 | 'class' => 'yii\i18n\PhpMessageSource', 34 | 'basePath' => '@vova07/users/messages', 35 | 'forceTranslation' => true 36 | ]; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 1.0 2 | --- 3 | 4 | - Code refactoring for universal compatibility (vova07) 5 | - Initial release (vova07) -------------------------------------------------------------------------------- /Module.php: -------------------------------------------------------------------------------- 1 | name . ' robot'`. 26 | */ 27 | public $robotName; 28 | 29 | /** 30 | * @var integer The time before a sent activation token becomes invalid. 31 | * By default is 24 hours. 32 | */ 33 | public $activationWithin = 86400; // 24 hours 34 | 35 | /** 36 | * @var integer The time before a sent recovery token becomes invalid. 37 | * By default is 4 hours. 38 | */ 39 | public $recoveryWithin = 14400; // 4 hours 40 | 41 | /** 42 | * @var integer The time before a sent confirmation token becomes invalid. 43 | * By default is 4 hours. 44 | */ 45 | public $emailWithin = 14400; // 4 hours 46 | 47 | /** 48 | * @var integer Users per page 49 | */ 50 | public $recordsPerPage = 10; 51 | 52 | /** 53 | * @var array User roles that can access backend module. 54 | */ 55 | public $adminRoles = ['superadmin', 'admin']; 56 | 57 | /** 58 | * @var \yii\swiftmailer\Mailer Mailer instance 59 | */ 60 | private $_mail; 61 | 62 | /** 63 | * @return \yii\swiftmailer\Mailer Mailer instance with predefined templates. 64 | */ 65 | public function getMail() 66 | { 67 | if ($this->_mail === null) { 68 | $this->_mail = Yii::$app->getMailer(); 69 | $this->_mail->htmlLayout = '@vova07/users/mails/layouts/html'; 70 | $this->_mail->textLayout = '@vova07/users/mails/layouts/text'; 71 | $this->_mail->viewPath = '@vova07/users/mails/views'; 72 | if ($this->robotEmail !== null) { 73 | $this->_mail->messageConfig['from'] = $this->robotName === null ? $this->robotEmail : [$this->robotEmail => $this->robotName]; 74 | } 75 | } 76 | return $this->_mail; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Yii2 users module. 2 | ================== 3 | This module provide a users managing system for your yii2 application. 4 | 5 | Installation 6 | ------------ 7 | 8 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 9 | 10 | Either run 11 | 12 | ``` 13 | php composer.phar require --prefer-dist vova07/yii2-users-module "*" 14 | ``` 15 | 16 | or add 17 | 18 | ``` 19 | "vova07/yii2-users-module": "*" 20 | ``` 21 | 22 | to the require section of your `composer.json` file. 23 | 24 | Configuration 25 | ------------- 26 | 27 | Add `yii2-users-module` to `module` section of each application config: 28 | 29 | ```php 30 | 'modules' => [ 31 | 'users' => [ 32 | 'class' => 'vova07\users\Module', 33 | 'requireEmailConfirmation' => false, // By default is true. It mean that new user will need to confirm their email address. 34 | 'robotEmail' => 'my@robot.email', // E-mail address from that will be sent all `users` emails. 35 | 'robotName' => 'My Robot Name', // By default is `Yii::$app->name . ' robot'`. 36 | 'activationWithin' => 86400, // The time before a sent activation token becomes invalid. 37 | 'recoveryWithin' => 14400, // The time before a sent recovery token becomes invalid. 38 | 'recordsPerPage' => 10, // Users pe page. 39 | 'adminRoles' => ['superadmin', 'admin'], // User roles that can access backend module. 40 | ] 41 | ] 42 | ``` 43 | 44 | Add or edit `user` component section: 45 | 46 | ```php 47 | 'user' => [ 48 | 'class' => 'yii\web\User', 49 | 'identityClass' => 'vova07\users\models\User', 50 | 'loginUrl' => ['/users/guest/login'] // For frontend app 51 | // 'loginUrl' => ['/users/admin/login'] // For backend app 52 | ] 53 | ``` 54 | 55 | Add or edit `authManager` component section: 56 | 57 | ```php 58 | 'authManager' => [ 59 | 'class' => 'yii\rbac\PhpManager', 60 | 'defaultRoles' => [ 61 | 'user', 62 | 'admin', 63 | 'superadmin' 64 | ], 65 | 'itemFile' => '@vova07/rbac/data/items.php', 66 | 'assignmentFile' => '@vova07/rbac/data/assignments.php', 67 | 'ruleFile' => '@vova07/rbac/data/rules.php', 68 | ] 69 | ``` 70 | 71 | Run module migration: 72 | 73 | ```php 74 | php yii migrate --migrationPath=@vova07/users/migrations 75 | ``` 76 | 77 | Usage 78 | ----- 79 | 80 | Once the extension is installed, simply use it in your code by: 81 | 82 | ```php 83 | Yii::$app->getModule('users'); 84 | ``` 85 | 86 | By default will be created one `superadmin` user with login `admin` and password `admin12345`. 87 | 88 | After installation you'll be able to access below links (relative to your site domain): 89 | ### Frontend: ### 90 | - `/users/` - All users page 91 | - `/users/admin/` - Admin page 92 | - `/login/` - Log In page 93 | - `/logout/` - Log Out page 94 | - `/signup/` - Sign Up page 95 | - `/recovery/` - Password recovery page 96 | - `/resend/` - Resend email activation token 97 | - `/activation/` - Accaunt activation page 98 | - `/recovery-confirmation/` - Password reset page 99 | - `/my/settings/email/` - Email change page 100 | - `/my/settings/password/` - Password change page 101 | - `/my/settings/update/` - Profile update page 102 | 103 | ### Backend ### 104 | You'll need to specify universal route `'<_m>/<_c>/<_a>' => '<_m>/<_c>/<_a>'` in your config file to access module actions. 105 | - `/users/admin/login/` - Log In page 106 | - `/users/admin/logout/` - Log Out page 107 | - `/users/crud/index/` - All users page 108 | - `/users/crud/view/` - User page 109 | - `/users/crud/create/` - Create new user page 110 | - `/users/crud/update/` - Update user page 111 | - `/users/crud/delete/` - Delete one user 112 | - `/users/crud/batch-delete/` - Delete more users 113 | 114 | Dependences 115 | ----------- 116 | - [yii2-control-widget](https://github.com/vova07/yii2-control-widget) 117 | - [yii2-rbac-module](https://github.com/vova07/yii2-rbac-module) 118 | - [yii2-swiftmailer](https://github.com/yiisoft/yii2/tree/master/extensions/swiftmailer) 119 | - [yii2](https://github.com/yiisoft/yii2) 120 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vova07/yii2-users-module", 3 | "description": "The users module for Yii framework.", 4 | "type": "yii2-extension", 5 | "keywords": ["yii2", "yii 2", "users", "user", "module", "modules", "account", "management", "profile", "profiles"], 6 | "license": "BSD-3-Clause", 7 | "authors": [ 8 | { 9 | "name": "Crudu Vasile", 10 | "email": "bazillio07@yandex.ru" 11 | } 12 | ], 13 | "support": { 14 | "issues": "https://github.com/vova07/yii2-users-module/issues?state=open", 15 | "source": "https://github.com/vova07/yii2-users-module" 16 | }, 17 | "require": { 18 | "yiisoft/yii2": "*", 19 | "yiisoft/yii2-swiftmailer": "*", 20 | "yiisoft/yii2-bootstrap": "*", 21 | "vova07/yii2-rbac-module": "*", 22 | "vova07/yii2-control-widget": "*" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "vova07\\users\\": "" 27 | } 28 | }, 29 | "extra": { 30 | "bootstrap": "vova07\\users\\Bootstrap" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /controllers/AdminController.php: -------------------------------------------------------------------------------- 1 | [ 24 | 'class' => AccessControl::className(), 25 | 'rules' => [ 26 | [ 27 | 'actions' => ['login'], 28 | 'allow' => true, 29 | 'roles' => ['?'] 30 | ], 31 | [ 32 | 'actions' => ['logout'], 33 | 'allow' => true, 34 | 'roles' => ['@'] 35 | ] 36 | ] 37 | ] 38 | ]; 39 | } 40 | 41 | /** 42 | * Login user. 43 | */ 44 | public function actionLogin() 45 | { 46 | if (!Yii::$app->user->isGuest) { 47 | $this->goHome(); 48 | } 49 | 50 | $model = new LoginForm(['scenario' => 'admin']); 51 | 52 | if ($model->load(Yii::$app->request->post())) { 53 | if ($model->validate()) { 54 | if ($model->login()) { 55 | return $this->goBack(); 56 | } 57 | } elseif (Yii::$app->request->isAjax) { 58 | Yii::$app->response->format = Response::FORMAT_JSON; 59 | return ActiveForm::validate($model); 60 | } 61 | } 62 | 63 | return $this->render( 64 | 'login', 65 | [ 66 | 'model' => $model 67 | ] 68 | ); 69 | } 70 | 71 | /** 72 | * Logout user. 73 | */ 74 | public function actionLogout() 75 | { 76 | Yii::$app->user->logout(); 77 | 78 | return $this->goHome(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /controllers/CrudController.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'class' => AccessControl::className(), 29 | 'rules' => [ 30 | [ 31 | 'allow' => true, 32 | 'roles' => $this->module->adminRoles 33 | ] 34 | ] 35 | ], 36 | 'verbs' => [ 37 | 'class' => VerbFilter::className(), 38 | 'actions' => [ 39 | 'index' => ['get'], 40 | 'view' => ['get'], 41 | 'create' => ['get', 'post'], 42 | 'update' => ['get', 'put', 'post'], 43 | 'delete' => ['post', 'delete'], 44 | 'batch-delete' => ['post', 'delete'] 45 | ] 46 | ] 47 | ]; 48 | } 49 | 50 | /** 51 | * Users page. 52 | */ 53 | function actionIndex() 54 | { 55 | $searchModel = new UserSearch(); 56 | $dataProvider = $searchModel->search(Yii::$app->request->get()); 57 | $statusArray = User::getStatusArray(); 58 | $roleArray = User::getRoleArray(); 59 | 60 | return $this->render( 61 | 'index', 62 | [ 63 | 'dataProvider' => $dataProvider, 64 | 'searchModel' => $searchModel, 65 | 'roleArray' => $roleArray, 66 | 'statusArray' => $statusArray 67 | ] 68 | ); 69 | } 70 | 71 | /** 72 | * User page. 73 | * 74 | * @param integer $id User ID 75 | */ 76 | public function actionView($id) 77 | { 78 | return $this->render( 79 | 'view', 80 | [ 81 | 'model' => $this->findModel($id), 82 | ] 83 | ); 84 | } 85 | 86 | /** 87 | * Create new user. 88 | */ 89 | public function actionCreate() 90 | { 91 | $user = new User(['scenario' => 'admin-create']); 92 | $profile = new Profile(); 93 | $statusArray = User::getStatusArray(); 94 | $roleArray = User::getRoleArray(); 95 | 96 | if ($user->load(Yii::$app->request->post()) && $profile->load(Yii::$app->request->post())) { 97 | if ($user->validate() && $profile->validate()) { 98 | $user->populateRelation('profile', $profile); 99 | if ($user->save(false)) { 100 | return $this->redirect(['update', 'id' => $user->id]); 101 | } else { 102 | Yii::$app->session->setFlash('danger', Yii::t('users', 'BACKEND_FLASH_FAIL_ADMIN_CREATE')); 103 | return $this->refresh(); 104 | } 105 | } elseif (Yii::$app->request->isAjax) { 106 | Yii::$app->response->format = Response::FORMAT_JSON; 107 | return array_merge(ActiveForm::validate($user), ActiveForm::validate($profile)); 108 | } 109 | } 110 | 111 | return $this->render( 112 | 'create', 113 | [ 114 | 'user' => $user, 115 | 'profile' => $profile, 116 | 'roleArray' => $roleArray, 117 | 'statusArray' => $statusArray 118 | ] 119 | ); 120 | } 121 | 122 | /** 123 | * Update user. 124 | * 125 | * @param integer $id User ID 126 | */ 127 | public function actionUpdate($id) 128 | { 129 | $user = $this->findModel($id); 130 | $user->setScenario('admin-update'); 131 | $profile = $user->profile; 132 | $statusArray = User::getStatusArray(); 133 | $roleArray = User::getRoleArray(); 134 | 135 | if ($user->load(Yii::$app->request->post()) && $profile->load(Yii::$app->request->post())) { 136 | if ($user->validate() && $profile->validate()) { 137 | $user->populateRelation('profile', $profile); 138 | if (!$user->save(false)) { 139 | Yii::$app->session->setFlash('danger', Yii::t('users', 'BACKEND_FLASH_FAIL_ADMIN_CREATE')); 140 | } 141 | return $this->refresh(); 142 | } elseif (Yii::$app->request->isAjax) { 143 | Yii::$app->response->format = Response::FORMAT_JSON; 144 | return array_merge(ActiveForm::validate($user), ActiveForm::validate($profile)); 145 | } 146 | } 147 | 148 | return $this->render( 149 | 'update', 150 | [ 151 | 'user' => $user, 152 | 'profile' => $profile, 153 | 'roleArray' => $roleArray, 154 | 'statusArray' => $statusArray 155 | ] 156 | ); 157 | } 158 | 159 | /** 160 | * Delete user. 161 | * 162 | * @param integer $id User ID 163 | */ 164 | public function actionDelete($id) 165 | { 166 | $this->findModel($id)->delete(); 167 | return $this->redirect(['index']); 168 | } 169 | 170 | /** 171 | * Delete multiple users. 172 | * 173 | * @throws HttpException 400 if $ids argument is null 174 | */ 175 | public function actionBatchDelete() 176 | { 177 | if (($ids = Yii::$app->request->post('ids')) !== null) { 178 | $models = $this->findModel($ids); 179 | foreach ($models as $model) { 180 | $model->delete(); 181 | } 182 | return $this->redirect(['index']); 183 | } else { 184 | throw new HttpException(400); 185 | } 186 | } 187 | 188 | /** 189 | * Find model by ID 190 | * @param integer|array $id User ID 191 | * @return User User model 192 | * @throws HttpException 404 error if user not found 193 | */ 194 | protected function findModel($id) 195 | { 196 | if (is_array($id)) { 197 | /** @var User $user */ 198 | $model = User::findIdentities($id); 199 | } else { 200 | /** @var User $user */ 201 | $model = User::findIdentity($id); 202 | } 203 | if ($model !== null) { 204 | return $model; 205 | } else { 206 | throw new HttpException(404); 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /controllers/DefaultController.php: -------------------------------------------------------------------------------- 1 | User::find()->active(), 24 | 'pagination' => [ 25 | 'pageSize' => $this->module->recordsPerPage 26 | ] 27 | ]); 28 | 29 | return $this->render( 30 | 'index', 31 | [ 32 | 'dataProvider' => $dataProvider 33 | ] 34 | ); 35 | } 36 | 37 | /** 38 | * User page. 39 | * 40 | * @param string $username Username 41 | */ 42 | public function actionView($username) 43 | { 44 | if (($model = User::findByUsername($username, 'active')) !== null) { 45 | return $this->render( 46 | 'view', 47 | [ 48 | 'model' => $model 49 | ] 50 | ); 51 | } else { 52 | throw new HttpException(404); 53 | } 54 | } 55 | 56 | /** 57 | * Confirm new e-mail address. 58 | * 59 | * @param string $key Confirmation token 60 | */ 61 | public function actionEmail($key) 62 | { 63 | $model = new Email(['token' => $key]); 64 | 65 | if ($model->isValidToken() === false) { 66 | Yii::$app->session->setFlash( 67 | 'danger', 68 | Yii::t('users', 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION_WITH_INVALID_KEY') 69 | ); 70 | } else { 71 | if ($model->confirm()) { 72 | Yii::$app->session->setFlash( 73 | 'success', 74 | Yii::t('users', 'FRONTEND_FLASH_SUCCESS_NEW_EMAIL_CONFIRMATION') 75 | ); 76 | } else { 77 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION')); 78 | } 79 | } 80 | 81 | return $this->goHome(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /controllers/GuestController.php: -------------------------------------------------------------------------------- 1 | [ 31 | 'class' => AccessControl::className(), 32 | 'rules' => [ 33 | [ 34 | 'allow' => true, 35 | 'roles' => ['?'] 36 | ] 37 | ] 38 | ] 39 | ]; 40 | } 41 | 42 | /** 43 | * Sign Up page. 44 | * If record will be successful created, user will be redirected to home page. 45 | */ 46 | public function actionSignup() 47 | { 48 | $user = new User(['scenario' => 'signup']); 49 | $profile = new Profile(); 50 | 51 | if ($user->load(Yii::$app->request->post()) && $profile->load(Yii::$app->request->post())) { 52 | if ($user->validate() && $profile->validate()) { 53 | $user->populateRelation('profile', $profile); 54 | if ($user->save(false)) { 55 | if ($this->module->requireEmailConfirmation === true) { 56 | Yii::$app->session->setFlash( 57 | 'success', 58 | Yii::t( 59 | 'users', 60 | 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITHOUT_LOGIN', 61 | [ 62 | 'url' => Url::toRoute('resend') 63 | ] 64 | ) 65 | ); 66 | } else { 67 | Yii::$app->user->login($user); 68 | Yii::$app->session->setFlash( 69 | 'success', 70 | Yii::t('users', 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITH_LOGIN') 71 | ); 72 | } 73 | return $this->goHome(); 74 | } else { 75 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_SIGNUP')); 76 | return $this->refresh(); 77 | } 78 | } elseif (Yii::$app->request->isAjax) { 79 | Yii::$app->response->format = Response::FORMAT_JSON; 80 | return ActiveForm::validate($user); 81 | } 82 | } 83 | 84 | return $this->render( 85 | 'signup', 86 | [ 87 | 'user' => $user, 88 | 'profile' => $profile 89 | ] 90 | ); 91 | } 92 | 93 | /** 94 | * Resend page. 95 | * Resend email confirmation token. 96 | */ 97 | public function actionResend() 98 | { 99 | $model = new ResendForm(); 100 | 101 | if ($model->load(Yii::$app->request->post())) { 102 | if ($model->validate()) { 103 | if ($model->resend()) { 104 | Yii::$app->session->setFlash('success', Yii::t('users', 'FRONTEND_FLASH_SUCCESS_RESEND')); 105 | return $this->goHome(); 106 | } else { 107 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_RESEND')); 108 | return $this->refresh(); 109 | } 110 | } elseif (Yii::$app->request->isAjax) { 111 | Yii::$app->response->format = Response::FORMAT_JSON; 112 | return ActiveForm::validate($model); 113 | } 114 | } 115 | 116 | return $this->render( 117 | 'resend', 118 | [ 119 | 'model' => $model 120 | ] 121 | ); 122 | } 123 | 124 | /** 125 | * Log In page. 126 | */ 127 | public function actionLogin() 128 | { 129 | if (!Yii::$app->user->isGuest) { 130 | $this->goHome(); 131 | } 132 | 133 | $model = new LoginForm(); 134 | 135 | if ($model->load(Yii::$app->request->post())) { 136 | if ($model->validate()) { 137 | if ($model->login()) { 138 | return $this->goBack(); 139 | } 140 | } elseif (Yii::$app->request->isAjax) { 141 | Yii::$app->response->format = Response::FORMAT_JSON; 142 | return ActiveForm::validate($model); 143 | } 144 | } 145 | 146 | return $this->render( 147 | 'login', 148 | [ 149 | 'model' => $model 150 | ] 151 | ); 152 | } 153 | 154 | /** 155 | * Activation page. 156 | * Activate a new user. 157 | * 158 | * @param string $key Activation token. 159 | */ 160 | public function actionActivation($key) 161 | { 162 | $model = new ActivationForm(['secure_key' => $key]); 163 | 164 | if ($model->validate() && $model->activation()) { 165 | Yii::$app->session->setFlash('success', Yii::t('users', 'FRONTEND_FLASH_SUCCESS_ACTIVATION')); 166 | } else { 167 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_ACTIVATION')); 168 | } 169 | 170 | return $this->goHome(); 171 | } 172 | 173 | /** 174 | * Recovery page. 175 | * Request password recovery. 176 | */ 177 | public function actionRecovery() 178 | { 179 | $model = new RecoveryForm(); 180 | 181 | if ($model->load(Yii::$app->request->post())) { 182 | if ($model->validate()) { 183 | if ($model->recovery()) { 184 | Yii::$app->session->setFlash('success', Yii::t('users', 'FRONTEND_FLASH_SUCCESS_RECOVERY')); 185 | return $this->goHome(); 186 | } else { 187 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_RECOVERY')); 188 | return $this->refresh(); 189 | } 190 | } elseif (Yii::$app->request->isAjax) { 191 | Yii::$app->response->format = Response::FORMAT_JSON; 192 | return ActiveForm::validate($model); 193 | } 194 | } 195 | 196 | return $this->render( 197 | 'recovery', 198 | [ 199 | 'model' => $model 200 | ] 201 | ); 202 | } 203 | 204 | /** 205 | * Recovery confirmation page. 206 | * Confirm password recovery request. 207 | * 208 | * @param string $key Confirmation token 209 | */ 210 | public function actionRecoveryConfirmation($key) 211 | { 212 | $model = new RecoveryConfirmationForm(['secure_key' => $key]); 213 | 214 | if (!$model->isValidSecureKey()) { 215 | Yii::$app->session->setFlash( 216 | 'danger', 217 | Yii::t('users', 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION_WITH_INVALID_KEY') 218 | ); 219 | return $this->goHome(); 220 | } 221 | 222 | if ($model->load(Yii::$app->request->post())) { 223 | if ($model->validate()) { 224 | if ($model->recovery()) { 225 | Yii::$app->session->setFlash( 226 | 'success', 227 | Yii::t('users', 'FRONTEND_FLASH_SUCCESS_RECOVERY_CONFIRMATION') 228 | ); 229 | return $this->goHome(); 230 | } else { 231 | Yii::$app->session->setFlash( 232 | 'danger', 233 | Yii::t('users', 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION') 234 | ); 235 | return $this->refresh(); 236 | } 237 | } elseif (Yii::$app->request->isAjax) { 238 | Yii::$app->response->format = Response::FORMAT_JSON; 239 | return ActiveForm::validate($model); 240 | } 241 | } 242 | 243 | return $this->render( 244 | 'recovery-confirmation', 245 | [ 246 | 'model' => $model 247 | ] 248 | ); 249 | 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /controllers/UserController.php: -------------------------------------------------------------------------------- 1 | [ 26 | 'class' => AccessControl::className(), 27 | 'rules' => [ 28 | [ 29 | 'allow' => true, 30 | 'roles' => ['@'] 31 | ] 32 | ] 33 | ] 34 | ]; 35 | } 36 | 37 | /** 38 | * Log Out page. 39 | */ 40 | public function actionLogout() 41 | { 42 | Yii::$app->user->logout(); 43 | 44 | return $this->goHome(); 45 | } 46 | 47 | /** 48 | * Change user password page. 49 | */ 50 | public function actionPassword() 51 | { 52 | $model = new PasswordForm(); 53 | 54 | if ($model->load(Yii::$app->request->post())) { 55 | if ($model->validate()) { 56 | if ($model->password()) { 57 | Yii::$app->session->setFlash('success', Yii::t('users', 'FRONTEND_FLASH_SUCCESS_PASSWORD_CHANGE')); 58 | return $this->redirect(['/users/default/view', 'username' => Yii::$app->user->identity->username]); 59 | } else { 60 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_PASSWORD_CHANGE')); 61 | return $this->refresh(); 62 | } 63 | } elseif (Yii::$app->request->isAjax) { 64 | Yii::$app->response->format = Response::FORMAT_JSON; 65 | return ActiveForm::validate($model); 66 | } 67 | } 68 | 69 | return $this->render( 70 | 'password', 71 | [ 72 | 'model' => $model 73 | ] 74 | ); 75 | } 76 | 77 | /** 78 | * Request email change page. 79 | */ 80 | public function actionEmail() 81 | { 82 | $model = new Email(); 83 | 84 | if ($model->load(Yii::$app->request->post())) { 85 | if ($model->validate()) { 86 | if ($model->save(false)) { 87 | Yii::$app->session->setFlash('success', Yii::t('users', 'FRONTEND_FLASH_SUCCES_EMAIL_CHANGE')); 88 | return $this->redirect(['/users/default/view', 'username' => Yii::$app->user->identity->username]); 89 | } else { 90 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_EMAIL_CHANGE')); 91 | return $this->refresh(); 92 | } 93 | } elseif (Yii::$app->request->isAjax) { 94 | Yii::$app->response->format = Response::FORMAT_JSON; 95 | return ActiveForm::validate($model); 96 | } 97 | } 98 | 99 | return $this->render( 100 | 'email', 101 | [ 102 | 'model' => $model 103 | ] 104 | ); 105 | } 106 | 107 | /** 108 | * User update page. 109 | */ 110 | public function actionUpdate() 111 | { 112 | $model = Profile::findByUserId(Yii::$app->user->id); 113 | 114 | if ($model->load(Yii::$app->request->post())) { 115 | if ($model->validate()) { 116 | if ($model->save(false)) { 117 | Yii::$app->session->setFlash('success', Yii::t('users', 'FRONTEND_FLASH_SUCCES_UPDATE')); 118 | } else { 119 | Yii::$app->session->setFlash('danger', Yii::t('users', 'FRONTEND_FLASH_FAIL_UPDATE')); 120 | } 121 | return $this->refresh(); 122 | } elseif (Yii::$app->request->isAjax) { 123 | Yii::$app->response->format = Response::FORMAT_JSON; 124 | return ActiveForm::validate($model); 125 | } 126 | } 127 | 128 | return $this->render( 129 | 'update', 130 | [ 131 | 'model' => $model 132 | ] 133 | ); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /helpers/Security.php: -------------------------------------------------------------------------------- 1 | getSecurity()->generateRandomKey() . '_' . time(); 20 | } 21 | 22 | /** 23 | * Check if token is not expired. 24 | * 25 | * @param string $token Token that must be validated 26 | * @param integer $duration Time during token is valid 27 | * @return boolean true if token is not expired 28 | */ 29 | public static function isValidToken($token, $duration) 30 | { 31 | $parts = explode('_', $token); 32 | $timestamp = (int)end($parts); 33 | return ($timestamp + $duration > time()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mails/layouts/html.php: -------------------------------------------------------------------------------- 1 | beginPage(); 11 | ?> 12 | 13 | 14 | 15 | 16 | <?= Html::encode($this->title) ?> 17 | head(); ?> 18 | 19 | 20 | beginBody(); ?> 21 | 22 | endBody(); ?> 23 | 24 | 25 | endPage(); ?> -------------------------------------------------------------------------------- /mails/views/email.php: -------------------------------------------------------------------------------- 1 | $model['token']], true); ?> 12 |

Hello,

13 |

Follow the link below to confirm your new e-mail:

14 |

-------------------------------------------------------------------------------- /mails/views/recovery.php: -------------------------------------------------------------------------------- 1 | $model['secure_key']], true); ?> 12 |

Hello ,

13 |

Follow the link below to recover your password:

14 |

-------------------------------------------------------------------------------- /mails/views/ru/email.php: -------------------------------------------------------------------------------- 1 | $model['token']], true); ?> 12 |

Здравствуйте!

13 |

Перейдите по ссылке ниже чтобы подтвердить новый электронный адрес:

14 |

-------------------------------------------------------------------------------- /mails/views/ru/recovery.php: -------------------------------------------------------------------------------- 1 | $model['secure_key']], true); ?> 12 |

Здравствуйте !

13 |

Перейдите по ссылке ниже чтобы восстановить пароль:

14 |

-------------------------------------------------------------------------------- /mails/views/ru/signup.php: -------------------------------------------------------------------------------- 1 | $model['secure_key']], true); ?> 12 |

Здравствуйте !

13 |

Перейдите по ссылке ниже чтобы подтвердить свой электронный адрес и активировать свой аккаунт:

14 |

-------------------------------------------------------------------------------- /mails/views/signup.php: -------------------------------------------------------------------------------- 1 | $model['secure_key']], true); ?> 12 |

Hello ,

13 |

Follow the link below to activate your account:

14 |

-------------------------------------------------------------------------------- /messages/config.php: -------------------------------------------------------------------------------- 1 | dirname(__DIR__), 5 | 'messagePath' => __DIR__, 6 | 'languages' => ['en', 'ru'], 7 | 'translator' => 'Yii::t', 8 | 'sort' => false, 9 | 'overwrite' => true, 10 | 'removeUnused' => true, 11 | 'only' => ['*.php'], 12 | 'except' => [ 13 | '.svn', 14 | '.git', 15 | '.gitignore', 16 | '.gitkeep', 17 | '.hgignore', 18 | '.hgkeep', 19 | '/messages', 20 | ], 21 | 'format' => 'php' 22 | ]; 23 | -------------------------------------------------------------------------------- /messages/en/users.php: -------------------------------------------------------------------------------- 1 | 'User has not been saved. Please try again!', 21 | 'EMAIL_SUBJECT_CHANGE' => 'Email confirmation token', 22 | 'EMAIL_SUBJECT_RECOVERY' => 'Your password reset request', 23 | 'EMAIL_SUBJECT_SIGNUP' => 'Email confirmation token', 24 | 'FRONTEND_FLASH_FAIL_ACTIVATION' => 'User has not been activated. Please try again!', 25 | 'FRONTEND_FLASH_FAIL_EMAIL_CHANGE' => 'Email has not been changed. Please try again!', 26 | 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION' => 'Email has not been confirmed. Please try again!', 27 | 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION_WITH_INVALID_KEY' => 'Invalid request token.', 28 | 'FRONTEND_FLASH_FAIL_PASSWORD_CHANGE' => 'Password has not been changed. Please try again!', 29 | 'FRONTEND_FLASH_FAIL_RECOVERY' => 'Password recovery failed. Please try again!', 30 | 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION' => 'Password recovery failed. Please try again!', 31 | 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION_WITH_INVALID_KEY' => 'Invalid request token.', 32 | 'FRONTEND_FLASH_FAIL_RESEND' => 'Resend email confirmation failed. Please try again!', 33 | 'FRONTEND_FLASH_FAIL_SIGNUP' => 'User sign up failed. Please try again!', 34 | 'FRONTEND_FLASH_FAIL_UPDATE' => 'Profile update failed. Please try again!', 35 | 'FRONTEND_FLASH_SUCCESS_ACTIVATION' => 'Your Account has been successfully activated. You can now log in using the username and password you chose during the registration.', 36 | 'FRONTEND_FLASH_SUCCESS_NEW_EMAIL_CONFIRMATION' => 'Your email has been successfully confirmed.', 37 | 'FRONTEND_FLASH_SUCCESS_PASSWORD_CHANGE' => 'Your password has been successfully changed.', 38 | 'FRONTEND_FLASH_SUCCESS_RECOVERY' => 'A verification link has been sent to the email address you entered.', 39 | 'FRONTEND_FLASH_SUCCESS_RECOVERY_CONFIRMATION' => 'Reset password successful. You may now login to the site.', 40 | 'FRONTEND_FLASH_SUCCESS_RESEND' => 'A verification link has been sent to the email address you entered.', 41 | 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITHOUT_LOGIN' => 'Your account has been created and a verification link has been sent to the email address you entered.', 42 | 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITH_LOGIN' => 'Your account has been created.', 43 | 'FRONTEND_FLASH_SUCCES_EMAIL_CHANGE' => 'Your email address has been successfully changed.', 44 | 'FRONTEND_FLASH_SUCCES_UPDATE' => 'Your account has been successfully updated.', 45 | 'ATTR_CREATED' => 'Created at', 46 | 'ATTR_EMAIL' => 'E-mail', 47 | 'ATTR_NAME' => 'Name', 48 | 'ATTR_NEW_EMAIL' => 'New e-mail', 49 | 'ATTR_NEW_PASSWORD' => 'New password', 50 | 'ATTR_NEW_REPASSWORD' => 'Repeat new password', 51 | 'ATTR_OLDEMAIL' => 'Current e-mail', 52 | 'ATTR_OLDPASSWORD' => 'Current password', 53 | 'ATTR_PASSWORD' => 'Password', 54 | 'ATTR_REMEMBER_ME' => 'Remember me', 55 | 'ATTR_REPASSWORD' => 'Repeat pssword', 56 | 'ATTR_ROLE' => 'Role', 57 | 'ATTR_SECURE_KEY' => 'Secure key', 58 | 'ATTR_STATUS' => 'Status', 59 | 'ATTR_SURNAME' => 'Surname', 60 | 'ATTR_UPDATED' => 'Updated at', 61 | 'ATTR_USERNAME' => 'Username', 62 | 'BACKEND_CREATE_SUBMIT' => 'Save', 63 | 'BACKEND_CREATE_TITLE' => 'Create new user', 64 | 'BACKEND_INDEX_TITLE' => 'Users page', 65 | 'BACKEND_LOGIN_OR' => 'or', 66 | 'BACKEND_LOGIN_RECOVERY' => 'Recover password', 67 | 'BACKEND_LOGIN_SUBMIT' => 'Log In', 68 | 'BACKEND_LOGIN_TITLE' => 'Log In', 69 | 'BACKEND_PROMPT_ROLE' => 'Select role', 70 | 'BACKEND_PROMPT_STATUS' => 'Select status', 71 | 'BACKEND_UPDATE_SUBMIT' => 'Update', 72 | 'BACKEND_UPDATE_TITLE' => 'Update user', 73 | 'BACKEND_VIEW_TITLE' => 'User page', 74 | 'ERROR_MSG_INVALID_OLD_PASSWORD' => 'Invalid current password', 75 | 'ERROR_MSG_INVALID_USERNAME_OR_PASSWORD' => 'Invalid username or password', 76 | 'FRONTEND_EMAIL_CHANGE_SUBMIT' => 'Change', 77 | 'FRONTEND_EMAIL_CHANGE_TITLE' => 'Change e-mail address', 78 | 'FRONTEND_INDEX_TITLE' => 'Users', 79 | 'FRONTEND_LOGIN_OR' => 'or', 80 | 'FRONTEND_LOGIN_RECOVERY' => 'Recover password', 81 | 'FRONTEND_LOGIN_SUBMIT' => 'Log In', 82 | 'FRONTEND_LOGIN_TITLE' => 'Log In', 83 | 'FRONTEND_PASSWORD_CHANGE_SUBMIT' => 'Change', 84 | 'FRONTEND_PASSWORD_CHANGE_TITLE' => 'Change password', 85 | 'FRONTEND_RECOVERY_CONFIRMATION_SUBMIT' => 'Save', 86 | 'FRONTEND_RECOVERY_CONFIRMATION_TITLE' => 'Password recovery', 87 | 'FRONTEND_RECOVERY_SUBMIT' => 'Recover', 88 | 'FRONTEND_RECOVERY_TITLE' => 'Password recovery', 89 | 'FRONTEND_RESEND_SUBMIT' => 'Resend', 90 | 'FRONTEND_RESEND_TITLE' => 'Resend e-mail confirmation', 91 | 'FRONTEND_SIGNUP_RESEND' => 'Resend e-mail confirmation', 92 | 'FRONTEND_SIGNUP_SUBMIT' => 'Sign Up', 93 | 'FRONTEND_SIGNUP_TITLE' => 'Sign Up', 94 | 'FRONTEND_UPDATE_SUBMIT' => 'Update', 95 | 'FRONTEND_UPDATE_TITLE' => 'Update user profile', 96 | 'STATUS_ACTIVE' => 'Active', 97 | 'STATUS_BANNED' => 'Banned', 98 | 'STATUS_INACTIVE' => 'Inactive', 99 | ]; 100 | -------------------------------------------------------------------------------- /messages/ru/users.php: -------------------------------------------------------------------------------- 1 | 'Код восстановления пароля.', 21 | 'EMAIL_SUBJECT_SIGNUP' => 'Код подтверждения новой учётной записи.', 22 | 'FRONTEND_FLASH_FAIL_UPDATE' => 'В момент обноеления профиля возникла ошибка. Попробуйте ещё раз пожалуйста!', 23 | 'FRONTEND_FLASH_SUCCES_UPDATE' => 'Профиль был успешно обновлён.', 24 | 'ATTR_CREATED' => 'Дата создания', 25 | 'ATTR_EMAIL' => 'E-mail', 26 | 'ATTR_NAME' => 'Имя', 27 | 'ATTR_NEW_EMAIL' => 'Новый e-mail', 28 | 'ATTR_NEW_PASSWORD' => 'Новый пароль', 29 | 'ATTR_NEW_REPASSWORD' => 'Повторите новый пароль', 30 | 'ATTR_OLDEMAIL' => 'Текущий e-mail', 31 | 'ATTR_OLDPASSWORD' => 'текущий пароль', 32 | 'ATTR_PASSWORD' => 'Пароль', 33 | 'ATTR_REMEMBER_ME' => 'Запомнить меня', 34 | 'ATTR_REPASSWORD' => 'Повторите пароль', 35 | 'ATTR_ROLE' => 'Роль', 36 | 'ATTR_SECURE_KEY' => 'Ключ безопасности', 37 | 'ATTR_STATUS' => 'Статус', 38 | 'ATTR_SURNAME' => 'Фамилия', 39 | 'ATTR_UPDATED' => 'Дата обновления', 40 | 'ATTR_USERNAME' => 'Логин', 41 | 'BACKEND_CREATE_SUBMIT' => 'Сохранить', 42 | 'BACKEND_CREATE_TITLE' => 'Создать нового пользователя', 43 | 'BACKEND_FLASH_FAIL_ADMIN_CREATE' => 'В момент создания нового пользователя возникла ошибка.', 44 | 'BACKEND_INDEX_TITLE' => 'Страница пользователей', 45 | 'BACKEND_LOGIN_OR' => 'или', 46 | 'BACKEND_LOGIN_RECOVERY' => 'Восстановить пароль', 47 | 'BACKEND_LOGIN_SUBMIT' => 'Войти', 48 | 'BACKEND_LOGIN_TITLE' => 'Авторизация', 49 | 'BACKEND_PROMPT_ROLE' => 'Выберите роль', 50 | 'BACKEND_PROMPT_STATUS' => 'Выберите статус', 51 | 'BACKEND_UPDATE_SUBMIT' => 'Обновить', 52 | 'BACKEND_UPDATE_TITLE' => 'Обновить пользователя', 53 | 'BACKEND_VIEW_TITLE' => 'Страница пользователя', 54 | 'EMAIL_SUBJECT_CHANGE' => 'Код подтверждения новой электронной почты.', 55 | 'ERROR_MSG_INVALID_OLD_PASSWORD' => 'Неправильный текущий пароль', 56 | 'ERROR_MSG_INVALID_USERNAME_OR_PASSWORD' => 'Неправильный логин или пароль', 57 | 'FRONTEND_EMAIL_CHANGE_SUBMIT' => 'Изменить', 58 | 'FRONTEND_EMAIL_CHANGE_TITLE' => 'Изменение адреса электронной почты', 59 | 'FRONTEND_FLASH_FAIL_ACTIVATION' => 'Неверный код активации или возмоможно аккаунт был уже ранее активирован.', 60 | 'FRONTEND_FLASH_FAIL_EMAIL_CHANGE' => 'В момент изменения электронного адреса возникла ошибка. Попробуйте ещё раз пожалуйста!', 61 | 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION' => 'В момент подтверждения нового электронного адреса возникла ошибка. Попробуйте ещё раз пожалуйста!', 62 | 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION_WITH_INVALID_KEY' => 'Неверный код подтверждения.', 63 | 'FRONTEND_FLASH_FAIL_PASSWORD_CHANGE' => 'В момент изменения пароля возникла ошибка. Попробуйте ещё раз пожалуйста!', 64 | 'FRONTEND_FLASH_FAIL_RECOVERY' => 'В момент отправки письма возникла ошибка. Попробуйте ещё раз пожалуйста!', 65 | 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION' => 'В момент подтверждения нового пароля возникла ошибка. Попробуйте ещё раз пожалуйста!', 66 | 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION_WITH_INVALID_KEY' => 'Неверный код подтверждения.', 67 | 'FRONTEND_FLASH_FAIL_RESEND' => 'В момент отправки письма возникла ошибка. Попробуйте ещё раз пожалуйста!', 68 | 'FRONTEND_FLASH_FAIL_SIGNUP' => 'В момент регистрации возникла ошибка. Попробуйте ещё раз пожалуйста!', 69 | 'FRONTEND_FLASH_SUCCESS_ACTIVATION' => 'Ваша учётная запись была успешно активирована.', 70 | 'FRONTEND_FLASH_SUCCESS_NEW_EMAIL_CONFIRMATION' => 'E-mail адрес был успешно обновлён!', 71 | 'FRONTEND_FLASH_SUCCESS_PASSWORD_CHANGE' => 'Пароль был успешно обновлён!', 72 | 'FRONTEND_FLASH_SUCCESS_RECOVERY' => 'На указанный вами электронный адрес было отправлено письмо с кодом восстановления пароля.', 73 | 'FRONTEND_FLASH_SUCCESS_RECOVERY_CONFIRMATION' => 'Пароль был успешно восстановлен.', 74 | 'FRONTEND_FLASH_SUCCESS_RESEND' => 'На указанный электронный адрес было отправлено письмо с кодом активации новой учётной записи.', 75 | 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITHOUT_LOGIN' => 'Учётная запись была успешно создана. Через несколько секунд вам на почту будет отправлен код для активации аккаунта. В случае если письмо не пришло в течении 15 минут, вы можете заново запросить отправку ключа по данной ссылке.', 76 | 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITH_LOGIN' => 'Учётная запись была успешно создана.', 77 | 'FRONTEND_FLASH_SUCCES_EMAIL_CHANGE' => 'На указанный новый электронный адрес было отправлено письмо с кодом подтверждения.', 78 | 'FRONTEND_INDEX_TITLE' => 'Пользователи', 79 | 'FRONTEND_LOGIN_OR' => 'или', 80 | 'FRONTEND_LOGIN_RECOVERY' => 'Восстановить пароль', 81 | 'FRONTEND_LOGIN_SUBMIT' => 'Войти', 82 | 'FRONTEND_LOGIN_TITLE' => 'Авторизация', 83 | 'FRONTEND_PASSWORD_CHANGE_SUBMIT' => 'Изменить', 84 | 'FRONTEND_PASSWORD_CHANGE_TITLE' => 'Смена пароля', 85 | 'FRONTEND_RECOVERY_CONFIRMATION_SUBMIT' => 'Сохранить', 86 | 'FRONTEND_RECOVERY_CONFIRMATION_TITLE' => 'Восстановление пароля', 87 | 'FRONTEND_RECOVERY_SUBMIT' => 'Восстановить', 88 | 'FRONTEND_RECOVERY_TITLE' => 'Восстановления пароля', 89 | 'FRONTEND_RESEND_SUBMIT' => 'Отправить', 90 | 'FRONTEND_RESEND_TITLE' => 'Повторная отправка e-mail подтверждения', 91 | 'FRONTEND_SIGNUP_RESEND' => 'Повторная отправка e-mail подтверждения', 92 | 'FRONTEND_SIGNUP_SUBMIT' => 'Зарегистрироватся', 93 | 'FRONTEND_SIGNUP_TITLE' => 'Регистрация', 94 | 'FRONTEND_UPDATE_SUBMIT' => 'Обновить', 95 | 'FRONTEND_UPDATE_TITLE' => 'Редактирование профиля', 96 | 'STATUS_ACTIVE' => 'Активный', 97 | 'STATUS_BANNED' => 'Забаненый', 98 | 'STATUS_INACTIVE' => 'Неактивный', 99 | ]; 100 | -------------------------------------------------------------------------------- /messages/uk/users.php: -------------------------------------------------------------------------------- 1 | 'Код відновлення паролю.', 21 | 'EMAIL_SUBJECT_SIGNUP' => 'Код підтвердження нового облікового запису.', 22 | 'FRONTEND_FLASH_FAIL_UPDATE' => 'В момент оновлення профілю виникла помилка. Спробуйте ще раз, будь ласка!', 23 | 'FRONTEND_FLASH_SUCCES_UPDATE' => 'Профіль був успішно оновлений.', 24 | 'ATTR_CREATED' => 'Дата створення', 25 | 'ATTR_EMAIL' => 'E-mail', 26 | 'ATTR_NAME' => 'Ім\'я', 27 | 'ATTR_NEW_EMAIL' => 'Новий e-mail', 28 | 'ATTR_NEW_PASSWORD' => 'Новий пароль', 29 | 'ATTR_NEW_REPASSWORD' => 'Повторіть новий пароль', 30 | 'ATTR_OLDEMAIL' => 'Діючий e-mail', 31 | 'ATTR_OLDPASSWORD' => 'Діючий пароль', 32 | 'ATTR_PASSWORD' => 'Пароль', 33 | 'ATTR_REMEMBER_ME' => 'Запам\'ятати мене', 34 | 'ATTR_REPASSWORD' => 'Повторіть пароль', 35 | 'ATTR_ROLE' => 'Роль', 36 | 'ATTR_SECURE_KEY' => 'Ключ безпеки', 37 | 'ATTR_STATUS' => 'Статус', 38 | 'ATTR_SURNAME' => 'Прізвище', 39 | 'ATTR_UPDATED' => 'Дата оновлення', 40 | 'ATTR_USERNAME' => 'Логін', 41 | 'BACKEND_CREATE_SUBMIT' => 'Зберегти', 42 | 'BACKEND_CREATE_TITLE' => 'Створити нового користувача', 43 | 'BACKEND_FLASH_FAIL_ADMIN_CREATE' => 'В момент створення нового користувача виникла помилка.', 44 | 'BACKEND_INDEX_TITLE' => 'Сторінка користувачів', 45 | 'BACKEND_LOGIN_OR' => 'або', 46 | 'BACKEND_LOGIN_RECOVERY' => 'Відновити пароль', 47 | 'BACKEND_LOGIN_SUBMIT' => 'Увійти', 48 | 'BACKEND_LOGIN_TITLE' => 'Авторизація', 49 | 'BACKEND_PROMPT_ROLE' => 'Виберіть роль', 50 | 'BACKEND_PROMPT_STATUS' => 'Виберіть статус', 51 | 'BACKEND_UPDATE_SUBMIT' => 'Оновити', 52 | 'BACKEND_UPDATE_TITLE' => 'Оновити користувача', 53 | 'BACKEND_VIEW_TITLE' => 'Сторінка користувача', 54 | 'EMAIL_SUBJECT_CHANGE' => 'Код підтверждення нової електронної пошти.', 55 | 'ERROR_MSG_INVALID_OLD_PASSWORD' => 'Невірний діючий пароль', 56 | 'ERROR_MSG_INVALID_USERNAME_OR_PASSWORD' => 'Невірний логін або пароль', 57 | 'FRONTEND_EMAIL_CHANGE_SUBMIT' => 'Змінити', 58 | 'FRONTEND_EMAIL_CHANGE_TITLE' => 'Змінити адресу електронної пошти', 59 | 'FRONTEND_FLASH_FAIL_ACTIVATION' => 'Невірний код активації або обліковий запис був активований раніше.', 60 | 'FRONTEND_FLASH_FAIL_EMAIL_CHANGE' => 'В момент зміни електронної адреси виникла помилка. Спробуйте ще раз, будь ласка!', 61 | 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION' => 'В момент підтверждення нової электронної адреси виникла помилка. Спробуйте ще раз, будь ласка!', 62 | 'FRONTEND_FLASH_FAIL_NEW_EMAIL_CONFIRMATION_WITH_INVALID_KEY' => 'Невірний код підтверждення.', 63 | 'FRONTEND_FLASH_FAIL_PASSWORD_CHANGE' => 'В момент зміни паролю виникла помилка. Спробуйте ще раз, будь ласка!', 64 | 'FRONTEND_FLASH_FAIL_RECOVERY' => 'В момент відправки листа виникла помилка. Спробуйте ще раз, будь ласка!', 65 | 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION' => 'В момент підтверждення нового паролю виникла помилка. Спробуйте ще раз, будь ласка!', 66 | 'FRONTEND_FLASH_FAIL_RECOVERY_CONFIRMATION_WITH_INVALID_KEY' => 'Невірний код підтверждення.', 67 | 'FRONTEND_FLASH_FAIL_RESEND' => 'В момент відправки листа виникла помилка. Спробуйте ще раз, будь ласка!', 68 | 'FRONTEND_FLASH_FAIL_SIGNUP' => 'В момент реєстрації виникла помилка. Спробуйте ще раз, будь ласка!', 69 | 'FRONTEND_FLASH_SUCCESS_ACTIVATION' => 'Ваш обліковий запис був успішно активований.', 70 | 'FRONTEND_FLASH_SUCCESS_NEW_EMAIL_CONFIRMATION' => 'E-mail адрес був успішно оновлений!', 71 | 'FRONTEND_FLASH_SUCCESS_PASSWORD_CHANGE' => 'Пароль був успішно оновлений!', 72 | 'FRONTEND_FLASH_SUCCESS_RECOVERY' => 'На вказану вами електронну адресу було відправлено листа с кодом відновлення паролю.', 73 | 'FRONTEND_FLASH_SUCCESS_RECOVERY_CONFIRMATION' => 'Пароль був успішно відновлений.', 74 | 'FRONTEND_FLASH_SUCCESS_RESEND' => 'На вказану вами електронну адресу було відправлено листа с кодом активації нового облікового запису.', 75 | 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITHOUT_LOGIN' => 'Обліковий запис був успішно створений. Через декілька секунд Вам на пошту буде надісланий код для активації облікового запису. В випадку, якщо лист не надійшов на протязі 15 хвилин, Ви можете запросити відправку ключа іще раз за данним посиланням.', 76 | 'FRONTEND_FLASH_SUCCESS_SIGNUP_WITH_LOGIN' => 'Обліковий запис був успішно створенний.', 77 | 'FRONTEND_FLASH_SUCCES_EMAIL_CHANGE' => 'На вказану нову електронну адресу було відправленно листа з кодом підтверждення.', 78 | 'FRONTEND_INDEX_TITLE' => 'Користувачі', 79 | 'FRONTEND_LOGIN_OR' => 'або', 80 | 'FRONTEND_LOGIN_RECOVERY' => 'Відновити пароль', 81 | 'FRONTEND_LOGIN_SUBMIT' => 'Увійти', 82 | 'FRONTEND_LOGIN_TITLE' => 'Авторизація', 83 | 'FRONTEND_PASSWORD_CHANGE_SUBMIT' => 'Змінити', 84 | 'FRONTEND_PASSWORD_CHANGE_TITLE' => 'Зміна паролю', 85 | 'FRONTEND_RECOVERY_CONFIRMATION_SUBMIT' => 'Зберегти', 86 | 'FRONTEND_RECOVERY_CONFIRMATION_TITLE' => 'Відновлення паролю', 87 | 'FRONTEND_RECOVERY_SUBMIT' => 'Відновлення', 88 | 'FRONTEND_RECOVERY_TITLE' => 'Відновлення паролю', 89 | 'FRONTEND_RESEND_SUBMIT' => 'Відпраити', 90 | 'FRONTEND_RESEND_TITLE' => 'Повторна відправка e-mail підтверждення', 91 | 'FRONTEND_SIGNUP_RESEND' => 'Повторна відправка e-mail підтверждення', 92 | 'FRONTEND_SIGNUP_SUBMIT' => 'Зареєструватися', 93 | 'FRONTEND_SIGNUP_TITLE' => 'Реєстрація', 94 | 'FRONTEND_UPDATE_SUBMIT' => 'Оновити', 95 | 'FRONTEND_UPDATE_TITLE' => 'Редагування профілю', 96 | 'STATUS_ACTIVE' => 'Активний', 97 | 'STATUS_BANNED' => 'Заблокований', 98 | 'STATUS_INACTIVE' => 'Неактивний', 99 | ]; 100 | -------------------------------------------------------------------------------- /migrations/m140418_204054_create_module_tbl.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 29 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 30 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 31 | } 32 | 33 | // Users table 34 | $this->createTable( 35 | '{{%users}}', 36 | [ 37 | 'id' => Schema::TYPE_PK, 38 | 'username' => Schema::TYPE_STRING . '(30) NOT NULL', 39 | 'email' => Schema::TYPE_STRING . '(100) NOT NULL', 40 | 'password_hash' => Schema::TYPE_STRING . ' NOT NULL', 41 | 'auth_key' => Schema::TYPE_STRING . '(32) NOT NULL', 42 | 'secure_key' => Schema::TYPE_STRING . '(53) NOT NULL', 43 | 'role' => Schema::TYPE_STRING . '(64) NOT NULL DEFAULT "user"', 44 | 'status_id' => 'tinyint(4) NOT NULL DEFAULT 0', 45 | 'created_at' => Schema::TYPE_INTEGER . ' NOT NULL', 46 | 'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL' 47 | ], 48 | $tableOptions 49 | ); 50 | 51 | // Indexes 52 | $this->createIndex('username', '{{%users}}', 'username', true); 53 | $this->createIndex('email', '{{%users}}', 'email', true); 54 | $this->createIndex('role', '{{%users}}', 'role'); 55 | $this->createIndex('status_id', '{{%users}}', 'status_id'); 56 | $this->createIndex('created_at', '{{%users}}', 'created_at'); 57 | 58 | // Users table 59 | $this->createTable( 60 | '{{%profiles}}', 61 | [ 62 | 'user_id' => Schema::TYPE_PK, 63 | 'name' => Schema::TYPE_STRING . '(50) NOT NULL', 64 | 'surname' => Schema::TYPE_STRING . '(50) NOT NULL' 65 | ], 66 | $tableOptions 67 | ); 68 | 69 | // Foreign Keys 70 | $this->addForeignKey('FK_profile_user', '{{%profiles}}', 'user_id', '{{%users}}', 'id', 'CASCADE', 'CASCADE'); 71 | 72 | // Users emails table 73 | $this->createTable( 74 | '{{%user_email}}', 75 | [ 76 | 'user_id' => Schema::TYPE_INTEGER . ' NOT NULL', 77 | 'email' => Schema::TYPE_STRING . '(100) NOT NULL', 78 | 'token' => Schema::TYPE_STRING . '(53) NOT NULL', 79 | 'PRIMARY KEY (`user_id`, `token`)' 80 | ], 81 | $tableOptions 82 | ); 83 | 84 | // Foreign Keys 85 | $this->addForeignKey( 86 | 'FK_user_email_user', 87 | '{{%user_email}}', 88 | 'user_id', 89 | '{{%users}}', 90 | 'id', 91 | 'CASCADE', 92 | 'CASCADE' 93 | ); 94 | 95 | // Add super-administrator 96 | $this->execute($this->getUserSql()); 97 | $this->execute($this->getProfileSql()); 98 | } 99 | 100 | /** 101 | * @return string SQL to insert first user 102 | */ 103 | private function getUserSql() 104 | { 105 | $time = time(); 106 | $password_hash = Yii::$app->security->generatePasswordHash('admin12345'); 107 | $auth_key = Yii::$app->security->generateRandomString(); 108 | $secure_key = Security::generateExpiringRandomKey(); 109 | return "INSERT INTO {{%users}} (`username`, `email`, `password_hash`, `auth_key`, `secure_key`, `role`, `status_id`, `created_at`, `updated_at`) VALUES ('admin', 'admin@demo.com', '$password_hash', '$auth_key', '$secure_key', 'superadmin', 1, $time, $time)"; 110 | } 111 | 112 | /** 113 | * @return string SQL to insert first profile 114 | */ 115 | private function getProfileSql() 116 | { 117 | return "INSERT INTO {{%profiles}} (`user_id`, `name`, `surname`) VALUES (1, 'Administration', 'Site')"; 118 | } 119 | 120 | /** 121 | * @inheritdoc 122 | */ 123 | public function safeDown() 124 | { 125 | $this->dropTable('{{%user_email}}'); 126 | $this->dropTable('{{%users}}'); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /models/LoginForm.php: -------------------------------------------------------------------------------- 1 | Yii::t('users', 'ATTR_USERNAME'), 64 | 'password' => Yii::t('users', 'ATTR_PASSWORD'), 65 | 'rememberMe' => Yii::t('users', 'ATTR_REMEMBER_ME') 66 | ]; 67 | } 68 | 69 | public function scenarios() 70 | { 71 | return [ 72 | self::SCENARIO_DEFAULT => ['username', 'password', 'rememberMe'], 73 | 'admin' => ['username', 'password', 'rememberMe'] 74 | ]; 75 | } 76 | 77 | /** 78 | * Validates the password. 79 | * This method serves as the inline validation for password. 80 | */ 81 | public function validatePassword($attribute, $params) 82 | { 83 | $user = $this->getUser(); 84 | if (!$user || !$user->validatePassword($this->$attribute)) { 85 | $this->addError($attribute, Yii::t('users', 'ERROR_MSG_INVALID_USERNAME_OR_PASSWORD')); 86 | } 87 | } 88 | 89 | /** 90 | * Finds user by username. 91 | * 92 | * @return User|null User instance 93 | */ 94 | protected function getUser() 95 | { 96 | if ($this->_user === null) { 97 | $scope = $this->scenario === 'admin' ? ['admin', 'active'] : 'active'; 98 | $this->_user = User::findByUsername($this->username, $scope); 99 | } 100 | return $this->_user; 101 | } 102 | 103 | /** 104 | * Logs in a user using the provided username and password. 105 | * 106 | * @return boolean whether the user is logged in successfully 107 | */ 108 | public function login() 109 | { 110 | return Yii::$app->user->login($this->user, $this->rememberMe ? 3600 * 24 * 30 : 0); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /models/Profile.php: -------------------------------------------------------------------------------- 1 | $id]); 36 | } 37 | 38 | /** 39 | * @inheritdoc 40 | */ 41 | public function rules() 42 | { 43 | return [ 44 | // Name 45 | ['name', 'match', 'pattern' => '/^[a-zа-яё]+$/iu'], 46 | // Surname 47 | ['surname', 'match', 'pattern' => '/^[a-zа-яё]+(-[a-zа-яё]+)?$/iu'] 48 | ]; 49 | } 50 | 51 | /** 52 | * @inheritdoc 53 | */ 54 | public function attributeLabels() 55 | { 56 | return [ 57 | 'name' => Yii::t('users', 'ATTR_NAME'), 58 | 'surname' => Yii::t('users', 'ATTR_SURNAME') 59 | ]; 60 | } 61 | 62 | /** 63 | * @return Profile|null Profile user 64 | */ 65 | public function getUser() 66 | { 67 | return $this->hasOne(User::className(), ['id' => 'user_id'])->inverseOf('profile'); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /models/User.php: -------------------------------------------------------------------------------- 1 | where(['id' => $ids]); 81 | if ($scope !== null) { 82 | if (is_array($scope)) { 83 | foreach ($scope as $value) { 84 | $query->$value(); 85 | } 86 | } else { 87 | $query->$scope(); 88 | } 89 | } 90 | return $query->all(); 91 | } 92 | 93 | /** 94 | * @inheritdoc 95 | */ 96 | public static function find() 97 | { 98 | return new UserQuery(get_called_class()); 99 | } 100 | 101 | /** 102 | * Find model by username. 103 | * 104 | * @param string $username Username 105 | * * @param string|array|null $scope Query scope 106 | */ 107 | public static function findByUsername($username, $scope = null) 108 | { 109 | $query = static::find()->where(['username' => $username]); 110 | if ($scope !== null) { 111 | if (is_array($scope)) { 112 | foreach ($scope as $value) { 113 | $query->$value(); 114 | } 115 | } else { 116 | $query->$scope(); 117 | } 118 | } 119 | return $query->one(); 120 | } 121 | 122 | /** 123 | * Find model by username. 124 | * 125 | * @param string $username Username 126 | * * @param string|array|null $scope Query scope 127 | */ 128 | public static function findByEmail($email, $scope = null) 129 | { 130 | $query = static::find()->where(['email' => $email]); 131 | if ($scope !== null) { 132 | if (is_array($scope)) { 133 | foreach ($scope as $value) { 134 | $query->$value(); 135 | } 136 | } else { 137 | $query->$scope(); 138 | } 139 | } 140 | return $query->one(); 141 | } 142 | 143 | /** 144 | * Find model by secure key. 145 | * 146 | * @param string $secureKey Secure key 147 | * * @param string|array|null $scope Query scope 148 | */ 149 | public static function findBySecureKey($secureKey, $scope = null) 150 | { 151 | $query = static::find()->where(['secure_key' => $secureKey]); 152 | if ($scope !== null) { 153 | if (is_array($scope)) { 154 | foreach ($scope as $value) { 155 | $query->$value(); 156 | } 157 | } else { 158 | $query->$scope(); 159 | } 160 | } 161 | return $query->one(); 162 | } 163 | 164 | /** 165 | * @inheritdoc 166 | */ 167 | public function behaviors() 168 | { 169 | return [ 170 | 'timestampBehavior' => [ 171 | 'class' => TimestampBehavior::className(), 172 | ] 173 | ]; 174 | } 175 | 176 | /** 177 | * @inheritdoc 178 | */ 179 | public function getId() 180 | { 181 | return $this->id; 182 | } 183 | 184 | /** 185 | * @inheritdoc 186 | */ 187 | public function getAuthKey() 188 | { 189 | return $this->auth_key; 190 | } 191 | 192 | /** 193 | * Auth Key validation. 194 | * @param string $authKey 195 | * @return boolean 196 | */ 197 | public function validateAuthKey($authKey) 198 | { 199 | return $this->auth_key === $authKey; 200 | } 201 | 202 | /** 203 | * Password validation. 204 | * @param string $password 205 | * @return boolean 206 | */ 207 | public function validatePassword($password) 208 | { 209 | return Yii::$app->security->validatePassword($password, $this->password_hash); 210 | } 211 | 212 | /** 213 | * @inheritdoc 214 | */ 215 | public function transactions() 216 | { 217 | return [ 218 | self::SCENARIO_DEFAULT => self::OP_ALL 219 | ]; 220 | } 221 | 222 | /** 223 | * @inheritdoc 224 | */ 225 | public function attributeLabels() 226 | { 227 | return [ 228 | 'username' => Yii::t('users', 'ATTR_USERNAME'), 229 | 'email' => Yii::t('users', 'ATTR_EMAIL'), 230 | 'role' => Yii::t('users', 'ATTR_ROLE'), 231 | 'status_id' => Yii::t('users', 'ATTR_STATUS'), 232 | 'created_at' => Yii::t('users', 'ATTR_CREATED'), 233 | 'updated_at' => Yii::t('users', 'ATTR_UPDATED'), 234 | ]; 235 | } 236 | 237 | /** 238 | * @return Profile|null User profile 239 | */ 240 | public function getProfile() 241 | { 242 | return $this->hasOne(Profile::className(), ['user_id' => 'id'])->inverseOf('user'); 243 | } 244 | 245 | /** 246 | * @inheritdoc 247 | */ 248 | public function beforeSave($insert) 249 | { 250 | if (parent::beforeSave($insert)) { 251 | if ($this->isNewRecord) { 252 | // Set default status 253 | if (!$this->status_id) { 254 | $this->status_id = $this->module->requireEmailConfirmation ? self::STATUS_INACTIVE : self::STATUS_ACTIVE; 255 | } 256 | // Set default role 257 | if (!$this->role) { 258 | $this->role = self::ROLE_DEFAULT; 259 | } 260 | // Generate auth and secure keys 261 | $this->generateAuthKey(); 262 | $this->generateSecureKey(); 263 | } 264 | return true; 265 | } 266 | return false; 267 | } 268 | 269 | /** 270 | * Generates "remember me" authentication key. 271 | */ 272 | public function generateAuthKey() 273 | { 274 | $this->auth_key = Yii::$app->security->generateRandomString(); 275 | } 276 | 277 | /** 278 | * Generates secure key. 279 | */ 280 | public function generateSecureKey() 281 | { 282 | $this->secure_key = Security::generateExpiringRandomKey(); 283 | } 284 | 285 | /** 286 | * Activates user account. 287 | * 288 | * @return boolean true if account was successfully activated 289 | */ 290 | public function activation() 291 | { 292 | $this->status_id = self::STATUS_ACTIVE; 293 | $this->generateSecureKey(); 294 | return $this->save(false); 295 | } 296 | 297 | /** 298 | * Recover password. 299 | * 300 | * @param string $password New Password 301 | * @return boolean true if password was successfully recovered 302 | */ 303 | public function recovery($password) 304 | { 305 | $this->setPassword($password); 306 | $this->generateSecureKey(); 307 | return $this->save(false); 308 | } 309 | 310 | /** 311 | * Generates password hash from password and sets it to the model. 312 | * 313 | * @param string $password 314 | */ 315 | public function setPassword($password) 316 | { 317 | $this->password_hash = Yii::$app->security->generatePasswordHash($password); 318 | } 319 | 320 | /** 321 | * Change user password. 322 | * 323 | * @return boolean true if password was successfully changed 324 | */ 325 | public function password($password) 326 | { 327 | $this->setPassword($password); 328 | return $this->save(false); 329 | } 330 | } 331 | -------------------------------------------------------------------------------- /models/UserQuery.php: -------------------------------------------------------------------------------- 1 | andWhere(['status_id' => User::STATUS_ACTIVE]); 24 | return $this; 25 | } 26 | 27 | /** 28 | * Select inactive users. 29 | * 30 | * @param ActiveQuery $query 31 | */ 32 | public function inactive() 33 | { 34 | $this->andWhere(['status_id' => User::STATUS_INACTIVE]); 35 | return $this; 36 | } 37 | 38 | /** 39 | * Select banned users. 40 | * 41 | * @param ActiveQuery $query 42 | */ 43 | public function banned() 44 | { 45 | $this->andWhere(['status_id' => User::STATUS_BANNED]); 46 | return $this; 47 | } 48 | 49 | /** 50 | * Select deleted users. 51 | * 52 | * @param ActiveQuery $query 53 | */ 54 | public function deleted() 55 | { 56 | $this->andWhere(['status_id' => User::STATUS_DELETED]); 57 | return $this; 58 | } 59 | 60 | /** 61 | * Select users with role "user". 62 | * 63 | * @param ActiveQuery $query 64 | */ 65 | public function registered() 66 | { 67 | $this->andWhere(['role' => User::ROLE_DEFAULT]); 68 | return $this; 69 | } 70 | 71 | /** 72 | * Select users with role "user". 73 | * 74 | * @param ActiveQuery $query 75 | */ 76 | public function admin() 77 | { 78 | $this->andWhere(['role' => $this->module->adminRoles]); 79 | return $this; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /models/backend/User.php: -------------------------------------------------------------------------------- 1 | _status === null) { 39 | $statuses = self::getStatusArray(); 40 | $this->_status = $statuses[$this->status_id]; 41 | } 42 | return $this->_status; 43 | } 44 | 45 | /** 46 | * @return array Status array. 47 | */ 48 | public static function getStatusArray() 49 | { 50 | return [ 51 | self::STATUS_ACTIVE => Yii::t('users', 'STATUS_ACTIVE'), 52 | self::STATUS_INACTIVE => Yii::t('users', 'STATUS_INACTIVE'), 53 | self::STATUS_BANNED => Yii::t('users', 'STATUS_BANNED') 54 | ]; 55 | } 56 | 57 | /** 58 | * @inheritdoc 59 | */ 60 | public function rules() 61 | { 62 | return [ 63 | // Required 64 | [['username', 'email'], 'required'], 65 | [['password', 'repassword'], 'required', 'on' => ['admin-create']], 66 | // Trim 67 | [['username', 'email', 'password', 'repassword', 'name', 'surname'], 'trim'], 68 | // String 69 | [['password', 'repassword'], 'string', 'min' => 6, 'max' => 30], 70 | // Unique 71 | [['username', 'email'], 'unique'], 72 | // Username 73 | ['username', 'match', 'pattern' => '/^[a-zA-Z0-9_-]+$/'], 74 | ['username', 'string', 'min' => 3, 'max' => 30], 75 | // E-mail 76 | ['email', 'string', 'max' => 100], 77 | ['email', 'email'], 78 | // Repassword 79 | ['repassword', 'compare', 'compareAttribute' => 'password'], 80 | // Role 81 | ['role', 'in', 'range' => array_keys(self::getRoleArray())], 82 | // Status 83 | ['status_id', 'in', 'range' => array_keys(self::getStatusArray())] 84 | ]; 85 | } 86 | 87 | /** 88 | * @return array Role array. 89 | */ 90 | public static function getRoleArray() 91 | { 92 | return ArrayHelper::map(Yii::$app->authManager->getRoles(), 'name', 'name'); 93 | } 94 | 95 | /** 96 | * @inheritdoc 97 | */ 98 | public function scenarios() 99 | { 100 | return [ 101 | 'admin-create' => ['username', 'email', 'password', 'repassword', 'status_id', 'role'], 102 | 'admin-update' => ['username', 'email', 'password', 'repassword', 'status_id', 'role'] 103 | ]; 104 | } 105 | 106 | /** 107 | * @inheritdoc 108 | */ 109 | public function attributeLabels() 110 | { 111 | $labels = parent::attributeLabels(); 112 | 113 | return array_merge( 114 | $labels, 115 | [ 116 | 'password' => Yii::t('users', 'ATTR_PASSWORD'), 117 | 'repassword' => Yii::t('users', 'ATTR_REPASSWORD') 118 | ] 119 | ); 120 | } 121 | 122 | /** 123 | * @inheritdoc 124 | */ 125 | public function beforeSave($insert) 126 | { 127 | if (parent::beforeSave($insert)) { 128 | if ($this->isNewRecord || (!$this->isNewRecord && $this->password)) { 129 | $this->setPassword($this->password); 130 | $this->generateAuthKey(); 131 | $this->generateSecureKey(); 132 | } 133 | return true; 134 | } 135 | return false; 136 | } 137 | 138 | /** 139 | * @inheritdoc 140 | */ 141 | public function afterSave($insert,$changedAttributes) 142 | { 143 | parent::afterSave($insert,$changedAttributes); 144 | 145 | if ($this->profile !== null) { 146 | $this->profile->save(false); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /models/backend/UserSearch.php: -------------------------------------------------------------------------------- 1 | array_keys(User::getRoleArray())], 63 | // Status 64 | ['status_id', 'in', 'range' => array_keys(User::getStatusArray())] 65 | ]; 66 | } 67 | 68 | /** 69 | * Search users by request criteria. 70 | * 71 | * @param array|null Filter params 72 | * @return ActiveDataProvider Data provider with users 73 | */ 74 | public function search($params) 75 | { 76 | $query = User::find(); 77 | $dataProvider = new ActiveDataProvider([ 78 | 'query' => $query, 79 | 'pagination' => [ 80 | 'pageSize' => $this->module->recordsPerPage 81 | ] 82 | ]); 83 | 84 | if (!($this->load($params) && $this->validate())) { 85 | return $dataProvider; 86 | } 87 | 88 | $this->addCondition($query, 'username', true); 89 | $this->addCondition($query, 'email', true); 90 | $this->addCondition($query, 'status_id'); 91 | $this->addCondition($query, 'role'); 92 | $this->addWithCondition($query, 'name', 'profile', 'name'); 93 | $this->addWithCondition($query, 'surname', 'profile', 'surname'); 94 | 95 | return $dataProvider; 96 | } 97 | 98 | /** 99 | * Add criteria condition. 100 | * 101 | * @param \yii\db\Query $query Query instance. 102 | * @param string $attribute Searched attribute name 103 | * @param boolean $partialMatch Matching type 104 | */ 105 | protected function addCondition($query, $attribute, $partialMatch = false) 106 | { 107 | $value = $this->$attribute; 108 | if (trim($value) === '') { 109 | return; 110 | } 111 | if ($partialMatch) { 112 | $query->andWhere(['like', $attribute, $value]); 113 | } else { 114 | $query->andWhere([$attribute => $value]); 115 | } 116 | } 117 | 118 | /** 119 | * Add inner join with criteria. 120 | * 121 | * @param \yii\db\Query $query Query instance 122 | * @param string $attribute Serched attribute name 123 | * @param string $relation Relation name 124 | * @param string $targetAttribute Target attribute name 125 | * @param boolean $partialMatch matching type 126 | */ 127 | protected function addWithCondition($query, $attribute, $relation, $targetAttribute, $partialMatch = false) 128 | { 129 | $value = $this->$attribute; 130 | if (trim($value) === '') { 131 | return; 132 | } 133 | if ($partialMatch) { 134 | $query->innerJoinWith([$relation]) 135 | ->andWhere(['like', $targetAttribute, $value]); 136 | } else { 137 | $query->innerJoinWith([$relation]) 138 | ->andWhere([$targetAttribute => $value]); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /models/frontend/ActivationForm.php: -------------------------------------------------------------------------------- 1 | 53], 36 | [ 37 | 'secure_key', 38 | 'exist', 39 | 'targetClass' => User::className(), 40 | 'filter' => function ($query) { 41 | $query->inactive(); 42 | } 43 | ] 44 | ]; 45 | } 46 | 47 | /** 48 | * @inheritdoc 49 | */ 50 | public function attributeLabels() 51 | { 52 | return [ 53 | 'secure_key' => Yii::t('users', 'ATTR_SECURE_KEY') 54 | ]; 55 | } 56 | 57 | /** 58 | * Activates user account. 59 | * 60 | * @return boolean true if account was successfully activated 61 | */ 62 | public function activation() 63 | { 64 | /** @var User $model */ 65 | $model = User::findBySecureKey($this->secure_key, 'inactive'); 66 | if ($model !== null) { 67 | return $model->activation(); 68 | } 69 | return false; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /models/frontend/Email.php: -------------------------------------------------------------------------------- 1 | _oldemail === null) { 48 | $this->_oldemail = Yii::$app->user->identity->email; 49 | } 50 | return $this->_oldemail; 51 | } 52 | 53 | /** 54 | * Check if token is valid. 55 | * 56 | * @return boolean true if token is valid 57 | */ 58 | public function isValidToken() 59 | { 60 | if (Security::isValidToken($this->token, $this->module->emailWithin) === true) { 61 | return ($this->_model = static::findOne(['token' => $this->token])) !== null; 62 | } 63 | return false; 64 | } 65 | 66 | /** 67 | * @inheritdoc 68 | */ 69 | public function rules() 70 | { 71 | return [ 72 | // E-mail 73 | ['email', 'required'], 74 | ['email', 'trim'], 75 | ['email', 'email'], 76 | ['email', 'string', 'max' => 100], 77 | ['email', 'compare', 'compareAttribute' => 'oldemail', 'operator' => '!=='], 78 | ['email', 'unique', 'targetClass' => User::className()], 79 | ]; 80 | } 81 | 82 | /** 83 | * @inheritdoc 84 | */ 85 | public function attributeLabels() 86 | { 87 | return [ 88 | 'email' => Yii::t('users', 'ATTR_NEW_EMAIL'), 89 | 'oldemail' => Yii::t('users', 'ATTR_OLDEMAIL'), 90 | ]; 91 | } 92 | 93 | /** 94 | * @return User|null Related user 95 | */ 96 | public function getUser() 97 | { 98 | return $this->hasOne(User::className(), ['id' => 'user_id']); 99 | } 100 | 101 | /** 102 | * @inheritdoc 103 | */ 104 | public function beforeSave($insert) 105 | { 106 | if (parent::beforeSave($insert)) { 107 | static::deleteAll(['user_id' => Yii::$app->user->identity->id]); 108 | $this->user_id = Yii::$app->user->identity->id; 109 | $this->generateToken(); 110 | $this->send(); 111 | 112 | return true; 113 | } 114 | return false; 115 | } 116 | 117 | /** 118 | * Generates secure key. 119 | */ 120 | public function generateToken() 121 | { 122 | $this->token = Security::generateExpiringRandomKey(); 123 | } 124 | 125 | /** 126 | * Send an email confirmation token. 127 | * 128 | * @return boolean true if email confirmation token was successfully sent 129 | */ 130 | public function send() 131 | { 132 | return $this->module->mail 133 | ->compose('email', ['model' => $this]) 134 | ->setTo($this->email) 135 | ->setSubject(Yii::t('users', 'EMAIL_SUBJECT_CHANGE') . ' ' . Yii::$app->name) 136 | ->send(); 137 | } 138 | 139 | /** 140 | * Confirm email change. 141 | * 142 | * @return boolean true if email was successfully confirmed. 143 | */ 144 | public function confirm() 145 | { 146 | $model = $this->_model; 147 | $user = $model->user; 148 | $user->email = $model->email; 149 | return $user->save(false) && $model->delete(); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /models/frontend/PasswordForm.php: -------------------------------------------------------------------------------- 1 | 6, 'max' => 30], 55 | // Password 56 | ['password', 'compare', 'compareAttribute' => 'oldpassword', 'operator' => '!=='], 57 | // Repassword 58 | ['repassword', 'compare', 'compareAttribute' => 'password'], 59 | // Oldpassword 60 | ['oldpassword', 'validateOldPassword'] 61 | ]; 62 | } 63 | 64 | /** 65 | * @inheritdoc 66 | */ 67 | public function attributeLabels() 68 | { 69 | return [ 70 | 'password' => Yii::t('users', 'ATTR_NEW_PASSWORD'), 71 | 'repassword' => Yii::t('users', 'ATTR_NEW_REPASSWORD'), 72 | 'oldpassword' => Yii::t('users', 'ATTR_OLDPASSWORD') 73 | ]; 74 | } 75 | 76 | /** 77 | * Validates the password. 78 | * This method serves as the inline validation for password. 79 | */ 80 | public function validateOldPassword($attribute, $params) 81 | { 82 | $user = $this->user; 83 | if (!$user || !$user->validatePassword($this->$attribute)) { 84 | $this->addError($attribute, Yii::t('users', 'ERROR_MSG_INVALID_OLD_PASSWORD')); 85 | } 86 | } 87 | 88 | /** 89 | * Change user password. 90 | * 91 | * @return boolean true if password was successfully changed 92 | */ 93 | public function password() 94 | { 95 | if (($model = $this->user) !== null) { 96 | return $model->password($this->password); 97 | } 98 | return false; 99 | } 100 | 101 | /** 102 | * Finds user by id. 103 | * 104 | * @return User|null User instance 105 | */ 106 | protected function getUser() 107 | { 108 | if ($this->_user === null) { 109 | $this->_user = User::find()->where(['id' => Yii::$app->user->identity->id])->active()->one(); 110 | } 111 | return $this->_user; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /models/frontend/RecoveryConfirmationForm.php: -------------------------------------------------------------------------------- 1 | 6, 'max' => 30], 56 | ['secure_key', 'string', 'max' => 53], 57 | // Repassword 58 | ['repassword', 'compare', 'compareAttribute' => 'password'], 59 | // Secure key 60 | [ 61 | 'secure_key', 62 | 'exist', 63 | 'targetClass' => User::className(), 64 | 'filter' => function ($query) { 65 | $query->active(); 66 | } 67 | ] 68 | ]; 69 | } 70 | 71 | /** 72 | * @inheritdoc 73 | */ 74 | public function attributeLabels() 75 | { 76 | return [ 77 | 'password' => Yii::t('users', 'ATTR_PASSWORD'), 78 | 'repassword' => Yii::t('users', 'ATTR_REPASSWORD') 79 | ]; 80 | } 81 | 82 | /** 83 | * Check if secure key is valid. 84 | * 85 | * @return boolean true if secure key is valid 86 | */ 87 | public function isValidSecureKey() 88 | { 89 | if (Security::isValidToken($this->secure_key, $this->module->recoveryWithin) === true) { 90 | return ($this->_user = User::findBySecureKey($this->secure_key, 'active')) !== null; 91 | } 92 | return false; 93 | } 94 | 95 | /** 96 | * Recover password. 97 | * 98 | * @return boolean true if password was successfully recovered 99 | */ 100 | public function recovery() 101 | { 102 | $model = $this->_user; 103 | if ($model !== null) { 104 | return $model->recovery($this->password); 105 | } 106 | return false; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /models/frontend/RecoveryForm.php: -------------------------------------------------------------------------------- 1 | 100], 41 | [ 42 | 'email', 43 | 'exist', 44 | 'targetClass' => User::className(), 45 | 'filter' => function ($query) { 46 | $query->active(); 47 | } 48 | ] 49 | ]; 50 | } 51 | 52 | /** 53 | * @inheritdoc 54 | */ 55 | public function attributeLabels() 56 | { 57 | return [ 58 | 'email' => Yii::t('users', 'ATTR_EMAIL') 59 | ]; 60 | } 61 | 62 | /** 63 | * Send a recovery password token. 64 | * 65 | * @return boolean true if recovery token was successfully sent 66 | */ 67 | public function recovery() 68 | { 69 | $this->_model = User::findByEmail($this->email, 'active'); 70 | if ($this->_model !== null) { 71 | return $this->send(); 72 | } 73 | return false; 74 | } 75 | 76 | /** 77 | * Send an email confirmation token. 78 | * 79 | * @return boolean true if email confirmation token was successfully sent 80 | */ 81 | public function send() 82 | { 83 | return $this->module->mail 84 | ->compose('recovery', ['model' => $this->_model]) 85 | ->setTo($this->email) 86 | ->setSubject(Yii::t('users', 'EMAIL_SUBJECT_RECOVERY') . ' ' . Yii::$app->name) 87 | ->send(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /models/frontend/ResendForm.php: -------------------------------------------------------------------------------- 1 | 100], 43 | [ 44 | 'email', 45 | 'exist', 46 | 'targetClass' => User::className(), 47 | 'filter' => function ($query) { 48 | $query->inactive(); 49 | } 50 | ] 51 | ]; 52 | } 53 | 54 | /** 55 | * @inheritdoc 56 | */ 57 | public function attributeLabels() 58 | { 59 | return [ 60 | 'email' => Yii::t('users', 'ATTR_EMAIL') 61 | ]; 62 | } 63 | 64 | /** 65 | * Resend email confirmation token 66 | * 67 | * @return boolean true if message was sent successfully 68 | */ 69 | public function resend() 70 | { 71 | $this->_model = User::findByEmail($this->email, 'inactive'); 72 | if ($this->_model !== null) { 73 | return $this->send(); 74 | } 75 | return false; 76 | } 77 | 78 | /** 79 | * Resend an email confirmation token. 80 | * 81 | * @return boolean true if email confirmation token was successfully sent 82 | */ 83 | public function send() 84 | { 85 | return $this->module->mail 86 | ->compose('signup', ['model' => $this->_model]) 87 | ->setTo($this->email) 88 | ->setSubject(Yii::t('users', 'EMAIL_SUBJECT_SIGNUP') . ' ' . Yii::$app->name) 89 | ->send(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /models/frontend/User.php: -------------------------------------------------------------------------------- 1 | 6, 'max' => 30], 41 | // Unique 42 | [['username', 'email'], 'unique'], 43 | // Username 44 | ['username', 'match', 'pattern' => '/^[a-zA-Z0-9_-]+$/'], 45 | ['username', 'string', 'min' => 3, 'max' => 30], 46 | // E-mail 47 | ['email', 'string', 'max' => 100], 48 | ['email', 'email'], 49 | // Repassword 50 | ['repassword', 'compare', 'compareAttribute' => 'password'] 51 | ]; 52 | } 53 | 54 | /** 55 | * @inheritdoc 56 | */ 57 | public function scenarios() 58 | { 59 | return [ 60 | 'signup' => ['username', 'email', 'password', 'repassword'], 61 | ]; 62 | } 63 | 64 | /** 65 | * @inheritdoc 66 | */ 67 | public function attributeLabels() 68 | { 69 | $labels = parent::attributeLabels(); 70 | 71 | return array_merge( 72 | $labels, 73 | [ 74 | 'password' => Yii::t('users', 'ATTR_PASSWORD'), 75 | 'repassword' => Yii::t('users', 'ATTR_REPASSWORD') 76 | ] 77 | ); 78 | } 79 | 80 | /** 81 | * @inheritdoc 82 | */ 83 | public function beforeSave($insert) 84 | { 85 | if (parent::beforeSave($insert)) { 86 | if ($this->isNewRecord) { 87 | $this->setPassword($this->password); 88 | } 89 | return true; 90 | } 91 | return false; 92 | } 93 | 94 | /** 95 | * @inheritdoc 96 | */ 97 | public function afterSave($insert, $changedAttributes) 98 | { 99 | parent::afterSave($insert, $changedAttributes); 100 | 101 | if ($insert) { 102 | if ($this->profile !== null) { 103 | $this->profile->save(false); 104 | } 105 | if ($this->module->requireEmailConfirmation === true) { 106 | $this->send(); 107 | } 108 | } 109 | } 110 | 111 | /** 112 | * Send an email confirmation token. 113 | * 114 | * @return boolean true if email was sent successfully 115 | */ 116 | public function send() 117 | { 118 | return $this->module->mail 119 | ->compose('signup', ['model' => $this]) 120 | ->setTo($this->email) 121 | ->setSubject(Yii::t('users', 'EMAIL_SUBJECT_SIGNUP') . ' ' . Yii::$app->name) 122 | ->send(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /traits/ModuleTrait.php: -------------------------------------------------------------------------------- 1 | _module === null) { 25 | $this->_module = Yii::$app->getModule('users'); 26 | } 27 | return $this->_module; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /views/admin/login.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'BACKEND_LOGIN_TITLE'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |

title); ?>

16 | [ 19 | 'template' => "
", 20 | ] 21 | ] 22 | ); ?> 23 | field($model, 'username') ?> 24 | field($model, 'password')->passwordInput() ?> 25 | field($model, 'rememberMe')->checkbox() ?> 26 |
27 |
28 | 'btn btn-primary']) ?> 29 |   30 | 31 |   32 | 33 |
34 |
35 | -------------------------------------------------------------------------------- /views/crud/_form.php: -------------------------------------------------------------------------------- 1 | 16 | 17 |
18 |
19 | field($profile, 'name') ?> 20 |
21 |
22 | field($profile, 'surname') ?> 23 |
24 |
25 |
26 |
27 | field($user, 'username') ?> 28 |
29 |
30 | field($user, 'email') ?> 31 |
32 |
33 |
34 |
35 | field($user, 'password')->passwordInput() ?> 36 |
37 |
38 | field($user, 'repassword')->passwordInput() ?> 39 |
40 |
41 |
42 |
43 | field($user, 'status_id')->dropDownList( 45 | $statusArray, 46 | [ 47 | 'prompt' => Yii::t('users', 'BACKEND_PROMPT_STATUS') 48 | ] 49 | ) ?> 50 |
51 |
52 | field($user, 'role')->dropDownList( 54 | $roleArray, 55 | [ 56 | 'prompt' => Yii::t('users', 'BACKEND_PROMPT_ROLE') 57 | ] 58 | ) ?> 59 |
60 |
61 |
62 |
63 | isNewRecord ? Yii::t('users', 'BACKEND_CREATE_SUBMIT') : Yii::t( 66 | 'users', 67 | 'BACKEND_UPDATE_SUBMIT' 68 | ), 69 | [ 70 | 'class' => $user->isNewRecord ? 'btn btn-success btn-large pull-right' : 'btn btn-primary btn-large pull-right' 71 | ] 72 | ) ?> 73 |
74 |
75 | -------------------------------------------------------------------------------- /views/crud/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'BACKEND_CREATE_TITLE'); 14 | 15 | echo Widget::widget( 16 | [ 17 | 'title' => $this->title, 18 | 'url' => ['index'], 19 | 'items' => [ 20 | 'cancel' => [ 21 | 'visible' => true 22 | ] 23 | ] 24 | ] 25 | ); 26 | 27 | echo $this->render( 28 | '_form', 29 | [ 30 | 'user' => $user, 31 | 'profile' => $profile, 32 | 'roleArray' => $roleArray, 33 | 'statusArray' => $statusArray 34 | ] 35 | ); -------------------------------------------------------------------------------- /views/crud/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'BACKEND_INDEX_TITLE'); 19 | 20 | echo Widget::widget( 21 | [ 22 | 'title' => $this->title, 23 | 'url' => ['index'], 24 | 'gridId' => 'users-grid', 25 | 'items' => [ 26 | 'create' => [ 27 | 'visible' => true 28 | ] 29 | ] 30 | ] 31 | ); 32 | 33 | Pjax::begin(); 34 | echo GridView::widget( 35 | [ 36 | 'id' => 'users-grid', 37 | 'dataProvider' => $dataProvider, 38 | 'filterModel' => $searchModel, 39 | 'columns' => [ 40 | [ 41 | 'class' => CheckboxColumn::classname() 42 | ], 43 | 'id', 44 | [ 45 | 'attribute' => 'username', 46 | 'format' => 'raw', 47 | 'value' => function ($model) { 48 | return Html::a($model['username'], ['view', 'id' => $model['id']], ['data-pjax' => 0]); 49 | } 50 | ], 51 | [ 52 | 'attribute' => 'name', 53 | 'value' => function ($model) { 54 | return $model->profile['name']; 55 | } 56 | ], 57 | [ 58 | 'attribute' => 'surname', 59 | 'value' => function ($model) { 60 | return $model->profile['surname']; 61 | } 62 | ], 63 | 'email', 64 | [ 65 | 'attribute' => 'status_id', 66 | 'value' => function ($model) { 67 | return $model->status; 68 | }, 69 | 'filter' => Html::activeDropDownList( 70 | $searchModel, 71 | 'status_id', 72 | $statusArray, 73 | ['class' => 'form-control', 'prompt' => Yii::t('users', 'BACKEND_PROMPT_STATUS')] 74 | ) 75 | ], 76 | [ 77 | 'attribute' => 'role', 78 | 'filter' => Html::activeDropDownList( 79 | $searchModel, 80 | 'role', 81 | $roleArray, 82 | ['class' => 'form-control', 'prompt' => Yii::t('users', 'BACKEND_PROMPT_ROLE')] 83 | ) 84 | ], 85 | [ 86 | 'class' => ActionColumn::className() 87 | ] 88 | ] 89 | ] 90 | ); 91 | Pjax::end(); -------------------------------------------------------------------------------- /views/crud/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'BACKEND_UPDATE_TITLE'); 14 | 15 | echo Widget::widget( 16 | [ 17 | 'title' => $this->title, 18 | 'url' => ['update', 'id' => $user['id']], 19 | 'modelId' => $user['id'], 20 | 'items' => [ 21 | 'create' => [ 22 | 'visible' => true 23 | ], 24 | 'cancel' => [ 25 | 'visible' => true 26 | ] 27 | ] 28 | ] 29 | ); 30 | 31 | echo $this->render( 32 | '_form', 33 | [ 34 | 'user' => $user, 35 | 'profile' => $profile, 36 | 'roleArray' => $roleArray, 37 | 'statusArray' => $statusArray 38 | ] 39 | ); -------------------------------------------------------------------------------- /views/crud/view.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'BACKEND_VIEW_TITLE'); 12 | 13 | echo Widget::widget( 14 | [ 15 | 'title' => $this->title, 16 | 'url' => ['view', 'id' => $model['id']], 17 | 'modelId' => $model['id'], 18 | 'items' => [ 19 | 'create' => [ 20 | 'visible' => true 21 | ], 22 | 'update' => [ 23 | 'visible' => true 24 | ], 25 | 'back' => [ 26 | 'visible' => true 27 | ] 28 | ] 29 | ] 30 | ); 31 | 32 | echo DetailView::widget( 33 | [ 34 | 'model' => $model, 35 | 'attributes' => [ 36 | 'id', 37 | 'username', 38 | 'email', 39 | [ 40 | 'attribute' => 'name', 41 | 'value' => $model->profile->name 42 | ], 43 | [ 44 | 'attribute' => 'surname', 45 | 'value' => $model->profile->surname 46 | ], 47 | 'status', 48 | 'created_at:date', 49 | 'updated_at:date' 50 | ] 51 | ] 52 | ); -------------------------------------------------------------------------------- /views/default/_index_item.php: -------------------------------------------------------------------------------- 1 | 11 |

profile['surname'] . ' ' . $model->profile['name'] . ' [' . $model['username'] . ']', ['/users/default/view', 'username' => $model['username']]) ?>

-------------------------------------------------------------------------------- /views/default/_index_loop.php: -------------------------------------------------------------------------------- 1 | $dataProvider, 12 | 'layout' => '
{items}
{pager}
', 13 | 'itemView' => '_index_item', 14 | 'itemOptions' => [ 15 | 'class' => 'user col-sm-2', 16 | 'tag' => 'article', 17 | 'itemscope' => true, 18 | 'itemtype' => 'http://schema.org/Person' 19 | ] 20 | ]); -------------------------------------------------------------------------------- /views/default/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_INDEX_TITLE'); 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |

title); ?>

14 | render('_index_loop', [ 15 | 'dataProvider' => $dataProvider 16 | ]); ?> -------------------------------------------------------------------------------- /views/default/view.php: -------------------------------------------------------------------------------- 1 | title = $model->profile['surname'] . ' ' . $model->profile['name'] . '[' . $model['username'] . ']'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |

title); ?>

-------------------------------------------------------------------------------- /views/guest/login.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_LOGIN_TITLE'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |

title); ?>

16 | [ 19 | 'template' => "
", 20 | ] 21 | ] 22 | ); ?> 23 | field($model, 'username') ?> 24 | field($model, 'password')->passwordInput() ?> 25 | field($model, 'rememberMe')->checkbox() ?> 26 |
27 |
28 | 'btn btn-primary']) ?> 29 |   30 | 31 |   32 | 33 |
34 |
35 | -------------------------------------------------------------------------------- /views/guest/recovery-confirmation.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_RECOVERY_CONFIRMATION_TITLE'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |

title); ?>

16 | [ 19 | 'template' => "
", 20 | ] 21 | ] 22 | ); ?> 23 | field($model, 'password')->passwordInput() ?> 24 | field($model, 'repassword')->passwordInput() ?> 25 | field($model, 'secure_key', ['template' => "{input}\n{error}"])->hiddenInput() ?> 26 |
27 |
28 | 'btn btn-success pull-right' 32 | ] 33 | ) ?> 34 |
35 |
36 | -------------------------------------------------------------------------------- /views/guest/recovery.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_RECOVERY_TITLE'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |

title); ?>

16 | 17 |
18 |
19 | field($model, 'email') ?> 20 |
21 |
22 |
23 |
24 | 'btn btn-success pull-right' 28 | ] 29 | ) ?> 30 |
31 |
32 | -------------------------------------------------------------------------------- /views/guest/resend.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_RESEND_TITLE'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |

title); ?>

16 | 17 |
18 |
19 | field($model, 'email') ?> 20 |
21 |
22 |
23 |
24 | 'btn btn-success pull-right' 28 | ] 29 | ) ?> 30 |
31 |
32 | -------------------------------------------------------------------------------- /views/guest/signup.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_SIGNUP_TITLE'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |

title); ?>

16 | 17 | 18 |
19 |
20 | field($profile, 'name') ?> 21 |
22 |
23 | field($profile, 'surname') ?> 24 |
25 |
26 |
27 |
28 | field($user, 'username') ?> 29 |
30 |
31 | field($user, 'email') ?> 32 |
33 |
34 |
35 |
36 | field($user, 'password')->passwordInput() ?> 37 |
38 |
39 | field($user, 'repassword')->passwordInput() ?> 40 |
41 |
42 |
43 |
44 | 'btn btn-success btn-large pull-right' 49 | ] 50 | ) ?> 51 | 52 |
53 |
54 | -------------------------------------------------------------------------------- /views/user/email.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_EMAIL_CHANGE_TITLE'); 12 | $this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 |

title); ?>

15 | [ 18 | 'template' => "
", 19 | ] 20 | ] 21 | ); ?> 22 | field($model, 'oldemail')->textInput(['readonly' => true]) ?> 23 | field($model, 'email') ?> 24 |
25 |
26 | 'btn btn-primary pull-right' 30 | ] 31 | ) ?> 32 |
33 |
34 | -------------------------------------------------------------------------------- /views/user/password.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_PASSWORD_CHANGE_TITLE'); 12 | $this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 |

title); ?>

15 | [ 18 | 'template' => "
", 19 | ] 20 | ] 21 | ); ?> 22 | field($model, 'oldpassword')->passwordInput() ?> 23 | field($model, 'password')->passwordInput() ?> 24 | field($model, 'repassword')->passwordInput() ?> 25 |
26 |
27 | 'btn btn-primary pull-right' 31 | ] 32 | ) ?> 33 |
34 |
35 | -------------------------------------------------------------------------------- /views/user/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('users', 'FRONTEND_UPDATE_TITLE'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |

title); ?>

16 | [ 19 | 'template' => "
", 20 | ] 21 | ] 22 | ); ?> 23 | field($model, 'name')->textInput() ?> 24 | field($model, 'surname')->textInput() ?> 25 |
26 |
27 | 'btn btn-primary pull-right' 31 | ] 32 | ) ?> 33 |
34 |
35 | --------------------------------------------------------------------------------