Browse Source

change auth procedure in AuthController.php

mahdi
mahdihty 4 years ago
parent
commit
78be4b3907
  1. 268
      app/Http/Controllers/AuthController.php
  2. 27
      app/Http/Controllers/NewAuthController.php
  3. 301
      app/Http/Controllers/OldAuthController.php
  4. 2
      app/Models/User.php
  5. 1
      database/migrations/2020_08_18_085016_create_users_table.php
  6. 5
      resources/lang/fa/notification.php
  7. 9
      routes/api.php

268
app/Http/Controllers/AuthController.php

@ -2,22 +2,18 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Business; use App\Models\Business;
use App\Models\Fingerprint;
use App\Models\User;
use App\Notifications\MailNotification; 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 Illuminate\Http\JsonResponse;
use App\Http\Resources\UserResource;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Facades\Socialite;
use Illuminate\Session\TokenMismatchException;
use phpDocumentor\Reflection\Type;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
class AuthController extends Controller class AuthController extends Controller
@ -34,33 +30,63 @@ class AuthController extends Controller
$user = Socialite::driver('google')->stateless()->user(); $user = Socialite::driver('google')->stateless()->user();
$find_user = User::where('email', $user->email)->first(); $find_user = User::where('email', $user->email)->first();
if ($find_user) {
$find_user->update([
'active' => true
]);
if (!$find_user)
{
Auth::setUser($find_user);
} else {
$user = User::create($user->user + [
'password' => Hash::make('google-login-user'),
$find_user = User::create($user->user + [
'password' => Hash::make(Str::random(8)),
'username' => $user->email, 'username' => $user->email,
'active' => true
'active' => true,
'has_password' => false
]); ]);
Auth::setUser($user);
}
Auth::setUser($find_user);
}
$finger_print = $this->createFingerPrint();
return redirect('http://localhost:3000/login?token='.$finger_print->token);
$finger_print = $this->createFingerPrint();
return redirect('http://localhost:3000/login?token='.$finger_print->token);
} catch (Exception $e) { } catch (Exception $e) {
dd($e->getMessage()); 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) public function login(Request $request)
{ {
// todo: Logging in from a new device will result in sending a notification // todo: Logging in from a new device will result in sending a notification
@ -85,77 +111,51 @@ class AuthController extends Controller
], Response::HTTP_NOT_FOUND); ], Response::HTTP_NOT_FOUND);
} }
public function register(Request $request)
public function verification(Request $request)
{ {
$this->validate($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)]);
'email' => 'required|email',
'signature' => 'required|string',
]);
$code_data = ['verification_code' => $this->sendVerificationCode(\request('email'), 'register')];
$method_data = ['method' => 'registerMain'];
$this->checkValidation($request->email, 'google', $request->signature);
Cache::put($request->email, $request->all() + $code_data + $method_data, 3600); // remain one hour
Auth::setUser(User::where('email', $request->email)->first());
return \response()->json([
'message' => 'Code send for user and user must be verified.'],
Response::HTTP_OK);
return [
'auth' => $this->createFingerPrint(),
'businesses' => Auth::user()->businesses->keyBy('id')->map(fn($b, $bid) => Business::info($bid))
];
} }
public function registerMain($user_info)
public function sendVerification($email, $type)
{ {
$user = User::create($user_info);
Auth::setUser($user);
$signature = Str::random(30);
return $this->createFingerPrint();
}
Cache::put($email, ['type' => $type, 'signature' => $signature], 3600);
public function sendVerificationCode($contact_way, $type)
{
$verification_code = rand(10001, 99999);
Notification::route('mail', $contact_way)->notify( new MailNotification([
Notification::route('mail', $email)->notify( new MailNotification([
'greeting' => __('notification.auth.verification.greeting'), 'greeting' => __('notification.auth.verification.greeting'),
'subject' => __('notification.auth.verification.subject'), 'subject' => __('notification.auth.verification.subject'),
'body' => __('notification.auth.verification.body', ['code' => $verification_code]),
'link' => __('notification.auth.verification.link', ['email' => $contact_way, 'type' => $type]),
'body' => __('notification.auth.verification.new_body'),
'link' => __('notification.auth.verification.link', [
'email' => $email,
'type' => $type,
'signature' => $signature
])
])); ]));
return $verification_code;
// return $verification_code;
} }
public function verification(Request $request)
public function checkValidation($email, $type, $signature)
{ {
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);
if (!Cache::has($email) || Cache::get($email)['type'] !== $type || Cache::get($email)['signature'] != $signature)
{
abort(403, 'Validation failed');
} }
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,);
Cache::forget($email);
} }
public function forgetPassword(Request $request) public function forgetPassword(Request $request)
@ -164,122 +164,58 @@ class AuthController extends Controller
'email' => 'required|email|exists:users,email' 'email' => 'required|email|exists:users,email'
]); ]);
$code_data = ['verification_code' => $this->sendVerificationCode(\request('email', 'forget'))];
$this->sendVerification($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);
return response()->json(['message' => 'Send email for validation'], 200);
} }
public function updatePassword(Request $request) public function updatePassword(Request $request)
{ {
if (!Cache::has($request->email)) {
return \response()->json(['message' => 'Code expired.'], Response::HTTP_BAD_REQUEST);
}
$this->validate($request, [ $this->validate($request, [
'email' => 'required|email', 'email' => 'required|email',
'password' => 'required|string|min:8|confirmed', 'password' => 'required|string|min:8|confirmed',
'verification_code' => 'required|string|min:4|max:4|in:'.Cache::get($request->email)['verification_code']
'signature' => 'required|string'
]); ]);
$this->checkValidation($request->email, 'forget', $request->signature);
$user = User::where('email', $request->email)->first(); $user = User::where('email', $request->email)->first();
$user->update([ $user->update([
'password' => Hash::make($request->password)
'password' => Hash::make($request->password),
'has_password' => true
]); ]);
Auth::setUser($user); 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();
}
$this->createFingerPrint();
throw new TokenMismatchException('Invalid token!');
return response()->json(['message' => 'Update successfully you must be login.'], 200);
} }
/**
* @param string $token
* @throws TokenMismatchException
*/
public function revoke(string $token)
public function register(Request $request)
{ {
/** @var Fingerprint $token */
$token = Fingerprint::firstWhere([
'token' => $token,
$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'
]); ]);
if ($token) {
return $token->delete();
}
throw new TokenMismatchException();
}
$this->checkValidation($request->email, 'register', $request->signature);
public function auth()
{
return new UserResource(Auth::user());
}
$request->merge(['password' => Hash::make($request->password)]);
public function authWithInfo()
{
return [
'auth' => new UserResource(Auth::user()),
'businesses' => Auth::user()->businesses->keyBy('id') ->map(fn($b, $bid) => Business::info($bid))
];
}
$user = User::create($request->all()+ [
'has_password' => true
]);
public function delete(Request $request)
{
Auth::user()->fingerprints()->delete();
unset(Auth::user()->token);
Auth::user()->delete();
Auth::setUser($user);
return 'success';
}
$this->createFingerPrint();
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();
return response()->json(['message' => 'Register successfully you must be login.'], 200);
} }
public function createFingerPrint() public function createFingerPrint()

