Skip to content

Commit

Permalink
Refactored auth manager
Browse files Browse the repository at this point in the history
  • Loading branch information
ElisDN committed May 8, 2018
1 parent b0be163 commit ef0b56f
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 23 deletions.
1 change: 1 addition & 0 deletions config/common.php
Expand Up @@ -64,6 +64,7 @@
],
'authManager' => [
'class' => 'app\modules\user\components\AuthManager',
'modelClass' => 'app\modules\user\models\User',
],
'i18n' => [
'translations' => [
Expand Down
103 changes: 81 additions & 22 deletions modules/user/components/AuthManager.php
Expand Up @@ -2,57 +2,88 @@

namespace app\modules\user\components;

use app\modules\user\models\User;
use yii\base\InvalidParamException;
use yii\base\InvalidValueException;
use yii\rbac\Assignment;
use yii\rbac\PhpManager;
use Yii;

class AuthManager extends PhpManager
{
/**
* @var string User model class name
* must be instance of AuthRoleModelInterface
*/
public $modelClass = 'app\models\User';

/**
* @inheritdoc
*/
public function getAssignments($userId)
{
$assignments = [];
if ($userId && $user = $this->getUser($userId)) {
$assignment = new Assignment();
$assignment->userId = $userId;
$assignment->roleName = $user->role;
return [$assignment->roleName => $assignment];
foreach ($user->getAuthRoleNames() as $roleName) {
$assignment = new Assignment();
$assignment->userId = $userId;
$assignment->roleName = $roleName;
$assignments[$assignment->roleName] = $assignment;
}
}
return [];
return $assignments;
}

/**
* @inheritdoc
*/
public function getAssignment($roleName, $userId)
{
if ($userId && $user = $this->getUser($userId)) {
if ($user->role == $roleName) {
if (in_array($roleName, $user->getAuthRoleNames())) {
$assignment = new Assignment();
$assignment->userId = $userId;
$assignment->roleName = $user->role;
$assignment->roleName = $roleName;
return $assignment;
}
}
return null;
}

/**
* @inheritdoc
*/
public function getUserIdsByRole($roleName)
{
return User::find()->andWhere(['role' => $roleName])->select('id')->column();
/** @var AuthRoleModelInterface $class */
$class = $this->modelClass;
return $class::findAuthIdsByRoleName($roleName);
}

/**
* @inheritdoc
*/
protected function updateItem($name, $item)
{
if (parent::updateItem($name, $item)) {
if ($item->name !== $name) {
User::updateAll(['role' => $name], ['role' => $item->name]);
/** @var AuthRoleModelInterface $class */
$class = $this->modelClass;
$class::updateAuthGlobalRoleName($name, $item->name);
}
return true;
}
return false;
}

/**
* @inheritdoc
*/
public function removeItem($item)
{
if (parent::removeItem($item)) {
User::updateAll(['role' => null], ['role' => $item->name]);
/** @var AuthRoleModelInterface $class */
$class = $this->modelClass;
$class::removeAuthGlobalRoleName($item->name);
return true;
}
return false;
Expand All @@ -61,56 +92,84 @@ public function removeItem($item)
public function removeAll()
{
parent::removeAll();
User::updateAll(['role' => null]);
/** @var AuthRoleModelInterface $class */
$class = $this->modelClass;
$class::removeAuthGlobalRoleNames();
}

public function removeAllAssignments()
{
parent::removeAllAssignments();
User::updateAll(['role' => null]);
/** @var AuthRoleModelInterface $class */
$class = $this->modelClass;
$class::removeAuthGlobalAssignments();
}

/**
* @inheritdoc
*/
public function assign($role, $userId)
{
if ($userId && $user = $this->getUser($userId)) {
$user->updateAttributes(['role' => $user->role = $role->name]);
return true;
if (in_array($role->name, $user->getAuthRoleNames())) {
throw new InvalidParamException("Authorization item '{$role->name}' has already been assigned to user '$userId'.");
} else {
$assignment = new Assignment([
'userId' => $userId,
'roleName' => $role->name,
'createdAt' => time(),
]);
$user->addAuthRoleName($role->name);
return $assignment;
}
}
return false;
}

/**
* @inheritdoc
*/
public function revoke($role, $userId)
{
if ($userId && $user = $this->getUser($userId)) {
if ($user->role == $role->name) {
$user->updateAttributes(['role' => $user->role = null]);
if (in_array($role->name, $user->getAuthRoleNames())) {
$user->removeAuthRoleName($role->name);
return true;
}
}
return false;
}

/**
* @inheritdoc
*/
public function revokeAll($userId)
{
if ($userId && $user = $this->getUser($userId)) {
$user->updateAttributes(['role' => $user->role = null]);
$user->clearAuthRoleNames();
return true;
}
return false;
}

/**
* @param integer $userId
* @return null|\yii\web\IdentityInterface|User
* @return null|AuthRoleModelInterface
*/
private function getUser($userId)
{
/** @var \yii\web\User $webUser */
$webUser = Yii::$app->get('user', false);
if ($webUser && !$webUser->getIsGuest() && $webUser->getId() == $userId) {
return $webUser->identity;
if ($webUser && !$webUser->getIsGuest() && $webUser->getId() == $userId && $webUser->getIdentity() instanceof AuthRoleModelInterface) {
return $webUser->getIdentity();
} else {
return User::findOne($userId);
/** @var AuthRoleModelInterface $class */
$class = $this->modelClass;
$identity = $class::findAuthRoleIdentity($userId);
if ($identity && !$identity instanceof AuthRoleModelInterface) {
throw new InvalidValueException('The identity object must implement AuthRoleInterface.');
}
return $identity;
}
}
}
59 changes: 59 additions & 0 deletions modules/user/components/AuthRoleModelInterface.php
@@ -0,0 +1,59 @@
<?php

namespace app\modules\user\components;

interface AuthRoleModelInterface
{
/**
* @param mixed $id
* @return AuthRoleModelInterface
*/
public static function findAuthRoleIdentity($id);

/**
* @param string $roleName
* @return array
*/
public static function findAuthIdsByRoleName($roleName);

/**
* @param string $oldRoleName
* @param string $newRoleName
*/
public static function updateAuthGlobalRoleName($oldRoleName, $newRoleName);

/**
* @param string $roleName
*/
public static function removeAuthGlobalRoleName($roleName);

/**
* On all roles removing
*/
public static function removeAuthGlobalRoleNames();

/**
* On all assignments removing
*/
public static function removeAuthGlobalAssignments();

/**
* @return array
*/
public function getAuthRoleNames();

/**
* @param string $roleName
*/
public function addAuthRoleName($roleName);

/**
* @param string $roleName
*/
public function removeAuthRoleName($roleName);

/**
* Removes all roles
*/
public function clearAuthRoleNames();
}
53 changes: 52 additions & 1 deletion modules/user/models/User.php
Expand Up @@ -2,6 +2,7 @@

namespace app\modules\user\models;

use app\modules\user\components\AuthRoleModelInterface;
use app\modules\user\models\query\UserQuery;
use app\modules\user\Module;
use Yii;
Expand All @@ -26,7 +27,7 @@
* @property string $role
* @property integer $status
*/
class User extends ActiveRecord implements IdentityInterface
class User extends ActiveRecord implements IdentityInterface, AuthRoleModelInterface
{
const STATUS_BLOCKED = 0;
const STATUS_ACTIVE = 1;
Expand Down Expand Up @@ -153,6 +154,56 @@ public function validateAuthKey($authKey)
return $this->getAuthKey() === $authKey;
}

public static function findAuthRoleIdentity($id)
{
return static::findOne($id);
}

public static function findAuthIdsByRoleName($roleName)
{
return static::find()->where(['role' => $roleName])->select(['id'])->column();
}

public static function updateAuthGlobalRoleName($oldRoleName, $newRoleName)
{
self::updateAll(['role' => $newRoleName], ['role' => $oldRoleName]);
}

public static function removeAuthGlobalRoleName($roleName)
{
self::updateAll(['role' => null], ['role' => $roleName]);
}

public static function removeAuthGlobalRoleNames()
{
self::updateAll(['role' => null]);
}

public static function removeAuthGlobalAssignments()
{
self::updateAll(['role' => null]);
}

public function getAuthRoleNames()
{
return [$this->role];
}

public function addAuthRoleName($roleName)
{
$this->updateAttributes(['role' => $this->role = $roleName]);
}

public function removeAuthRoleName($roleName)
{
$this->updateAttributes(['role' => $this->role = null]);
}

public function clearAuthRoleNames()
{
$this->updateAttributes(['role' => $this->role = null]);
}

/**
* Finds user by username
*
Expand Down

0 comments on commit ef0b56f

Please sign in to comment.