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

Commit ef23c49

Browse files
committed
Merge pull request #4 from ezimuel/feature/multiple-users
[BC break] Added the support of multiple users Conflicts: src/UserInterface.php src/UserRepository/PdoDatabase.php src/UserRepository/UserTrait.php src/UserRepositoryInterface.php
2 parents a4bbfc7 + 8360235 commit ef23c49

File tree

10 files changed

+124
-13
lines changed

10 files changed

+124
-13
lines changed

src/UserInterface.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ interface UserInterface
1414
public function getUsername() : string;
1515

1616
/**
17-
* Get the user role
17+
* Get all user roles
18+
*
19+
* @return string[]|null
1820
*/
19-
public function getUserRole() : string;
21+
public function getUserRoles() : ?array;
2022
}

src/UserRepository/Htpasswd.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,18 @@ public function authenticate(string $credential, string $password = null) : ?Use
5959
fclose($handle);
6060

6161
return $found && password_verify($password, $hash) ?
62-
$this->generateUser($credential, '') :
62+
$this->generateUser($credential) :
6363
null;
6464
}
6565

66+
/**
67+
* {@inheritDoc}
68+
*/
69+
public function getRolesFromUser(string $username): ?array
70+
{
71+
return null;
72+
}
73+
6674
/**
6775
* Check bcrypt usage for security reason
6876
*

src/UserRepository/PdoDatabase.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public function __construct(PDO $pdo, array $config)
4141
public function authenticate(string $credential, string $password = null) : ?UserInterface
4242
{
4343
$sql = sprintf(
44-
'SELECT * FROM %s WHERE %s = :username',
44+
"SELECT %s FROM %s WHERE %s = :username",
45+
$this->config['field']['password'],
4546
$this->config['table'],
4647
$this->config['field']['username']
4748
);
@@ -53,7 +54,32 @@ public function authenticate(string $credential, string $password = null) : ?Use
5354
$result = $stmt->fetchObject();
5455

5556
return password_verify($password, $result->{$this->config['field']['password']}) ?
56-
$this->generateUser($credential, $this->config['field']['role'] ?? '') :
57+
$this->generateUser($credential, $this->getRolesFromUser($credential)) :
5758
null;
5859
}
60+
61+
/**
62+
* {@inheritDoc}
63+
*/
64+
public function getRolesFromUser(string $username): ?array
65+
{
66+
if (! isset($this->config['sql_get_roles'])) {
67+
return null;
68+
}
69+
if (false === strpos($this->config['sql_get_roles'], ':username')) {
70+
throw new Exception\InvalidConfigException(
71+
'The sql_get_roles must include a :username parameter'
72+
);
73+
}
74+
$stmt = $this->pdo->prepare($this->config['sql_get_roles']);
75+
$stmt->bindParam(':username', $username);
76+
if (! $stmt->execute()) {
77+
return null;
78+
}
79+
$roles = [];
80+
foreach ($stmt->fetchAll(PDO::FETCH_NUM) as $role) {
81+
$roles[] = $role[0];
82+
}
83+
return $roles;
84+
}
5985
}

src/UserRepository/UserTrait.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,28 @@
1212
trait UserTrait
1313
{
1414
/**
15-
* Generate a user from $username and $role
15+
* Generate a user from username and list of roles
1616
*/
17-
protected function generateUser(string $username, string $role) : UserInterface
17+
protected function generateUser(string $username, ?array $roles = null) : UserInterface
1818
{
19-
return new class($username, $role) implements UserInterface {
19+
return new class($username, $roles) implements UserInterface {
2020
private $username;
21-
private $role;
21+
private $roles;
2222

23-
public function __construct($username, $role)
23+
public function __construct(string $username, $roles)
2424
{
2525
$this->username = $username;
26-
$this->role = $role;
26+
$this->roles = $roles;
2727
}
2828

2929
public function getUsername() : string
3030
{
3131
return $this->username;
3232
}
3333

34-
public function getUserRole() : string
34+
public function getUserRoles() : ?array
3535
{
36-
return $this->role;
36+
return $this->roles;
3737
}
3838
};
3939
}

src/UserRepositoryInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,12 @@ interface UserRepositoryInterface
1616
* @param string $credential can be also a token
1717
*/
1818
public function authenticate(string $credential, string $password = null) : ?UserInterface;
19+
20+
/**
21+
* Get the user roles if present.
22+
*
23+
* @param string $username
24+
* @return string[]|null
25+
*/
26+
public function getRolesFromUser(string $username) : ?array;
1927
}

test/TestAssets/pdo_role.sqlite

2 KB
Binary file not shown.

test/TestAssets/pdo_roles.sqlite

4 KB
Binary file not shown.

test/TestAssets/sqlite_with_role.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE TABLE user(
2+
username TEXT,
3+
password TEXT,
4+
role TEXT
5+
);
6+
7+
INSERT INTO user (username, password, role) VALUES ('test', '$2y$10$C822kPutHb8S/An9pBzJHeaN2/uqytA88O5VtTaY9m9EzWCJPDF7e', 'admin');

test/TestAssets/sqlite_with_roles.sql

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
CREATE TABLE user(
2+
username TEXT,
3+
password TEXT
4+
);
5+
6+
CREATE TABLE role(
7+
role TEXT
8+
);
9+
10+
CREATE TABLE user_role(
11+
username TEXT,
12+
role TEXT
13+
);
14+
15+
INSERT INTO user (username, password) VALUES
16+
('test', '$2y$10$C822kPutHb8S/An9pBzJHeaN2/uqytA88O5VtTaY9m9EzWCJPDF7e');
17+
18+
INSERT INTO role (role) VALUES
19+
('user'),
20+
('admin');
21+
22+
INSERT INTO user_role (username, role) VALUES
23+
('test', 'user'),
24+
('test', 'admin');

test/UserRepository/PdoDatabaseTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,40 @@ public function testAuthenticateInvalidUser()
5050
$user = $pdoDatabase->authenticate('test', 'foo');
5151
$this->assertNull($user);
5252
}
53+
54+
public function testAuthenticateWithRole()
55+
{
56+
$pdo = new PDO('sqlite:'. __DIR__ . '/../TestAssets/pdo_role.sqlite');
57+
$pdoDatabase = new PdoDatabase($pdo, [
58+
'table' => 'user',
59+
'field' => [
60+
'username' => 'username',
61+
'password' => 'password'
62+
],
63+
'sql_get_roles' => 'SELECT role FROM user WHERE username = :username'
64+
]);
65+
66+
$user = $pdoDatabase->authenticate('test', 'password');
67+
$this->assertInstanceOf(UserInterface::class, $user);
68+
$this->assertEquals('test', $user->getUsername());
69+
$this->assertEquals(['admin'], $user->getUserRoles());
70+
}
71+
72+
public function testAuthenticateWithRoles()
73+
{
74+
$pdo = new PDO('sqlite:'. __DIR__ . '/../TestAssets/pdo_roles.sqlite');
75+
$pdoDatabase = new PdoDatabase($pdo, [
76+
'table' => 'user',
77+
'field' => [
78+
'username' => 'username',
79+
'password' => 'password'
80+
],
81+
'sql_get_roles' => 'SELECT role FROM user_role WHERE username = :username'
82+
]);
83+
84+
$user = $pdoDatabase->authenticate('test', 'password');
85+
$this->assertInstanceOf(UserInterface::class, $user);
86+
$this->assertEquals('test', $user->getUsername());
87+
$this->assertEquals(['user', 'admin'], $user->getUserRoles());
88+
}
5389
}

0 commit comments

Comments
 (0)