diff --git a/src/Administration.php b/src/Administration.php index 10435cc..7244b8d 100644 --- a/src/Administration.php +++ b/src/Administration.php @@ -20,9 +20,10 @@ final class Administration extends UserManager { * @internal * * @param PdoDatabase $databaseConnection the database connection to operate on + * @param string|null $dbTablePrefix (optional) the prefix for the names of all database tables used by this component */ - public function __construct(PdoDatabase $databaseConnection) { - parent::__construct($databaseConnection); + public function __construct(PdoDatabase $databaseConnection, $dbTablePrefix = null) { + parent::__construct($databaseConnection, $dbTablePrefix); } /** @@ -274,7 +275,7 @@ final class Administration extends UserManager { $role = (int) $role; $rolesBitmask = $this->db->selectValue( - 'SELECT roles_mask FROM users WHERE id = ?', + 'SELECT roles_mask FROM ' . $this->dbTablePrefix . 'users WHERE id = ?', [ $userId ] ); @@ -302,7 +303,7 @@ final class Administration extends UserManager { private function deleteUsersByColumnValue($columnName, $columnValue) { try { return $this->db->delete( - 'users', + $this->dbTablePrefix . 'users', [ $columnName => $columnValue ] @@ -329,7 +330,7 @@ final class Administration extends UserManager { private function modifyRolesForUserByColumnValue($columnName, $columnValue, callable $modification) { try { $userData = $this->db->selectRow( - 'SELECT id, roles_mask FROM users WHERE ' . $columnName . ' = ?', + 'SELECT id, roles_mask FROM ' . $this->dbTablePrefix . 'users WHERE ' . $columnName . ' = ?', [ $columnValue ] ); } @@ -345,7 +346,7 @@ final class Administration extends UserManager { try { $this->db->exec( - 'UPDATE users SET roles_mask = ? WHERE id = ?', + 'UPDATE ' . $this->dbTablePrefix . 'users SET roles_mask = ? WHERE id = ?', [ $newRolesBitmask, (int) $userData['id'] diff --git a/src/Auth.php b/src/Auth.php index c11b79d..1e20bed 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -49,9 +49,10 @@ final class Auth extends UserManager { * @param bool $useHttps whether HTTPS (TLS/SSL) will be used (recommended) * @param bool $allowCookiesScriptAccess whether cookies should be accessible via client-side scripts (*not* recommended) * @param string $ipAddress the IP address that should be used instead of the default setting (if any), e.g. when behind a proxy + * @param string|null $dbTablePrefix (optional) the prefix for the names of all database tables used by this component */ - public function __construct($databaseConnection, $useHttps = false, $allowCookiesScriptAccess = false, $ipAddress = null) { - parent::__construct($databaseConnection); + public function __construct($databaseConnection, $useHttps = false, $allowCookiesScriptAccess = false, $ipAddress = null, $dbTablePrefix = null) { + parent::__construct($databaseConnection, $dbTablePrefix); $this->useHttps = $useHttps; $this->allowCookiesScriptAccess = $allowCookiesScriptAccess; @@ -114,7 +115,7 @@ final class Auth extends UserManager { if (isset($parts[0]) && isset($parts[1])) { try { $rememberData = $this->db->selectRow( - 'SELECT a.user, a.token, a.expires, b.email, b.username, b.status, b.roles_mask FROM users_remembered AS a JOIN users AS b ON a.user = b.id WHERE a.selector = ?', + 'SELECT a.user, a.token, a.expires, b.email, b.username, b.status, b.roles_mask FROM ' . $this->dbTablePrefix . 'users_remembered AS a JOIN ' . $this->dbTablePrefix . 'users AS b ON a.user = b.id WHERE a.selector = ?', [ $parts[0] ] ); } @@ -247,7 +248,7 @@ final class Auth extends UserManager { try { $this->db->insert( - 'users_remembered', + $this->dbTablePrefix . 'users_remembered', [ 'user' => $userId, 'selector' => $selector, @@ -272,7 +273,7 @@ final class Auth extends UserManager { private function deleteRememberDirective($userId) { try { $this->db->delete( - 'users_remembered', + $this->dbTablePrefix . 'users_remembered', [ 'user' => $userId ] ); } @@ -341,7 +342,7 @@ final class Auth extends UserManager { private function onLoginSuccessful($userId, $email, $username, $status, $roles, $remembered) { try { $this->db->update( - 'users', + $this->dbTablePrefix . 'users', [ 'last_login' => time() ], [ 'id' => $userId ] ); @@ -433,7 +434,7 @@ final class Auth extends UserManager { try { $confirmationData = $this->db->selectRow( - 'SELECT id, email, token, expires FROM users_confirmations WHERE selector = ?', + 'SELECT id, email, token, expires FROM ' . $this->dbTablePrefix . 'users_confirmations WHERE selector = ?', [ $selector ] ); } @@ -446,7 +447,7 @@ final class Auth extends UserManager { if ($confirmationData['expires'] >= time()) { try { $this->db->update( - 'users', + $this->dbTablePrefix . 'users', [ 'verified' => 1 ], [ 'email' => $confirmationData['email'] ] ); @@ -457,7 +458,7 @@ final class Auth extends UserManager { try { $this->db->delete( - 'users_confirmations', + $this->dbTablePrefix . 'users_confirmations', [ 'id' => $confirmationData['id'] ] ); } @@ -496,7 +497,7 @@ final class Auth extends UserManager { try { $passwordInDatabase = $this->db->selectValue( - 'SELECT password FROM users WHERE id = ?', + 'SELECT password FROM ' . $this->dbTablePrefix . 'users WHERE id = ?', [ $userId ] ); } @@ -537,7 +538,7 @@ final class Auth extends UserManager { try { $this->db->update( - 'users', + $this->dbTablePrefix . 'users', [ 'password' => $newPassword ], [ 'id' => $userId ] ); @@ -745,7 +746,7 @@ final class Auth extends UserManager { try { $projection = implode(', ', $requestedColumns); $userData = $this->db->selectRow( - 'SELECT ' . $projection . ' FROM users WHERE email = ?', + 'SELECT ' . $projection . ' FROM ' . $this->dbTablePrefix . 'users WHERE email = ?', [ $email ] ); } @@ -771,7 +772,7 @@ final class Auth extends UserManager { private function getOpenPasswordResetRequests($userId) { try { $requests = $this->db->selectValue( - 'SELECT COUNT(*) FROM users_resets WHERE user = ? AND expires > ?', + 'SELECT COUNT(*) FROM ' . $this->dbTablePrefix . 'users_resets WHERE user = ? AND expires > ?', [ $userId, time() @@ -814,7 +815,7 @@ final class Auth extends UserManager { try { $this->db->insert( - 'users_resets', + $this->dbTablePrefix . 'users_resets', [ 'user' => $userId, 'selector' => $selector, @@ -855,7 +856,7 @@ final class Auth extends UserManager { try { $resetData = $this->db->selectRow( - 'SELECT id, user, token, expires FROM users_resets WHERE selector = ?', + 'SELECT id, user, token, expires FROM ' . $this->dbTablePrefix . 'users_resets WHERE selector = ?', [ $selector ] ); } @@ -876,7 +877,7 @@ final class Auth extends UserManager { try { $this->db->delete( - 'users_resets', + $this->dbTablePrefix . 'users_resets', [ 'id' => $resetData['id'] ] ); } @@ -1260,7 +1261,7 @@ final class Auth extends UserManager { try { $this->db->insert( - 'users_throttling', + $this->dbTablePrefix . 'users_throttling', [ 'action_type' => $actionType, 'selector' => $selector, @@ -1273,7 +1274,7 @@ final class Auth extends UserManager { // if we have a duplicate entry, update the old entry try { $this->db->exec( - 'UPDATE users_throttling SET attempts = attempts+1 WHERE action_type = ? AND selector = ? AND time_bucket = ?', + 'UPDATE ' . $this->dbTablePrefix . 'users_throttling SET attempts = attempts+1 WHERE action_type = ? AND selector = ? AND time_bucket = ?', [ $actionType, $selector, @@ -1291,7 +1292,7 @@ final class Auth extends UserManager { try { $attempts = $this->db->selectValue( - 'SELECT attempts FROM users_throttling WHERE action_type = ? AND selector = ? AND time_bucket = ?', + 'SELECT attempts FROM ' . $this->dbTablePrefix . 'users_throttling WHERE action_type = ? AND selector = ? AND time_bucket = ?', [ $actionType, $selector, @@ -1354,7 +1355,7 @@ final class Auth extends UserManager { * @return Administration */ public function admin() { - return new Administration($this->db); + return new Administration($this->db, $this->dbTablePrefix); } /** diff --git a/src/UserManager.php b/src/UserManager.php index 41c1daf..3ad516c 100644 --- a/src/UserManager.php +++ b/src/UserManager.php @@ -29,6 +29,8 @@ abstract class UserManager { /** @var PdoDatabase the database connection to operate on */ protected $db; + /** @var string the prefix for the names of all database tables used by this component */ + protected $dbTablePrefix; /** * Creates a random string with the given maximum length @@ -51,8 +53,9 @@ abstract class UserManager { /** * @param PdoDatabase|PdoDsn|\PDO $databaseConnection the database connection to operate on + * @param string|null $dbTablePrefix (optional) the prefix for the names of all database tables used by this component */ - protected function __construct($databaseConnection) { + protected function __construct($databaseConnection, $dbTablePrefix = null) { if ($databaseConnection instanceof PdoDatabase) { $this->db = $databaseConnection; } @@ -67,6 +70,8 @@ abstract class UserManager { throw new \InvalidArgumentException('The database connection must be an instance of either `PdoDatabase`, `PdoDsn` or `PDO`'); } + + $this->dbTablePrefix = (string) $dbTablePrefix; } /** @@ -118,7 +123,7 @@ abstract class UserManager { if ($username !== null) { // count the number of users who do already have that specified username $occurrencesOfUsername = $this->db->selectValue( - 'SELECT COUNT(*) FROM users WHERE username = ?', + 'SELECT COUNT(*) FROM ' . $this->dbTablePrefix . 'users WHERE username = ?', [ $username ] ); @@ -135,7 +140,7 @@ abstract class UserManager { try { $this->db->insert( - 'users', + $this->dbTablePrefix . 'users', [ 'email' => $email, 'password' => $password, @@ -179,7 +184,7 @@ abstract class UserManager { $projection = implode(', ', $requestedColumns); $users = $this->db->select( - 'SELECT ' . $projection . ' FROM users WHERE username = ? LIMIT 0, 2', + 'SELECT ' . $projection . ' FROM ' . $this->dbTablePrefix . 'users WHERE username = ? LIMIT 0, 2', [ $username ] ); } @@ -277,7 +282,7 @@ abstract class UserManager { try { $this->db->insert( - 'users_confirmations', + $this->dbTablePrefix . 'users_confirmations', [ 'email' => $email, 'selector' => $selector,