Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit e5cdee5

Browse files
committed
Changed the UserRepositoryInterface and refactored the user's factory
1 parent 2da5809 commit e5cdee5

13 files changed

+225
-88
lines changed

docs/book/v1/intro.md

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ authorization level of a user (for this scope, it is consumed by
4343
## Default User class
4444

4545
We provide a default implementation of `UserInterface` via the class `Zend\Expressive\Authentication\DefaultUser`.
46-
This class is a basic implementation of `UserInterface`. This class is final and
47-
it's immutable, that means you cannot change it state at runtime.
46+
The class is final and immutable, in order to prevent runtime changes.
47+
We provide a factory class for generating `DefaultUser` instances via
48+
`Zend\Expressive\Authentication\DefaultUserFactory`.
49+
4850
In order to set the identity and the user's role we provided a default factory
4951
class that generates a `UserInterface` object. This factory is
5052
`Zend\Expressive\Authentication\UserInterfaceFactory`. This class uses a `generate`
@@ -56,19 +58,16 @@ If you want, you can customize the `UserInterfaceFactory` using your custom
5658
follows:
5759

5860
```php
59-
// src/ConfigProvider.php
61+
return [
6062
// ...
61-
public function getDependencies() : array
62-
{
63-
return [
63+
'dependencies' => [
64+
'factories' => [
6465
// ...
65-
'factories' => [
66-
// here change the UserInterfaceFactory::class with your class
67-
UserInterface::class => UserInterfaceFactory::class
68-
]
69-
];
70-
}
71-
// ...
66+
// change the DefaultUserFactory::class with your custom factory
67+
UserInterface::class => DefaultUserFactory::class
68+
]
69+
]
70+
];
7271
```
7372

7473
## Usage in the route
@@ -104,18 +103,16 @@ Basic Access Authentication* adapter and the *htpasswd* file as the user
104103
repository.
105104

106105
```php
107-
// src/ConfigProvider.php
106+
return [
108107
// ...
109-
public function getDependencies() : array
110-
{
111-
return [
108+
'dependencies' => [
109+
// ...
110+
'aliases' => [
112111
// ...
113-
'aliases' => [
114-
// ...
115-
AuthenticationInterface::class => Basic\BasicAccess::class,
116-
UserRepositoryInterface::class => UserRepository\Htpasswd::class
117-
]
118-
];
119-
}
120-
// ...
112+
AuthenticationInterface::class => Basic\BasicAccess::class,
113+
UserRepositoryInterface::class => UserRepository\Htpasswd::class
114+
]
115+
]
116+
];
117+
121118
```

docs/book/v1/user-repository.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,30 @@ interface UserRepositoryInterface
3131
* @param string $username
3232
* @return string[]
3333
*/
34-
public function getRolesFromUser(string $username) : array;
34+
public function getUserRoles(string $username) : array;
35+
36+
/**
37+
* Get the user details if present.
38+
*
39+
* @param string $identity
40+
* @return string[]
41+
*/
42+
public function getUserDetails(string $identity) : array;
3543
}
3644
```
3745

38-
It contains two functions: `authenticate()` and `getRolesFromUser()`. The first
39-
is used to authenticate using the user's credential. If authenticated, the
40-
result will be a `UserInterface` instance, otherwise a null value is returned.
46+
It contains 3 functions: `authenticate()`, `getUserRoles()`, and `getUserDetails`.
47+
The first function is used to authenticate the user's credential. If
48+
authenticated, the result will be a `UserInterface` instance, otherwise a null
49+
value is returned.
4150

42-
The second function is `getRolesFromUser()` and it specifies how to retrieve
51+
The second function is `getUserRoles()` and it specifies how to retrieve
4352
the roles for a user. If a user does not have roles, this function will return
4453
an empty array.
4554

55+
The last function is `getUserDetails()` and it specifies the additional user
56+
information (details), if any.
57+
4658

4759
## Configure the user repository
4860

@@ -93,7 +105,8 @@ return [
93105
'identity' => 'identity field name',
94106
'password' => 'password field name',
95107
],
96-
'sql_get_roles' => 'SQL to retrieve roles with :identity parameter',
108+
'sql_get_roles' => 'SQL to retrieve roles with :identity parameter',
109+
'sql_get_details' => 'SQL to retrieve user details by :identity'
97110
],
98111
],
99112
];
@@ -121,3 +134,6 @@ typical query might look like the following:
121134
```sql
122135
SELECT role FROM user WHERE username = :identity
123136
```
137+
138+
The `sql_get_details` parameter is similar to `sql_get_roles`, it specified the
139+
SQL query for retrieving the user's additional details, if any.

src/ConfigProvider.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public function getAuthenticationConfig() : array
4141
* 'identity' => 'identity field name',
4242
* 'password' => 'password field name',
4343
* ],
44-
* 'sql_get_roles' => 'SQL to retrieve roles by :identity',
44+
* 'sql_get_roles' => 'SQL to retrieve user roles by :identity',
45+
* 'sql_get_details' => 'SQL to retrieve user details by :identity'
4546
* ],
4647
* ]
4748
*/
@@ -64,7 +65,7 @@ public function getDependencies() : array
6465
AuthenticationMiddleware::class => AuthenticationMiddlewareFactory::class,
6566
UserRepository\Htpasswd::class => UserRepository\HtpasswdFactory::class,
6667
UserRepository\PdoDatabase::class => UserRepository\PdoDatabaseFactory::class,
67-
UserInterface::class => UserInterfaceFactory::class
68+
UserInterface::class => DefaultUserFactory::class
6869
]
6970
];
7071
}

src/DefaultUser.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ final class DefaultUser implements UserInterface
1515

1616
private $roles;
1717

18-
public function __construct(string $identity, array $roles = [])
18+
private $details;
19+
20+
public function __construct(string $identity, array $roles = [], array $details = [])
1921
{
2022
$this->identity = $identity;
2123
$this->roles = $roles;
24+
$this->details = $details;
2225
}
2326

2427
public function getIdentity() : string
@@ -30,4 +33,14 @@ public function getRoles() : array
3033
{
3134
return $this->roles;
3235
}
36+
37+
public function getDetails() : array
38+
{
39+
return $this->details;
40+
}
41+
42+
public function getDetail(string $name, $default = null)
43+
{
44+
return $this->details[$name] ?? $default;
45+
}
3346
}

src/UserInterfaceFactory.php renamed to src/DefaultUserFactory.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111

1212
use Psr\Container\ContainerInterface;
1313

14-
class UserInterfaceFactory
14+
class DefaultUserFactory
1515
{
16-
public function generate(string $identity, array $roles = []) : UserInterface
16+
public function __invoke(ContainerInterface $container) : callable
1717
{
18-
return new DefaultUser($identity, $roles);
18+
return function (string $identity, array $roles = [], array $details = []) {
19+
return new DefaultUser($identity, $roles, $details);
20+
};
1921
}
2022
}

src/UserInterface.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,14 @@ public function getIdentity() : string;
2222
* @return string[]
2323
*/
2424
public function getRoles() : array;
25+
26+
/**
27+
* Get a detail $name if present, $default otherwise
28+
*/
29+
public function getDetail(string $name, $default = null);
30+
31+
/**
32+
* Get all the details, if any
33+
*/
34+
public function getDetails() : array;
2535
}

src/UserRepository/Htpasswd.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
use Zend\Expressive\Authentication\Exception;
1313
use Zend\Expressive\Authentication\UserInterface;
14-
use Zend\Expressive\Authentication\UserInterfaceFactory;
1514
use Zend\Expressive\Authentication\UserRepositoryInterface;
1615

1716
/**
@@ -27,14 +26,14 @@ class Htpasswd implements UserRepositoryInterface
2726
private $filename;
2827

2928
/**
30-
* @var UserInterfaceFactory
29+
* @var callable
3130
*/
3231
private $userFactory;
3332

3433
/**
3534
* @throws Exception\InvalidConfigException
3635
*/
37-
public function __construct(string $filename, UserInterfaceFactory $userFactory)
36+
public function __construct(string $filename, callable $userFactory)
3837
{
3938
if (! file_exists($filename)) {
4039
throw new Exception\InvalidConfigException(sprintf(
@@ -67,15 +66,23 @@ public function authenticate(string $credential, string $password = null) : ?Use
6766
fclose($handle);
6867

6968
if ($found && password_verify($password ?? '', $hash)) {
70-
return $this->userFactory->generate($credential, $this->getRolesFromUser($credential));
69+
return ($this->userFactory)($credential);
7170
}
7271
return null;
7372
}
7473

7574
/**
7675
* {@inheritDoc}
7776
*/
78-
public function getRolesFromUser(string $identity) : array
77+
public function getUserRoles(string $identity) : array
78+
{
79+
return [];
80+
}
81+
82+
/**
83+
* {@inheritDoc}
84+
*/
85+
public function getUserDetails(string $identity) : array
7986
{
8087
return [];
8188
}

src/UserRepository/PdoDatabase.php

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
use PDOException;
1414
use Zend\Expressive\Authentication\Exception;
1515
use Zend\Expressive\Authentication\UserInterface;
16-
use Zend\Expressive\Authentication\UserInterfaceFactory;
1716
use Zend\Expressive\Authentication\UserRepositoryInterface;
1817

1918
/**
@@ -33,14 +32,14 @@ class PdoDatabase implements UserRepositoryInterface
3332
private $config;
3433

3534
/**
36-
* @var UserInterfaceFactory
35+
* @var callable
3736
*/
3837
private $userFactory;
3938

4039
public function __construct(
4140
PDO $pdo,
4241
array $config,
43-
UserInterfaceFactory $userFactory
42+
callable $userFactory
4443
) {
4544
$this->pdo = $pdo;
4645
$this->config = $config;
@@ -75,9 +74,10 @@ public function authenticate(string $credential, string $password = null) : ?Use
7574
}
7675

7776
if (password_verify($password, $result->{$this->config['field']['password']})) {
78-
return $this->userFactory->generate(
77+
return ($this->userFactory)(
7978
$credential,
80-
$this->getRolesFromUser($credential)
79+
$this->getUserRoles($credential),
80+
$this->getUserDetails($credential)
8181
);
8282
}
8383
return null;
@@ -86,7 +86,7 @@ public function authenticate(string $credential, string $password = null) : ?Use
8686
/**
8787
* {@inheritDoc}
8888
*/
89-
public function getRolesFromUser(string $identity) : array
89+
public function getUserRoles(string $identity) : array
9090
{
9191
if (! isset($this->config['sql_get_roles'])) {
9292
return [];
@@ -123,4 +123,42 @@ public function getRolesFromUser(string $identity) : array
123123
}
124124
return $roles;
125125
}
126+
127+
public function getUserDetails(string $identity) : array
128+
{
129+
if (! isset($this->config['sql_get_details'])) {
130+
return [];
131+
}
132+
133+
if (false === strpos($this->config['sql_get_details'], ':identity')) {
134+
throw new Exception\InvalidConfigException(
135+
'The sql_get_details configuration setting must include a :identity parameter'
136+
);
137+
}
138+
139+
try {
140+
$stmt = $this->pdo->prepare($this->config['sql_get_details']);
141+
} catch (PDOException $e) {
142+
throw new Exception\RuntimeException(sprintf(
143+
'Error preparing retrieval of user details: %s',
144+
$e->getMessage()
145+
));
146+
}
147+
if (false === $stmt) {
148+
throw new Exception\RuntimeException(sprintf(
149+
'Error preparing retrieval of user details: unknown error'
150+
));
151+
}
152+
$stmt->bindParam(':identity', $identity);
153+
154+
if (! $stmt->execute()) {
155+
return [];
156+
}
157+
158+
$details = [];
159+
foreach ($stmt->fetchAll(PDO::FETCH_NUM) as $detail) {
160+
$details[] = $detail[0];
161+
}
162+
return $details;
163+
}
126164
}

src/UserRepositoryInterface.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,13 @@ public function authenticate(string $credential, string $password = null) : ?Use
2626
* @param string $identity
2727
* @return string[]
2828
*/
29-
public function getRolesFromUser(string $identity) : array;
29+
public function getUserRoles(string $identity) : array;
30+
31+
/**
32+
* Get the user details if present.
33+
*
34+
* @param string $identity
35+
* @return string[]
36+
*/
37+
public function getUserDetails(string $identity) : array;
3038
}

0 commit comments

Comments
 (0)