27
app/Http/Controllers/NewAuthController.php

@ -1,27 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class NewAuthController extends Controller
{
public function emailChecking()
{
if (1) {
// email exists in db
}
if (2) {
// email exists in cache
}
if (3) {
// email exists in invite table
}
if (4) {
// none of above
}
}
}

301
app/Http/Controllers/OldAuthController.php

@ -0,0 +1,301 @@
<?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 OldAuthController 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);
}
}

2
app/Models/User.php

@ -29,7 +29,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
'has_avatar' => 'boolean', 'has_avatar' => 'boolean',
]; ];
protected $fillable = ['name', 'email','mobile', 'username','password','active','has_avatar'];
protected $fillable = ['name', 'email','mobile', 'username','password','active','has_avatar', 'has_password'];
protected $fillable_relations = ['projects']; protected $fillable_relations = ['projects'];

1
database/migrations/2020_08_18_085016_create_users_table.php

@ -21,6 +21,7 @@ class CreateUsersTable extends Migration
$table->string('username')->unique(); $table->string('username')->unique();
$table->string('password'); $table->string('password');
$table->boolean('active')->default(false); $table->boolean('active')->default(false);
$table->boolean('has_password')->default(false);
$table->boolean('has_avatar')->default(false); $table->boolean('has_avatar')->default(false);
$table->timestamp('created_at')->nullable(); $table->timestamp('created_at')->nullable();
$table->timestamp('updated_at')->useCurrent(); $table->timestamp('updated_at')->useCurrent();

