diff --git a/lib/User/Bootstrap.php b/lib/User/Bootstrap.php index 3ee7d56..db455bf 100644 --- a/lib/User/Bootstrap.php +++ b/lib/User/Bootstrap.php @@ -1,6 +1,8 @@ hasModule('user') && $app->getModule('user') instanceof Module) { $map = $this->buildClassMap($app->getModule('user')->classMap); - $this->initContainer($app,$map); + $this->initContainer($app, $map); $this->initTranslations($app); $this->initMailServiceConfiguration($app, $app->getModule('user')); @@ -30,6 +32,7 @@ class Bootstrap implements BootstrapInterface $this->initControllerNamespace($app); $this->initUrlRoutes($app); $this->initAuthCollection($app); + $this->initAuthManager($app); } else { /** @var $app ConsoleApplication */ $this->initConsoleCommands($app); @@ -66,6 +69,7 @@ class Bootstrap implements BootstrapInterface $di->set(Helper\AuthHelper::class); $di->set(Helper\GravatarHelper::class); $di->set(Helper\SecurityHelper::class); + $di->set(Helper\TimezoneHelper::class); // services $di->set(Service\AccountConfirmationService::class); @@ -143,6 +147,23 @@ class Bootstrap implements BootstrapInterface } } + /** + * Ensures the auth manager is the one provided by the library. + * + * @param Application $app + */ + protected function initAuthModule(Application $app) + { + if (!($app->getAuthManager() instanceof AuthManagerInterface)) { + $app->set( + 'authManager', + [ + 'class' => AuthDbManagerComponent::class + ] + ); + } + } + /** * Initializes web url routes (rules in Yii2) * @@ -170,7 +191,7 @@ class Bootstrap implements BootstrapInterface * Ensures required mail parameters needed for the mail service. * * @param Application $app - * @param Module $module + * @param Module|\yii\base\Module $module */ protected function initMailServiceConfiguration(Application $app, Module $module) { diff --git a/lib/User/Component/AuthDbManagerComponent.php b/lib/User/Component/AuthDbManagerComponent.php new file mode 100644 index 0000000..a546ef8 --- /dev/null +++ b/lib/User/Component/AuthDbManagerComponent.php @@ -0,0 +1,75 @@ +from($this->itemTable); + + if ($type !== null) { + $query->where(['type' => $type]); + } else { + $query->orderBy('type'); + } + + foreach ($excludeItems as $name) { + $query->andWhere('name <> :item', ['item' => $name]); + } + + $items = []; + + foreach ($query->all($this->db) as $row) { + $items[$row['name']] = $this->populateItem($row); + } + + return $items; + } + + /** + * Returns both roles and permissions assigned to user. + * + * @param integer $userId + * + * @return array + */ + public function getItemsByUser($userId) + { + if (empty($userId)) { + return []; + } + + $query = (new Query()) + ->select('b.*') + ->from(['a' => $this->assignmentTable, 'b' => $this->itemTable]) + ->where('{{a}}.[[item_name]]={{b}}.[[name]]') + ->andWhere(['a.user_id' => (string)$userId]); + + $roles = []; + foreach ($query->all($this->db) as $row) { + $roles[$row['name']] = $this->populateItem($row); + $roles[$row['name']] = $this->populateItem($row); + } + + return $roles; + } + + /** + * @inheritdoc + */ + public function getItem($name) + { + return parent::getItem($name); + } +} diff --git a/lib/User/Contracts/AuthManagerInterface.php b/lib/User/Contracts/AuthManagerInterface.php new file mode 100644 index 0000000..8fc5562 --- /dev/null +++ b/lib/User/Contracts/AuthManagerInterface.php @@ -0,0 +1,29 @@ +authHelper = $authHelper; + parent::__construct($id, $module, $config); + } + + /** + * @inheritdoc + */ + public function behaviors() + { + return [ + 'access' => [ + 'class' => AccessControl::className(), + 'ruleConfig' => [ + 'class' => AccessRuleFilter::className(), + ], + 'rules' => [ + [ + 'allow' => true, + 'roles' => ['admin'], + ], + ], + ], + ]; + } + + public function actionIndex() + { + $searchModel = $this->make($this->getSearchModelClass()); + + return $this->render( + 'index', + [ + 'searchModel' => $searchModel, + 'dataProvider' => $searchModel->search(Yii::$app->request->get()) + ] + ); + } + + public function actionCreate() + { + /** @var AbstractAuthItem $model */ + $model = $this->make($this->getModelClass(), [], ['scenario' => 'create']); + + $this->make(AjaxRequestModelValidator::class, [$model])->validate(); + + if ($model->load(Yii::$app->request->post())) { + if ($this->make(AuthItemEditionService::class, [$model])->run()) { + Yii::$app + ->getSession() + ->setFlash('success', Yii::t('user', 'Authorization item successfully created.')); + + return $this->redirect(['index']); + + } else { + Yii::$app->getSession()->setFlash('danger', Yii::t('user', 'Unable to create authorization item.')); + } + } + + return $this->render( + 'create', + [ + 'model' => $model, + 'unassignedItems' => $this->authHelper->getUnassignedItems($model) + ] + ); + } + + public function actionUpdate($name) + { + $authItem = $this->getItem($name); + + /** @var AbstractAuthItem $model */ + $model = $this->make($this->getModelClass(), [], ['scenario' => 'update', 'item' => $authItem]); + + $this->make(AjaxRequestModelValidator::class, [$model])->validate(); + + if ($model->load(Yii::$app->request->post())) { + + if ($this->make(AuthItemEditionService::class, [$model])->run()) { + Yii::$app + ->getSession() + ->setFlash('success', Yii::t('user', 'Authorization item successfully updated.')); + + return $this->redirect(['index']); + + } else { + Yii::$app->getSession()->setFlash('danger', Yii::t('user', 'Unable to update authorization item.')); + } + } + + return $this->render( + 'update', + [ + 'model' => $model, + 'unassignedItems' => $this->authHelper->getUnassignedItems($model) + ] + ); + } + + public function actionDelete($name) + { + $item = $this->getItem($name); + + if ($this->authHelper->remove($item)) { + Yii::$app->getSession()->setFlash('success', Yii::t('user', 'Authorization item successfully removed.')); + } else { + Yii::$app->getSession()->setFlash('success', Yii::t('user', 'Unable to remove authorization item.')); + } + + return $this->redirect(['index']); + } + + /** + * The fully qualified class name of the model + * + * @return string + */ + abstract protected function getModelClass(); + + /** + * The fully qualified class name of the search model + * + * @return string + */ + abstract protected function getSearchModelClass(); + + /** + * Returns the an auth item + * + * @param string $name + * + * @return \yii\rbac\Role|\yii\rbac\Permission|\yii\rbac\Rule + */ + abstract protected function getItem($name); + +} diff --git a/lib/User/Controller/AdminController.php b/lib/User/Controller/AdminController.php index b7932f5..2cfe63a 100644 --- a/lib/User/Controller/AdminController.php +++ b/lib/User/Controller/AdminController.php @@ -208,6 +208,7 @@ class AdminController extends Controller '_assignments', [ 'user' => $user, + 'params' => Yii::$app->request->post() ] ); } diff --git a/lib/User/Controller/PermissionController.php b/lib/User/Controller/PermissionController.php new file mode 100644 index 0000000..33d9524 --- /dev/null +++ b/lib/User/Controller/PermissionController.php @@ -0,0 +1,41 @@ +authHelper->getPermission($name); + + if ($authItem !== null) { + return $authItem; + } + + throw new NotFoundHttpException(); + } + +} diff --git a/lib/User/Controller/ProfileController.php b/lib/User/Controller/ProfileController.php index ddcf0bf..f0ede02 100644 --- a/lib/User/Controller/ProfileController.php +++ b/lib/User/Controller/ProfileController.php @@ -58,6 +58,7 @@ class ProfileController extends Controller public function actionShow($id) { $profile = $this->profileQuery->whereId($id)->one(); + if ($profile === null) { throw new NotFoundHttpException(); } diff --git a/lib/User/Controller/RoleController.php b/lib/User/Controller/RoleController.php new file mode 100644 index 0000000..b0812f2 --- /dev/null +++ b/lib/User/Controller/RoleController.php @@ -0,0 +1,40 @@ +authHelper->getRole($name); + + if ($authItem !== null) { + return $authItem; + } + + throw new NotFoundHttpException(); + } + +} diff --git a/lib/User/Factory/AuthItemFactory.php b/lib/User/Factory/AuthItemFactory.php new file mode 100644 index 0000000..e368a14 --- /dev/null +++ b/lib/User/Factory/AuthItemFactory.php @@ -0,0 +1,50 @@ + 'makeRole', + Item::TYPE_PERMISSION => 'makePermission' + ]; + + /** + * @param $name + * + * @return \yii\rbac\Permission + */ + public static function makePermission($name) + { + return Yii::$app->getAuthManager()->createPermission($name); + } + + /** + * @param $name + * + * @return \yii\rbac\Role + */ + public static function makeRole($name) + { + return Yii::$app->getAuthManager()->createRole($name); + } + + /** + * @param $type + * @param $name + * + * @return \yii\rbac\Role|\yii\rbac\Permission + * @throws Exception + */ + public static function makeByType($type, $name) + { + if (array_key_exists($type, self::$map)) { + return call_user_func([self::class, self::$map[$type]], $name); + } + + throw new Exception('Unknown strategy type'); + } +} diff --git a/lib/User/Helper/AuthHelper.php b/lib/User/Helper/AuthHelper.php index 5266c53..6b69d13 100644 --- a/lib/User/Helper/AuthHelper.php +++ b/lib/User/Helper/AuthHelper.php @@ -1,30 +1,31 @@ - */ class AuthHelper { + use AuthManagerTrait; + /** - * Checks whether + * Checks whether a user has certain role * + * @param $userId * @param $role * * @return bool */ public function hasRole($userId, $role) { - if (Yii::$app->getAuthManager()) { - $roles = array_keys(Yii::$app->getAuthManager()->getRolesByUser($userId)); + if ($this->getAuthManager()) { + $roles = array_keys($this->getAuthManager()->getRolesByUser($userId)); return in_array($role, $roles, true); } @@ -41,11 +42,61 @@ class AuthHelper { /** @var Module $module */ $module = Yii::$app->getModule('user'); - $hasAdministratorPermissionName = Yii::$app->getAuthManager() && $module->administratorPermissionName + $hasAdministratorPermissionName = $this->getAuthManager() && $module->administratorPermissionName ? Yii::$app->getUser()->can($module->administratorPermissionName) : false; return $hasAdministratorPermissionName || in_array($username, $module->administrators); } + /** + * @param $name + * + * @return null|\yii\rbac\Item|Permission + */ + public function getPermission($name) + { + return $this->getAuthManager()->getPermission($name); + } + + /** + * @param $name + * + * @return null|\yii\rbac\Item|Role + */ + public function getRole($name) + { + return $this->getAuthManager()->getRole($name); + } + + /** + * Removes a role, permission or rule from the RBAC system. + * + * @param Role|Permission|Rule $object + * + * @return bool whether the role, permission or rule is successfully removed + */ + public function remove($object) + { + return $this->getAuthManager()->remove($object); + } + + /** + * @param AbstractAuthItem $model + * + * @return array + */ + public function getUnassignedItems(AbstractAuthItem $model) + { + $excludeItems = $model->item !== null ? [$model->item->name] : []; + $items = $this->getAuthManager()->getItems($model->getType(), $excludeItems); + + return ArrayHelper::map( + $items, + 'name', + function ($item) { + return empty($item->description) ? $item->name : "{$item->name} ({$item->description})"; + } + ); + } } diff --git a/lib/User/Helper/TimezoneHelper.php b/lib/User/Helper/TimezoneHelper.php new file mode 100644 index 0000000..7a4c0ce --- /dev/null +++ b/lib/User/Helper/TimezoneHelper.php @@ -0,0 +1,35 @@ +getOffset() / 60 / 60; + $timeZones[] = [ + 'timezone' => $timeZone, + 'name' => "{$timeZone} (UTC " . ($offset > 0 ? '+' : '') . "{$offset})", + 'offset' => $offset + ]; + } + + ArrayHelper::multisort($timeZones, 'offset', SORT_DESC, SORT_NUMERIC); + + return $timeZones; + } +} diff --git a/lib/User/Model/AbstractAuthItem.php b/lib/User/Model/AbstractAuthItem.php new file mode 100644 index 0000000..5e7a810 --- /dev/null +++ b/lib/User/Model/AbstractAuthItem.php @@ -0,0 +1,120 @@ +item instanceof Item) { + $this->itemName = $this->item->name; + $this->name = $this->item->name; + $this->description = $this->item->description; + $this->children = array_keys($this->getAuthManager()->getChildren($this->item->name)); + if ($this->item->ruleName !== null) { + $this->rule = get_class($this->getAuthManager()->getRule($this->item->ruleName)); + } + } + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'name' => Yii::t('user', 'Name'), + 'description' => Yii::t('user', 'Description'), + 'children' => Yii::t('user', 'Children'), + 'rule' => Yii::t('user', 'Rule'), + ]; + } + + /** + * @inheritdoc + */ + public function scenarios() + { + return [ + 'create' => ['name', 'description', 'children', 'rule'], + 'update' => ['name', 'description', 'children', 'rule'], + ]; + } + + /** + * @inheritdoc + */ + public function rules() + { + return [ + ['itemName', 'safe'], + ['name', 'required'], + ['name', 'match', 'pattern' => '/^[\w][\w-.:]+[\w]$/'], + [['name', 'description', 'rule'], 'trim'], + [ + 'name', + function () { + if ($this->getAuthManager()->getItem($this->name) !== null) { + $this->addError('name', Yii::t('user', 'Auth item with such name already exists')); + } + }, + 'when' => function () { + return $this->scenario == 'create' || $this->item->name != $this->name; + } + ], + ['children', RbacItemsValidator::class], + ['rule', RbacRuleValidator::class], + ]; + } + + /** + * @return bool + */ + public function getIsNewRecord() + { + return $this->item === null; + } + + /** + * @return Item + */ + abstract public function getType(); +} diff --git a/lib/User/Model/Assignment.php b/lib/User/Model/Assignment.php new file mode 100644 index 0000000..9904753 --- /dev/null +++ b/lib/User/Model/Assignment.php @@ -0,0 +1,54 @@ +user_id === null) { + throw new InvalidConfigException('"user_id" must be set.'); + } + + $this->items = array_keys($this->getAuthManager()->getItemsByUser($this->user_id)); + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'items' => Yii::t('user', 'Items') + ]; + } + + /** + * @inheritdoc + */ + public function rules() + { + return [ + ['user_id', 'required'], + ['items', RbacItemsValidator::class], + ['user_id', 'integer'] + ]; + } +} diff --git a/lib/User/Model/Permission.php b/lib/User/Model/Permission.php new file mode 100644 index 0000000..9598489 --- /dev/null +++ b/lib/User/Model/Permission.php @@ -0,0 +1,12 @@ + ['name', 'description', 'rule_name'], + ]; + } + + public function search($params = []) + { + /** @var ArrayDataProvider $dataProvider */ + $dataProvider = $this->make(ArrayDataProvider::class); + + $query = (new Query()) + ->select(['name', 'description', 'rule_name']) + ->andWhere(['type' => $this->getType()]) + ->from($this->getAuthManager()->itemTable); + + if ($this->load($params) && $this->validate()) { + $query + ->andFilterWhere(['like', 'name', $this->name]) + ->andFilterWhere(['like', 'description', $this->description]) + ->andFilterWhere(['like', 'rule_name', $this->rule_name]); + } + + $dataProvider->allModels = $query->all($this->getAuthManager()->db); + + return $dataProvider; + + } +} diff --git a/lib/User/Search/PermissionSearch.php b/lib/User/Search/PermissionSearch.php new file mode 100644 index 0000000..c4f2efb --- /dev/null +++ b/lib/User/Search/PermissionSearch.php @@ -0,0 +1,16 @@ +model = $model; + } + + public function run() + { + if (!$this->model->validate()) { + return false; + } + try { + if ($this->model->getIsNewRecord()) { + $item = AuthItemFactory::makeByType($this->model->getType(), $this->model->name); + } else { + $item = $this->model->item; + } + + $item->name = $this->model->name; + $item->description = $this->model->description; + + if (!empty($this->model->rule)) { + $rule = $this->make($this->model->rule); + if (null === $this->getAuthManager()->getRule($rule->name)) { + $this->getAuthManager()->add($rule); + } + $item->ruleName = $rule->name; + } else { + $item->ruleName = null; + } + + if ($this->model->getIsNewRecord()) { + $this->getAuthManager()->add($item); + } else { + $this->getAuthManager()->update($this->model->itemName, $item); + $this->model->itemName = $item->name; + } + + $this->model->item = $item; + + return $this->updateChildren(); + + } catch (Exception $e) { + return false; + } + } + + /** + * Updates Auth Item children + * + * @return bool + */ + protected function updateChildren() + { + $children = $this->getAuthManager()->getChildren($this->model->item->name); + $childrenNames = array_keys($children); + + if (is_array($this->model->children)) { + + // remove those not linked anymore + foreach (array_diff($childrenNames, $this->model->children) as $item) { + if (!$this->getAuthManager()->removeChild($this->model->item, $children[$item])) { + return false; + } + + } + // add new children + foreach (array_diff($this->model->children, $childrenNames) as $item) { + if (!$this->getAuthManager()->addChild($this->model->item, $this->getAuthManager()->getItem($item))) { + return false; + } + } + } else { + return $this->getAuthManager()->removeChildren($this->model->item); + } + + return true; + } +} diff --git a/lib/User/Service/UpdateAuthAssignmentsService.php b/lib/User/Service/UpdateAuthAssignmentsService.php new file mode 100644 index 0000000..0cad148 --- /dev/null +++ b/lib/User/Service/UpdateAuthAssignmentsService.php @@ -0,0 +1,44 @@ +model = $model; + } + + public function run() + { + if ($this->model->validate()) { + return false; + } + + if (!is_array($this->model->items)) { + $this->model->items = []; + } + + $assignedItems = $this->getAuthManager()->getItemsByUser($this->model->user_id); + $assignedItemsNames = array_keys($assignedItems); + + foreach (array_diff($assignedItemsNames, $this->model->items) as $item) { + $this->model->getAuthManager()->revoke($assignedItems[$item], $this->model->user_id); + } + + foreach (array_diff($this->model->items, $assignedItemsNames) as $item) { + $this->getAuthManager()->assign($this->getAuthManager()->getItem($item), $this->model->user_id); + } + + return $this->model->updated = true; + + } +} diff --git a/lib/User/Traits/AuthManagerTrait.php b/lib/User/Traits/AuthManagerTrait.php new file mode 100644 index 0000000..5e041f9 --- /dev/null +++ b/lib/User/Traits/AuthManagerTrait.php @@ -0,0 +1,16 @@ +getAuthManager(); + } +} diff --git a/lib/User/Validator/RbacItemsValidator.php b/lib/User/Validator/RbacItemsValidator.php new file mode 100644 index 0000000..1960689 --- /dev/null +++ b/lib/User/Validator/RbacItemsValidator.php @@ -0,0 +1,25 @@ +getAuthManager()->getItem($item) == null) { + return [Yii::t('user', 'There is neither role nor permission with name "{0}"', [$item]), []]; + } + } + } + +} diff --git a/lib/User/Validator/RbacRuleValidator.php b/lib/User/Validator/RbacRuleValidator.php new file mode 100644 index 0000000..055bd2c --- /dev/null +++ b/lib/User/Validator/RbacRuleValidator.php @@ -0,0 +1,26 @@ +isInstantiable() == false) { + return [Yii::t('user', 'Rule class can not be instantiated'), []]; + } + if ($class->isSubclassOf('\yii\rbac\Rule') == false) { + return [Yii::t('user', 'Rule class must extend "yii\rbac\Rule"'), []]; + } + } +} diff --git a/lib/User/Widget/AssignmentsWidget.php b/lib/User/Widget/AssignmentsWidget.php index 16588c2..2d79f8d 100644 --- a/lib/User/Widget/AssignmentsWidget.php +++ b/lib/User/Widget/AssignmentsWidget.php @@ -2,44 +2,68 @@ namespace Da\User\Widget; -use dektrium\rbac\components\DbManager; -use dektrium\rbac\models\Assignment; -use Yii; +use Da\User\Model\Assignment; +use Da\User\Service\UpdateAuthAssignmentsService; +use Da\User\Traits\AuthManagerTrait; +use Da\User\Traits\ContainerTrait; use yii\base\InvalidConfigException; use yii\base\Widget; +use yii\helpers\ArrayHelper; class AssignmentsWidget extends Widget { - /** @var integer ID of the user to whom auth items will be assigned. */ + use AuthManagerTrait; + use ContainerTrait; + + /** + * @var integer ID of the user to whom auth items will be assigned. + */ public $userId; + /** + * @var string[] the post parameters + */ + public $params = []; - /** @var DbManager */ - protected $manager; - - /** @inheritdoc */ + /** + * @inheritdoc + * @throws InvalidConfigException + */ public function init() { parent::init(); - $this->manager = Yii::$app->authManager; if ($this->userId === null) { - throw new InvalidConfigException('You should set ' . __CLASS__ . '::$userId'); + throw new InvalidConfigException( __CLASS__ . '::$userId is required'); } } - /** @inheritdoc */ + /** + * @inheritdoc + */ public function run() { - $model = Yii::createObject([ - 'class' => Assignment::className(), - 'user_id' => $this->userId, - ]); + $model = $this->make(Assignment::class, [], ['user_id' => $this->userId]); - if ($model->load(\Yii::$app->request->post())) { - $model->updateAssignments(); + if ($model->load($this->params)) { + $this->make(UpdateAuthAssignmentsService::class, [$model])->run(); } return $this->render('/widgets/assignments/form', [ 'model' => $model, + 'availableItems' => $this->getAvailableItems() ]); } + + /** + * Returns all available auth items to be attached to the user + * + * @return array + */ + protected function getAvailableItems() + { + return ArrayHelper::map($this->getAuthManager()->getItems(), 'name', function ($item) { + return empty($item->description) + ? $item->name + : $item->name . ' (' . $item->description . ')'; + }); + } } diff --git a/lib/User/resources/views/admin/_assignments.php b/lib/User/resources/views/admin/_assignments.php index 1c09fda..99dd900 100644 --- a/lib/User/resources/views/admin/_assignments.php +++ b/lib/User/resources/views/admin/_assignments.php @@ -5,6 +5,7 @@ use Da\User\Widget\AssignmentsWidget; /** * @var yii\web\View $this * @var \Da\User\Model\User $user + * @var string[] $params */ ?> @@ -20,6 +21,6 @@ use Da\User\Widget\AssignmentsWidget; ] ) ?> - $user->id]) ?> + $user->id, 'params' => $params]) ?> endContent() ?> diff --git a/lib/User/resources/views/admin/create.php b/lib/User/resources/views/admin/create.php index b91aa82..daf4779 100644 --- a/lib/User/resources/views/admin/create.php +++ b/lib/User/resources/views/admin/create.php @@ -14,7 +14,7 @@ $this->params['breadcrumbs'][] = ['label' => Yii::t('user', 'Users'), 'url' => [ $this->params['breadcrumbs'][] = $this->title; ?> - +
render( '/shared/_alert', [ @@ -22,69 +22,86 @@ $this->params['breadcrumbs'][] = $this->title; ] ) ?> -render('_menu') ?> -
-
+
-
- [ - 'class' => 'nav-pills nav-stacked', - ], - 'items' => [ - ['label' => Yii::t('user', 'Account details'), 'url' => ['/user/admin/create']], - [ - 'label' => Yii::t('user', 'Profile details'), - 'options' => [ - 'class' => 'disabled', - 'onclick' => 'return false;', - ] - ], - [ - 'label' => Yii::t('user', 'Information'), - 'options' => [ - 'class' => 'disabled', - 'onclick' => 'return false;', - ] - ], - ], - ] - ) ?> +
+

