8000 Implement user settings to change email address · laravelio/laravel.io@86df6f9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 86df6f9

Browse files
committed
Implement user settings to change email address
1 parent 7b6f1c8 commit 86df6f9

File tree

12 files changed

+215
-27
lines changed

12 files changed

+215
-27
lines changed

app/Lio/Accounts/UserUpdater.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php namespace Lio\Accounts;
2+
3+
use Illuminate\Support\Str;
4+
use Illuminate\Validation\Validator;
5+
6+
class UserUpdater
7+
{
8+
/**
9+
* @var \Lio\Accounts\UserRepository
10+
*/
11+
protected $users;
12+
13+
/**
14+
* @var \Lio\Accounts\SendConfirmationEmail
15+
*/
16+
protected $confirmation;
17+
18+
/**
19+
* @param \Lio\Accounts\UserRepository $users
20+
* @param \Lio\Accounts\SendConfirmationEmail $confirmation
21+
*/
22+
public function __construct(UserRepository $users, SendConfirmationEmail $confirmation)
23+
{
24+
$this->users = $users;
25+
$this->confirmation = $confirmation;
26+
}
27+
28+
/**
29+
* @param \Lio\Accounts\UserUpdaterListener $listener
30+
* @param \Lio\Accounts\User $user
31+
* @param array $data
32+
* @param \Illuminate\Validation\Validator $validator
33+
* @return mixed
34+
*/
35+
public function update(UserUpdaterListener $listener, User $user, array $data, Validator $validator = null)
36+
{
37+
// check the passed in validator
38+
if ($validator && ! $validator->isValid()) {
39+
return $listener->userValidationError($validator->getErrors());
40+
}
41+
42+
return $this->updateUser($user, $listener, $data);
43+
}
44+
45+
/**
46+
* @param \Lio\Accounts\User $user
47+
* @param \Lio\Accounts\UserUpdaterListener $listener
48+
* @param array $data
49+
* @return mixed
50+
*/
51+
private function updateUser(User $user, UserUpdaterListener $listener, array $data)
52+
{
53+
$oldEmail = $user->email;
54+
55+
$user->fill($data);
56+
57+
// If the email changed, the user will need to re-confirm it.
58+
if ($data['email'] !== $oldEmail) {
59+
$user->confirmed = false;
60+
61+
// Set a confirmation code for the user. He'll need to verify his email address
62+
// with this code before he can use certain sections on the website.
63+
$confirmationCode = Str::random(30);
64+
65+
// We'll generate a new one if we find a user with the same code.
66+
while ($this->users->getByConfirmationCode($confirmationCode) !== null) {
67+
$confirmationCode = Str::random(30);
68+
}
69+
70+
$user->confirmation_code = $confirmationCode;
71+
}
72+
73+
// check the model validation
74+
if (! $this->users->save($user)) {
75+
return $listener->userValidationError($user->getErrors());
76+
}
77+
78+
// Send a confirmation email to the user.
79+
if ($data['email'] !== $oldEmail) {
80+
$this->confirmation->send($user);
81+
}
82+
83+
return $listener->userUpdated($user, $data['email'] !== $oldEmail);
84+
}
85+ 10000
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php namespace Lio\Accounts;
2+
3+
interface UserUpdaterListener
4+
{
5+
public function userValidationError($errors);
6+
public function userUpdated($user, $emailChanged = false);
7+
}

app/Lio/Github/GithubAuthenticator.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ private function loginUser($listener, $user, $githubData)
3737
return $listener->userIsBanned($user);
3838
}
3939

40-
if (! $user->isConfirmed()) {
41-
return $listener->userIsntConfirmed($user);
42-
}
43-
4440
$user->fill($githubData);
4541
$this->users->save($user);
4642

app/Lio/Github/GithubAuthenticatorListener.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@ interface GithubAuthenticatorListener
44
{
55
public function userFound($user);
66
public function userIsBanned($user);
7-
public function userIsntConfirmed($user);
87
public function userNotFound($githubData);
98
}

app/controllers/AuthController.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,6 @@ public function userIsBanned($user)
165165
return $this->redirectHome();
166166
}
167167

