stateless()->redirect(); } public function handleGoogleCallback(Request $request) { try { $user = Socialite::driver('google')->stateless()->user(); $find_user = User::where('email', $user->email)->first(); if (!$find_user) { $find_user = User::create($user->user + [ 'password' => Hash::make(Str::random(8)), 'username' => $user->email, 'active' => true, 'has_password' => false ]); } Auth::setUser($find_user); $finger_print = $this->createFingerPrint(); return redirect('http://localhost:3000/login?token='.$finger_print->token); } catch (Exception $e) { dd($e->getMessage()); } } public function emailChecking(Request $request) { $this->validate($request, [ 'email' => 'required|email', ]); $user = User::where('email', $request->email)->first(); if ($user && $user->has_password) { // email exists in db // user before set a password return response()->json(['message' => 'User exists must be login'], 200); } if ($user && !$user->has_password) { // email exists in db // user hasn't password (we set password for user) $this->sendVerification($request->email, 'google'); return response()->json(['message' => 'Send email for validation'], 200); } if (Cache::has($request->email)) { // email exists in cache $this->sendVerification($request->email, Cache::get($request->email)['type']); return response()->json(['message' => 'Send email for validation'], 200); } if (!$user && !Cache::has($request->email)) { // user not exists in db and cache $this->sendVerification($request->email, 'register'); return response()->json(['message' => 'Send email for validation'], 200); } } public function login(Request $request) { // todo: Logging in from a new device will result in sending a notification $this->validate($request, [ 'email' => 'required|email|exists:users,email', 'password' => 'required|string|min:6' ]); $user = User::where('email', $request->email)->first(); if ($user && Hash::check($request->password, $user->password)) { Auth::setUser($user); // for new device login $this->loginNotif($this->firstOrNot()); return [ 'auth' => $this->createFingerPrint(), 'businesses' => Auth::user()->businesses->keyBy('id')->map(fn($b, $bid) => Business::info($bid)) ]; } return new JsonResponse([ 'message' => trans('auth.failed'), 'status' => Response::HTTP_NOT_FOUND, ], Response::HTTP_NOT_FOUND); } public function verification(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'signature' => 'required|string', ]); $this->checkValidation($request->email, 'google', $request->signature); Auth::setUser(User::where('email', $request->email)->first()); return [ 'auth' => $this->createFingerPrint(), 'businesses' => Auth::user()->businesses->keyBy('id')->map(fn($b, $bid) => Business::info($bid)) ]; } public function sendVerification($email, $type) { $signature = Str::random(30); Cache::put($email, ['type' => $type, 'signature' => $signature], 3600); Notification::route('mail', $email)->notify( new MailNotification([ 'greeting' => __('notification.auth.verification.greeting'), 'subject' => __('notification.auth.verification.subject'), 'body' => __('notification.auth.verification.new_body'), 'link' => __('notification.auth.verification.link', [ 'email' => $email, 'type' => $type, 'signature' => $signature ]) ])); } public function checkValidation($email, $type, $signature) { if (!Cache::has($email) || Cache::get($email)['type'] !== $type || Cache::get($email)['signature'] != $signature) { abort(403, 'Validation failed'); } Cache::forget($email); } public function forgetPassword(Request $request) { $this->validate($request, [ 'email' => 'required|email|exists:users,email' ]); $this->sendVerification($request->email, 'forget'); return response()->json(['message' => 'Send email for validation'], 200); } public function updatePassword(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'password' => 'required|string|min:8|confirmed', 'signature' => 'required|string' ]); $this->checkValidation($request->email, 'forget', $request->signature); $user = User::where('email', $request->email)->first(); $user->update([ 'password' => Hash::make($request->password), 'has_password' => true ]); Auth::setUser($user); $this->createFingerPrint(); return response()->json(['message' => 'Update successfully you must be login.'], 200); } public function register(Request $request) { $this->validate($request, [ 'name' => 'required|string|max:225|min:2', 'username' => ['required', Rule::unique('users', 'username')], 'email' => ['required', 'email', Rule::unique('users', 'email')], 'password' => 'required|string|min:6', 'signature' => 'required|string' ]); $this->checkValidation($request->email, 'register', $request->signature); $request->merge(['password' => Hash::make($request->password)]); $user = User::create($request->all()+ [ 'has_password' => true ]); Auth::setUser($user); $this->createFingerPrint(); return response()->json(['message' => 'Register successfully you must be login.'], 200); } public function resendLink(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'type' => 'required|string' ]); $user_db = User::where('email', $request->email)->first(); $user_cache = Cache::get($request->email); if ($user_db || $user_cache) { $this->sendVerification($request->email, $request->type); return response()->json(['message' => 'Link resend successfully'], 200); } abort(403); } public function createFingerPrint() { $attributes = [ 'agent' => request()->getAgent(), 'ip' => request()->getClientIp(), 'os' => request()->getOS(), 'latitude' => \request()->getLocation()->getAttribute('lat'), 'longitude' => \request()->getLocation()->getAttribute('lon'), ]; $values = [ 'token' => Str::random(60) ]; return Auth::user()->fingerprints()->firstOrCreate($attributes, $attributes + $values); } public function firstOrNot() { return Auth::user()->fingerprints()->where([ ['agent', '!=',request()->getAgent()], ['ip', '!=',request()->getClientIp()], ['os', '!=',request()->getOS()], ['latitude', '!=',\request()->getLocation()->getAttribute('lat')], ['longitude', '!=',\request()->getLocation()->getAttribute('lon')], ])->exists(); } public function loginNotif($send) { if ($send) { Notification::send(Auth::user(), new MailNotification([ 'greeting' => 'hi', 'subject' => 'login with another device', 'body' => 'Warning someone login to your account with new device. check it and dont worry', ])); Notification::send(Auth::user(), new DBNotification([ 'body' => 'Warning someone login to your account with new device. check it and dont worry', ])); } } public function auth() { return new UserResource(Auth::user()); } public function authWithInfo() { return [ 'auth' => new UserResource(Auth::user()), 'businesses' => Auth::user()->businesses->keyBy('id') ->map(fn($b, $bid) => Business::info($bid)) ]; } public function updateFcmToken(Request $request) { Auth::user()->fingerprints()->where( [ ['agent', request()->getAgent()], ['ip', request()->getClientIp()], ['os', request()->getOS()], ['latitude', \request()->getLocation()->getAttribute('lat')], ['longitude', \request()->getLocation()->getAttribute('lon')], ] )->firstOrFail()->update([ 'fcm_token' => $request->fcm_token ]); return $this->authWithInfo(); } }