Есть у меня куча разрозненных сервисов, и давнее желание собрать это все в один сайт.
И вот процессе освоения yii воплощения вышеупомянутого желания, родилась мысль написать "новую" концепцию распределения доступов, не на основе ролей, а на основе индивидуальных разрешений, но при этом пользователей предполагается большое число.
В качестве отвлеченно примера можно привести больницу.
Врач специалист в своей области + у него может быть несколько дополнительных специализаций.
Ему необходимо предоставить доступ во все разделы, в которых он является специалистом.
Если действовать классически, то придется прописывать каждому врачу доступ в каждый раздел.
Если подойти на основе ролей, то со временем кол-во ролей может начать стремится к 2 в степени кол-ва специализаций.
Потому решил сделать так, возможно что не ново для рецептов, тогда можно просто снести тему, а возможно кому и пригодится.
Что не нравится самому:
- return (object)$val
- 'access'=>5),//CONTACT+PICTURE Не получилось сделать 'access'=>self::CONTACT| self::PICTURE
Хотя тогда все можно делать на checkbox'ах и будет вообще красиво
Код: Выделить всё
class User extends CModel{
//Accesses
const NOTHING=0;
const CONTACT=1;
const MUSIC =2;
const PICTURE=4;
const TEXT =8;
const ALL =0xFFFFFFFF;
static private $users=array(
array('id'=>1,'userName'=>'Admin','pass'=>'123','access'=>self::ALL),
array('id'=>2,'userName'=>'Petr', 'pass'=>'123','access'=>5),//CONTACT+PICTURE
);
/**
* @param $username
* @return null|object
*/
static function getUserByName($username){
foreach(self::$users as $val){
if($val['userName']==$username) return (object)$val;
}
return null;
}
/**
* @param $id
* @return null|object
*/
static function getUserById($id){
foreach(self::$users as $val){
if($val['id']==$id) return (object)$val;
}
return null;
}
function attributeNames(){return array();}
}
Код: Выделить всё
class UserIdentity extends CUserIdentity{
private $_id;
public function authenticate(){
$user=User::getUserByName($this->username);
if($user===null) $this->errorCode=self::ERROR_USERNAME_INVALID;
elseif($user->pass!==$this->password)$this->errorCode=self::ERROR_PASSWORD_INVALID;
else{
$this->_id=$user->id;
$this->username=$user->userName;
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId(){ return $this->_id; }
}
Код: Выделить всё
class WebUser extends CWebUser{
private $_model=null;
function getAccess(){
if($user=$this->getModel()){
return $user->access;
}
}
private function getModel(){
if(!$this->isGuest && $this->_model===null){
$this->_model=User::getUserById($this->id);
}
return $this->_model;
}
}
Код: Выделить всё
public function accessRules(){
return array(
array('allow',
'actions'=>array('picture'),
'expression'=>'$user->access & User::PICTURE'),
array('allow',
'actions'=>array('text'),
'expression'=>'$user->access & User::TEXT'),
array('deny', 'users'=>array('*')),
);
}