title) ?>

-
-
-
-
-
- . - . -
- 'horizontal', - 'enableAjaxValidation' => true, - 'enableClientValidation' => false, - 'fieldConfig' => [ - 'horizontalCssClasses' => [ - 'wrapper' => 'col-sm-9', - ], - ], - ] - ); ?> + render('/shared/_menu') ?> +
+
+
+
+ [ + 'class' => 'nav-pills nav-stacked', + ], + 'items' => [ + [ + 'label' => Yii::t('user', 'Account details'), + 'url' => ['/user/admin/create'] + ], + [ + 'label' => Yii::t('user', 'Profile details'), + 'options' => [ + 'class' => 'disabled', + 'onclick' => 'return false;', + ] + ], + [ + 'label' => Yii::t('user', 'Information'), + 'options' => [ + 'class' => 'disabled', + 'onclick' => 'return false;', + ] + ], + ], + ] + ) ?> +
+
+
+
+
+
+
+ . + . +
+ 'horizontal', + 'enableAjaxValidation' => true, + 'enableClientValidation' => false, + 'fieldConfig' => [ + 'horizontalCssClasses' => [ + 'wrapper' => 'col-sm-9', + ], + ], + ] + ); ?> - render('_user', ['form' => $form, 'user' => $user]) ?> + render('_user', ['form' => $form, 'user' => $user]) ?> -
-
- 'btn btn-block btn-success']) ?> +
+
+ 'btn btn-block btn-success'] + ) ?> +
+
+ + +
+
- -
+ diff --git a/lib/User/resources/views/admin/index.php b/lib/User/resources/views/admin/index.php index 6c65b91..5a315af 100644 --- a/lib/User/resources/views/admin/index.php +++ b/lib/User/resources/views/admin/index.php @@ -17,14 +17,7 @@ $this->title = Yii::t('user', 'Manage users'); $this->params['breadcrumbs'][] = $this->title; ?> -render( - '/shared/_alert', - [ - 'module' => Yii::$app->getModule('user'), - ] -) ?> - -render('/admin/_menu') ?> +beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> @@ -113,3 +106,5 @@ $this->params['breadcrumbs'][] = $this->title; ); ?> + +endContent() ?> diff --git a/lib/User/resources/views/admin/update.php b/lib/User/resources/views/admin/update.php index 3140ee6..a3c1411 100644 --- a/lib/User/resources/views/admin/update.php +++ b/lib/User/resources/views/admin/update.php @@ -3,6 +3,7 @@ use Da\User\Model\User; use yii\bootstrap\Nav; use yii\web\View; +use yii\helpers\Html; /** * @var View $this @@ -15,7 +16,7 @@ $this->params['breadcrumbs'][] = ['label' => Yii::t('user', 'Users'), 'url' => [ $this->params['breadcrumbs'][] = $this->title; ?> - +
render( '/shared/_alert', [ @@ -23,84 +24,106 @@ $this->params['breadcrumbs'][] = $this->title; ] ) ?> -render('_menu') ?> -
-
+
-
- [ - 'class' => 'nav-pills nav-stacked', - ], - 'items' => [ - [ - 'label' => Yii::t('user', 'Account details'), - 'url' => ['/user/admin/update', 'id' => $user->id] - ], - [ - 'label' => Yii::t('user', 'Profile details'), - 'url' => ['/user/admin/update-profile', 'id' => $user->id] - ], - [ - 'label' => Yii::t('user', 'Information'), - 'url' => ['/user/admin/info', 'id' => $user->id] - ], - [ - 'label' => Yii::t('user', 'Assignments'), - 'url' => ['/user/admin/assignments', 'id' => $user->id], - ], - '
', - [ - 'label' => Yii::t('user', 'Confirm'), - 'url' => ['/user/admin/confirm', 'id' => $user->id], - 'visible' => !$user->isConfirmed, - 'linkOptions' => [ - 'class' => 'text-success', - 'data-method' => 'post', - 'data-confirm' => Yii::t('user', 'Are you sure you want to confirm this user?'), - ], - ], - [ - 'label' => Yii::t('user', 'Block'), - 'url' => ['/user/admin/block', 'id' => $user->id], - 'visible' => !$user->isBlocked, - 'linkOptions' => [ - 'class' => 'text-danger', - 'data-method' => 'post', - 'data-confirm' => Yii::t('user', 'Are you sure you want to block this user?'), - ], - ], - [ - 'label' => Yii::t('user', 'Unblock'), - 'url' => ['/user/admin/block', 'id' => $user->id], - 'visible' => $user->isBlocked, - 'linkOptions' => [ - 'class' => 'text-success', - 'data-method' => 'post', - 'data-confirm' => Yii::t('user', 'Are you sure you want to unblock this user?'), - ], - ], - [ - 'label' => Yii::t('user', 'Delete'), - 'url' => ['/user/admin/delete', 'id' => $user->id], - 'linkOptions' => [ - 'class' => 'text-danger', - 'data-method' => 'post', - 'data-confirm' => Yii::t('user', 'Are you sure you want to delete this user?'), - ], - ], - ], - ] - ) ?> +
+

title) ?>

-
-
-
-
- + render('/shared/_menu') ?> +
+
+
+
+ [ + 'class' => 'nav-pills nav-stacked', + ], + 'items' => [ + [ + 'label' => Yii::t('user', 'Account details'), + 'url' => ['/user/admin/update', 'id' => $user->id] + ], + [ + 'label' => Yii::t('user', 'Profile details'), + 'url' => ['/user/admin/update-profile', 'id' => $user->id] + ], + [ + 'label' => Yii::t('user', 'Information'), + 'url' => ['/user/admin/info', 'id' => $user->id] + ], + [ + 'label' => Yii::t('user', 'Assignments'), + 'url' => ['/user/admin/assignments', 'id' => $user->id], + ], + '
', + [ + 'label' => Yii::t('user', 'Confirm'), + 'url' => ['/user/admin/confirm', 'id' => $user->id], + 'visible' => !$user->isConfirmed, + 'linkOptions' => [ + 'class' => 'text-success', + 'data-method' => 'post', + 'data-confirm' => Yii::t( + 'user', + 'Are you sure you want to confirm this user?' + ), + ], + ], + [ + 'label' => Yii::t('user', 'Block'), + 'url' => ['/user/admin/block', 'id' => $user->id], + 'visible' => !$user->isBlocked, + 'linkOptions' => [ + 'class' => 'text-danger', + 'data-method' => 'post', + 'data-confirm' => Yii::t( + 'user', + 'Are you sure you want to block this user?' + ), + ], + ], + [ + 'label' => Yii::t('user', 'Unblock'), + 'url' => ['/user/admin/block', 'id' => $user->id], + 'visible' => $user->isBlocked, + 'linkOptions' => [ + 'class' => 'text-success', + 'data-method' => 'post', + 'data-confirm' => Yii::t( + 'user', + 'Are you sure you want to unblock this user?' + ), + ], + ], + [ + 'label' => Yii::t('user', 'Delete'), + 'url' => ['/user/admin/delete', 'id' => $user->id], + 'linkOptions' => [ + 'class' => 'text-danger', + 'data-method' => 'post', + 'data-confirm' => Yii::t( + 'user', + 'Are you sure you want to delete this user?' + ), + ], + ], + ], + ] + ) ?> +
+
+
+
+
+
+ +
+
+
+
diff --git a/lib/User/resources/views/permission/_form.php b/lib/User/resources/views/permission/_form.php new file mode 100644 index 0000000..732fff8 --- /dev/null +++ b/lib/User/resources/views/permission/_form.php @@ -0,0 +1,36 @@ + + + false, + 'enableAjaxValidation' => true, +]) ?> + +field($model, 'name') ?> + +field($model, 'description') ?> + +field($model, 'rule') ?> + +field($model, 'children')->widget(Select2::className(), [ + 'data' => $unassignedItems, + 'options' => [ + 'id' => 'children', + 'multiple' => true + ], +]) ?> + + 'btn btn-success btn-block']) ?> + + diff --git a/lib/User/resources/views/permission/create.php b/lib/User/resources/views/permission/create.php new file mode 100644 index 0000000..27d4095 --- /dev/null +++ b/lib/User/resources/views/permission/create.php @@ -0,0 +1,24 @@ +title = Yii::t('user', 'Create new permission'); +$this->params['breadcrumbs'][] = $this->title; + +?> + +beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> + +render( + '_form', + [ + 'model' => $model, + 'unassignedItems' => $unassignedItems + ] +) ?> + +endContent() ?> diff --git a/lib/User/resources/views/permission/index.php b/lib/User/resources/views/permission/index.php new file mode 100644 index 0000000..450b4b6 --- /dev/null +++ b/lib/User/resources/views/permission/index.php @@ -0,0 +1,60 @@ +title = Yii::t('user', 'Permissions'); +$this->params['breadcrumbs'][] = $this->title; + +?> + +beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> + + $dataProvider, + 'filterModel' => $searchModel, + 'layout' => "{items}\n{pager}", + 'columns' => [ + [ + 'attribute' => 'name', + 'header' => Yii::t('user', 'Name'), + 'options' => [ + 'style' => 'width: 20%' + ], + ], + [ + 'attribute' => 'description', + 'header' => Yii::t('user', 'Description'), + 'options' => [ + 'style' => 'width: 55%' + ], + ], + [ + 'attribute' => 'rule_name', + 'header' => Yii::t('user', 'Rule name'), + 'options' => [ + 'style' => 'width: 20%' + ], + ], + [ + 'class' => ActionColumn::className(), + 'template' => '{update} {delete}', + 'urlCreator' => function ($action, $model) { + return Url::to(['/user/permission/' . $action, 'name' => $model['name']]); + }, + 'options' => [ + 'style' => 'width: 5%' + ], + ] + ], + ] +) ?> +endContent() ?> diff --git a/lib/User/resources/views/permission/update.php b/lib/User/resources/views/permission/update.php new file mode 100644 index 0000000..8124521 --- /dev/null +++ b/lib/User/resources/views/permission/update.php @@ -0,0 +1,25 @@ +title = Yii::t('user', 'Update permission'); +$this->params['breadcrumbs'][] = $this->title; + +?> + +beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> + +render( + '_form', + [ + 'model' => $model, + 'unassignedItems' => $unassignedItems + ] +) ?> + +endContent() ?> + diff --git a/lib/User/resources/views/registration/register.php b/lib/User/resources/views/registration/register.php index 1cf07e9..966a4a1 100644 --- a/lib/User/resources/views/registration/register.php +++ b/lib/User/resources/views/registration/register.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE.md - * file that was distributed with this source code. - */ - use yii\helpers\Html; use yii\widgets\ActiveForm; diff --git a/lib/User/resources/views/role/_form.php b/lib/User/resources/views/role/_form.php new file mode 100644 index 0000000..49738fe --- /dev/null +++ b/lib/User/resources/views/role/_form.php @@ -0,0 +1,41 @@ +get(AuthHelper::class)->getUnassignedItems($model); +?> + + false, + 'enableAjaxValidation' => true, + ] +) ?> + +field($model, 'name') ?> + +field($model, 'description') ?> + +field($model, 'rule') ?> + +field($model, 'children')->widget( + Select2::className(), + [ + 'data' => $unassignedItems, + 'options' => [ + 'id' => 'children', + 'multiple' => true + ], + ] +) ?> + + 'btn btn-success btn-block']) ?> + + diff --git a/lib/User/resources/views/role/create.php b/lib/User/resources/views/role/create.php new file mode 100644 index 0000000..2624220 --- /dev/null +++ b/lib/User/resources/views/role/create.php @@ -0,0 +1,24 @@ +title = Yii::t('user', 'Create new role'); +$this->params['breadcrumbs'][] = $this->title; + +?> + +beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> + +render( + '_form', + [ + 'model' => $model, + 'unassignedItems' => $unassignedItems + ] +) ?> + +endContent() ?> diff --git a/lib/User/resources/views/role/index.php b/lib/User/resources/views/role/index.php new file mode 100644 index 0000000..73a257a --- /dev/null +++ b/lib/User/resources/views/role/index.php @@ -0,0 +1,61 @@ +title = Yii::t('user', 'Roles'); +$this->params['breadcrumbs'][] = $this->title; + +?> + +beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> + + $dataProvider, + 'filterModel' => $searchModel, + 'layout' => "{items}\n{pager}", + 'columns' => [ + [ + 'attribute' => 'name', + 'header' => Yii::t('user', 'Name'), + 'options' => [ + 'style' => 'width: 20%' + ], + ], + [ + 'attribute' => 'description', + 'header' => Yii::t('user', 'Description'), + 'options' => [ + 'style' => 'width: 55%' + ], + ], + [ + 'attribute' => 'rule_name', + 'header' => Yii::t('user', 'Rule name'), + 'options' => [ + 'style' => 'width: 20%' + ], + ], + [ + 'class' => ActionColumn::className(), + 'template' => '{update} {delete}', + 'urlCreator' => function ($action, $model) { + return Url::to(['/user/role/' . $action, 'name' => $model['name']]); + }, + 'options' => [ + 'style' => 'width: 5%' + ], + ] + ], + ] +) ?> + +endContent() ?> diff --git a/lib/User/resources/views/role/update.php b/lib/User/resources/views/role/update.php new file mode 100644 index 0000000..c372c25 --- /dev/null +++ b/lib/User/resources/views/role/update.php @@ -0,0 +1,24 @@ +title = Yii::t('user', 'Update role'); +$this->params['breadcrumbs'][] = $this->title; + +?> + +beginContent('@Da/User/resources/views/shared/admin_layout.php') ?> + +render( + '_form', + [ + 'model' => $model, + 'unassignedItems' => $unassignedItems + ] +) ?> + +endContent() ?> diff --git a/lib/User/resources/views/settings/account.php b/lib/User/resources/views/settings/account.php index 8607219..89a5a9f 100644 --- a/lib/User/resources/views/settings/account.php +++ b/lib/User/resources/views/settings/account.php @@ -12,6 +12,7 @@ use yii\widgets\ActiveForm; $this->title = Yii::t('user', 'Account settings'); $this->params['breadcrumbs'][] = $this->title; ?> +
render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?> diff --git a/lib/User/resources/views/settings/networks.php b/lib/User/resources/views/settings/networks.php index 1499f37..2cd63d8 100644 --- a/lib/User/resources/views/settings/networks.php +++ b/lib/User/resources/views/settings/networks.php @@ -13,6 +13,8 @@ $this->title = Yii::t('user', 'Networks'); $this->params['breadcrumbs'][] = $this->title; ?> +
+ render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?>
@@ -28,12 +30,14 @@ $this->params['breadcrumbs'][] = $this->title;