168-
public function userIsntConfirmed($user)
169-
{
170-
Session::flash('error', 'Please confirm your email address (' . $user->email . ') before trying to login.
171-
<a style="color:#fff" href="' . route('user.reconfirm', $user->confirmation_code) . '">Re-send confirmation email.</a>');
172-
173-
return $this->redirectHome();
174-
}
175-
176168
public function userNotFound($githubData)
177169
{
178170
Session::put('userGithubData', $githubData);

app/controllers/UsersController.php

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,60 @@
11
<?php
22

33
use Lio\Accounts\UserRepository;
4+
use Lio\Accounts\UserUpdater;
5+
use Lio\Accounts\UserUpdaterListener;
46

5-
class UsersController extends BaseController
7+
class UsersController extends BaseController implements UserUpdaterListener
68
{
9+
/**
10+
* @var \Lio\Accounts\UserRepository
11+
*/
712
private $users;
813

9-
public function __construct(UserRepository $users)
14+
/**
15+
* @var \Lio\Accounts\UserUpdater
16+
*/
17+
private $updater;
18+
19+
/**
20+
* @param \Lio\Accounts\UserRepository $users
21+
* @param \Lio\Accounts\UserUpdater $updater
22+
*/
23+
public function __construct(UserRepository $users, UserUpdater $updater)
1024
{
1125
$this->users = $users;
26+
$this->updater = $updater;
1227
}
1328

1429
public function getProfile($userName)
1530
{
1631
$user = $this->users->requireByName($userName);
1732

33+
// Make sure that the user which is updated is the one who is currently logged in.
34+
if (Auth::user()->id !== $user->id) {
35+
App::abort(403);
36+
}
37+
1838
$threads = $user->getLatestThreadsPaginated(5);
1939
$replies = $user->getLatestRepliesPaginated(5);
2040

2141
$this->view('users.profile', compact('user', 'threads', 'replies'));
2242
}
2343

44+
public function getSettings($userName)
45+
{
46+
$user = $this->users->requireByName($userName);
47+
48+
$this->view('users.settings', compact('user'));
49+
}
50+
51+
public function putSettings($userName)
52+
{
53+
$user = $this->users->requireByName($userName);
54+
55+
return $this->updater->update($this, $user, Input::only('email'));
56+
}
57+
2458
public function getThreads($userName)
2559
{
2660
$user = $this->users->requireByName($userName);
@@ -38,4 +72,20 @@ public function getReplies($userName)
3872

3973
$this->view('users.replies', compact('user', 'replies'));
4074
}
75+
76+
public function userValidationError($errors)
77+
{
78+
return $this->redirectBack(['errors' => $errors]);
79+
}
80+
81+
public function userUpdated($user, $emailChanged = false)
82+
{
83+
if ($emailChanged) {
84+
Session::flash('success', 'Settings updated. An email confirmation was sent to ' . $user->email);
85+
} else {
86+
Session::flash('success', 'Settings updated');
87+
}
88+
89+
return Redirect::route('user', $user->name);
90+
}
4191
}

app/filters.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,6 @@
4141

4242
Auth::logout();
4343

44-
return Redirect::home();
45-
} elseif (! Auth::user()->isConfirmed()) {
46-
// Don't let people who haven't confirmed their email use the authed sections on the website.
47-
Session::flash('error', 'Please confirm your email address (' . Auth::user()->email . ') before you try to login.
48-
<a style="color:#fff" href="' . route('user.reconfirm', Auth::user()->confirmation_code) . '">Re-send confirmation email.</a>');
49-
50-
Auth::logout();
51-
5244
return Redirect::home();
5345
}
5446
});
@@ -59,6 +51,17 @@
5951
return Auth::basic();
6052
});
6153

