Added oauth login

This commit is contained in:
Deon George 2019-09-03 14:43:59 +10:00
parent 21ea60c4f9
commit 8224fba840
No known key found for this signature in database
GPG Key ID: 7670E8DC27415254
17 changed files with 426 additions and 21 deletions

View File

@ -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();
}

View File

@ -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
View 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]);
}
}

View 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
View 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);
}
}

View File

@ -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)

View File

@ -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
View File

6
composer.lock generated
View File

@ -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",

View File

@ -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,

View File

@ -99,4 +99,12 @@ return [
],
],
'social' => [
'google' => [
'name' => 'Google',
'id' => 'google',
'class' => 'danger',
'icon' => 'google',
],
],
];

View File

@ -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',
],
];

View File

@ -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']);
});
}
}

View 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">
&nbsp;
</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

View File

@ -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>

View 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

View File

@ -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');