.

- ['/user/security/auth'], - 'accounts' => $user->socialNetworkAccounts, - 'autoRender' => false, - 'popupMode' => false, - ]) ?> + ['/user/security/auth'], + 'accounts' => $user->socialNetworkAccounts, + 'autoRender' => false, + 'popupMode' => false, + ] + ) ?> getClients() as $client): ?> @@ -45,13 +49,21 @@ $this->params['breadcrumbs'][] = $this->title; diff --git a/lib/User/resources/views/settings/profile.php b/lib/User/resources/views/settings/profile.php index 897d661..3696b57 100644 --- a/lib/User/resources/views/settings/profile.php +++ b/lib/User/resources/views/settings/profile.php @@ -1,26 +1,24 @@ - * - * For the full copyright and license information, please view the LICENSE.md - * file that was distributed with this source code. - */ - use yii\helpers\Html; +use yii\widgets\ActiveForm; +use yii\helpers\ArrayHelper; +use Da\User\Helper\TimezoneHelper; /** * @var yii\web\View $this * @var yii\widgets\ActiveForm $form - * @var dektrium\user\models\Profile $profile + * @var \Da\User\Model\Profile $model + * @var TimezoneHelper $timezoneHelper */ $this->title = Yii::t('user', 'Profile settings'); $this->params['breadcrumbs'][] = $this->title; +$timezoneHelper = $model->make(TimezoneHelper::class); ?> +
+ render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?>
@@ -33,17 +31,19 @@ $this->params['breadcrumbs'][] = $this->title; title) ?>
- 'profile-form', - 'options' => ['class' => 'form-horizontal'], - 'fieldConfig' => [ - 'template' => "{label}\n
{input}
\n
{error}\n{hint}
", - 'labelOptions' => ['class' => 'col-lg-3 control-label'], - ], - 'enableAjaxValidation' => true, - 'enableClientValidation' => false, - 'validateOnBlur' => false, - ]); ?> + $model->formName(), + 'options' => ['class' => 'form-horizontal'], + 'fieldConfig' => [ + 'template' => "{label}\n
{input}
\n
{error}\n{hint}
", + 'labelOptions' => ['class' => 'col-lg-3 control-label'], + ], + 'enableAjaxValidation' => true, + 'enableClientValidation' => false, + 'validateOnBlur' => false, + ] + ); ?> field($model, 'name') ?> @@ -55,18 +55,12 @@ $this->params['breadcrumbs'][] = $this->title; field($model, 'timezone') - ->dropDownList( - \yii\helpers\ArrayHelper::map( - \dektrium\user\helpers\Timezone::getAll(), - 'timezone', - 'name' - ) - ); ?> - + ->dropDownList(ArrayHelper::map($timezoneHelper->getAll(),'timezone','name')); + ?> field($model, 'gravatar_email') ->hint( - \yii\helpers\Html::a( + Html::a( Yii::t('user', 'Change your avatar at Gravatar.com'), 'http://gravatar.com' ) @@ -76,14 +70,12 @@ $this->params['breadcrumbs'][] = $this->title;
- 'btn btn-block btn-success'] - ) ?>
+ 'btn btn-block btn-success']) ?> +
- +
diff --git a/lib/User/resources/views/admin/_menu.php b/lib/User/resources/views/shared/_menu.php similarity index 82% rename from lib/User/resources/views/admin/_menu.php rename to lib/User/resources/views/shared/_menu.php index bcd01b5..6efd76e 100644 --- a/lib/User/resources/views/admin/_menu.php +++ b/lib/User/resources/views/shared/_menu.php @@ -17,11 +17,11 @@ use yii\bootstrap\Nav; ], [ 'label' => Yii::t('user', 'Roles'), - 'url' => ['/rbac/role/index'] + 'url' => ['/user/role/index'] ], [ 'label' => Yii::t('user', 'Permissions'), - 'url' => ['/rbac/permission/index'] + 'url' => ['/user/permission/index'] ], [ 'label' => Yii::t('user', 'Create'), @@ -32,11 +32,11 @@ use yii\bootstrap\Nav; ], [ 'label' => Yii::t('user', 'New role'), - 'url' => ['/rbac/role/create'] + 'url' => ['/user/role/create'] ], [ 'label' => Yii::t('user', 'New permission'), - 'url' => ['/rbac/permission/create'] + 'url' => ['/user/permission/create'] ], ], ], diff --git a/lib/User/resources/views/shared/admin_layout.php b/lib/User/resources/views/shared/admin_layout.php new file mode 100644 index 0000000..de94da7 --- /dev/null +++ b/lib/User/resources/views/shared/admin_layout.php @@ -0,0 +1,25 @@ + +
+render( + '/shared/_alert', + [ + 'module' => Yii::$app->getModule('user'), + ] +) ?> +
+
+
+
+

