Skip to content

Commit

Permalink
refactor(permissions): remove Casbin and refactor permission logic (#399
Browse files Browse the repository at this point in the history
)

* refactor(permissions): remove Casbin and refactor permission logic

- Remove Casbin dependency and related code
- Refactor permission logic to use database-based approach
- Update menu and role models to use new permission system
- Modify permission controller and middleware to reflect changes
- Update tests to cover new permission functionality

* refactor(user-seeder): remove unused import

- Remove unused import of Casbin\Enforcer from user_seeder_20240926.php

* refactor(casbin): remove casbin factory and update role status

- Remove Casbin\Enforcer and Mine\Casbin\Factory from dependencies.php- Comment out 'adapter' setting in permission.php
- Update RoleSchema to use status value instead of status object- Improve type safety in RoleService by ignoring phpstan check

* refactor(config): update dependencies and permission configurations

- Update UploadInterface class reference in dependencies.php
- Comment out adapter setting in permission.php
  • Loading branch information
zds-s authored Oct 31, 2024
1 parent 71799e2 commit b445b22
Show file tree
Hide file tree
Showing 39 changed files with 393 additions and 491 deletions.
64 changes: 64 additions & 0 deletions app/Command/UpdateCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);
/**
* This file is part of MineAdmin.
*
* @link https://www.mineadmin.com
* @document https://doc.mineadmin.com
* @contact [email protected]
* @license https://github.com/mineadmin/MineAdmin/blob/master/LICENSE
*/

namespace App\Command;

use App\Model\Permission\Menu;
use App\Model\Permission\Role;
use App\Model\Permission\User;
use Hyperf\Command\Annotation\AsCommand;
use Hyperf\Command\Concerns\InteractsWithIO;
use Hyperf\DbConnection\Db;

class UpdateCommand
{
use InteractsWithIO;

#[AsCommand(
signature: 'mine:update-20241031'
)]
public function handle()
{
$this->output->title('Update 2024_10_31_193302_create_user_belongs_role');
Db::table(\Hyperf\Config\config('permission.database.table'))->insert([
'v0' => 'admin',
'v1' => 'superAdmin',
'ptype' => 'g',
]);
$result = Db::table(\Hyperf\Config\config('permission.database.table'))->select([
'v1', 'v0', 'ptype',
])->get();
$result->map(static function (\stdClass $item) {
if ($item->ptype === 'g') {
$username = $item->v0;
$roleCode = $item->v1;
$userId = User::where('username', $username)->value('id');
$roleId = Role::where('code', $roleCode)->value('id');
$userId && $roleId && Db::table('user_belongs_role')->insert([
'user_id' => $userId,
'role_id' => $roleId,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
} elseif ($item->ptype === 'p') {
$menuId = Menu::where('name', $item->v1)->value('id');
$roleId = Role::where('code', $item->v0)->value('id');
$menuId && $roleId && Db::table('user_belongs_role')->insert([
'menu_id' => $menuId,
'role_id' => $roleId,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
}
});
}
}
4 changes: 2 additions & 2 deletions app/Http/Admin/Controller/Permission/RoleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ public function batchGrantPermissionsForRole(int $id, BatchGrantPermissionsForRo
if (! $this->service->existsById($id)) {
throw new BusinessException(code: ResultCode::NOT_FOUND);
}
$permissionIds = Arr::get($request->validated(), 'permissions', []);
$this->service->batchGrantPermissionsForRole($id, $permissionIds);
$permissionsCode = Arr::get($request->validated(), 'permissions', []);
$this->service->batchGrantPermissionsForRole($id, $permissionsCode);
return $this->success();
}
}
2 changes: 1 addition & 1 deletion app/Http/Admin/Controller/PermissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function menus(): Result
'status' => Status::Normal,
'children' => true,
'parent_id' => 0,
]) : $this->currentUser->menus()
]) : $this->currentUser->permissions()
);
}

Expand Down
17 changes: 3 additions & 14 deletions app/Http/Admin/Middleware/PermissionMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use App\Exception\BusinessException;
use App\Http\Common\ResultCode;
use App\Http\CurrentUser;
use App\Service\PermissionService;
use Hyperf\Collection\Arr;
use Hyperf\Di\Annotation\AnnotationCollector;
use Hyperf\HttpServer\Router\Dispatched;
Expand All @@ -32,7 +31,6 @@ final class PermissionMiddleware implements MiddlewareInterface

