You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
7.6 KiB

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\User;
  4. use App\Models\Business;
  5. use App\Models\Fingerprint;
  6. use Illuminate\Support\Str;
  7. use Illuminate\Http\Request;
  8. use Illuminate\Validation\Rule;
  9. use Illuminate\Http\JsonResponse;
  10. use App\Http\Resources\UserResource;
  11. use Illuminate\Support\Facades\Auth;
  12. use Illuminate\Support\Facades\Hash;
  13. use Illuminate\Support\Facades\Cache;
  14. use Laravel\Lumen\Routing\Controller;
  15. use Laravel\Socialite\Facades\Socialite;
  16. use Illuminate\Session\TokenMismatchException;
  17. use phpDocumentor\Reflection\Location;
  18. use Symfony\Component\HttpFoundation\Response;
  19. class AuthController extends Controller
  20. {
  21. public function redirectToGoogle()
  22. {
  23. return Socialite::driver('google')->stateless()->redirect();
  24. }
  25. public function handleGoogleCallback(Request $request)
  26. {
  27. try {
  28. $user = Socialite::driver('google')->stateless()->user();
  29. $find_user = User::where('email', $user->email)->first();
  30. if ($find_user) {
  31. $find_user->update([
  32. 'active' => true
  33. ]);
  34. Auth::setUser($find_user);
  35. } else {
  36. $user = User::create($user->user + [
  37. 'password' => Hash::make('google-login-user'),
  38. 'username' => $user->email,
  39. 'active' => true
  40. ]);
  41. Auth::setUser($user);
  42. }
  43. $finger_print = $this->createFingerPrint();
  44. return redirect('http://localhost:3000/login?token='.$finger_print->token);
  45. } catch (Exception $e) {
  46. dd($e->getMessage());
  47. }
  48. }
  49. public function login(Request $request)
  50. {
  51. // todo: Logging in from a new device will result in sending a notification
  52. $this->validate($request, [
  53. 'email' => 'required|email|exists:users,email',
  54. 'password' => 'required|string|min:6'
  55. ]);
  56. $user = User::where('email', $request->email)->first();
  57. if ($user && Hash::check($request->password, $user->password)) {
  58. Auth::setUser($user);
  59. return [
  60. 'auth' => $this->createFingerPrint(),
  61. 'businesses' => Auth::user()->businesses->keyBy('id')->map(fn($b, $bid) => Business::info($bid))
  62. ];
  63. }
  64. return new JsonResponse([
  65. 'message' => trans('auth.failed'),
  66. 'status' => Response::HTTP_NOT_FOUND,
  67. ], Response::HTTP_NOT_FOUND);
  68. }
  69. public function register(Request $request)
  70. {
  71. $this->validate($request, [
  72. 'name' => 'required|string|max:225|min:2',
  73. 'username' => ['required', Rule::unique('users', 'username')],
  74. 'email' => ['required', 'email', Rule::unique('users', 'email')],
  75. 'password' => 'required|string|min:8'
  76. ]);
  77. $request->merge(['password' => Hash::make($request->password)]);
  78. $code_data = ['verification_code' => $this->sendVerificationCode()];
  79. $method_data = ['method' => 'registerMain'];
  80. Cache::put($request->email, $request->all() + $code_data + $method_data, 3600); // remain one hour
  81. return \response()->json([
  82. 'message' => 'Code send for user and user must be verified.'],
  83. Response::HTTP_OK);
  84. }
  85. public function registerMain($user_info)
  86. {
  87. $user = User::create($user_info);
  88. Auth::setUser($user);
  89. return $this->createFingerPrint();
  90. }
  91. public function sendVerificationCode($contact_way = null)
  92. {
  93. $verification_code = 1234; // rand(10001, 99999)
  94. //send code for user with contact way
  95. return $verification_code;
  96. }
  97. public function verification(Request $request)
  98. {
  99. if (!Cache::has($request->email)) {
  100. return \response()->json(['message' => 'Code expired.'], Response::HTTP_BAD_REQUEST);
  101. }
  102. $user_info = Cache::get($request->email);
  103. $this->validate($request, [
  104. 'email' => 'required|email',
  105. 'verification_code' => 'required|string|min:4|max:4|in:'.$user_info['verification_code']
  106. ]);
  107. Cache::forget($request->email);
  108. return isset($user_info['method']) ?
  109. call_user_func('self::'.$user_info['method'], $user_info) :
  110. \response()->json(['message' => 'Code verified successfully.'], Response::HTTP_OK,);
  111. }
  112. public function forgetPassword(Request $request)
  113. {
  114. $this->validate($request, [
  115. 'email' => 'required|email|exists:users,email'
  116. ]);
  117. $code_data = ['verification_code' => $this->sendVerificationCode()];
  118. Cache::put($request->email, $request->all() + $code_data, 3600); // remain one hour
  119. return \response()->json([
  120. 'message' => 'Code send for user and user must be verified.'],
  121. Response::HTTP_OK);
  122. }
  123. public function updatePassword(Request $request)
  124. {
  125. if (!Cache::has($request->email)) {
  126. return \response()->json(['message' => 'Code expired.'], Response::HTTP_BAD_REQUEST);
  127. }
  128. $this->validate($request, [
  129. 'email' => 'required|email',
  130. 'password' => 'required|string|min:8|confirmed',
  131. 'verification_code' => 'required|string|min:4|max:4|in:'.Cache::get($request->email)['verification_code']
  132. ]);
  133. $user = User::where('email', $request->email)->first();
  134. $user->update([
  135. 'password' => Hash::make($request->password)
  136. ]);
  137. Auth::setUser($user);
  138. return $this->createFingerPrint();
  139. }
  140. /**
  141. * @param Request $request
  142. * @return mixed
  143. * @throws TokenMismatchException
  144. */
  145. public function logout(Request $request)
  146. {
  147. $token = $request->getCurrentToken();
  148. if (blank($token)) {
  149. return new JsonResponse([
  150. 'message' => 'Not authorized request.',
  151. 'status' => Response::HTTP_UNAUTHORIZED
  152. ]);
  153. }
  154. /** @var Fingerprint $token */
  155. $token = Auth::user()->fingerprints()->firstWhere([
  156. 'token' => $token,
  157. ]);
  158. if ($token) {
  159. return $token->delete();
  160. }
  161. throw new TokenMismatchException('Invalid token!');
  162. }
  163. /**
  164. * @param string $token
  165. * @throws TokenMismatchException
  166. */
  167. public function revoke(string $token)
  168. {
  169. /** @var Fingerprint $token */
  170. $token = Auth::user()->fingerprints()->firstWhere([
  171. 'token' => $token,
  172. ]);
  173. if ($token) {
  174. return $token->delete();
  175. }
  176. throw new TokenMismatchException();
  177. }
  178. public function auth()
  179. {
  180. return new UserResource(Auth::user());
  181. }
  182. public function authWithInfo()
  183. {
  184. return [
  185. 'auth' => new UserResource(Auth::user()),
  186. 'businesses' => Auth::user()->businesses->keyBy('id') ->map(fn($b, $bid) => Business::info($bid))
  187. ];
  188. }
  189. public function delete(Request $request)
  190. {
  191. Auth::user()->fingerprints()->delete();
  192. unset(Auth::user()->token);
  193. Auth::user()->delete();
  194. return 'success';
  195. }
  196. public function createFingerPrint()
  197. {
  198. $attributes = [
  199. 'agent' => request()->getAgent(),
  200. 'ip' => request()->getClientIp(),
  201. 'os' => request()->getOS(),
  202. 'latitude' => 5,
  203. 'longitude' => 5,
  204. ];
  205. $values = [
  206. 'token' => Str::random(60)
  207. ];
  208. return Auth::user()->fingerprints()->firstOrCreate($attributes, $attributes + $values);
  209. }
  210. }