2
0

UserController.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Resources\UserResource;
  4. use App\Models\UserInfo;
  5. use Illuminate\Http\Request;
  6. class UserController extends Controller
  7. {
  8. /**
  9. * 列出用户
  10. *
  11. * 按 view 指定的口径返回用户列表,支持按昵称搜索、按角色过滤、分页与排序。
  12. * 注意:view 只识别 key 和 all 两个值,传其他值或不传会因为查询对象未初始化而报错。
  13. *
  14. * @queryParam view string required 查询口径。key=按关键字匹配用户名或昵称;all=全部用户。Enum: key,all
  15. * @queryParam key string view=key 时的关键字,同时模糊匹配 username 与 nickname
  16. * @queryParam search string 按昵称再做一次模糊过滤(nickname like %search%)
  17. * @queryParam role string 按角色过滤,匹配 role 这个 JSON 数组中是否包含该值。Example: admin
  18. * @queryParam order string 排序字段。Default: username
  19. * @queryParam dir string 排序方向。Enum: asc,desc Default: desc
  20. * @queryParam offset integer 分页起始位置。Default: 0
  21. * @queryParam limit integer 每页条数。Default: 20
  22. */
  23. public function index(Request $request)
  24. {
  25. // FIXME: switch 没有 default 分支,view 不是 key/all(含不传)时 $table 从未初始化,下面直接致命错误 500;
  26. // 建议补 default 返回 400 错误,或先给 $table 一个基础查询再按 view 叠加条件。
  27. switch ($request->input('view')) {
  28. case 'key':
  29. // FIXME: where(...)->orWhere(...) 没有分组括号,后面追加的 search / role 过滤会因 AND/OR 优先级
  30. // 对 orWhere 那半边失效;建议把这两个条件包进 where(function ($q) { ... }) 里。
  31. $table = UserInfo::where('username', 'like', '%'.$request->input('key').'%')
  32. ->orWhere('nickname', 'like', '%'.$request->input('key').'%');
  33. break;
  34. case 'all':
  35. $table = UserInfo::where('id', '>', 0);
  36. break;
  37. }
  38. if ($request->has('search')) {
  39. $table = $table->where('nickname', 'like', '%'.$request->input('search').'%');
  40. }
  41. if ($request->has('role')) {
  42. $table = $table->whereJsonContains('role', $request->input('role'));
  43. }
  44. $count = $table->count();
  45. $table = $table->orderBy(
  46. $request->input('order', 'username'),
  47. $request->input('dir', 'desc')
  48. );
  49. $table = $table->skip($request->input('offset', 0))
  50. ->take($request->input('limit', 20));
  51. $result = $table->get();
  52. return $this->ok(['rows' => UserResource::collection($result), 'count' => $count]);
  53. }
  54. /**
  55. * 新建用户(未实现)
  56. *
  57. * 路由已注册 POST /api/v2/user,但方法体为空,不做任何事也不返回内容。
  58. * 用户注册走认证相关接口,不走这里。
  59. */
  60. public function store(Request $request)
  61. {
  62. //
  63. }
  64. /**
  65. * 查看单个用户
  66. *
  67. * 按 userid 查询用户资料并返回(id、用户名、昵称、邮箱、角色、头像等)。
  68. * 方法内没有任何鉴权,任何人都可以读取;查不到用户时会以空资源返回。
  69. *
  70. * @urlParam user integer required 用户的 userid(不是表自增主键 id)
  71. */
  72. public function show($id)
  73. {
  74. // FIXME: 没有任何鉴权,任何人可读取任意用户资料(含邮箱);且 userid 不存在时会以空资源返回。
  75. // 建议按产品侧确认的可见性策略补鉴权,并对查不到的情况返回 404。
  76. $user = UserInfo::where('userid', $id)->first();
  77. return $this->ok(new UserResource($user));
  78. }
  79. /**
  80. * 更新用户资料或角色
  81. *
  82. * 两种互斥的用法:请求体里带 roles 时只更新角色(整体覆盖,以 JSON 存入 role 字段);
  83. * 不带 roles 时更新昵称、头像、邮箱三个字段(未传的会被置空)。
  84. * 方法内没有任何鉴权,也没有校验,调用方需自行保证权限;userid 不存在时会报错。
  85. *
  86. * @urlParam user integer required 用户的 userid(不是表自增主键 id)
  87. *
  88. * @bodyParam roles array 角色列表,传了就只更新角色,整体覆盖原有角色
  89. * @bodyParam nickName string 昵称,未传 roles 时生效
  90. * @bodyParam avatar string 头像文件名,未传 roles 时生效
  91. * @bodyParam email string 邮箱,未传 roles 时生效
  92. */
  93. public function update(Request $request, $id)
  94. {
  95. // FIXME: 安全问题——本方法没有任何鉴权和参数校验,任意调用者都能改他人的 roles(提权)、邮箱、昵称、头像;
  96. // 需先由产品侧确认权限策略(本人仅可改资料、roles 仅管理员可改)后再补鉴权与 validate,同时处理 userid 不存在报错。
  97. $user = UserInfo::where('userid', $id)->first();
  98. if ($request->has('roles')) {
  99. $user->role = json_encode($request->input('roles'));
  100. } else {
  101. $user->nickname = $request->input('nickName');
  102. $user->avatar = $request->input('avatar');
  103. $user->email = $request->input('email');
  104. }
  105. $user->save();
  106. return $this->ok(new UserResource($user));
  107. }
  108. /**
  109. * 删除用户(未实现)
  110. *
  111. * 路由已注册 DELETE /api/v2/user/{user},但方法体为空,不会删除任何数据也不返回内容。
  112. *
  113. * @urlParam user integer required 用户的 userid
  114. */
  115. public function destroy($id)
  116. {
  117. // FIXME: 方法体为空但路由已暴露 DELETE,调用方会以为删除成功;且同样没有鉴权。
  118. // 建议要么实现并加上鉴权,要么下掉该路由。
  119. //
  120. }
  121. }