Skip to content

Commit 3c07f08

Browse files
committed
Merge branch 'develop'
2 parents 00e15c7 + 6ddb729 commit 3c07f08

File tree

7 files changed

+171
-30
lines changed

7 files changed

+171
-30
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"rhubarbphp/rhubarb": "*"
1717
},
1818
"require-dev": {
19-
"phpunit/phpunit": "3.*"
19+
"phpunit/phpunit": "4.*",
20+
"codeception/codeception": "*"
2021
}
2122
}
2223

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* Copyright 2015 RhubarbPHP
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace Rhubarb\Scaffolds\TokenBasedRestApi\Authentication\LoginProviderBasedAuthenticationProviders;
20+
21+
use Rhubarb\RestApi\Authentication\ModelLoginProviderAuthenticationProvider;
22+
use Rhubarb\Scaffolds\Authentication\LoginProviders\LoginProvider;
23+
24+
class LoginProviderCredentialsAuthenticationProvider extends ModelLoginProviderAuthenticationProvider
25+
{
26+
protected function getLoginProviderClassName()
27+
{
28+
return LoginProvider::class;
29+
}
30+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* Copyright 2015 RhubarbPHP
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace Rhubarb\Scaffolds\TokenBasedRestApi\Authentication\LoginProviderBasedAuthenticationProviders;
20+
21+
use Rhubarb\Crown\LoginProviders\LoginProvider;
22+
use Rhubarb\Scaffolds\TokenBasedRestApi\Authentication\TokenAuthenticationProvider;
23+
use Rhubarb\Stem\Models\Model;
24+
25+
class LoginProviderTokenAuthenticationProvider extends TokenAuthenticationProvider
26+
{
27+
protected function logUserIn(Model $user)
28+
{
29+
$loginProvider = LoginProvider::getProvider();
30+
$loginProvider->forceLogin($user);
31+
}
32+
}

src/Model/ApiToken.php

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,34 @@
1919
namespace Rhubarb\Scaffolds\TokenBasedRestApi\Model;
2020

2121
use Rhubarb\Scaffolds\TokenBasedRestApi\Exceptions\TokenInvalidException;
22+
use Rhubarb\Stem\Exceptions\RecordNotFoundException;
2223
use Rhubarb\Stem\Filters\AndGroup;
2324
use Rhubarb\Stem\Filters\Equals;
2425
use Rhubarb\Stem\Filters\GreaterThan;
2526
use Rhubarb\Stem\Models\Model;
2627
use Rhubarb\Stem\Models\Validation\HasValue;
2728
use Rhubarb\Stem\Models\Validation\Validator;
28-
use Rhubarb\Stem\Repositories\MySql\Schema\Columns\AutoIncrement;
29-
use Rhubarb\Stem\Repositories\MySql\Schema\Columns\DateTime;
30-
use Rhubarb\Stem\Repositories\MySql\Schema\Columns\ForeignKey;
31-
use Rhubarb\Stem\Repositories\MySql\Schema\Columns\Varchar;
32-
use Rhubarb\Stem\Repositories\MySql\Schema\Index;
33-
use Rhubarb\Stem\Repositories\MySql\Schema\MySqlSchema;
29+
use Rhubarb\Stem\Schema\Columns\AutoIncrementColumn;
30+
use Rhubarb\Stem\Schema\Columns\DateTimeColumn;
31+
use Rhubarb\Stem\Schema\Columns\ForeignKeyColumn;
32+
use Rhubarb\Stem\Schema\Columns\StringColumn;
33+
use Rhubarb\Stem\Schema\Index;
34+
use Rhubarb\Stem\Schema\ModelSchema;
3435

3536
class ApiToken extends Model
3637
{
38+
const TOKEN_EXPIRATION = "+1 day";
39+
3740
protected function createSchema()
3841
{
39-
$schema = new MySqlSchema("tblApiToken");
42+
$schema = new ModelSchema("tblApiToken");
4043

4144
$schema->addColumn(
42-
new AutoIncrement("ApiTokenID"),
43-
new ForeignKey("AuthenticatedUserID"),
44-
new Varchar("Token", 100),
45-
new Varchar("IpAddress", 20),
46-
new DateTime("Expires")
45+
new AutoIncrementColumn("ApiTokenID"),
46+
new ForeignKeyColumn("AuthenticatedUserID"),
47+
new StringColumn("Token", 100),
48+
new StringColumn("IpAddress", 20),
49+
new DateTimeColumn("Expires")
4750
);
4851

4952
$schema->labelColumnName = "Token";
@@ -91,6 +94,32 @@ public static function createToken(Model $user, $ipAddress)
9194
return $token;
9295
}
9396

97+
/**
98+
* Looks up an existing valid token for the user at the specified IP address. If none is found, it
99+
* creates a new one.
100+
*
101+
* @param Model $user
102+
* @param string $ipAddress Usually the current HTTP requester's IP, retrieved from $_SERVER[REMOTE_ADDR]
103+
* @return ApiToken
104+
*/
105+
public static function retrieveOrCreateToken(Model $user, $ipAddress)
106+
{
107+
try {
108+
$token = self::findFirst(new AndGroup([
109+
new Equals("AuthenticatedUserID", $user->UniqueIdentifier),
110+
new Equals("IpAddress", $ipAddress),
111+
new GreaterThan("Expires", "now", true)
112+
]));
113+
114+
$token->Expires = self::TOKEN_EXPIRATION;
115+
$token->save();
116+
} catch (RecordNotFoundException $ex) {
117+
$token = self::createToken($user, $ipAddress);
118+
}
119+
120+
return $token;
121+
}
122+
94123
protected function createConsistencyValidator()
95124
{
96125
$validator = new Validator();
@@ -102,9 +131,9 @@ protected function createConsistencyValidator()
102131
protected function beforeSave()
103132
{
104133
if ($this->isNewRecord()) {
105-
$this->Expires = "+1 day";
134+
$this->Expires = self::TOKEN_EXPIRATION;
106135
}
107136

108137
parent::beforeSave();
109138
}
110-
}
139+
}

src/TokenBasedRestApiModule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ class TokenBasedRestApiModule extends Module
3333
private static $authenticationUserModelName = "User";
3434

3535
public function __construct(
36-
$loginProviderAuthenticationProviderClassName,
37-
$tokenAuthenticationProviderClassName,
36+
$loginProviderAuthenticationProviderClassName = '\Rhubarb\Scaffolds\TokenBasedRestApi\Authentication\LoginProviderBasedAuthenticationProviders\LoginProviderCredentialsAuthenticationProvider',
37+
$tokenAuthenticationProviderClassName = '\Rhubarb\Scaffolds\TokenBasedRestApi\Authentication\LoginProviderBasedAuthenticationProviders\LoginProviderTokenAuthenticationProvider',
3838
$apiStubUrl = "/api/",
3939
$authenticationUserModelName = "User",
4040
$tokenResourceClassName = '\Rhubarb\Scaffolds\TokenBasedRestApi\Resources\TokenResource'
@@ -64,7 +64,7 @@ protected function initialise()
6464
SolutionSchema::registerSchema("TokenBasedRestApi",
6565
'\Rhubarb\Scaffolds\TokenBasedRestApi\Model\TokenBasedRestApiSolutionSchema');
6666

67-
AuthenticationProvider::setDefaultAuthenticationProviderClassName($this->tokenAuthenticationProviderClassName);
67+
AuthenticationProvider::setProviderClassName($this->tokenAuthenticationProviderClassName);
6868

6969
$tokenHandler = new TokenCreationUrlHandler($this->loginProviderAuthenticationProviderClassName, [],
7070
$this->tokenResourceClassName);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace Rhubarb\Scaffolds\TokenBasedRestApi\Tests\Fixtures;
4+
5+
use Rhubarb\Crown\Tests\RhubarbTestCase;
6+
use Rhubarb\RestApi\Clients\RestHttpRequest;
7+
use Rhubarb\RestApi\Clients\TokenAuthenticatedRestClient;
8+
9+
abstract class TokenAuthenticatedRestApiClientTestCase extends RhubarbTestCase
10+
{
11+
protected function getApiUri()
12+
{
13+
return "/api";
14+
}
15+
16+
protected function getTokensUri()
17+
{
18+
return "/tokens";
19+
}
20+
21+
abstract protected function getUsername();
22+
23+
abstract protected function getPassword();
24+
25+
protected function getToken()
26+
{
27+
return false;
28+
}
29+
30+
public function makeApiCall($uri, $method = "get", $payload = null)
31+
{
32+
$client = new TokenAuthenticatedRestClient(
33+
$this->getApiUri(),
34+
$this->getUsername(),
35+
$this->getPassword(),
36+
$this->getTokensUri()
37+
);
38+
39+
$token = $this->getToken();
40+
41+
if ($token) {
42+
$client->setToken($token);
43+
}
44+
45+
$request = new RestHttpRequest($uri, $method, $payload);
46+
$response = $client->makeRequest($request);
47+
48+
return $response;
49+
}
50+
}

tests/Model/ApiTokenTest.php

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020

2121
use Rhubarb\Crown\DateTime\RhubarbDateTime;
2222
use Rhubarb\Crown\Tests\RhubarbTestCase;
23+
use Rhubarb\Scaffolds\Authentication\DatabaseSchema;
2324
use Rhubarb\Scaffolds\Authentication\User;
2425
use Rhubarb\Scaffolds\TokenBasedRestApi\Model\ApiToken;
26+
use Rhubarb\Scaffolds\TokenBasedRestApi\Model\TokenBasedRestApiSolutionSchema;
2527
use Rhubarb\Stem\Schema\SolutionSchema;
2628

2729
class ApiTokenTest extends RhubarbTestCase
@@ -30,21 +32,18 @@ public static function setUpBeforeClass()
3032
{
3133
parent::setUpBeforeClass();
3234

33-
SolutionSchema::registerSchema("Authentication",
34-
"\Rhubarb\Scaffolds\Authentication\DatabaseSchema");
35-
SolutionSchema::registerSchema("TokenBasedRestApi",
36-
"\Rhubarb\Scaffolds\TokenBasedRestApi\Model\TokenBasedRestApiSolutionSchema");
37-
SolutionSchema::registerSchema("ApiTokenTest",
38-
"\Rhubarb\Scaffolds\TokenBasedRestApi\Tests\Model\UnitTestTokenBaseRestApiSolutionSchema");
35+
SolutionSchema::registerSchema("Authentication", DatabaseSchema::class);
36+
SolutionSchema::registerSchema("TokenBasedRestApi", TokenBasedRestApiSolutionSchema::class);
37+
SolutionSchema::registerSchema("ApiTokenTest", UnitTestTokenBaseRestApiSolutionSchema::class);
3938
}
4039

4140
public function testTokenGetsExpiry()
4241
{
4342
$token = new ApiToken();
4443
$token->Token = "abc123";
45-
$token->Save();
44+
$token->save();
4645

47-
$this->assertInstanceOf("Rhubarb\Crown\DateTime\RhubarbDateTime", $token->Expires);
46+
$this->assertInstanceOf(RhubarbDateTime::class, $token->Expires);
4847
$this->assertGreaterThanOrEqual(new RhubarbDateTime("+1 day"), $token->Expires);
4948
}
5049

@@ -53,7 +52,7 @@ public function testTokenCreation()
5352
$user = new User();
5453
$user->Username = "billy";
5554
$user->Forename = "bob";
56-
$user->Save();
55+
$user->save();
5756

5857
$token = ApiToken::createToken($user, "127.0.0.5");
5958

@@ -66,7 +65,7 @@ public function testTokenCanBeValidated()
6665
$user = new User();
6766
$user->Username = "billy2";
6867
$user->Forename = "bob2";
69-
$user->Save();
68+
$user->save();
7069

7170
$token = ApiToken::createToken($user, "127.0.0.5");
7271

@@ -88,12 +87,12 @@ protected function defineRelationships()
8887
{
8988
parent::defineRelationships();
9089

91-
$this->DeclareOneToManyRelationships(
90+
$this->declareOneToManyRelationships(
9291
[
9392
"User" =>
9493
[
9594
"Tokens" => "ApiToken.AuthenticatedUserID:AuthenticatedUser"
9695
]
9796
]);
9897
}
99-
}
98+
}

0 commit comments

Comments
 (0)