public function __construct(
private readonly CurrentUser $currentUser,
private readonly PermissionService $permissionService
) {}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
Expand Down Expand Up @@ -69,21 +67,12 @@ private function handlePermission(Permission $permission): void
}
$operation = $permission->getOperation();
$codes = $permission->getCode();
$username = $this->currentUser->user()->username;
$enforce = $this->permissionService->getEnforce();
$allPermissionCode = $enforce->getImplicitPermissionsForUser($username);
if (Arr::isList($allPermissionCode)) {
$result = [];
array_walk_recursive($allPermissionCode, static function ($value) use (&$result) {
$result[] = $value;
});
$allPermissionCode = $result;
}
foreach ($codes as $code) {
if ($operation === Permission::OPERATION_AND && ! \in_array($code, $allPermissionCode, true)) {
$isMenu = $this->currentUser->hasMenu($code);
if ($operation === Permission::OPERATION_AND && ! $isMenu) {
throw new BusinessException(code: ResultCode::FORBIDDEN);
}
if ($operation === Permission::OPERATION_OR && \in_array($code, $allPermissionCode, true)) {
if ($operation === Permission::OPERATION_OR && $isMenu) {
return;
}
}
Expand Down
9 changes: 7 additions & 2 deletions app/Http/CurrentUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public function id(): int
/**
* @return Collection<int,Menu>
*/
public function menus(): Collection
public function permissions(): Collection
{
// @phpstan-ignore-next-line
return $this->user()->getMenus();
return $this->user()->getPermissions();
}

/**
Expand All @@ -64,6 +64,11 @@ public function roles(): Collection
return $this->user()->getRoles()->map(static fn (Role $role) => $role->only(['name', 'code', 'remark']));
}

public function hasMenu(string $menuCode): bool
{
return $this->user()->roles()->whereHas('menus', static fn ($query) => $query->where('name', $menuCode))->exists();
}

public function isSystem(): bool
{
return $this->user()->user_type === Type::SYSTEM;
Expand Down
72 changes: 0 additions & 72 deletions app/Model/ModelListener/UserListener.php

This file was deleted.

36 changes: 16 additions & 20 deletions app/Model/Permission/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@

namespace App\Model\Permission;

use App\Model\Enums\User\Status;
use Carbon\Carbon;
use Hyperf\Database\Model\Collection;
use Hyperf\Database\Model\Relations\BelongsToMany;
use Hyperf\DbConnection\Model\Model as MineModel;
use Mine\Casbin\Rule\Rule;

/**
* @property int $id 主键
* @property string $name 角色名称
* @property string $code 角色代码
* @property int $data_scope 数据范围(1:全部数据权限 2:自定义数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限)
* @property int $status 状态 (1正常 2停用)
* @property Status $status 状态 (1正常 2停用)
* @property int $sort 排序
* @property int $created_by 创建者
* @property int $updated_by 更新者
Expand All @@ -49,9 +49,12 @@ final class Role extends MineModel
* The attributes that should be cast to native types.
*/
protected array $casts = [
'id' => 'integer', 'data_scope' => 'integer',
'status' => 'integer', 'sort' => 'integer',
'created_by' => 'integer', 'updated_by' => 'integer',
'id' => 'integer',
'data_scope' => 'integer',
'status' => Status::class,
'sort' => 'integer',
'created_by' => 'integer',
'updated_by' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
Expand All @@ -64,14 +67,10 @@ public function menus(): BelongsToMany
// @phpstan-ignore-next-line
return $this->belongsToMany(
Menu::class,
// @phpstan-ignore-next-line
Rule::getModel()->getTable(),
'v0',
'v1',
'code',
'name'
// @phpstan-ignore-next-line
)->where(Rule::getModel()->getTable() . '.ptype', 'p');
'role_belongs_menu',
'role_id',
'menu_id'
);
}

public function users(): BelongsToMany
Expand All @@ -80,12 +79,9 @@ public function users(): BelongsToMany
return $this->belongsToMany(
User::class,
// @phpstan-ignore-next-line
Rule::getModel()->getTable(),
'v1',
'v0',
'code',
'username'
// @phpstan-ignore-next-line
)->where(Rule::getModel()->getTable() . '.ptype', 'g');
'user_belongs_role',
'role_id',
'user_id'
);
}
}
31 changes: 19 additions & 12 deletions app/Model/Permission/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
use App\Model\Enums\User\Type;
use Carbon\Carbon;
use Hyperf\Collection\Collection;
use Hyperf\Database\Model\Events\Creating;
use Hyperf\Database\Model\Relations\BelongsToMany;
use Hyperf\DbConnection\Model\Model;
use Mine\Casbin\Rule\Rule;

/**
* @property int $id 用户ID,主键
Expand Down Expand Up @@ -63,9 +63,14 @@ final class User extends Model
* The attributes that should be cast to native types.
*/
protected array $casts = [
'id' => 'integer', 'status' => Status::class, 'user_type' => Type::class,
'created_by' => 'integer', 'updated_by' => 'integer', 'created_at' => 'datetime',
'updated_at' => 'datetime', 'backend_setting' => 'json',
'id' => 'integer',
'status' => Status::class,
'user_type' => Type::class,
'created_by' => 'integer',
'updated_by' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'backend_setting' => 'json',
];

public function roles(): BelongsToMany
Expand All @@ -74,20 +79,22 @@ public function roles(): BelongsToMany
return $this->belongsToMany(
Role::class,
// @phpstan-ignore-next-line
Rule::getModel()->getTable(),
'v0',
'v1',
'username',
'code'
// @phpstan-ignore-next-line
)->where(Rule::getModel()->getTable() . '.ptype', '=', 'g');
'user_belongs_role',
);
}

public function setPasswordAttribute($value): void
{
$this->attributes['password'] = password_hash((string) $value, \PASSWORD_DEFAULT);
}

public function creating(Creating $event)
{
if (! $this->isDirty('password')) {
$this->resetPassword();
}
}

public function verifyPassword(string $password): bool
{
return password_verify($password, $this->password);
Expand All @@ -110,7 +117,7 @@ public function getRoles(): Collection
->get();
}

public function getMenus(): Collection
public function getPermissions(): Collection
{
// @phpstan-ignore-next-line
return $this->roles()->get()->map(static function (Role $role) {
Expand Down
2 changes: 1 addition & 1 deletion app/Schema/RoleSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function __construct(Role $model)
$this->name = $model->name;
$this->code = $model->code;
$this->dataScope = $model->data_scope;
$this->status = $model->status;
$this->status = $model->status->value;
$this->sort = $model->sort;
$this->createdBy = $model->created_by;
$this->updatedBy = $model->updated_by;
Expand Down
Loading

0 comments on commit b445b22

Please sign in to comment.