54+
Route::filter('confirmed', function() {
55+
if (Auth::guest() || ! Auth::user()->isConfirmed()) {
56+
// Don't let people who haven't confirmed their email use the authed sections on the website.
57+
Session::flash('error', 'Please confirm your email address (' . Auth::user()->email . ') before you try to use this section.
58+
<a style="color:#fff" href="' . route('user.reconfirm', Auth::user()->confirmation_code) . '">Re-send confirmation email.</a>
59+
<a href="' . route('user.settings', Auth::user()->name) . '" style="color:#eee;">Change e-mail address.</a>');
60+
61+
return Redirect::home();
62+
}
63+
});
64+
6265
/*
6366
|--------------------------------------------------------------------------
6467
| Guest Filter

app/routes.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
Route::get('user/{userSlug}/threads', 'UsersController@getThreads');
3636
Route::get('user/{userSlug}/replies', 'UsersController@getReplies');
3737

38+
Route::group(['before' => 'auth'], function () {
39+
Route::get('user/{userSlug}/settings', ['as' => 'user.settings', 'uses' => 'UsersController@getSettings']);
40+
Route::put('user/{userSlug}/settings', ['before' => 'csrf', 'as' => 'user.settings.update', 'uses' => 'UsersController@putSettings']);
41+
});
42+
3843
// contributors
3944
Route::get('contributors', 'ContributorsController@getIndex');
4045

@@ -51,7 +56,7 @@
5156
Route::get('bin/{hash}/raw', 'PastesController@getRaw');
5257
Route::get('bin/{hash}', 'PastesController@getShow');
5358

54-
Route::group(['before' => 'auth'], function() {
59+
Route::group(['before' => 'auth|confirmed'], function() {
5560
Route::post('bin', ['before' => 'csrf', 'uses' => 'PastesController@postCreate']);
5661
Route::post('bin/fork/{hash}', ['before' => 'csrf', 'uses' => 'PastesController@postFork']);
5762
});
@@ -71,7 +76,7 @@
7176
// Route::get('articles/search', 'ArticlesController@getSearch');
7277

7378
// forum
74-
Route::group(['before' => 'auth'], function() {
79+
Route::group(['before' => 'auth|confirmed'], function() {
7580
Route::get('forum/create-thread', 'ForumThreadsController@getCreateThread');
7681
Route::post('forum/create-thread', ['before' => 'csrf', 'uses' => 'ForumThreadsController@postCreateThread']);
7782

@@ -101,7 +106,7 @@
101106
Route::get('api/forum', 'Api\ForumThreadsController@getIndex');
102107

103108
// admin
104-
Route::group(['before' => 'auth', 'prefix' => 'admin', 'namespace' => 'Admin'], function() {
109+
Route::group(['before' => 'auth|confirmed', 'prefix' => 'admin', 'namespace' => 'Admin'], function() {
105110
Route::get('/', function() {
106111
return Redirect::action('Admin\UsersController@getIndex');
107112
});

app/views/layouts/default.blade.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<div style="background: #2fb352; padding: .75em; text-align:center; color:#eee; font-size:1.1em">
3131
Please confirm your email address ({{ Auth::user()->email }}).
3232
<a href="{{ route('user.reconfirm', Auth::user()->confirmation_code) }}" style="color:#eee;">Re-send confirmation email.</a>
33+
<a href="{{ route('user.settings', Auth::user()->name) }}" style="color:#eee;">Change e-mail address.</a>
3334
</div>
3435
@endif
3536

app/views/users/_sidebar.blade.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@
55
{{ $user->imageMedium }}
66
@endif
77
<h1>{{ $user->name }}</h1>
8-
<a class="button" target="_blank" href="{{ $user->github_url }}">Visit GitHub Profile</a>
8+
<p><a class="button" target="_blank" href="{{ $user->github_url }}">Visit GitHub Profile</a></p>
9+
10+
@if (Auth::check())
11+
<p><a class="button" href="{{ route('user.settings', $user->name) }}">Edit Account Settings</a></p>
12+
@endif
913
</div>

app/views/users/settings.blade.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@extends('layouts._two_columns_left_sidebar')
2+
3+
@section('sidebar')
4+
@include('users._sidebar')
5+
@stop
6+
7+
@section('content')
8+
9+
<section class="user-content">
10+
<div class="header">
11+
<h1>Account Settings</h1>
12+
</div>
13+
<div class="user-settings">
14+
{{ Form::open(['route' => ['user.settings.update', $user->name], 'method' => 'put']) }}
15+
<p>
16+
{{ Form::label('email') }}
17+
{{ Form::email('email', $user->email) }}
18+
</p>
19+
20+
@if ($errors->has('email'))
21+
<p>{{ $errors->first('email') }}</p>
22+
@else
23+
<span class="help-inline">If you change your e-mail address, you'll have to reconfirm it.</span>
24+
@endif
25+
26+
<p>{{ Form::submit('Save Settings', ['class' => 'button']) }}</p>
27+
{{ Form::close() }}
28+
</div>
29+
</section>
30+
31+
@stop

public/scss/modules/_user.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,21 @@
7777
}
7878
}
7979

80+
.user-settings {
81+
padding: 15px;
82+
83+
label {
84+
display: inline-block;
85+
width: 40px;
86+
}
87+
input {
88+
display: inline-block;
89+
padding: 5px 7px;
90+
width: 100%;
91+
max-width: 300px;
92+
}
93+
}
94+
8095
.admin-bar {
8196
margin: 15px 0 0 0;
8297
padding: 15px 0 0 0;

0 commit comments

Comments
 (0)
0