Meine Anwendung hat technisch zwei Bereiche, einen globalen Bereich (Feedback, Benutzerprofil, Benutzereinstellungen, etc) und einen Gruppenbereich (Kontakte, Projekte, Gruppenprofile, Gruppeneinstellungen, etc).Yii2 RBAC Mehrfachzuweisungen für jeden Benutzer basierend auf Gruppen
Ich verwende den RBAC DBManager für den globalen Bereich, und es funktioniert gut, aber ich habe Probleme bei der Implementierung eines Autorisierungsmechanismus für den Gruppenbereich.
Der Grund dafür ist, dass Gruppen unter den Benutzern geteilt werden können und ein Benutzer möglicherweise mehrere Zuweisungen in der Tabelle group_access (id, group_id, user_id, item_name) hat, da sie Mitglieder mehrerer Gruppen sein können unterschiedliche Berechtigungsstufen für diese Gruppen.
Hier ist meine Auth Setup:
$auth = Yii::$app->authManager;
// group permissions
$manageGroupUsers = $auth->createPermission('manage_group_users');
$manageGroupUsers->description = 'Manage Group Users';
$auth->add($manageGroupUsers);
$manageGroupSettings = $auth->createPermission('manage_group_settings');
$manageGroupSettings->description = 'Manage Group Settings';
$auth->add($manageGroupSettings);
// app permissions
$manageAppUsers = $auth->createPermission('manage_app_users');
$manageAppUsers->description = 'Manage App Users';
$auth->add($manageAppUsers);
$manageAppGroups = $auth->createPermission('manage_app_groups');
$manageAppGroups->description = 'Manage App Groups';
$auth->add($manageAppGroups);
$manageAppSettings = $auth->createPermission('manage_app_settings');
$manageAppSettings->description = 'Manage App Settings';
$auth->add($manageAppSettings);
$manageAppFeedback = $auth->createPermission('manage_app_feedback');
$manageAppFeedback->description = 'Manage App Feedback';
$auth->add($manageAppFeedback);
// group roles
// -- create role
$groupUser = $auth->createRole('group_user');
$groupUser->description = 'Group Users';
$auth->add($groupUser);
// -- create role
$groupAdmin = $auth->createRole('group_admin');
$groupAdmin->description = 'Group Administrators';
$auth->add($groupAdmin);
// add permissions
$auth->addChild($groupAdmin, $manageGroupUsers);
$auth->addChild($groupAdmin, $manageGroupSettings);
// inherit permissions
$auth->addChild($groupAdmin, $groupUser);
// -- create role
$groupCreator = $auth->createRole('group_creator');
$groupCreator->description = 'Group Creators';
$auth->add($groupCreator);
// inherit permissions
$auth->addChild($groupCreator, $groupAdmin);
// app roles
// -- create role
$appUser = $auth->createRole('app_user');
$appUser->description = 'App Users';
$auth->add($appUser);
// -- create role
$appSupport = $auth->createRole('app_support');
$appSupport->description = 'Support Users';
$auth->add($appSupport);
// add permissions
$auth->addChild($appSupport, $manageAppFeedback);
// -- create role
$appAdmin = $auth->createRole('app_admin');
$appAdmin->description = 'App Administrators';
$auth->add($appAdmin);
// add permissions
$auth->addChild($appAdmin, $manageAppUsers);
$auth->addChild($appAdmin, $manageAppGroups);
$auth->addChild($appAdmin, $manageAppSettings);
// inherit permissions
$auth->addChild($appAdmin, $appUser);
$auth->addChild($appAdmin, $appSupport);
// -- create role
$appCreator = $auth->createRole('app_creator');
$appCreator->description = 'App Creators';
$auth->add($appCreator);
// inherit permissions
$auth->addChild($appCreator, $appAdmin);
Meine group_access Tabelle hat das gleiche Schema wie die auth_assignment Tabelle, mit der Ausnahme, dass es eine group_id Spalte hat, und die user_id Spalte ist nicht eindeutig.
Der Benutzer hat nur eine Zuweisung in Bezug auf den globalen Bereich, kann aber viele verschiedene Aufgaben im Gruppenbereich haben, da er möglicherweise Administratorrechte für Gruppe a, aber nur Benutzerberechtigungen für Gruppe b hat.
Meine DB eingerichtet ist, wie:
Benutzer (status_id, Benutzername, auth_key, password_hash, E-Mail, etc.)
Gruppen (status_id, Name, Beschreibung, etc.)
Group_Access (group_id, user_id, item_name) Jeder Benutzer erhält eine Zuweisung für jede Gruppe, auf die er Zugriff hat.
sample_group_access_records [ [ 'id' => 1, 'User_id' => 35, 'group_id' => 17, 'item_name' => 'group_admin' ], [ 'id' => 2, 'user_id' => 35, 'group_id' => 356, 'item_name' => 'group_user' ], [ 'id' => 3, 'user_id' => 35, 'group_id' => 211, 'Elementname' => 'Gruppe_Creator' ], ];
Die checkaccess Funktion der Benutzer-ID qualifizieren können, und ich kann sogar die kürzere „kann“ Version verwenden, die für den angemeldeten Benutzer funktioniert gut, aber ich brauche Zugriff auf einen Benutzer Option wie unten überprüfen basiert:
Option::getOption('user', 'active_group_id')
Dies ist eine benutzerdefinierte Funktion, die die aktive Gruppen-ID aus einer Benutzeroptions-Tabelle abruft. Wenn ein Benutzer Gruppen wechselt, wird dies geändert. Mein Optionsmodell hat drei Typen: "App", "Benutzer", "Gruppe".
Es wäre nett, wenn ich eine Funktion herausfinden könnte, die das gleiche wie das native checkAccess ist, aber checkGroupAccess genannt wird und automatisch die active_group_id erhält und die Benutzerzuweisungen aus der Tabelle group_access zieht und die Berechtigungsprüfung durchführt.
Ich hoffe, das macht Sinn.
Vielen Dank für Ihre Zeit.
Mike
** AKTUALISIERT **
Also, ich habe eine Lösung, die benutzerdefinierten Funktionen verwenden checkaccess für die richtigen Berechtigungen für die Gruppe oder globale Bereiche zu überprüfen.
Ich habe zwei Tabellen (user_access, group_access), die ein ähnliches Schema wie die Standard {{auth_assignment}} Tabelle haben, von denen ich jetzt nicht verwende. Ich verwende die Tabellen {{auth_item}}, {{auth_item_child}} und {{auth_rule}}.
Ich habe zwei Modelle, eines für jede der Zugriffstabellen GroupAccess => group_access und UserAccess => user_access.
Ich habe auch ein Modell für die Zugriffsfunktionen und haben es auf die Komponentenkonfiguration zugeordnet.
Hier mein Zugangsmodell ist:
<?php
namespace app\models;
use Yii;
class Access
{
public function canUser($type, $permissionName, $params = [])
{
switch ($type) {
case 'group':
$userID = Yii::$app->user->identity->id;
$groupID = Yii::$app->options->getOption('user', 'active_group_id');
$queryAll = GroupAccess::find()
->where('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID])
->asArray()
->all();
$assignments = [];
foreach ($queryAll as $queryItem) {
$assignments[$queryItem['item_name']] = [
'userId' => $queryItem['user_id'],
'roleName' => $queryItem['item_name'],
'createdAt' => $queryItem['created_date'],
];
}
$result = self::checkAccess($userID, $permissionName, $assignments, $params);
return $result;
break;
case 'user':
$userID = Yii::$app->user->identity->id;
$queryAll = UserAccess::find()
->where(['user_id' => $userID])
->asArray()
->all();
$assignments = [];
foreach ($queryAll as $queryItem) {
$assignments[$queryItem['item_name']] = [
'userId' => $queryItem['user_id'],
'roleName' => $queryItem['item_name'],
'createdAt' => $queryItem['created_date'],
];
}
$result = self::checkAccess($userID, $permissionName, $assignments, $params);
return $result;
break;
}
}
public function checkAccess($userID, $permissionName, $assignments, $params = [])
{
$auth = Yii::$app->authManager;
$auth->loadFromCache();
if ($auth->items !== null) {
return $auth->checkAccessFromCache($userID, $permissionName, $params, $assignments);
} else {
return $auth->checkAccessRecursive($userID, $permissionName, $params, $assignments);
}
}
public function assign($type, $role, $userID = null, $groupID = null)
{
switch ($type) {
case 'group':
// clear existing assigments
self::revoke('group', $userID, $groupID);
$groupAccess = new GroupAccess();
$groupAccess->group_id = $groupID;
$groupAccess->user_id = $userID;
$groupAccess->item_name = $role;
$groupAccess->created_date = time();
return $groupAccess->save();
break;
case 'user':
// clear existing assignments
self::revoke('user', $userID);
$userAccess = new UserAccess();
$userAccess->user_id = $userID;
$userAccess->item_name = $role;
$userAccess->created_date = time();
return $userAccess->save();
break;
}
}
public function revoke($type, $userID, $groupID = null)
{
switch ($type) {
case 'group':
GroupAccess::deleteAll('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID]);
break;
case 'user':
UserAccess::deleteAll('user_id = :user_id', [':user_id' => $userID]);
break;
}
}
}
Und hier sind einige Beispiele die Funktionen für den Zugriff verwendet:
// get the user option
echo Yii::$app->options->getOption('user', 'active_group_id');
// assign group role
Yii::$app->access->assign('group', 'group_creator', 22, 18);
// assign user role
Yii::$app->access->assign('user', 'app_user', 22);
// revoke group access
Yii::$app->access->revoke('group', 22, 18);
// revoke user access
Yii::$app->access->revoke('user', 22);
// test user permission
var_dump(Yii::$app->access->canUser('user', 'manage_app_settings'));
// test the group permission
var_dump(Yii::$app->access->canUser('group', 'manage_group_settings'));
Im Wesentlichen kopierte ich die checkaccess-Funktion aus dem DbManager und nachbearbeitet es ein wenig, um den Benutzerzugriff anhand der Gruppe zu überprüfen.
Das einzige Problem ist, dass ich eine Änderung an der tatsächlichen DbManager-Source-Klasse vornehmen musste, um die $ items (Eigenschaft), checkAccessFromCache (function) und checkAccessRecursive (function) alle öffentlich zu machen, damit sie außerhalb von zugegriffen werden können die Klasse. Der Hauptnachteil ist die Aktualisierbarkeit ...
Irgendwo herum?
Danke.
ich geschrieben habe eine funktionierende Lösung. –