AppValidator.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <?php
  2. namespace App\Module\OpenAPI\Validators;
  3. use App\Module\OpenAPI\Enums\APP_STATUS;
  4. use App\Module\OpenAPI\Enums\AUTH_TYPE;
  5. use App\Module\OpenAPI\Enums\SCOPE_TYPE;
  6. use App\Module\OpenAPI\Models\OpenApiApp;
  7. use UCore\Validator;
  8. /**
  9. * OpenAPI应用验证器
  10. *
  11. * 用于验证应用相关的数据
  12. */
  13. class AppValidator extends Validator
  14. {
  15. /**
  16. * 验证应用数据
  17. *
  18. * @param mixed $value
  19. * @param array $data
  20. * @return bool
  21. */
  22. public function validate(mixed $value, array $data): bool
  23. {
  24. $validationType = $this->args[0] ?? 'create';
  25. return match($validationType) {
  26. 'create' => $this->validateCreate($data),
  27. 'update' => $this->validateUpdate($data),
  28. 'status' => $this->validateStatus($value),
  29. 'scopes' => $this->validateScopes($value),
  30. 'auth_type' => $this->validateAuthType($value),
  31. 'callback_url' => $this->validateCallbackUrl($value),
  32. 'app_id_unique' => $this->validateAppIdUnique($value),
  33. default => false,
  34. };
  35. }
  36. /**
  37. * 验证创建应用数据
  38. *
  39. * @param array $data
  40. * @return bool
  41. */
  42. protected function validateCreate(array $data): bool
  43. {
  44. // 验证必填字段
  45. $requiredFields = ['name', 'description', 'callback_url'];
  46. foreach ($requiredFields as $field) {
  47. if (empty($data[$field])) {
  48. $this->addError("字段 {$field} 不能为空");
  49. return false;
  50. }
  51. }
  52. // 验证应用名称长度
  53. if (strlen($data['name']) > 255) {
  54. $this->addError('应用名称不能超过255个字符');
  55. return false;
  56. }
  57. // 验证描述长度
  58. if (strlen($data['description']) > 1000) {
  59. $this->addError('应用描述不能超过1000个字符');
  60. return false;
  61. }
  62. // 验证回调地址
  63. if (!$this->validateCallbackUrl($data['callback_url'])) {
  64. return false;
  65. }
  66. // 验证权限范围
  67. if (isset($data['scopes']) && !$this->validateScopes($data['scopes'])) {
  68. return false;
  69. }
  70. // 验证认证类型
  71. if (isset($data['auth_type']) && !$this->validateAuthType($data['auth_type'])) {
  72. return false;
  73. }
  74. return true;
  75. }
  76. /**
  77. * 验证更新应用数据
  78. *
  79. * @param array $data
  80. * @return bool
  81. */
  82. protected function validateUpdate(array $data): bool
  83. {
  84. // 验证应用名称
  85. if (isset($data['name'])) {
  86. if (empty($data['name'])) {
  87. $this->addError('应用名称不能为空');
  88. return false;
  89. }
  90. if (strlen($data['name']) > 255) {
  91. $this->addError('应用名称不能超过255个字符');
  92. return false;
  93. }
  94. }
  95. // 验证描述
  96. if (isset($data['description']) && strlen($data['description']) > 1000) {
  97. $this->addError('应用描述不能超过1000个字符');
  98. return false;
  99. }
  100. // 验证回调地址
  101. if (isset($data['callback_url']) && !$this->validateCallbackUrl($data['callback_url'])) {
  102. return false;
  103. }
  104. // 验证权限范围
  105. if (isset($data['scopes']) && !$this->validateScopes($data['scopes'])) {
  106. return false;
  107. }
  108. // 验证认证类型
  109. if (isset($data['auth_type']) && !$this->validateAuthType($data['auth_type'])) {
  110. return false;
  111. }
  112. // 验证状态
  113. if (isset($data['status']) && !$this->validateStatus($data['status'])) {
  114. return false;
  115. }
  116. return true;
  117. }
  118. /**
  119. * 验证应用状态
  120. *
  121. * @param string $status
  122. * @return bool
  123. */
  124. protected function validateStatus(string $status): bool
  125. {
  126. $validStatuses = array_column(APP_STATUS::cases(), 'value');
  127. if (!in_array($status, $validStatuses)) {
  128. $this->addError("无效的应用状态: {$status}");
  129. return false;
  130. }
  131. return true;
  132. }
  133. /**
  134. * 验证权限范围
  135. *
  136. * @param array $scopes
  137. * @return bool
  138. */
  139. protected function validateScopes(array $scopes): bool
  140. {
  141. if (empty($scopes)) {
  142. $this->addError('权限范围不能为空');
  143. return false;
  144. }
  145. $validScopes = array_column(SCOPE_TYPE::cases(), 'value');
  146. foreach ($scopes as $scope) {
  147. if (!in_array($scope, $validScopes)) {
  148. $this->addError("无效的权限范围: {$scope}");
  149. return false;
  150. }
  151. }
  152. return true;
  153. }
  154. /**
  155. * 验证认证类型
  156. *
  157. * @param string $authType
  158. * @return bool
  159. */
  160. protected function validateAuthType(string $authType): bool
  161. {
  162. $validAuthTypes = array_column(AUTH_TYPE::cases(), 'value');
  163. if (!in_array($authType, $validAuthTypes)) {
  164. $this->addError("无效的认证类型: {$authType}");
  165. return false;
  166. }
  167. return true;
  168. }
  169. /**
  170. * 验证回调地址
  171. *
  172. * @param string $url
  173. * @return bool
  174. */
  175. protected function validateCallbackUrl(string $url): bool
  176. {
  177. if (empty($url)) {
  178. $this->addError('回调地址不能为空');
  179. return false;
  180. }
  181. // 验证URL格式
  182. if (!filter_var($url, FILTER_VALIDATE_URL)) {
  183. $this->addError('回调地址格式不正确');
  184. return false;
  185. }
  186. // 验证协议
  187. $scheme = parse_url($url, PHP_URL_SCHEME);
  188. if (!in_array($scheme, ['http', 'https'])) {
  189. $this->addError('回调地址必须使用HTTP或HTTPS协议');
  190. return false;
  191. }
  192. // 验证长度
  193. if (strlen($url) > 500) {
  194. $this->addError('回调地址不能超过500个字符');
  195. return false;
  196. }
  197. return true;
  198. }
  199. /**
  200. * 验证应用ID唯一性
  201. *
  202. * @param string $appId
  203. * @return bool
  204. */
  205. protected function validateAppIdUnique(string $appId): bool
  206. {
  207. $exists = OpenApiApp::where('app_id', $appId)->exists();
  208. if ($exists) {
  209. $this->addError("应用ID {$appId} 已存在");
  210. return false;
  211. }
  212. return true;
  213. }
  214. }