Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Зуев Егор
/
wiki.dev
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Authored by
Dan Brown
2015-09-04 20:40:36 +0100
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Commit
eac7378ce02c8f8a366e637f0f9b0863d3d8b47a
eac7378c
1 parent
3d18a04c
Made social accounts attachable
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
257 additions
and
48 deletions
app/Exceptions/UserNotFound.php → app/Exceptions/SocialSignInException.php
app/Http/Controllers/Auth/AuthController.php
app/Http/Controllers/UserController.php
app/Http/Middleware/RedirectIfAuthenticated.php
app/Http/routes.php
app/Services/SocialAuthService.php
app/SocialAccount.php
app/User.php
database/migrations/2015_09_04_165821_create_social_accounts_table.php
resources/assets/sass/_variables.scss
resources/views/auth/login.blade.php
resources/views/base.blade.php
resources/views/users/edit.blade.php
app/Exceptions/
UserNotFound
.php
→
app/Exceptions/
SocialSignInException
.php
View file @
eac7378
<?php
namespace
Oxbow\Exceptions
;
class
UserNotFound
extends
NotifyException
class
SocialSignInException
extends
NotifyException
{
}
\ No newline at end of file
...
...
app/Http/Controllers/Auth/AuthController.php
View file @
eac7378
...
...
@@ -2,7 +2,7 @@
namespace
Oxbow\Http\Controllers\Auth
;
use
Oxbow\Exceptions\
UserNotFound
;
use
Oxbow\Exceptions\
SocialSignInException
;
use
Oxbow\Services\SocialAuthService
;
use
Oxbow\User
;
use
Validator
;
...
...
@@ -37,7 +37,7 @@ class AuthController extends Controller
*/
public
function
__construct
(
SocialAuthService
$socialAuthService
)
{
$this
->
middleware
(
'guest'
,
[
'
except'
=>
'getLogout'
]);
$this
->
middleware
(
'guest'
,
[
'
only'
=>
[
'getLogin'
,
'postLogin'
]
]);
$this
->
socialAuthService
=
$socialAuthService
;
}
...
...
@@ -95,7 +95,7 @@ class AuthController extends Controller
*/
public
function
getSocialLogin
(
$socialDriver
)
{
return
$this
->
socialAuthService
->
l
ogIn
(
$socialDriver
);
return
$this
->
socialAuthService
->
startL
ogIn
(
$socialDriver
);
}
/**
...
...
@@ -103,13 +103,21 @@ class AuthController extends Controller
*
* @param $socialDriver
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
* @throws
UserNotFound
* @throws
SocialSignInException
*/
public
function
socialCallback
(
$socialDriver
)
{
$user
=
$this
->
socialAuthService
->
getUserFromCallback
(
$socialDriver
);
\Auth
::
login
(
$user
,
true
);
return
redirect
(
$this
->
redirectPath
);
return
$this
->
socialAuthService
->
handleCallback
(
$socialDriver
);
}
/**
* Detach a social account from a user.
* @param $socialDriver
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public
function
detachSocialAccount
(
$socialDriver
)
{
return
$this
->
socialAuthService
->
detachSocialAccount
(
$socialDriver
);
}
}
...
...
app/Http/Controllers/UserController.php
View file @
eac7378
...
...
@@ -6,6 +6,7 @@ use Illuminate\Http\Request;
use
Illuminate\Support\Facades\Hash
;
use
Oxbow\Http\Requests
;
use
Oxbow\Services\SocialAuthService
;
use
Oxbow\User
;
class
UserController
extends
Controller
...
...
@@ -74,16 +75,19 @@ class UserController extends Controller
/**
* Show the form for editing the specified user.
*
* @param int $id
* @param int $id
* @param SocialAuthService $socialAuthService
* @return Response
*/
public
function
edit
(
$id
)
public
function
edit
(
$id
,
SocialAuthService
$socialAuthService
)
{
$this
->
checkPermissionOr
(
'user-update'
,
function
()
use
(
$id
)
{
return
$this
->
currentUser
->
id
==
$id
;
});
$user
=
$this
->
user
->
findOrFail
(
$id
);
return
view
(
'users/edit'
,
[
'user'
=>
$user
]);
$activeSocialDrivers
=
$socialAuthService
->
getActiveDrivers
();
return
view
(
'users/edit'
,
[
'user'
=>
$user
,
'activeSocialDrivers'
=>
$activeSocialDrivers
]);
}
/**
...
...
@@ -107,13 +111,14 @@ class UserController extends Controller
]);
$user
=
$this
->
user
->
findOrFail
(
$id
);
$user
->
fill
(
$request
->
all
(
));
$user
->
fill
(
$request
->
except
(
'password'
));
if
(
$this
->
currentUser
->
can
(
'user-update'
)
&&
$request
->
has
(
'role'
))
{
$user
->
attachRoleId
(
$request
->
get
(
'role'
));
}
if
(
$request
->
has
(
'password'
)
&&
$request
->
get
(
'password'
)
!=
''
)
{
//dd('cat');
$password
=
$request
->
get
(
'password'
);
$user
->
password
=
Hash
::
make
(
$password
);
}
...
...
app/Http/Middleware/RedirectIfAuthenticated.php
View file @
eac7378
...
...
@@ -17,7 +17,7 @@ class RedirectIfAuthenticated
/**
* Create a new filter instance.
*
* @param Guard
$auth
* @param Guard $auth
* @return void
*/
public
function
__construct
(
Guard
$auth
)
...
...
@@ -28,14 +28,14 @@ class RedirectIfAuthenticated
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request
$request
* @param \Closure $next
* @param \Illuminate\Http\Request $request
* @param \Closure
$next
* @return mixed
*/
public
function
handle
(
$request
,
Closure
$next
)
{
if
(
$this
->
auth
->
check
())
{
return
redirect
(
'/
home
'
);
return
redirect
(
'/'
);
}
return
$next
(
$request
);
...
...
app/Http/routes.php
View file @
eac7378
...
...
@@ -78,13 +78,15 @@ Route::group(['middleware' => 'auth'], function () {
});
// Login using social authentication
Route
::
get
(
'/login/service/{socialDriver}'
,
'Auth\AuthController@getSocialLogin'
);
Route
::
get
(
'/login/service/{socialDriver}/callback'
,
'Auth\AuthController@socialCallback'
);
Route
::
get
(
'/login/service/{socialDriver}/detach'
,
'Auth\AuthController@detachSocialAccount'
);
// Login/Logout routes
Route
::
get
(
'/login'
,
'Auth\AuthController@getLogin'
);
Route
::
post
(
'/login'
,
'Auth\AuthController@postLogin'
);
Route
::
get
(
'/logout'
,
'Auth\AuthController@getLogout'
);
// Login using social authentication
Route
::
get
(
'/login/service/{socialService}'
,
'Auth\AuthController@getSocialLogin'
);
Route
::
get
(
'/login/service/{socialService}/callback'
,
'Auth\AuthController@socialCallback'
);
// Password reset link request routes...
Route
::
get
(
'/password/email'
,
'Auth\PasswordController@getEmail'
);
...
...
app/Services/SocialAuthService.php
View file @
eac7378
...
...
@@ -2,29 +2,40 @@
use
Laravel\Socialite\Contracts\Factory
as
Socialite
;
use
Oxbow\Exceptions\SocialDriverNotConfigured
;
use
Oxbow\Exceptions\
UserNotFound
;
use
Oxbow\Exceptions\
SocialSignInException
;
use
Oxbow\Repos\UserRepo
;
use
Oxbow\SocialAccount
;
use
Oxbow\User
;
class
SocialAuthService
{
protected
$userRepo
;
protected
$socialite
;
protected
$socialAccount
;
protected
$validSocialDrivers
=
[
'google'
,
'github'
];
/**
* SocialAuthService constructor.
* @param $userRepo
* @param $socialite
* @param UserRepo $userRepo
* @param Socialite $socialite
* @param SocialAccount $socialAccount
*/
public
function
__construct
(
UserRepo
$userRepo
,
Socialite
$socialite
)
public
function
__construct
(
UserRepo
$userRepo
,
Socialite
$socialite
,
SocialAccount
$socialAccount
)
{
$this
->
userRepo
=
$userRepo
;
$this
->
socialite
=
$socialite
;
$this
->
socialAccount
=
$socialAccount
;
}
public
function
logIn
(
$socialDriver
)
/**
* Start the social login path.
* @param $socialDriver
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* @throws SocialDriverNotConfigured
*/
public
function
startLogIn
(
$socialDriver
)
{
$driver
=
$this
->
validateDriver
(
$socialDriver
);
return
$this
->
socialite
->
driver
(
$driver
)
->
redirect
();
...
...
@@ -34,23 +45,78 @@ class SocialAuthService
* Get a user from socialite after a oAuth callback.
*
* @param $socialDriver
* @return
mixed
* @return
User
* @throws SocialDriverNotConfigured
* @throws
UserNotFound
* @throws
SocialSignInException
*/
public
function
getUserFrom
Callback
(
$socialDriver
)
public
function
handle
Callback
(
$socialDriver
)
{
$driver
=
$this
->
validateDriver
(
$socialDriver
);
// Get user details from social driver
$socialUser
=
$this
->
socialite
->
driver
(
$driver
)
->
user
();
$socialId
=
$socialUser
->
getId
();
// Get any attached social accounts or users
$socialAccount
=
$this
->
socialAccount
->
where
(
'driver_id'
,
'='
,
$socialId
)
->
first
();
$user
=
$this
->
userRepo
->
getByEmail
(
$socialUser
->
getEmail
());
$isLoggedIn
=
\Auth
::
check
();
$currentUser
=
\Auth
::
user
();
// When a user is not logged in but a matching SocialAccount exists,
// Log the user found on the SocialAccount into the application.
if
(
!
$isLoggedIn
&&
$socialAccount
!==
null
)
{
return
$this
->
logUserIn
(
$socialAccount
->
user
);
}
// When a user is logged in but the social account does not exist,
// Create the social account and attach it to the user & redirect to the profile page.
if
(
$isLoggedIn
&&
$socialAccount
===
null
)
{
$this
->
fillSocialAccount
(
$socialDriver
,
$socialUser
);
$currentUser
->
socialAccounts
()
->
save
(
$this
->
socialAccount
);
\Session
::
flash
(
'success'
,
title_case
(
$socialDriver
)
.
' account was successfully attached to your profile.'
);
return
redirect
(
$currentUser
->
getEditUrl
());
}
// When a user is logged in and the social account exists and is already linked to the current user.
if
(
$isLoggedIn
&&
$socialAccount
!==
null
&&
$socialAccount
->
user
->
id
===
$currentUser
->
id
)
{
\Session
::
flash
(
'error'
,
'This '
.
title_case
(
$socialDriver
)
.
' account is already attached to your profile.'
);
return
redirect
(
$currentUser
->
getEditUrl
());
}
// When a user is logged in, A social account exists but the users do not match.
// Change the user that the social account is assigned to.
if
(
$isLoggedIn
&&
$socialAccount
!==
null
&&
$socialAccount
->
user
->
id
!=
$currentUser
->
id
)
{
$socialAccount
->
user_id
=
$currentUser
->
id
;
$socialAccount
->
save
();
\Session
::
flash
(
'success'
,
'This '
.
title_case
(
$socialDriver
)
.
' account is now attached to your profile.'
);
}
// Redirect if the email is not a current user.
if
(
$user
===
null
)
{
throw
new
UserNotFound
(
'A user with the email '
.
$socialUser
->
getEmail
()
.
' was not found.'
,
'/login'
);
throw
new
SocialSignInException
(
'A system user with the email '
.
$socialUser
->
getEmail
()
.
' was not found and this '
.
$socialDriver
.
' account is not linked to any users.'
,
'/login'
);
}
return
$this
->
authenticateUserWithNewSocialAccount
(
$user
,
$socialUser
,
$socialUser
);
}
/**
* Logs a user in and creates a new social account entry for future usage.
* @param User $user
* @param string $socialDriver
* @param \Laravel\Socialite\Contracts\User $socialUser
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
private
function
authenticateUserWithNewSocialAccount
(
$user
,
$socialDriver
,
$socialUser
)
{
$this
->
fillSocialAccount
(
$socialDriver
,
$socialUser
);
$user
->
socialAccounts
()
->
save
(
$this
->
socialAccount
);
return
$this
->
logUserIn
(
$user
);
}
return
$user
;
private
function
logUserIn
(
$user
)
{
\Auth
::
login
(
$user
);
return
redirect
(
'/'
);
}
/**
...
...
@@ -65,7 +131,7 @@ class SocialAuthService
$driver
=
trim
(
strtolower
(
$socialDriver
));
if
(
!
in_array
(
$driver
,
$this
->
validSocialDrivers
))
abort
(
404
,
'Social Driver Not Found'
);
if
(
!
$this
->
check
l
DriverConfigured
(
$driver
))
throw
new
SocialDriverNotConfigured
;
if
(
!
$this
->
checkDriverConfigured
(
$driver
))
throw
new
SocialDriverNotConfigured
;
return
$driver
;
}
...
...
@@ -75,7 +141,7 @@ class SocialAuthService
* @param $driver
* @return bool
*/
private
function
check
l
DriverConfigured
(
$driver
)
private
function
checkDriverConfigured
(
$driver
)
{
$upperName
=
strtoupper
(
$driver
);
$config
=
[
env
(
$upperName
.
'_APP_ID'
,
false
),
env
(
$upperName
.
'_APP_SECRET'
,
false
),
env
(
'APP_URL'
,
false
)];
...
...
@@ -90,12 +156,36 @@ class SocialAuthService
{
$activeDrivers
=
[];
foreach
(
$this
->
validSocialDrivers
as
$driverName
)
{
if
(
$this
->
check
l
DriverConfigured
(
$driverName
))
{
if
(
$this
->
checkDriverConfigured
(
$driverName
))
{
$activeDrivers
[
$driverName
]
=
true
;
}
}
return
$activeDrivers
;
}
/**
* @param $socialDriver
* @param $socialUser
*/
private
function
fillSocialAccount
(
$socialDriver
,
$socialUser
)
{
$this
->
socialAccount
->
fill
([
'driver'
=>
$socialDriver
,
'driver_id'
=>
$socialUser
->
getId
(),
'avatar'
=>
$socialUser
->
getAvatar
()
]);
}
/**
* Detach a social account from a user.
* @param $socialDriver
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public
function
detachSocialAccount
(
$socialDriver
)
{
\Auth
::
user
()
->
socialAccounts
()
->
where
(
'driver'
,
'='
,
$socialDriver
)
->
delete
();
\Session
::
flash
(
'success'
,
$socialDriver
.
' account successfully detached'
);
return
redirect
(
\Auth
::
user
()
->
getEditUrl
());
}
}
\ No newline at end of file
...
...
app/SocialAccount.php
0 → 100644
View file @
eac7378
<?php
namespace
Oxbow
;
use
Illuminate\Database\Eloquent\Model
;
class
SocialAccount
extends
Model
{
protected
$fillable
=
[
'user_id'
,
'driver'
,
'driver_id'
,
'timestamps'
];
public
function
user
()
{
return
$this
->
belongsTo
(
'Oxbow\User'
);
}
}
app/User.php
View file @
eac7378
...
...
@@ -97,6 +97,31 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
}
/**
* Get the social account associated with this user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public
function
socialAccounts
()
{
return
$this
->
hasMany
(
'Oxbow\SocialAccount'
);
}
/**
* Check if the user has a social account,
* If a driver is passed it checks for that single account type.
* @param bool|string $socialDriver
* @return bool
*/
public
function
hasSocialAccount
(
$socialDriver
=
false
)
{
if
(
$socialDriver
===
false
)
{
return
$this
->
socialAccounts
()
->
count
()
>
0
;
}
return
$this
->
socialAccounts
()
->
where
(
'driver'
,
'='
,
$socialDriver
)
->
exists
();
}
/**
* Returns the user's avatar,
* Uses Gravatar as the avatar service.
*
...
...
@@ -108,4 +133,9 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
$emailHash
=
md5
(
strtolower
(
trim
(
$this
->
email
)));
return
'//www.gravatar.com/avatar/'
.
$emailHash
.
'?s='
.
$size
.
'&d=identicon'
;
}
public
function
getEditUrl
()
{
return
'/users/'
.
$this
->
id
;
}
}
...
...
database/migrations/2015_09_04_165821_create_social_accounts_table.php
0 → 100644
View file @
eac7378
<?php
use
Illuminate\Database\Schema\Blueprint
;
use
Illuminate\Database\Migrations\Migration
;
class
CreateSocialAccountsTable
extends
Migration
{
/**
* Run the migrations.
*
* @return void
*/
public
function
up
()
{
Schema
::
create
(
'social_accounts'
,
function
(
Blueprint
$table
)
{
$table
->
increments
(
'id'
);
$table
->
integer
(
'user_id'
)
->
indexed
();
$table
->
string
(
'driver'
)
->
indexed
();
$table
->
string
(
'driver_id'
);
$table
->
string
(
'avatar'
);
$table
->
timestamps
();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public
function
down
()
{
Schema
::
drop
(
'social_accounts'
);
}
}
resources/assets/sass/_variables.scss
View file @
eac7378
...
...
@@ -37,7 +37,7 @@ $primary: #0288D1;
$primary-dark
:
#0288D1
;
$secondary
:
#e27b41
;
$positive
:
#52A256
;
$negative
:
#
D32F2
F
;
$negative
:
#
E84F4
F
;
// Item Colors
$color-book
:
#009688
;
...
...
resources/views/auth/login.blade.php
View file @
eac7378
...
...
@@ -30,7 +30,7 @@
<a
href=
"/login/service/google"
style=
"color: #DC4E41;"
><i
class=
"zmdi zmdi-google-plus-box zmdi-hc-4x"
></i></a>
@endif
@if(isset($socialDrivers['github']))
<a
href=
"/login/service/github"
style=
"color:#
000
;"
><i
class=
"zmdi zmdi-github zmdi-hc-4x"
></i></a>
<a
href=
"/login/service/github"
style=
"color:#
444
;"
><i
class=
"zmdi zmdi-github zmdi-hc-4x"
></i></a>
@endif
@endif
</div>
...
...
resources/views/base.blade.php
View file @
eac7378
...
...
@@ -55,6 +55,9 @@
@if($currentUser->can('settings-update'))
<a
href=
"/settings"
><i
class=
"zmdi zmdi-settings"
></i>
Settings
</a>
@endif
@if(!$signedIn)
<a
href=
"/login"
><i
class=
"zmdi zmdi-sign-in"
></i>
Sign In
</a>
@endif
</div>
@if($signedIn)
<img
class=
"avatar"
src=
"{{$currentUser->getAvatar(30)}}"
alt=
"{{ $currentUser->name }}"
>
...
...
resources/views/users/edit.blade.php
View file @
eac7378
...
...
@@ -42,22 +42,43 @@
<hr
class=
"margin-top large"
>
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<h3>
Permissions
</h3>
<p>
User Role:
<strong>
{{$user->role->display_name}}
</strong>
.
</p>
<ul
class=
"text-muted"
>
@foreach($user->role->permissions as $permission)
<li>
{{ $permission->display_name }}
</li>
@endforeach
</ul>
@if($currentUser->id === $user->id)
<h3>
Social Accounts
</h3>
<p
class=
"text-muted"
>
Here you can connect your other accounts for quicker and easier login.
<br>
Disconnecting an account here does not previously authorized access. Revoke access from your profile settings on the connected social account.
</p>
<div
class=
"row"
>
@if(isset($activeSocialDrivers['google']))
<div
class=
"col-md-3 text-center"
>
<div><i
class=
"zmdi zmdi-google-plus-box zmdi-hc-4x"
style=
"color: #DC4E41;"
></i></div>
<div>
@if($user->hasSocialAccount('google'))
<a
href=
"/login/service/google/detach"
class=
"button neg"
>
Disconnect Account
</a>
@else
<a
href=
"/login/service/google"
class=
"button pos"
>
Attach Account
</a>
@endif
</div>
</div>
@endif
@if(isset($activeSocialDrivers['github']))
<div
class=
"col-md-3 text-center"
>
<div><i
class=
"zmdi zmdi-github zmdi-hc-4x"
style=
"color: #444;"
></i></div>
<div>
@if($user->hasSocialAccount('github'))
<a
href=
"/login/service/github/detach"
class=
"button neg"
>
Disconnect Account
</a>
@else
<a
href=
"/login/service/github"
class=
"button pos"
>
Attach Account
</a>
@endif
</div>
</div>
@endif
</div>
</div>
@endif
</div>
<p
class=
"margin-top large"
><br></p>
@stop
...
...
Please
register
or
sign in
to post a comment