ScopeListValidator.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. namespace App\Module\OpenAPI\Validators;
  3. use App\Module\OpenAPI\Enums\SCOPE_TYPE;
  4. use UCore\Validator;
  5. /**
  6. * 权限列表验证器
  7. */
  8. class ScopeListValidator extends Validator
  9. {
  10. /**
  11. * 验证权限列表是否有效
  12. *
  13. * @param mixed $value 权限列表数组
  14. * @param array $data 验证数据
  15. * @return bool 验证是否通过
  16. */
  17. public function validate(mixed $value, array $data): bool
  18. {
  19. // 从 args 获取参数
  20. $processedKey = $this->args[0] ?? 'processedScopes';
  21. // 如果没有提供权限列表,使用默认权限
  22. if (empty($value)) {
  23. $value = ['USER_READ', 'GAME_READ'];
  24. }
  25. // 确保是数组
  26. if (!is_array($value)) {
  27. $this->addError('权限范围必须是数组格式');
  28. return false;
  29. }
  30. // 验证权限范围数量
  31. if (count($value) > 20) {
  32. $this->addError('权限范围数量不能超过20个');
  33. return false;
  34. }
  35. // 获取所有有效权限
  36. $validScopes = $this->getAllValidScopes();
  37. $processedScopes = [];
  38. foreach ($value as $scope) {
  39. if (!is_string($scope)) {
  40. $this->addError('权限范围必须是字符串');
  41. return false;
  42. }
  43. $scope = trim($scope);
  44. if (empty($scope)) {
  45. continue;
  46. }
  47. // 验证权限是否有效
  48. if (!in_array($scope, $validScopes)) {
  49. $this->addError("无效的权限范围: {$scope}");
  50. return false;
  51. }
  52. $processedScopes[] = $scope;
  53. }
  54. // 去重
  55. $processedScopes = array_unique($processedScopes);
  56. if (empty($processedScopes)) {
  57. $this->addError('至少需要配置一个权限范围');
  58. return false;
  59. }
  60. // 验证权限依赖关系
  61. if (!$this->validateScopeDependencies($processedScopes)) {
  62. return false;
  63. }
  64. // 验证危险权限
  65. if (!$this->validateDangerousScopes($processedScopes)) {
  66. return false;
  67. }
  68. // 将处理后的权限保存到验证对象中
  69. $this->validation->$processedKey = array_values($processedScopes);
  70. return true;
  71. }
  72. /**
  73. * 获取所有有效的权限范围
  74. *
  75. * @return array
  76. */
  77. protected function getAllValidScopes(): array
  78. {
  79. $scopes = array_column(SCOPE_TYPE::cases(), 'value');
  80. // 添加特殊权限
  81. $scopes[] = '*'; // 通配符权限
  82. $scopes[] = 'ADMIN'; // 管理员权限
  83. return $scopes;
  84. }
  85. /**
  86. * 验证权限依赖关系
  87. *
  88. * @param array $scopes
  89. * @return bool
  90. */
  91. protected function validateScopeDependencies(array $scopes): bool
  92. {
  93. // 权限依赖关系
  94. $dependencies = [
  95. 'USER_WRITE' => ['USER_READ'],
  96. 'USER_DELETE' => ['USER_READ', 'USER_WRITE'],
  97. 'GAME_WRITE' => ['GAME_READ'],
  98. 'GAME_ADMIN' => ['GAME_READ', 'GAME_WRITE'],
  99. 'ITEM_WRITE' => ['ITEM_READ'],
  100. 'ITEM_TRANSFER' => ['ITEM_READ', 'ITEM_WRITE'],
  101. 'FUND_WRITE' => ['FUND_READ'],
  102. 'FUND_TRANSFER' => ['FUND_READ', 'FUND_WRITE'],
  103. 'TRADE_WRITE' => ['TRADE_READ'],
  104. 'TRADE_CANCEL' => ['TRADE_READ', 'TRADE_WRITE'],
  105. 'STATS_EXPORT' => ['STATS_READ'],
  106. 'SYSTEM_ADMIN' => ['SYSTEM_READ'],
  107. ];
  108. foreach ($scopes as $scope) {
  109. if (isset($dependencies[$scope])) {
  110. foreach ($dependencies[$scope] as $dependency) {
  111. if (!in_array($dependency, $scopes)) {
  112. $this->addError("权限 {$scope} 需要依赖权限 {$dependency}");
  113. return false;
  114. }
  115. }
  116. }
  117. }
  118. return true;
  119. }
  120. /**
  121. * 验证危险权限
  122. *
  123. * @param array $scopes
  124. * @return bool
  125. */
  126. protected function validateDangerousScopes(array $scopes): bool
  127. {
  128. $dangerousScopes = [
  129. 'USER_DELETE',
  130. 'FUND_TRANSFER',
  131. 'TRADE_CANCEL',
  132. 'SYSTEM_ADMIN',
  133. 'ADMIN',
  134. '*'
  135. ];
  136. $foundDangerous = array_intersect($scopes, $dangerousScopes);
  137. if (!empty($foundDangerous)) {
  138. // 这里可以添加额外的验证逻辑,比如需要管理员审批等
  139. // 目前只是记录警告,不阻止创建
  140. foreach ($foundDangerous as $dangerous) {
  141. $this->addWarning("权限 {$dangerous} 是高风险权限,请谨慎使用");
  142. }
  143. }
  144. return true;
  145. }
  146. }