Skip to content

Commit 02776b7

Browse files
authored
Merge pull request #10 from RhubarbPHP/feature/ProtectedUrls
Protected urls
2 parents bbaedf7 + 92f99b2 commit 02776b7

File tree

11 files changed

+167
-136
lines changed

11 files changed

+167
-136
lines changed

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# Change Log
22

3-
### 1.0.x
3+
### 1.1.x
4+
5+
### 1.1.0
6+
7+
* Changed: Model initialisation to allow easily overriding the model class
8+
* Added: Support for multiple URLs protected by different LoginProviders
49

510
### 1.0.2
611

@@ -19,4 +24,4 @@
1924

2025
### 1.0.0
2126

22-
* Changed: Changes for 1.0.0 of Leaf
27+
* Changed: Changes for 1.0.0 of Leaf

src/AuthenticationModule.php

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,78 +18,87 @@
1818

1919
namespace Rhubarb\Scaffolds\Authentication;
2020

21-
use Rhubarb\Crown\LoginProviders\LoginProvider;
2221
use Rhubarb\Crown\LoginProviders\UrlHandlers\ValidateLoginUrlHandler;
2322
use Rhubarb\Crown\Module;
24-
use Rhubarb\Crown\UrlHandlers\ClassMappedUrlHandler;
2523
use Rhubarb\Leaf\UrlHandlers\LeafCollectionUrlHandler;
24+
use Rhubarb\Scaffolds\Authentication\Settings\ProtectedUrl;
25+
use Rhubarb\Scaffolds\Authentication\UrlHandlers\CallableUrlHandler;
2626
use Rhubarb\Stem\Schema\SolutionSchema;
2727
use Rhubarb\Stem\StemModule;
2828