title) ?>

+
+
+ render('_menu') ?> + +
+
+
+
diff --git a/lib/User/resources/views/widgets/assignments/form.php b/lib/User/resources/views/widgets/assignments/form.php index 6cee984..3d54888 100644 --- a/lib/User/resources/views/widgets/assignments/form.php +++ b/lib/User/resources/views/widgets/assignments/form.php @@ -1,22 +1,13 @@ - * - * For the full copyright and license information, please view the LICENSE.md - * file that was distributed with this source code. - */ - -use dektrium\rbac\models\Assignment; use kartik\select2\Select2; use yii\bootstrap\Alert; use yii\helpers\Html; use yii\widgets\ActiveForm; /** - * @var $model Assignment + * @var $model \Da\User\Model\Assignment + * @var $availableItems string[] */ ?> @@ -27,7 +18,7 @@ use yii\widgets\ActiveForm; 'options' => [ 'class' => 'alert-success' ], - 'body' => Yii::t('rbac', 'Assignments have been updated'), + 'body' => Yii::t('user', 'Assignments have been updated'), ]) ?> @@ -40,14 +31,14 @@ use yii\widgets\ActiveForm; field($model, 'items')->widget(Select2::className(), [ - 'data' => $model->getAvailableItems(), + 'data' => $availableItems, 'options' => [ 'id' => 'items', 'multiple' => true ], ]) ?> - 'btn btn-success btn-block']) ?> + 'btn btn-success btn-block']) ?>
isConnected($client) ? - Html::a(Yii::t('user', 'Disconnect'), $auth->createClientUrl($client), [ - 'class' => 'btn btn-danger btn-block', - 'data-method' => 'post', - ]) : - Html::a(Yii::t('user', 'Connect'), $auth->createClientUrl($client), [ - 'class' => 'btn btn-success btn-block', - ]) + Html::a( + Yii::t('user', 'Disconnect'), + $auth->createClientUrl($client), + [ + 'class' => 'btn btn-danger btn-block', + 'data-method' => 'post', + ] + ) : + Html::a( + Yii::t('user', 'Connect'), + $auth->createClientUrl($client), + [ + 'class' => 'btn btn-success btn-block', + ] + ) ?>