1

私は自分のアプリへのユーザー アクセスを制御するために Yii RBAC を使用しています。これは 3 つの mySql テーブルで構成されています。

authitem(RBAC ロール アイテム)

authitemchild(他のロールに属するすべての RBAC ルール)

authitemassignment(ユーザーへの役割の割り当て)

たとえば、次のようなテーブルがあるとします。

正規品:

|   name (pk)   |
 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

オーティテムチャイルド

|   parent (pk)   |   child (pk)   |
 areaASuperUser    areaACreateOnly
 areaASuperUser    areaAReadOnly
 areaASuperUser    areaAUpdateOnly
 areaASuperUser    areaADeleteOnly

 areaBSuperUser    areaBCreateOnly
 areaBSuperUser    areaBReadOnly
 areaBSuperUser    areaBUpdateOnly
 areaBSuperUser    areaBDeleteOnly

auititemassignment

|    itemname (pk)   |   userid (pk)   |
 areaASuperUser       1

上記のシナリオでは、ID が 1 のユーザーは、areaA で完全な CRUD アクセス権を持っています。私が必要としているのは、ユーザーがアクセスできないすべてのロールのリストです。また、ユーザーアクセスできるすべてのロールの子も考慮する必要があります。

ユーザーがアクセスできないすべてのロールを簡単に取得できます。

SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `authassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE  `aa`.`itemname` IS NULL

しかし、これは次を返します:

 |   name    |
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

また、すべての areaA* ロールは areaASuperUser の子であるため、それらを返したくありません。

アドバイスや正しい方向へのプッシュは大歓迎です!

*編集:

ありがとう@SuVeRa、あなたの答え:

SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `authassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE  
`aa`.`itemname` IS NULL 
AND `ai`.`name` NOT IN (
    SELECT
    `aic`.`child` itemname
    FROM `authitemchild` `aic`
    JOIN `authassignment` `aa`
    ON `aa`.`itemname` = `aic`.`parent`
    WHERE `aa`.`userid` = 1
)

上記の例では完全に機能しますが、アプリを拡張して、子供向けの複数のレベルを含めるようにしました。

正規品:

|   name (pk)   |

 areaABSuperUser

 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly

オーティテムチャイルド

|   parent (pk)   |   child (pk)   |
 areaABSuperUser   areaASuperUser
 areaABSuperUser   areaBSuperUser

 areaASuperUser    areaACreateOnly
 areaASuperUser    areaAReadOnly
 areaASuperUser    areaAUpdateOnly
 areaASuperUser    areaADeleteOnly

 areaBSuperUser    areaBCreateOnly
 areaBSuperUser    areaBReadOnly
 areaBSuperUser    areaBUpdateOnly
 areaBSuperUser    areaBDeleteOnly

 areaCSuperUser    areaCCreateOnly
 areaCSuperUser    areaCReadOnly
 areaCSuperUser    areaCUpdateOnly
 areaCSuperUser    areaCDeleteOnly

auititemassignment

|    itemname (pk)   |   userid (pk)   |
 areaABSuperUser      1

元の答えが返されます。

 |   name    |
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly

親と子は除外されますが、子の子は除外されません。私が求めている結果 (この 2 番目の例) は次のとおりです。

 |   name    |
 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly

***編集2:

特に Yii の場合:

私は Yii についてもう少し調べてみました。CAuthManagerには、 hasItemChild()isAssigned()getItemChildren()など、必要なデータを取得するのに役立ついくつかの便利なメソッドがあります。

4

1 に答える 1

1

このクエリはあなたを助けるかもしれません

SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `auithitemassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE  
`aa`.`itemname` IS NULL 
AND `ai`.`name` NOT IN (
    SELECT
    `aic`.`child` itemname
    FROM `authitemchild` `aic`
    JOIN `auithitemassignment` `aa`
    ON `aa`.`itemname` = `aic`.`parent`
    WHERE `aa`.`userid` = 1
)
于 2012-09-18T11:00:19.993 に答える