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.
301 lines
9.0 KiB
301 lines
9.0 KiB
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\User;
|
|
use App\Models\Business;
|
|
use App\Models\Fingerprint;
|
|
use App\Notifications\MailNotification;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\Rule;
|
|
use Illuminate\Http\JsonResponse;
|
|
use App\Http\Resources\UserResource;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Laravel\Socialite\Facades\Socialite;
|
|
use Illuminate\Session\TokenMismatchException;
|
|
use phpDocumentor\Reflection\Type;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class AuthController extends Controller
|
|
{
|
|
public function redirectToGoogle()
|
|
{
|
|
return Socialite::driver('google')->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->update([
|
|
'active' => true
|
|
]);
|
|
|
|
Auth::setUser($find_user);
|
|
|
|
} else {
|
|
|
|
$user = User::create($user->user + [
|
|
'password' => Hash::make('google-login-user'),
|
|
'username' => $user->email,
|
|
'active' => true
|
|
]);
|
|
|
|
Auth::setUser($user);
|
|
|
|
}
|
|
$finger_print = $this->createFingerPrint();
|
|
return redirect('http://localhost:3000/login?token='.$finger_print->token);
|
|
|
|
} catch (Exception $e) {
|
|
dd($e->getMessage());
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
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 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:8'
|
|
]);
|
|
|
|
$request->merge(['password' => Hash::make($request->password)]);
|
|
|
|
$code_data = ['verification_code' => $this->sendVerificationCode(\request('email'), 'register')];
|
|
$method_data = ['method' => 'registerMain'];
|
|
|
|
Cache::put($request->email, $request->all() + $code_data + $method_data, 3600); // remain one hour
|
|
|
|
return \response()->json([
|
|
'message' => 'Code send for user and user must be verified.'],
|
|
Response::HTTP_OK);
|
|
|
|
}
|
|
|
|
public function registerMain($user_info)
|
|
{
|
|
$user = User::create($user_info);
|
|
|
|
Auth::setUser($user);
|
|
|
|
return $this->createFingerPrint();
|
|
}
|
|
|
|
public function sendVerificationCode($contact_way, $type)
|
|
{
|
|
$verification_code = rand(10001, 99999);
|
|
|
|
Notification::route('mail', $contact_way)->notify( new MailNotification([
|
|
'greeting' => __('notification.auth.verification.greeting'),
|
|
'subject' => __('notification.auth.verification.subject'),
|
|
'body' => __('notification.auth.verification.body', ['code' => $verification_code]),
|
|
'link' => __('notification.auth.verification.link', ['email' => $contact_way, 'type' => $type]),
|
|
]));
|
|
|
|
return $verification_code;
|
|
}
|
|
|
|
public function verification(Request $request)
|
|
{
|
|
if (!Cache::has($request->email)) {
|
|
return \response()->json(['message' => 'Code expired.'], Response::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
$user_info = Cache::get($request->email);
|
|
|
|
$this->validate($request, [
|
|
'email' => 'required|email',
|
|
'verification_code' => 'required|string|min:4|max:4|in:'.$user_info['verification_code']
|
|
]);
|
|
|
|
// Cache::forget($request->email);
|
|
|
|
if (isset($user_info['method'])) {
|
|
Cache::forget($request->email);
|
|
return call_user_func('self::'.$user_info['method'], $user_info);
|
|
}
|
|
|
|
return \response()->json(['message' => 'Code verified successfully.'], Response::HTTP_OK,);
|
|
|
|
// return isset($user_info['method']) ?
|
|
// call_user_func('self::'.$user_info['method'], $user_info) :
|
|
// \response()->json(['message' => 'Code verified successfully.'], Response::HTTP_OK,);
|
|
}
|
|
|
|
public function forgetPassword(Request $request)
|
|
{
|
|
$this->validate($request, [
|
|
'email' => 'required|email|exists:users,email'
|
|
]);
|
|
|
|
$code_data = ['verification_code' => $this->sendVerificationCode(\request('email', 'forget'))];
|
|
|
|
Cache::put($request->email, $request->all() + $code_data, 3600); // remain one hour
|
|
|
|
return \response()->json([
|
|
'message' => 'Code send for user and user must be verified.'],
|
|
Response::HTTP_OK);
|
|
}
|
|
|
|
public function updatePassword(Request $request)
|
|
{
|
|
if (!Cache::has($request->email)) {
|
|
return \response()->json(['message' => 'Code expired.'], Response::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
$this->validate($request, [
|
|
'email' => 'required|email',
|
|
'password' => 'required|string|min:8|confirmed',
|
|
'verification_code' => 'required|string|min:4|max:4|in:'.Cache::get($request->email)['verification_code']
|
|
]);
|
|
|
|
$user = User::where('email', $request->email)->first();
|
|
|
|
$user->update([
|
|
'password' => Hash::make($request->password)
|
|
]);
|
|
|
|
Auth::setUser($user);
|
|
|
|
Cache::forget($request->email);
|
|
|
|
return $this->createFingerPrint();
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
* @return mixed
|
|
* @throws TokenMismatchException
|
|
*/
|
|
public function logout(Request $request)
|
|
{
|
|
$token = $request->bearerToken();
|
|
|
|
if (blank($token)) {
|
|
return new JsonResponse([
|
|
'message' => 'Not authorized request.',
|
|
'status' => Response::HTTP_UNAUTHORIZED
|
|
]);
|
|
}
|
|
|
|
/** @var Fingerprint $token */
|
|
$token = Auth::user()->fingerprints()->firstWhere([
|
|
'token' => $token,
|
|
]);
|
|
|
|
if ($token) {
|
|
return $token->delete();
|
|
}
|
|
|
|
throw new TokenMismatchException('Invalid token!');
|
|
}
|
|
|
|
/**
|
|
* @param string $token
|
|
* @throws TokenMismatchException
|
|
*/
|
|
public function revoke(string $token)
|
|
{
|
|
/** @var Fingerprint $token */
|
|
$token = Fingerprint::firstWhere([
|
|
'token' => $token,
|
|
]);
|
|
|
|
if ($token) {
|
|
return $token->delete();
|
|
}
|
|
|
|
throw new TokenMismatchException();
|
|
}
|
|
|
|
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 delete(Request $request)
|
|
{
|
|
Auth::user()->fingerprints()->delete();
|
|
unset(Auth::user()->token);
|
|
Auth::user()->delete();
|
|
|
|
return 'success';
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|