-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
669 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
|
||
return [ | ||
'很抱歉,您没有权限执行该操作' => 202001, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
namespace Miaoxing\App\Metadata; | ||
|
||
/** | ||
* @property string|null $id 编号 | ||
* @property string $appId 应用编号 | ||
* @property string $name 名称 | ||
* @property string $code 标识 | ||
* @property string $description 描述 | ||
* @property bool $isEnabled 是否启用 | ||
* @property string|null $createdAt | ||
* @property string|null $updatedAt | ||
* @property string $createdBy | ||
* @property string $updatedBy | ||
* @property string|null $deletedAt | ||
* @property string $deletedBy | ||
* @internal will change in the future | ||
*/ | ||
trait PermissionTrait | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace Miaoxing\App\Metadata; | ||
|
||
/** | ||
* @property string|null $id 编号 | ||
* @property string $appId 应用编号 | ||
* @property string $roleId 角色编号 | ||
* @property string $permissionId 权限编号 | ||
* @property string|null $createdAt | ||
* @property string|null $updatedAt | ||
* @property string $createdBy | ||
* @property string $updatedBy | ||
* @property string|null $deletedAt | ||
* @property string $deletedBy | ||
* @internal will change in the future | ||
*/ | ||
trait PermissionsRoleTrait | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php | ||
|
||
namespace Miaoxing\App\Metadata; | ||
|
||
/** | ||
* @property string|null $id 编号 | ||
* @property string $appId 应用编号 | ||
* @property string $parentId 父级角色编号 | ||
* @property int $level 层级 | ||
* @property string $name 名称 | ||
* @property string $code 标识 | ||
* @property string $description 描述 | ||
* @property bool $isEnabled 是否启用 | ||
* @property array $actions 菜单和操作 | ||
* @property string|null $createdAt | ||
* @property string|null $updatedAt | ||
* @property string $createdBy | ||
* @property string $updatedBy | ||
* @property string|null $deletedAt | ||
* @property string $deletedBy | ||
* @internal will change in the future | ||
*/ | ||
trait RoleTrait | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace Miaoxing\App\Metadata; | ||
|
||
/** | ||
* @property string|null $id | ||
* @property string $appId 应用编号 | ||
* @property string $userId 用户编号 | ||
* @property string $roleId 角色编号 | ||
* @property string|null $createdAt | ||
* @property string|null $updatedAt | ||
* @property string $createdBy | ||
* @property string $updatedBy | ||
* @property string|null $deletedAt | ||
* @property string $deletedBy | ||
* @internal will change in the future | ||
*/ | ||
trait RolesUserTrait | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace Miaoxing\App\Middleware; | ||
|
||
use Miaoxing\Plugin\Service\User; | ||
use Miaoxing\Services\Middleware\BaseMiddleware; | ||
use Wei\BaseController; | ||
|
||
class CheckPagePermission extends BaseMiddleware | ||
{ | ||
public function __invoke($next, BaseController $controller = null) | ||
{ | ||
if (false === $controller->getOption('requireAuth')) { | ||
return $next(); | ||
} | ||
|
||
$ret = User::cur()->checkPagePermission($this->req->getMethod(), $this->req->getPathInfo()); | ||
if ($ret->isErr()) { | ||
return $ret; | ||
} | ||
return $next(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
<?php | ||
|
||
namespace Miaoxing\App\Migration; | ||
|
||
use Wei\Migration\BaseMigration; | ||
|
||
class V20220810105803CreatePermissionTables extends BaseMigration | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function up() | ||
{ | ||
$this->schema->table('permissions')->tableComment('权限') | ||
->bigId()->comment('编号') | ||
->uBigInt('app_id')->comment('应用编号') | ||
->string('name', 32)->comment('名称') | ||
->string('code', 128)->comment('标识') | ||
->string('description')->comment('描述') | ||
->bool('is_enabled')->comment('是否启用')->defaults(true) | ||
->timestamps() | ||
->userstamps() | ||
->softDeletable() | ||
->exec(); | ||
|
||
$this->schema->table('roles')->tableComment('角色') | ||
->bigId()->comment('编号') | ||
->uBigInt('app_id')->comment('应用编号') | ||
->uBigInt('parent_id')->comment('父级角色编号') | ||
->uTinyInt('level')->comment('层级')->defaults(1) | ||
->string('name', 32)->comment('名称') | ||
->string('code', 128)->comment('标识') | ||
->string('description')->comment('描述') | ||
->bool('is_enabled')->comment('是否启用')->defaults(true) | ||
->json('actions')->comment('菜单和操作') | ||
->timestamps() | ||
->userstamps() | ||
->softDeletable() | ||
->exec(); | ||
|
||
$this->schema->table('permissions_roles')->tableComment('角色权限') | ||
->bigId()->comment('编号') | ||
->uBigInt('app_id')->comment('应用编号') | ||
->uBigInt('role_id')->comment('角色编号') | ||
->uBigInt('permission_id')->comment('权限编号') | ||
->timestamps() | ||
->userstamps() | ||
->softDeletable() | ||
->exec(); | ||
|
||
$this->schema->table('permissions_users')->tableComment('用户权限') | ||
->bigId() | ||
->uBigInt('app_id')->comment('应用编号') | ||
->uBigInt('user_id')->comment('用户编号') | ||
->uBigInt('permission_id')->comment('权限编号') | ||
->timestamps() | ||
->userstamps() | ||
->softDeletable() | ||
->exec(); | ||
|
||
$this->schema->table('roles_users')->tableComment('用户角色') | ||
->bigId() | ||
->uBigInt('app_id')->comment('应用编号') | ||
->uBigInt('user_id')->comment('用户编号') | ||
->uBigInt('role_id')->comment('角色编号') | ||
->timestamps() | ||
->userstamps() | ||
->softDeletable() | ||
->exec(); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function down() | ||
{ | ||
$this->schema->dropIfExists('permissions'); | ||
$this->schema->dropIfExists('roles'); | ||
$this->schema->dropIfExists('permissions_roles'); | ||
$this->schema->dropIfExists('permissions_users'); | ||
$this->schema->dropIfExists('roles_users'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<?php | ||
|
||
namespace Miaoxing\App\Model; | ||
|
||
use Wei\Ret; | ||
|
||
/** | ||
* @mixin \LoggerPropMixin | ||
* @mixin \PermissionMapPropMixin | ||
*/ | ||
trait HasPermissionTrait | ||
{ | ||
public function getPermissionCodes(): array | ||
{ | ||
return array_unique(array_merge( | ||
$this->getActionPermissionCodes(), | ||
$this->enabledRoles->enabledPermissions->getAll('code'), | ||
$this->enabledPermissions->getAll('code') | ||
)); | ||
} | ||
|
||
/** | ||
* @return string[] | ||
*/ | ||
public function getActionPermissionCodes(): array | ||
{ | ||
if ($this->isSuperAdmin()) { | ||
return ['*']; | ||
} | ||
|
||
$actions = $this->enabledRoles->getAll('actions'); | ||
return array_unique(array_merge(...$actions)); | ||
} | ||
|
||
/** | ||
* Check if user have the specified permission | ||
* | ||
* @param string $code | ||
* @return Ret | ||
*/ | ||
public function checkPermission(string $code): Ret | ||
{ | ||
if ($this->hasPermission($code)) { | ||
return suc(); | ||
} | ||
return err('很抱歉,您没有权限执行该操作'); | ||
} | ||
|
||
/** | ||
* Whether the user have the specified permission | ||
* | ||
* @param string $code | ||
* @return bool | ||
*/ | ||
public function hasPermission(string $code): bool | ||
{ | ||
// TODO 根据场景实现逐级查找,变量查找按需查找 | ||
return in_array($code, $this->getPermissionCodes(), true); | ||
} | ||
|
||
/** | ||
* @param string $method | ||
* @param string $path | ||
* @return Ret | ||
*/ | ||
public function checkPagePermission(string $method, string $path): Ret | ||
{ | ||
if ($this->hasPagePermission($method, $path)) { | ||
return suc(); | ||
} | ||
return err('很抱歉,您没有权限执行该操作'); | ||
} | ||
|
||
public function hasPagePermission(string $method, string $path): bool | ||
{ | ||
if ($this->isSuperAdmin()) { | ||
return true; | ||
} | ||
|
||
// 1. 获取权限 | ||
$permissions = $this->getActionPermissionCodes(); | ||
$this->logger->debug('Get user menu permissions', $permissions); | ||
|
||
// 2. 转换菜单为页面 | ||
$map = $this->permissionMap->getMap(); | ||
$map = array_intersect_key($map, array_flip($permissions)); | ||
$map = array_unique(array_merge(...array_values($map))); | ||
$this->logger->debug('Get user action permissions', $map); | ||
|
||
// 3. 检查当前页面是否在里面 | ||
$path = ltrim($path, '/'); | ||
if ($this->hasPagePermissionIn($method, $path, $map)) { | ||
return true; | ||
} | ||
|
||
// Whether has role permission | ||
$rolePermissionCodes = $this->enabledRoles->enabledPermissions->getAll('code'); | ||
if ($this->hasPagePermissionIn($method, $path, $rolePermissionCodes)) { | ||
return true; | ||
} | ||
|
||
// Whether has direct permission | ||
$permissionCodes = $this->enabledPermissions->getAll('code'); | ||
return $this->hasPagePermissionIn($method, $path, $permissionCodes); | ||
} | ||
|
||
/** | ||
* Whether has page permission in the specified permission codes | ||
* | ||
* @param string $method | ||
* @param string $path | ||
* @param array $permissions | ||
* @return bool | ||
*/ | ||
protected function hasPagePermissionIn(string $method, string $path, array $permissions): bool | ||
{ | ||
$path = ltrim($path, '/'); | ||
foreach ($permissions as $permission) { | ||
$parts = explode(' ', $permission, 2); | ||
$apiMethod = $parts[0]; | ||
$apiPath = $parts[1] ?? null; | ||
|
||
if ($method !== $apiMethod) { | ||
continue; | ||
} | ||
|
||
if ($apiPath === $path) { | ||
return true; | ||
} | ||
|
||
if (false !== strpos($apiPath, '[')) { | ||
$regex = preg_replace('#[.\+*?[^\]${}=!|:-]#', '\\\\$0', $apiPath); | ||
$regex = str_replace(['\[', '\]'], ['(?P<', '>.+?)'], $regex); | ||
$regex = '#^' . $regex . '$#uUD'; | ||
if (preg_match($regex, $path)) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
} |
Oops, something went wrong.