5
resources/lang/fa/notification.php

@ -88,9 +88,10 @@ return [
'auth' => [ 'auth' => [
'verification' => [ 'verification' => [
'greeting' => 'سلام کاربر گرامی!', 'greeting' => 'سلام کاربر گرامی!',
'subject' => 'کد تایید',
'subject' => 'لینک احراز هویت',
'body' => 'کد تایید شما :code', 'body' => 'کد تایید شما :code',
'link' => 'http://localhost:3000/verification?email=:email&type=:type'
'new_body' => 'برای ادامه فرایند ثبت نام لینک زیر را دنبال کنید.',
'link' => 'http://localhost:3000/verification?email=:email&type=:type&signature=:signature'
] ]
], ],

9
routes/api.php

@ -6,12 +6,6 @@ $router->get('/lab', function () {
throw new \Exception("^_^"); throw new \Exception("^_^");
}); });
$router->get('/ntest', function () {
$user = \App\Models\User::find(1);
\Illuminate\Support\Facades\Notification::send($user, new \App\Notifications\SmsNotification(['verification_code' => "1234"]));
// (new \App\Utilities\HelperClass\NotificationHelper())
// ->makeSmsNotif('template_name', ['user' => 'myUser', 'business' => 'myBusiness']);
})->middleware('bindBusiness');
$router->group(['prefix' => 'actions'], function () use ($router) { $router->group(['prefix' => 'actions'], function () use ($router) {
$router->group(['prefix' => 'businesses'], function () use ($router) { $router->group(['prefix' => 'businesses'], function () use ($router) {
$router->group(['prefix' => '{business}', 'middleware' => 'bindBusiness'], function () use ($router) { $router->group(['prefix' => '{business}', 'middleware' => 'bindBusiness'], function () use ($router) {
@ -25,6 +19,7 @@ $router->get('/{transaction}/redirection', 'CreditController@redirection');
$router->group(['prefix' => 'auth'], function () use ($router) { $router->group(['prefix' => 'auth'], function () use ($router) {
$router->get('/', 'AuthController@auth')->middleware('auth:api'); $router->get('/', 'AuthController@auth')->middleware('auth:api');
$router->post('/checking', 'AuthController@emailChecking');
$router->delete('/', 'AuthController@delete'); $router->delete('/', 'AuthController@delete');
$router->get('/info', 'AuthController@authWithInfo')->middleware('auth:api'); $router->get('/info', 'AuthController@authWithInfo')->middleware('auth:api');
$router->post('login', 'AuthController@login'); $router->post('login', 'AuthController@login');
@ -35,7 +30,7 @@ $router->group(['prefix' => 'auth'], function () use ($router) {
$router->post('forget-password', 'AuthController@forgetPassword'); $router->post('forget-password', 'AuthController@forgetPassword');
$router->post('update-password', 'AuthController@updatePassword'); $router->post('update-password', 'AuthController@updatePassword');
$router->post('verification', 'AuthController@verification');
$router->post('verification', 'AuthController@verification')->name('verification');
$router->get('google/redirect', 'AuthController@redirectToGoogle')->name('google.redirect'); $router->get('google/redirect', 'AuthController@redirectToGoogle')->name('google.redirect');
$router->get('google/callback', 'AuthController@handleGoogleCallback')->name('google.callback'); $router->get('google/callback', 'AuthController@handleGoogleCallback')->name('google.callback');

Loading…
Cancel
Save