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.
 
 

268 lines
7.6 KiB

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Business;
use App\Models\Fingerprint;
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 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()];
$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 = null)
{
$verification_code = 1234; // rand(10001, 99999)
//send code for user with contact way
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);
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()];
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);
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 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);
}
}