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

Commit 8360235

Browse files
committed
Added the support of multiple users
1 parent 9daeef9 commit 8360235

File tree

10 files changed

+120
-11
lines changed

10 files changed

+120
-11
lines changed

src/UserInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function getUsername(): string;
1818
/**
1919
* Get the user role
2020
*
21-
* @return string
21+
* @return array|null
2222
*/
23-
public function getUserRole(): string;
23+
public function getUserRoles(): ?array;
2424
}

src/UserRepository/Htpasswd.php

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

5858
return $found && password_verify($password, $hash) ?
59-
$this->generateUser($credential, '') :
59+
$this->generateUser($credential) :
6060
null;
6161
}
6262

63+
/**
64+
* {@inheritDoc}
65+
*/
66+
public function getRolesFromUser(string $username): ?array
67+
{
68+
return null;
69+
}
70+
6371
/**
6472
* Check bcrypt usage for security reason
6573
*

src/UserRepository/PdoDatabase.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ public function __construct(PDO $pdo, array $config)
3737
public function authenticate(string $credential, string $password = null): ?UserInterface
3838
{
3939
$sql = sprintf(
40-
"SELECT * FROM %s WHERE %s = :username",
40+
"SELECT %s FROM %s WHERE %s = :username",
41+
$this->config['field']['password'],
4142
$this->config['table'],
4243
$this->config['field']['username']
4344
);
@@ -49,7 +50,32 @@ public function authenticate(string $credential, string $password = null): ?User
4950
$result = $stmt->fetchObject();
5051

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

src/UserRepository/UserTrait.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ trait UserTrait
1818
* @param string $role
1919
* @return UserInterface
2020
*/
21-
protected function generateUser(string $username, string $role): UserInterface
21+
protected function generateUser(string $username, ?array $roles = null): UserInterface
2222
{
23-
return new class($username, $role) implements UserInterface {
24-
public function __construct($username, $role)
23+
return new class($username, $roles) implements UserInterface {
24+
public function __construct(string $username, $roles)
2525
{
2626
$this->username = $username;
27-
$this->role = $role;
27+
$this->roles = $roles;
2828
}
2929

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

35-
public function getUserRole(): string
35+
public function getUserRoles(): ?array
3636
{
37-
return $this->role;
37+
return $this->roles;
3838
}
3939
};
4040
}

src/UserRepositoryInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ interface UserRepositoryInterface
1818
* @return UserInterface|null
1919
*/
2020
public function authenticate(string $credential, string $password = null): ?UserInterface;
21+
22+
/**
23+
* Get the user roles if present
24+
*
25+
* @param string $username
26+
* @return array|null
27+
*/
28+
public function getRolesFromUser(string $username): ?array;
2129
}

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)