Added oauth login
This commit is contained in:
parent
21ea60c4f9
commit
8224fba840
@ -2,11 +2,20 @@
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Models\AccountOauth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Socialite;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Mail\SocialLink;
|
||||
use App\Models\Oauth;
|
||||
use App\User;
|
||||
use function App\Console\Commands\object_to_array;
|
||||
|
||||
class SocialLoginController extends Controller
|
||||
{
|
||||
public function redirectToProvider($provider)
|
||||
@ -18,16 +27,97 @@ class SocialLoginController extends Controller
|
||||
{
|
||||
$openiduser = Socialite::with($provider)->user();
|
||||
|
||||
$user = Socialite::with($provider)->findOrCreateUser($openiduser);
|
||||
$oo = Oauth::firstOrCreate(['name'=>$provider,'active'=>TRUE]);
|
||||
|
||||
Auth::login($user,FALSE);
|
||||
// See if this user has connected and linked previously
|
||||
$aoo = $oo->accounts->where('userid',$openiduser->id);
|
||||
|
||||
/*
|
||||
if (! $user->profile_update)
|
||||
if ($aoo->count() == 1)
|
||||
{
|
||||
return redirect()->to(url('settings'));
|
||||
$aoo = $aoo->first();
|
||||
|
||||
if ((is_null($user=$aoo->user) AND (is_null($aoo->account) OR is_null($user=$aoo->account->user))) OR ! $user->active)
|
||||
{
|
||||
if (! $user) {
|
||||
$user = User::where('email',$openiduser->email)->first();
|
||||
}
|
||||
|
||||
if (! $user OR ! $user->active)
|
||||
{
|
||||
return redirect('/login')->with('error','Invalid account, or account inactive, please contact an admin.');
|
||||
}
|
||||
|
||||
return $this->link($provider,$aoo,$user);
|
||||
}
|
||||
|
||||
// All Set to login
|
||||
Auth::login($user,FALSE);
|
||||
|
||||
// If there are too many users, then we have a problem
|
||||
} elseif ($aoo->count() > 1) {
|
||||
return redirect('/login')->with('error','Seems you have multiple oauth IDs, please contact an admin.');
|
||||
|
||||
// User is using OAUTH for the first time.
|
||||
} else {
|
||||
$uo = User::active()->where('email',$openiduser->email);
|
||||
|
||||
// See if their is an account with this email address
|
||||
if ($uo->count() == 1)
|
||||
{
|
||||
$aoo = new AccountOauth;
|
||||
$aoo->userid = $openiduser->id;
|
||||
$aoo->oauth_data = $openiduser->user;
|
||||
$oo->accounts()->save($aoo);
|
||||
|
||||
return $this->link($provider,$aoo,$uo->first());
|
||||
|
||||
// If there are too many users, then we have a problem
|
||||
} elseif ($uo->count() > 1) {
|
||||
return redirect('/login')->with('error','Seems you have multiple accounts, please contact an admin.');
|
||||
|
||||
} else {
|
||||
return redirect('/login')->with('error','Seems you dont have an account with that email, please contact an admin.');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return redirect()->intended();
|
||||
}
|
||||
|
||||
/**
|
||||
* We have identified the user and oauth, just need them to confirm the link
|
||||
*
|
||||
* @param $provider
|
||||
* @param User $uo
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function link($provider,AccountOauth $ao,User $uo)
|
||||
{
|
||||
Mail::to($uo->email)->send(new SocialLink($ao));
|
||||
|
||||
return view('auth.social_link')
|
||||
->with('oauthid',$ao->id)
|
||||
->with('provider',$provider);
|
||||
}
|
||||
|
||||
public function linkcomplete(Request $request,$provider)
|
||||
{
|
||||
// Load our oauth id
|
||||
$aoo = AccountOauth::findOrFail($request->post('oauthid'));
|
||||
|
||||
// Check our email matches
|
||||
if (Arr::get($aoo->oauth_data,'email','invalid') !== $request->post('email'))
|
||||
return redirect('/login')->with('error','Account details didnt match to make link.');
|
||||
|
||||
// Check our token matches
|
||||
if ($aoo->link_token !== $request->post('token'))
|
||||
return redirect('/login')->with('error','Token details didnt match to make link.');
|
||||
|
||||
// Load our email.
|
||||
$uo = User::where('email',$request->post('email'))->firstOrFail();
|
||||
|
||||
$aoo->user_id = $uo->id;
|
||||
$aoo->save();
|
||||
Auth::login($uo,FALSE);
|
||||
|
||||
return redirect()->intended();
|
||||
}
|
||||
|
@ -35,12 +35,12 @@ class OrderRequest extends Mailable
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
switch ($this->service->category)
|
||||
switch (get_class($this->service->type))
|
||||
{
|
||||
case 'ADSL': $subject = sprintf('%s: %s',$this->service->category,$this->service->service_adsl->service_address);
|
||||
case 'App\Models\Service\Adsl': $subject = sprintf('NBN: %s',$this->service->type->service_address);
|
||||
break;
|
||||
|
||||
case 'VOIP': $subject = sprintf('%s: %s',$this->service->category,$this->service->service_voip->service_number);
|
||||
case 'App\Models\Service\Voip': $subject = sprintf('VOIP: %s',$this->service->type->service_number);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
43
app/Mail/SocialLink.php
Normal file
43
app/Mail/SocialLink.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
use App\Models\AccountOauth;
|
||||
use App\User;
|
||||
|
||||
class SocialLink extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $token;
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param User $o
|
||||
* @param string $token
|
||||
*/
|
||||
public function __construct(AccountOauth $o)
|
||||
{
|
||||
$this->token = $o->link_token;
|
||||
$this->user = $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this
|
||||
->markdown('email.system.social_link')
|
||||
->subject('Link your Account')
|
||||
->with(['site'=>$this->user->site]);
|
||||
}
|
||||
}
|
47
app/Models/AccountOauth.php
Normal file
47
app/Models/AccountOauth.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use App\User;
|
||||
use App\Traits\NextKey;
|
||||
|
||||
class AccountOauth extends Model
|
||||
{
|
||||
use NextKey;
|
||||
const RECORD_ID = 'account_oauth';
|
||||
public $incrementing = FALSE;
|
||||
|
||||
protected $table = 'ab_account_oauth';
|
||||
const CREATED_AT = 'date_orig';
|
||||
const UPDATED_AT = 'date_last';
|
||||
public $dateFormat = 'U';
|
||||
|
||||
protected $casts = [
|
||||
'oauth_data'=>'array',
|
||||
];
|
||||
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
public function site()
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
public function User()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a link token to use when validating account.
|
||||
*/
|
||||
public function getLinkTokenAttribute()
|
||||
{
|
||||
return strtoupper(substr(md5($this->id.$this->date_last),0,8));
|
||||
}
|
||||
}
|
25
app/Models/Oauth.php
Normal file
25
app/Models/Oauth.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use App\User;
|
||||
use App\Traits\NextKey;
|
||||
|
||||
class Oauth extends Model
|
||||
{
|
||||
use NextKey;
|
||||
const RECORD_ID = 'oauth';
|
||||
public $incrementing = FALSE;
|
||||
|
||||
protected $table = 'ab_oauth';
|
||||
public $timestamps = FALSE;
|
||||
|
||||
protected $fillable = ['name','active'];
|
||||
|
||||
public function accounts()
|
||||
{
|
||||
return $this->hasMany(AccountOauth::class);
|
||||
}
|
||||
}
|
@ -18,6 +18,9 @@ trait NextKey
|
||||
static::creating(function($model)
|
||||
{
|
||||
$model->id = self::NextId();
|
||||
|
||||
if (! $model->site_id)
|
||||
$model->site_id = config('SITE_SETUP')->id;
|
||||
});
|
||||
|
||||
static::saved(function($model)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
@ -82,6 +83,11 @@ class User extends Authenticatable
|
||||
return $this->hasManyThrough(Models\Payment::class,Models\Account::class);
|
||||
}
|
||||
|
||||
public function site()
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
public function services()
|
||||
{
|
||||
return $this->hasManyThrough(Models\Service::class,Models\Account::class);
|
||||
|
0
bootstrap/cache/.gitignore
vendored
Executable file → Normal file
0
bootstrap/cache/.gitignore
vendored
Executable file → Normal file
6
composer.lock
generated
6
composer.lock
generated
@ -2357,11 +2357,11 @@
|
||||
},
|
||||
{
|
||||
"name": "leenooks/laravel",
|
||||
"version": "0.3.10",
|
||||
"version": "0.3.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://dev.leenooks.net/leenooks/laravel",
|
||||
"reference": "1efdfca55f77c3a473b5009a5abca11f8cbd97b1"
|
||||
"reference": "a946ce44185a21abd28c56981b55867201c403e9"
|
||||
},
|
||||
"require": {
|
||||
"acacha/user": "^0.2.2",
|
||||
@ -2399,7 +2399,7 @@
|
||||
"laravel",
|
||||
"leenooks"
|
||||
],
|
||||
"time": "2019-07-03T07:16:46+00:00"
|
||||
"time": "2019-09-03T04:37:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maximebf/debugbar",
|
||||
|
@ -174,6 +174,7 @@ return [
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
Laravel\Socialite\SocialiteServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Other Service Providers...
|
||||
@ -233,6 +234,7 @@ return [
|
||||
'Schema' => Illuminate\Support\Facades\Schema::class,
|
||||
'Session' => Illuminate\Support\Facades\Session::class,
|
||||
'SnappyImage' => Barryvdh\Snappy\Facades\SnappyImage::class,
|
||||
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
|
||||
'Storage' => Illuminate\Support\Facades\Storage::class,
|
||||
'Str' => Illuminate\Support\Str::class,
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
|
@ -99,4 +99,12 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
'social' => [
|
||||
'google' => [
|
||||
'name' => 'Google',
|
||||
'id' => 'google',
|
||||
'class' => 'danger',
|
||||
'icon' => 'google',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
@ -44,10 +44,16 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
'ezypay' => [
|
||||
'plugin' => 'DD_EZYPAY',
|
||||
'base_uri' => 'https://api.ezypay.com/api/v1/',
|
||||
'token_user' => env('EZYPAY_TOKEN'),
|
||||
'guid' => env('EZYPAY_GUID'),
|
||||
],
|
||||
'ezypay' => [
|
||||
'plugin' => 'DD_EZYPAY',
|
||||
'base_uri' => 'https://api.ezypay.com/api/v1/',
|
||||
'token_user' => env('EZYPAY_TOKEN'),
|
||||
'guid' => env('EZYPAY_GUID'),
|
||||
],
|
||||
|
||||
'google' => [
|
||||
'client_id' => env('AUTH_GOOGLE_CLIENT_ID'),
|
||||
'client_secret' => env('AUTH_GOOGLE_SECRET'),
|
||||
'redirect' => '/auth/google/callback',
|
||||
],
|
||||
];
|
||||
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddUserToAccountoauth extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users',function(Blueprint $table) {
|
||||
$table->index(['id','site_id'],'site_user_id_idx');
|
||||
});
|
||||
|
||||
Schema::table('ab_account_oauth', function (Blueprint $table) {
|
||||
$table->dropPrimary(['id','site_id','account_id','oauth_id']);
|
||||
$table->primary(['id','site_id','oauth_id']);
|
||||
});
|
||||
|
||||
Schema::table('ab_account_oauth', function (Blueprint $table) {
|
||||
$table->bigInteger('account_id')->nullable()->change();
|
||||
|
||||
$table->integer('user_id')->unsigned()->nullable();
|
||||
$table->unique(['site_id','user_id','oauth_id']);
|
||||
$table->index(['user_id','site_id'],'site_user_id_idx');
|
||||
$table->foreign(['user_id','site_id'],'site_user_id')->references(['id','site_id'])->on('users');
|
||||
});
|
||||
|
||||
Schema::table('ab_oauth', function (Blueprint $table) {
|
||||
$table->string('name',32)->change();
|
||||
$table->unique(['site_id','name']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('ab_account_oauth', function (Blueprint $table) {
|
||||
$table->dropPrimary(['id','site_id','oauth_id']);
|
||||
$table->primary(['id','site_id','account_id','oauth_id']);
|
||||
});
|
||||
|
||||
Schema::table('ab_account_oauth', function (Blueprint $table) {
|
||||
$table->dropForeign('site_user_id');
|
||||
$table->dropUnique(['site_id','user_id','oauth_id']);
|
||||
$table->dropIndex('site_user_id_idx');
|
||||
$table->dropColumn('user_id');
|
||||
|
||||
$table->bigInteger('account_id')->change();
|
||||
});
|
||||
|
||||
Schema::table('users',function(Blueprint $table) {
|
||||
$table->dropIndex('site_user_id_idx');
|
||||
});
|
||||
|
||||
Schema::table('ab_oauth', function (Blueprint $table) {
|
||||
$table->string('name',32)->nullable()->change();
|
||||
$table->dropUnique(['site_id','name']);
|
||||
});
|
||||
}
|
||||
}
|
80
resources/theme/backend/adminlte/auth/social_link.blade.php
Normal file
80
resources/theme/backend/adminlte/auth/social_link.blade.php
Normal file
@ -0,0 +1,80 @@
|
||||
@extends('adminlte::layouts.auth')
|
||||
|
||||
@section('htmlheader_title')
|
||||
Link Account
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="login-box">
|
||||
<div class="login-logo">
|
||||
<a>{!! config('app.name_html_long') !!}</a>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success">
|
||||
<strong>NOTE:</strong> Link your account.<br><br>
|
||||
<ul>
|
||||
<li>An email has been sent to you with a token, please use those details here:</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@if (count($errors) > 0)
|
||||
<div class="alert alert-danger">
|
||||
<strong>Whoops!</strong> {{ trans('adminlte_lang::message.someproblems') }}<br><br>
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- /.login-logo -->
|
||||
<div class="card">
|
||||
<div class="card-body login-card-body">
|
||||
<p class="login-box-msg">Link your account</p>
|
||||
|
||||
<form method="post" action="{{ url('/auth/'.$provider.'/linkcomplete') }}">
|
||||
{{ csrf_field() }}
|
||||
<input type="hidden" name="oauthid" value="{{ $oauthid }}">
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input type="email" name="email" class="form-control" placeholder="Email">
|
||||
<div class="input-group-append">
|
||||
<span class="fa fa-envelope input-group-text"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input type="password" name="token" class="form-control" placeholder="Token">
|
||||
<div class="input-group-append">
|
||||
<span class="fa fa-lock input-group-text"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-4">
|
||||
<button type="submit" name="submit" class="btn btn-primary btn-block btn-flat">Link</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="mb-1">
|
||||
<a name="reset" href="{{ url('/password/reset') }}">{{ trans('adminlte_lang::message.forgotpassword') }}</a>
|
||||
</p>
|
||||
|
||||
@isset($register)
|
||||
<p class="mb-0">
|
||||
<a href="register.html" class="text-center">Register a new account</a>
|
||||
</p>
|
||||
@endisset
|
||||
</div>
|
||||
<!-- /.login-card-body -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.login-box -->
|
||||
@endsection
|
@ -14,7 +14,7 @@
|
||||
<!-- BEGIN TOP BAR MENU -->
|
||||
<div class="col-md-6 col-sm-6 additional-nav">
|
||||
<ul class="list-unstyled list-inline pull-right">
|
||||
<li><a href="{{ url('login') }}">Log In</a></li>
|
||||
<li><a href="{{ url('home') }}">Log In</a></li>
|
||||
<li><a href="{{ url('register') }}">Registration</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
18
resources/views/email/system/social_link.blade.php
Normal file
18
resources/views/email/system/social_link.blade.php
Normal file
@ -0,0 +1,18 @@
|
||||
@component('mail::message',['site'=>$site])
|
||||
Howdy,
|
||||
|
||||
A request was made to link your account to a social login.
|
||||
|
||||
If you didnt make this request, you can ignore this, and the request will be ignored.
|
||||
|
||||
If you did make the request, then please enter the code displayed below.
|
||||
|
||||
@component('mail::panel')
|
||||
{{ $token }}
|
||||
@endcomponent
|
||||
|
||||
Once you've keyed in this code, you'll be able to login to your account using your social login instead of a username and a password.
|
||||
|
||||
Thanks,<br>
|
||||
{{ config('app.name') }}
|
||||
@endcomponent
|
@ -14,6 +14,13 @@
|
||||
Auth::routes();
|
||||
Route::get('/logout','Auth\LoginController@logout');
|
||||
|
||||
Route::group(['middleware'=>['theme:adminlte-be']],function() {
|
||||
Route::get('auth/{socialProvider}', 'Auth\SocialLoginController@redirectToProvider');
|
||||
Route::get('auth/{socialProvider}/callback', 'Auth\SocialLoginController@handleProviderCallback');
|
||||
Route::get('auth/{socialProvider}/link', 'Auth\SocialLoginController@link');
|
||||
Route::post('auth/{socialProvider}/linkcomplete', 'Auth\SocialLoginController@linkcomplete');
|
||||
});
|
||||
|
||||
// Generic Image Renderer - Render images that we dont have with a generic image
|
||||
Route::get('image/generic/{width}/{height}/{color}/{name?}','MediaController@image')->name('image');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user