使用示例
在程式碼中使用資料許可權、目前支援多種方式進行動態開啟與關閉。 以下舉幾種常見的開發案例
對整個模型進行資料許可權控制
以預設的 User
模型為例,假設我們需要對 User
模型進行資料許可權控制。
可以在 User
模型中 use DataScopes
trait 來啟用資料許可權作用域。
php
use App\Library\DataPermission\Scope\DataScopes;
class User {}
// 使用資料許可權作用域
use DataScopes;
// 其他程式碼...
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
這樣會使所有對 User
模型的查詢都自動應用資料許可權控制。
對某個程式碼塊進行資料許可權控制
得益於 Hyperf Aop 特性,我們可以在類或者類方法上使用 DataScope 註解來對指定的程式碼塊開啟資料許可權控制。
以自帶的使用者模組的分頁列表為例
php
class UserService
{
#[DataScope(
scopeType: ScopeType::CREATED_BY,
onlyTables: ['user']
)]
public function page(array $params, int $page = 1, int $pageSize = 10): array
{
return parent::page($params, $page, $pageSize); // TODO: Change the autogenerated stub
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
這樣在呼叫 page
方法時,資料許可權會自動應用到查詢中。
對指定的 ORM Query 進行許可權控制
在某些特定場景中,需要更加細化的進行許可權隔離。此時可以透過 Factory::make()->build()
方法來對指定的 Query 進行限制
php
use App\Library\DataPermission\Factory;
use App\Model\Permission\User;
use App\Model\Permission\Wallet;
class DemoService {
public function test(User $user): void{
$walletQuery = Wallet::query();
// 對 WalletQuery 單獨進行資料隔離拼接
Factory::make()->build($user,$walletQuery->getQuery());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
指定其他欄位作為隔離條件
在某些情況下,業務表中可能會與預設的 created_by
dept_id
欄位名稱不一致,或者在某些複雜 join 查詢中。表名經過 table as xxxx
類似的操作。這個時候就需要指定新的隔離欄位了。以下舉幾個例子方便理解在不同的使用方法中如何指定新的欄位
在使用註解隔離某個方法的時候
自帶的 DataScope
註解有一些引數可以很方便的我們指定新的欄位
php
<?php
declare(strict_types=1);
/**
* This file is part of MineAdmin.
*
* @link https://www.mineadmin.com
* @document https://doc.mineadmin.com
* @contact root@imoi.cn
* @license https://github.com/mineadmin/MineAdmin/blob/master/LICENSE
*/
namespace App\Library\DataPermission\Attribute;
use App\Library\DataPermission\ScopeType;
use Hyperf\Di\Annotation\AbstractAnnotation;
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
final class DataScope extends AbstractAnnotation
{
public function __construct(
// 指定部門欄位名稱
private readonly string $deptColumn = 'dept_id',
// 建立人欄位名稱
private readonly string $createdByColumn = 'created_by',
// 隔離方式
private readonly ScopeType $scopeType = ScopeType::DEPT_CREATED_BY,
// 只對指定的表進行隔離。為空則全部隔離
private readonly ?array $onlyTables = null
) {}
public function getOnlyTables(): ?array
{
return $this->onlyTables;
}
public function getDeptColumn(): string
{
return $this->deptColumn;
}
public function getCreatedByColumn(): string
{
return $this->createdByColumn;
}
public function getScopeType(): ScopeType
{
return $this->scopeType;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
在手動使用 Factory::make()->build
時
而在手動呼叫 Factory
例項進行條件拼接的時候。就需要使用 App\Library\DataPermission\Context
來進行配置了。
php
use App\Library\DataPermission\Context as Ctx;
use App\Library\DataPermission\Factory;
// 只對 sss 表進行資料隔離
Ctx::setOnlyTables(['sss']);
// 設定部門欄位名稱
Ctx::setDeptColumn('department_id');
// 設定建立人欄位名稱
Ctx::setCreatedByColumn('creator');
// 設定隔離方式
Ctx::setScopeType(ScopeType::DEPT_CREATED_BY);
$query = XXXModel::query();
Factory::make()->build($user,$query->getQuery());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WARNING
需要注意,不管哪種使用方式。如果新開一個協程。都要重新設定一遍才能起效