UserManagerController.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <?php
  2. namespace App\Api\v1\Controllers;
  3. use App\Api\v1\Requests\UserManagerPromoteRequest;
  4. use App\Api\v1\Requests\UserManagerStoreRequest;
  5. use App\Api\v1\Resources\UserManagerResource;
  6. use App\Http\Controllers\Controller;
  7. use App\Models\User;
  8. use Illuminate\Http\Request;
  9. use Illuminate\Support\Facades\Hash;
  10. use Illuminate\Support\Facades\Log;
  11. use Illuminate\Support\Facades\Password;
  12. use Laravel\Passport\TokenRepository;
  13. class UserManagerController extends Controller
  14. {
  15. /**
  16. * Display all users.
  17. *
  18. * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
  19. */
  20. public function index(Request $request)
  21. {
  22. return UserManagerResource::collection(User::all());
  23. }
  24. /**
  25. * Get a user
  26. *
  27. * @return \App\Api\v1\Resources\UserManagerResource
  28. */
  29. public function show(User $user)
  30. {
  31. $this->authorize('view', $user);
  32. return new UserManagerResource($user);
  33. }
  34. /**
  35. * Reset user's password
  36. *
  37. * @return \Illuminate\Http\JsonResponse
  38. */
  39. public function resetPassword(Request $request, User $user)
  40. {
  41. Log::info(sprintf('Password reset for User ID #%s requested by User ID #%s', $user->id, $request->user()->id));
  42. $this->authorize('update', $user);
  43. $credentials = [
  44. 'token' => $this->broker()->createToken($user),
  45. 'email' => $user->email,
  46. 'password' => $user->password,
  47. ];
  48. $response = $this->broker()->reset(
  49. $credentials, function ($user) {
  50. $user->resetPassword();
  51. $user->save();
  52. }
  53. );
  54. if ($response == Password::PASSWORD_RESET) {
  55. Log::info(sprintf('Temporary password set for User ID #%s', $user->id));
  56. $response = $this->broker()->sendResetLink(
  57. ['email' => $credentials['email']]
  58. );
  59. } else {
  60. return response()->json([
  61. 'message' => 'bad request',
  62. 'reason' => is_string($response) ? __($response) : __('errors.no_pwd_reset_for_this_user_type'),
  63. ], 400);
  64. }
  65. return $response == Password::RESET_LINK_SENT
  66. ? new UserManagerResource($user)
  67. : response()->json([
  68. 'message' => 'bad request',
  69. 'reason' => __($response),
  70. ], 400);
  71. }
  72. /**
  73. * Store a newly created user in storage.
  74. *
  75. * @return \Illuminate\Http\JsonResponse
  76. */
  77. public function store(UserManagerStoreRequest $request)
  78. {
  79. $this->authorize('create', User::class);
  80. $validated = $request->validated();
  81. $user = User::create([
  82. 'name' => $validated['name'],
  83. 'email' => $validated['email'],
  84. 'password' => Hash::make($validated['password']),
  85. ]);
  86. Log::info(sprintf('User ID #%s created by user ID #%s', $user->id, $request->user()->id));
  87. if ($validated['is_admin']) {
  88. if ($user->promoteToAdministrator()) {
  89. $user->save();
  90. Log::notice(sprintf('User ID #%s set as administrator at creation by user ID #%s', $user->id, $request->user()->id));
  91. }
  92. }
  93. $user->refresh();
  94. return (new UserManagerResource($user))
  95. ->response()
  96. ->setStatusCode(201);
  97. }
  98. /**
  99. * Purge user's PATs.
  100. *
  101. * @return \Illuminate\Http\JsonResponse
  102. */
  103. public function revokePATs(Request $request, User $user, TokenRepository $tokenRepository)
  104. {
  105. Log::info(sprintf('Deletion of all personal access tokens for User ID #%s requested by User ID #%s', $user->id, $request->user()->id));
  106. $this->authorize('update', $user);
  107. $tokens = $tokenRepository->forUser($user->getAuthIdentifier());
  108. $tokens->load('client')->filter(function ($token) {
  109. return $token->client->personal_access_client && ! $token->revoked;
  110. })->each(function ($token) {
  111. $token->revoke();
  112. });
  113. Log::info(sprintf('All personal access tokens for User ID #%s have been revoked', $user->id));
  114. return response()->json(null, 204);
  115. }
  116. /**
  117. * Purge user's webauthn credentials.
  118. *
  119. * @return \Illuminate\Http\JsonResponse
  120. */
  121. public function revokeWebauthnCredentials(Request $request, User $user)
  122. {
  123. Log::info(sprintf('Deletion of all security devices for User ID #%s requested by User ID #%s', $user->id, $request->user()->id));
  124. $this->authorize('update', $user);
  125. $user->flushCredentials();
  126. // WebauthnOnly user options need to be reset to prevent impossible login when
  127. // no more registered device exists.
  128. // See #110
  129. if (blank($user->webAuthnCredentials()->WhereEnabled()->get())) {
  130. $user['preferences->useWebauthnOnly'] = false;
  131. $user->save();
  132. Log::notice(sprintf('No more Webauthn credential for user ID #%s, useWebauthnOnly user preference reset to false', $user->id));
  133. }
  134. Log::info(sprintf('All security devices for User ID #%s have been revoked', $user->id));
  135. return response()->json(null, 204);
  136. }
  137. /**
  138. * Remove the specified user from storage.
  139. *
  140. * @return \Illuminate\Http\JsonResponse
  141. */
  142. public function destroy(Request $request, User $user)
  143. {
  144. $this->authorize('delete', $user);
  145. // This will delete the user and all its 2FAs & Groups thanks to the onCascadeDelete constrains.
  146. // Deletion will not be done (and returns False) if the user is the only existing admin (see UserObserver clas)
  147. return $user->delete() === false
  148. ? response()->json([
  149. 'message' => __('errors.cannot_delete_the_only_admin'),
  150. ], 403)
  151. : response()->json(null, 204);
  152. }
  153. /**
  154. * Promote (or demote) a user
  155. *
  156. * @return \App\Api\v1\Resources\UserManagerResource
  157. */
  158. public function promote(UserManagerPromoteRequest $request, User $user)
  159. {
  160. $this->authorize('promote', $user);
  161. if ($user->promoteToAdministrator($request->validated('is_admin')))
  162. {
  163. $user->save();
  164. Log::info(sprintf('User ID #%s set is_admin=%s for User ID #%s', $request->user()->id, $user->isAdministrator(), $user->id));
  165. return new UserManagerResource($user);
  166. }
  167. return response()->json([
  168. 'message' => __('errors.cannot_demote_the_only_admin'),
  169. ], 403);
  170. }
  171. /**
  172. * Get the broker to be used during password reset.
  173. *
  174. * @return \Illuminate\Contracts\Auth\PasswordBroker|\Illuminate\Auth\Passwords\PasswordBroker
  175. */
  176. protected function broker()
  177. {
  178. return Password::broker();
  179. }
  180. }