2929
class AuthenticationModule extends Module
3030
{
31-
protected $urlToProtect;
32-
protected $loginUrl;
33-
3431
/**
3532
* Creates an instance of the Authentication module.
3633
*
3734
* @param null $loginProviderClassName
3835
* @param string $urlToProtect Optional. The URL stub to protect by requiring a login. Defaults to
3936
* the entire URL tree.
4037
* @param string $loginUrl The URL to redirect the user to for logging in
41-
* @param string $identityColumnName The name of the column in the user table storing the login identity.
38+
* @internal param string $identityColumnName The name of the column in the user table storing the login identity.
4239
*/
43-
public function __construct($loginProviderClassName = null, $urlToProtect = "/", $loginUrl = "/login/")
40+
public function __construct($loginProviderClassName = null, $urlToProtect = '/', $loginUrl = '/login/')
4441
{
4542
parent::__construct();
4643

47-
$this->urlToProtect = $urlToProtect;
48-
$this->loginUrl = $loginUrl;
49-
50-
if ($loginProviderClassName != null) {
51-
LoginProvider::setProviderClassName($loginProviderClassName);
44+
if ($loginProviderClassName !== null) {
45+
$this->registerProtectedUrl(new ProtectedUrl(
46+
$urlToProtect,
47+
$loginProviderClassName,
48+
$loginUrl
49+
));
5250
}
5351
}
5452

53+
public function registerProtectedUrl(ProtectedUrl $urlToProtect)
54+
{
55+
$this->protectedUrls[] = $urlToProtect;
56+
}
57+
58+
/** @var ProtectedUrl[] */
59+
private $protectedUrls = [];
60+
5561
public function initialise()
5662
{
57-
SolutionSchema::registerSchema("Authentication", __NAMESPACE__ . '\DatabaseSchema');
63+
SolutionSchema::registerSchema('Authentication', DatabaseSchema::class);
5864
}
5965

6066
protected function registerUrlHandlers()
6167
{
62-
$reset = new LeafCollectionUrlHandler(
63-
__NAMESPACE__ . '\Leaves\ResetPassword',
64-
__NAMESPACE__ . '\Leaves\ConfirmResetPassword');
65-
66-
$login = new ClassMappedUrlHandler(__NAMESPACE__ . '\Leaves\Login', [
67-
"reset/" => $reset
68-
]);
69-
70-
$login->setName("login");
71-
72-
$validateLoginUrlHandler = new ValidateLoginUrlHandler(LoginProvider::getProvider(), $this->loginUrl);
73-
74-
$this->addUrlHandlers(
75-
[
76-
$this->loginUrl => $login,
77-
$this->urlToProtect => $validateLoginUrlHandler
68+
foreach ($this->protectedUrls as $url) {
69+
70+
$provider = $url->loginProviderClassName;
71+
72+
$this->addUrlHandlers([
73+
$url->loginUrl => $login = new CallableUrlHandler(function () use ($url) {
74+
$className = $url->loginLeafClassName;
75+
return new $className($url->loginProviderClassName);
76+
}, [
77+
$url->resetChildUrl => $reset = new LeafCollectionUrlHandler(
78+
$url->resetPasswordLeafClassName,
79+
$url->confirmResetPasswordLeafClassName
80+
),
81+
$url->logoutChildUrl => $logout = new CallableUrlHandler(function () use ($url) {
82+
$className = $url->logoutLeafClassName;
83+
return new $className($url->loginProviderClassName);
84+
}),
85+
]),
86+
$url->urlToProtect => $protected =
87+
new ValidateLoginUrlHandler($provider::singleton(), $url->loginUrl),
7888
]);
7989

80-
$logout = new ClassMappedUrlHandler(__NAMESPACE__ . '\Leaves\Logout');
90+
// Make sure that the login url handlers are given greater precedence than those of the application.
91+
$login->setPriority(10);
92+
$login->setName('login');
8193

82-
$logout->setName("logout");
94+
$logout->setPriority(10);
95+
$logout->setName('logout');
8396

84-
$this->addUrlHandlers(
85-
[
86-
"/logout/" => $logout
87-
]);
97+
$reset->setPriority(10);
98+
$reset->setName('reset');
8899

89-
// Make sure that the login url handlers are given greater precedence than those of the application.
90-
$login->setPriority(10);
91-
//$reset->setPriority(10);
92-
$validateLoginUrlHandler->setPriority(10);
100+
$protected->setPriority(10);
101+
}
93102
}
94103

95104
/**

src/DatabaseSchema.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ public function __construct($version = 0.1)
2626
{
2727
parent::__construct($version);
2828

29-
$this->addModel("User", "Rhubarb\Scaffolds\Authentication\User");
29+
$this->addModel('User', User::class);
3030
}
31-
}
31+
}

src/Leaves/Login.php

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,23 @@
2222
use Rhubarb\Crown\LoginProviders\Exceptions\LoginDisabledException;
2323
use Rhubarb\Crown\LoginProviders\Exceptions\LoginFailedException;
2424
use Rhubarb\Crown\LoginProviders\LoginProvider;
25+
use Rhubarb\Crown\Request\Request;
2526
use Rhubarb\Crown\Request\WebRequest;
2627
use Rhubarb\Crown\Response\RedirectResponse;
2728
use Rhubarb\Leaf\Leaves\Leaf;
28-
use Rhubarb\Leaf\Leaves\LeafModel;
2929
use Rhubarb\Scaffolds\Authentication\Settings\AuthenticationSettings;
3030

3131
class Login extends Leaf
3232
{
33-
private $loginProviderClassName = "";
33+
protected $loginProviderClassName = "";
3434

3535
/**
3636
* @var LoginModel
3737
*/
3838
protected $model;
3939

4040
/**
41-
* @param null $loginProviderClassName If not supplied, the default login provider will be used.
42-
* @param string $identityColumnName
41+
* @param string $loginProviderClassName If not supplied, the default login provider will be used.
4342
*/
4443
public function __construct($loginProviderClassName = null)
4544
{
@@ -60,7 +59,7 @@ private function getLoginProvider()
6059
{
6160
$provider = $this->loginProviderClassName;
6261

63-
if ($provider == ""){
62+
if ($provider == "") {
6463
return LoginProvider::getProvider();
6564
}
6665

@@ -85,24 +84,6 @@ protected function getDefaultSuccessUrl()
8584
return "/";
8685
}
8786

88-
/**
89-
* Called just before the view is rendered.
90-
*
91-
* Guaranteed to only be called once during a normal page execution.
92-
*/
93-
protected function beforeRenderView()
94-
{
95-
$login = $this->getLoginProvider();
96-
97-
if (isset($_GET["logout"])) {
98-
$login->logOut();
99-
}
100-
101-
if ( $login->isLoggedIn() ){
102-
$this->onSuccess();
103-
}
104-
}
105-
10687
protected function parseRequest(WebRequest $request)
10788
{
10889
$login = $this->getLoginProvider();
@@ -132,39 +113,52 @@ protected function getViewClass()
132113
/**
133114
* Should return a class that derives from LeafModel
134115
*
135-
* @return LeafModel
116+
* @return LoginModel
136117
*/
137118
protected function createModel()
138119
{
139-
$model = new LoginModel();
120+
return new LoginModel();
121+
}
140122

141-
if (isset($_GET["rd"])) {
142-
$model->redirectUrl = $_GET["rd"];
123+
protected function onModelCreated()
124+
{
125+
/** @var WebRequest $request */
126+
$request = Request::current();
127+
$redirectUrl = $request->get('rd');
128+
if ($redirectUrl) {
129+
$redirectUrl = urldecode($redirectUrl);
130+
$this->model->redirectUrl = $redirectUrl;
143131
}
144132

145-
$model->attemptLoginEvent->attachHandler(
146-
function () {
147-
$login = $this->getLoginProvider();
148-
149-
try {
150-
if ($login->login($this->model->username, $this->model->password)) {
133+
$this->model->attemptLoginEvent->attachHandler(function () {
134+
$login = $this->getLoginProvider();
151135

152-
if ($this->model->rememberMe) {
153-
$login = $this->getLoginProvider();
154-
$login->rememberLogin();
155-
}
136+
try {
137+
if ($login->login($this->model->username, $this->model->password)) {
156138

157-
$this->onSuccess();
139+
if ($this->model->rememberMe) {
140+
$login = $this->getLoginProvider();
141+
$login->rememberLogin();
158142
}
159-
} catch (LoginDisabledException $er) {
160-
$this->model->disabled = true;
161-
$this->model->failed = true;
162-
} catch (LoginFailedException $er) {
163-
$this->model->failed = true;
143+
144+
$this->onSuccess();
164145
}
146+
} catch (LoginDisabledException $er) {
147+
$this->model->disabled = true;
148+
$this->model->failed = true;
149+
} catch (LoginFailedException $er) {
150+
$this->model->failed = true;
165151
}
166-
);
152+
});
153+
}
167154

168-
return $model;
155+
/**
156+
* Allows setting the URL for the forgotten password link on the login form
157+
*
158+
* @param $url
159+
*/
160+
public function setPasswordResetUrl($url)
161+
{
162+
$this->model->passwordResetUrl = $url;
169163
}
170164
}

src/Leaves/LoginModel.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,19 @@ class LoginModel extends LeafModel
4747
*/
4848
public $attemptLoginEvent;
4949

50+
public $passwordResetUrl = '/login/reset/';
51+
5052
public function __construct()
5153
{
5254
parent::__construct();
5355

5456
$this->attemptLoginEvent = new Event();
5557
}
5658

57-
5859
protected function getExposableModelProperties()
5960
{
6061
$list = parent::getExposableModelProperties();
61-
$list[] = "RedirectUrl";
62+
$list[] = 'redirectUrl';
6263

6364
return $list;
6465
}

src/Leaves/LoginView.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public function createSubLeaves()
5050
public function printViewContent()
5151
{
5252
if ($this->model->failed) {
53-
print "<div class='c-alert c-alert--error'>Sorry, this username and password combination could not be found, please check and try again.</div>";
53+
print '<div class="c-alert c-alert--error">Sorry, this username and password combination could not be found, please check and try again.</div>';
5454
}
5555

5656
?>
@@ -66,10 +66,10 @@ public function printViewContent()
6666

6767
<div class="c-form__actions">
6868
<div class="c-form__actions-remember">
69-
<label class="c-form__label c-form__label--checkbox"><?= $this->leaves["rememberMe"] . " Remember Me"; ?></label>
69+
<label class="c-form__label c-form__label--checkbox"><?= $this->leaves["rememberMe"]; ?> Remember Me</label>
7070
</div>
7171
<div class="c-form__actions-forgot">
72-
<a href="/login/reset/">I've forgotten my password.</a>
72+
<a href="<?= $this->model->passwordResetUrl; ?>">I've forgotten my password.</a>
7373
</div>
7474
</div>
7575

src/Leaves/Logout.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
namespace Rhubarb\Scaffolds\Authentication\Leaves;
2020

21-
use Rhubarb\Crown\LoginProviders\LoginProvider;
2221
use Rhubarb\Crown\Request\WebRequest;
2322
use Rhubarb\Leaf\Leaves\Leaf;
2423
use Rhubarb\Leaf\Leaves\LeafModel;
@@ -28,8 +27,8 @@ class Logout extends Leaf
2827
private $loginProviderClassName = "";
2928

3029
/**
31-
* @var LogoutModel
32-
*/
30+
* @var LogoutModel
31+
*/
3332
protected $model;
3433

3534
/**
@@ -59,7 +58,7 @@ protected function getViewClass()
5958
*/
6059
protected function createModel()
6160
{
62-
$model = new LogoutModel();
61+
$model = new LeafModel();
6362

6463
return $model;
6564
}
@@ -69,7 +68,7 @@ protected function parseRequest(WebRequest $request)
6968
$login = $this->getLoginProvider();
7069
$login->logOut();
7170

72-
return parent::parseRequest($request); // TODO: Change the autogenerated stub
71+
return parent::parseRequest($request);
7372
}
7473

7574
/**
@@ -81,10 +80,6 @@ private function getLoginProvider()
8180
{
8281
$provider = $this->loginProviderClassName;
8382

84-
if ($provider == "") {
85-
return LoginProvider::getProvider();
86-
}
87-
8883
return $provider::singleton();
8984
}
9085
}

0 commit comments

Comments
 (0)