Merge branch 'develop' into develop-14

This commit is contained in:
Marcin Łojewski
2018-07-09 20:19:50 +02:00
committed by GitHub
58 changed files with 504 additions and 75 deletions

View File

@@ -6,9 +6,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased] ## [Unreleased]
### Added ### Added
- SHA512 Whirlpool hashing algorithm - SHA512 Whirlpool hash algorithm
- phpass hashing implementation - WoltLab Community Framework 2.x hash algorithm
- phpass hash implementation
- Support for salt column - Support for salt column
- User quota synchronization
### Changed
- Example SQL script in README file
- Fixed misspelling
### Changed ### Changed
- Support for Nextcloud 14 only - Support for Nextcloud 14 only
@@ -18,18 +24,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed ### Fixed
- Table and column autocomplete in settings panel - Table and column autocomplete in settings panel
## [4.0.0-rc2] ## [4.0.0-rc2] - 2018-06-14
### Added ### Added
- User active column - User active column
### Changed ### Changed
- Fixed "Use of undefined constant" error for Argon2 Crypt with PHP below 7.2. - Fixed "Use of undefined constant" error for Argon2 Crypt with PHP below 7.2.
## [4.0.0-rc1] ## [4.0.0-rc1] - 2018-06-13
### Added ### Added
- New hashing algorithms: Argon2 Crypt (PHP 7.2 and above), Blowfish Crypt, Courier base64-encoded MD5, Courier base64-encoded SHA1, - New hash algorithms: Argon2 Crypt (PHP 7.2 and above), Blowfish Crypt, Courier base64-encoded MD5, Courier base64-encoded SHA1, Courier base64-encoded SHA256, Courier hexadecimal MD5, Extended DES Crypt, SHA256 Crypt, SHA512 Crypt, SSHA512, Standard DES Crypt
Courier base64-encoded SHA256, Courier hexadecimal MD5, Extended DES Crypt, SHA256 Crypt,
SHA512 Crypt, SSHA512, Standard DES Crypt
- Option to allow users to change their display names - Option to allow users to change their display names
- Option to allow user to change its avatar - Option to allow user to change its avatar
- Database query results cache - Database query results cache
@@ -40,10 +44,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- The whole core implementation, which is NOT COMPATIBLE with the previous versions. - The whole core implementation, which is NOT COMPATIBLE with the previous versions.
- Minimum supported PHP version - 7.0 - Minimum supported PHP version - 7.0
## Removed ### Removed
- MySQL ENCRYPT() hashing implementation - Function is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release. - MySQL ENCRYPT() hash implementation - Function is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release.
- MySQL PASSWORD() hashing implementation - Function is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release. - MySQL PASSWORD() hash implementation - Function is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release.
- Redmine hashing implementation - Cannot implement in new core system. - Redmine hash implementation - Cannot implement in new core system.
- User active column - Use database view instead - User active column - Use database view instead
- Domain support - Domain support

View File

@@ -50,8 +50,9 @@ Name | Description | Details
**Allow display name change** | With this option enabled user can change its display name. The display name change is propagated to the database. | Optional.<br/>Default: false.<br/>Requires: user *Display name* column. **Allow display name change** | With this option enabled user can change its display name. The display name change is propagated to the database. | Optional.<br/>Default: false.<br/>Requires: user *Display name* column.
**Allow password change** | Can user change its password. The password change is propagated to the database. See [Hash algorithms](#hash-algorithms). | Optional.<br/>Default: false. **Allow password change** | Can user change its password. The password change is propagated to the database. See [Hash algorithms](#hash-algorithms). | Optional.<br/>Default: false.
**Use cache** | Use database query results cache. The cache can be cleared any time with the *Clear cache* button click. | Optional.<br/>Default: false. **Use cache** | Use database query results cache. The cache can be cleared any time with the *Clear cache* button click. | Optional.<br/>Default: false.
**Hashing algorithm** | How users passwords are stored in the database. See [Hash algorithms](#hash-algorithms). | Mandatory. **Hash algorithm** | How users passwords are stored in the database. See [Hash algorithms](#hash-algorithms). | Mandatory.
**Email sync** | Sync e-mail address with the Nextcloud.<br/>- *None* - Disables this feature. This is the default option.<br/>- *Synchronise only once* - Copy the e-mail address to the Nextcloud storage if its not set.<br/>- *Nextcloud always wins* - Always copy the e-mail address to the database. This updates the user table.<br/>- *SQL always wins* - Always copy the e-mail address to the Nextcloud storage. | Optional.<br/>Default: *None*.<br/>Requires: user *Email* column. **Email sync** | Sync e-mail address with the Nextcloud.<br/>- *None* - Disables this feature. This is the default option.<br/>- *Synchronise only once* - Copy the e-mail address to the Nextcloud preferences if its not set.<br/>- *Nextcloud always wins* - Always copy the e-mail address to the database. This updates the user table.<br/>- *SQL always wins* - Always copy the e-mail address to the Nextcloud preferences. | Optional.<br/>Default: *None*.<br/>Requires: user *Email* column.
**Quota sync** | Sync user quota with the Nextcloud.<br/>- *None* - Disables this feature. This is the default option.<br/>- *Synchronise only once* - Copy the user quota to the Nextcloud preferences if its not set.<br/>- *Nextcloud always wins* - Always copy the user quota to the database. This updates the user table.<br/>- *SQL always wins* - Always copy the user quota to the Nextcloud preferences. | Optional.<br/>Default: *None*.<br/>Requires: user *Quota* column.
**Home mode** | User storage path.<br/>- *Default* - Let the Nextcloud manage this. The default option.<br/>- *Query* - Use location from the user table pointed by the *home* column.<br/>- *Static* - Use static location. The `%u` variable is replaced with the username of the user. | Optional<br/>Default: *Default*. **Home mode** | User storage path.<br/>- *Default* - Let the Nextcloud manage this. The default option.<br/>- *Query* - Use location from the user table pointed by the *home* column.<br/>- *Static* - Use static location. The `%u` variable is replaced with the username of the user. | Optional<br/>Default: *Default*.
**Home Location** | User storage path for the `static` *home mode*. | Mandatory if the *Home mode* is set to `Static`. **Home Location** | User storage path for the `static` *home mode*. | Mandatory if the *Home mode* is set to `Static`.
@@ -64,11 +65,12 @@ Name | Description | Details
**Table name** | The table name. | Mandatory for user backend. **Table name** | The table name. | Mandatory for user backend.
**Username** | Username column. | Mandatory for user backend. **Username** | Username column. | Mandatory for user backend.
**Email** | E-mail column. | Mandatory for *Email sync* option. **Email** | E-mail column. | Mandatory for *Email sync* option.
**Quota** | Quota column. | Mandatory for *Quota sync* option.
**Home** | Home path column. | Mandatory for `Query` *Home sync* option. **Home** | Home path column. | Mandatory for `Query` *Home sync* option.
**Password** | Password hash column. | Mandatory for user backend. **Password** | Password hash column. | Mandatory for user backend.
**Display name** | Display name column. | Optional. **Display name** | Display name column. | Optional.
**Active** | Flag indicating if user can log in. | Optional.<br/>Default: true. **Active** | Flag indicating if user can log in. | Optional.<br/>Default: true.
**Can change avatar** | Flag indicating if user can change its avatar. | Optional.<br/>Default: false. **Provide avatar** | Flag indicating if user can change its avatar. | Optional.<br/>Default: false.
**Salt** | Salt which is appended to password when checking or changing the password. | Optional. **Salt** | Salt which is appended to password when checking or changing the password. | Optional.
#### Group table #### Group table
@@ -106,36 +108,34 @@ but be aware that some functionalities requires data changes (update queries).
If you don't have any database model yet you can use below tables (MySQL): If you don't have any database model yet you can use below tables (MySQL):
``` ```
CREATE TABLE sql_users CREATE TABLE sql_user
( (
id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(16) PRIMARY KEY,
username VARCHAR(16) NOT NULL,
display_name TEXT NULL, display_name TEXT NULL,
email TEXT NULL, email TEXT NULL,
quota TEXT NULL,
home TEXT NULL, home TEXT NULL,
password TEXT NOT NULL, password TEXT NOT NULL,
active TINYINT(1) NOT NULL DEFAULT '1', active TINYINT(1) NOT NULL DEFAULT '1',
can_change_avatar BOOLEAN NOT NULL DEFAULT FALSE, provide_avatar BOOLEAN NOT NULL DEFAULT FALSE
CONSTRAINT users_username_uindex UNIQUE (username)
); );
CREATE TABLE sql_group CREATE TABLE sql_group
( (
id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(16) PRIMARY KEY,
name VARCHAR(16) NOT NULL,
display_name TEXT NULL, display_name TEXT NULL,
admin BOOLEAN NOT NULL DEFAULT FALSE, admin BOOLEAN NOT NULL DEFAULT FALSE
CONSTRAINT group_name_uindex UNIQUE (name)
); );
CREATE TABLE sql_user_group CREATE TABLE sql_user_group
( (
id INT AUTO_INCREMENT PRIMARY KEY,
group_name VARCHAR(16) NOT NULL,
username VARCHAR(16) NOT NULL, username VARCHAR(16) NOT NULL,
CONSTRAINT user_group_group_name_username_uindex UNIQUE (group_name, username), group_name VARCHAR(16) NOT NULL,
INDEX user_group_group_name_index (group_name), PRIMARY KEY (username, group_name),
INDEX user_group_username_index (username) FOREIGN KEY (username) REFERENCES sql_user (username),
FOREIGN KEY (group_name) REFERENCES sql_group (name),
INDEX sql_user_group_username_idx (username),
INDEX sql_user_group_group_name_idx (group_name)
); );
``` ```
@@ -149,7 +149,7 @@ User table: wp_users
Username column: user_login Username column: user_login
Password column: user_pass Password column: user_pass
Hashing algorithm: Unix (Crypt) or Portable PHP password Hash algorithm: Unix (Crypt) or Portable PHP password
``` ```
#### JHipster #### JHipster
@@ -166,7 +166,7 @@ Password column: password_hash
Email column: email Email column: email
Active column: activated Active column: activated
Hashing algorithm: Unix (Crypt) Hash algorithm: Unix (Crypt)
``` ```
## Hash algorithms ## Hash algorithms
@@ -196,6 +196,7 @@ SHA1 | No salt supported. | 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
SHA512 Whirlpool | No salt supported. | a96b16ebb691dbe968b0d66d0d924cff5cf5de5e0885181d00761d87f295b2bf3d3c66187c050fc01c196ff3acaa48d3561ffd170413346e934a32280d632f2e SHA512 Whirlpool | No salt supported. | a96b16ebb691dbe968b0d66d0d924cff5cf5de5e0885181d00761d87f295b2bf3d3c66187c050fc01c196ff3acaa48d3561ffd170413346e934a32280d632f2e
SSHA256 | Generates 32 chars salt. | {SSHA256}+WxTB3JxprNteeovsuSYtgI+UkVPA9lfwGoYkz3Ff7hjd1FSdmlTMkNsSExyR21KM3NvNTZ5V0p4WXJMUjFzUg== SSHA256 | Generates 32 chars salt. | {SSHA256}+WxTB3JxprNteeovsuSYtgI+UkVPA9lfwGoYkz3Ff7hjd1FSdmlTMkNsSExyR21KM3NvNTZ5V0p4WXJMUjFzUg==
SSHA512 | Generates 32 chars salt. | {SSHA512}It+v1kAEUBbhMJYJ2swAtz+RLE6ispv/FB6G/ALhK/YWwEmrloY+0jzrWIfmu+rWUXp8u0Tg4jLXypC5oXAW00IyYnRVdEZJbE9wak96bkNRVWFCYmlJNWxrdTA0QmhL SSHA512 | Generates 32 chars salt. | {SSHA512}It+v1kAEUBbhMJYJ2swAtz+RLE6ispv/FB6G/ALhK/YWwEmrloY+0jzrWIfmu+rWUXp8u0Tg4jLXypC5oXAW00IyYnRVdEZJbE9wak96bkNRVWFCYmlJNWxrdTA0QmhL
WoltLab Community Framework 2.x | Double salted bcrypt. | $2a$08$XEQDKNU/Vbootwxv5Gp7gujxFX/RUFsZLvQPYM435Dd3/p17fto02
## Development ## Development
@@ -205,7 +206,7 @@ Add a new class in the `OCA\UserSQL\Platform` namespace which extends the `Abstr
Add this driver in `admin.php` template to `$drivers` variable and in method `getPlatform(Connection $connection)` Add this driver in `admin.php` template to `$drivers` variable and in method `getPlatform(Connection $connection)`
of `PlatformFactory` class. of `PlatformFactory` class.
#### New hashing algorithm support #### New hash algorithm support
Create a new class in `OCA\UserSQL\Crypto` namespace which implements `IPasswordAlgorithm` interface. Create a new class in `OCA\UserSQL\Crypto` namespace which implements `IPasswordAlgorithm` interface.
Do not forget to write unit tests. Do not forget to write unit tests.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -76,7 +76,7 @@ user_sql.adminSettingsUI = function () {
); );
autocomplete( autocomplete(
"#db-table-user-column-uid, #db-table-user-column-email, #db-table-user-column-home, #db-table-user-column-password, #db-table-user-column-name, #db-table-user-column-active, #db-table-user-column-avatar, #db-table-user-column-salt", "#db-table-user-column-uid, #db-table-user-column-email, #db-table-user-column-quota, #db-table-user-column-home, #db-table-user-column-password, #db-table-user-column-name, #db-table-user-column-active, #db-table-user-column-avatar, #db-table-user-column-salt",
"/apps/user_sql/settings/autocomplete/table/user" "/apps/user_sql/settings/autocomplete/table/user"
); );

View File

@@ -94,7 +94,7 @@ class EmailSync implements IUserAction
$result = false; $result = false;
switch ($this->properties[Opt::EMAIL_SYNC]) { switch ($this->properties[Opt::EMAIL_SYNC]) {
case App::EMAIL_INITIAL: case App::SYNC_INITIAL:
if (empty($ncMail) && !empty($user->email)) { if (empty($ncMail) && !empty($user->email)) {
$this->config->setUserValue( $this->config->setUserValue(
$user->uid, "settings", "email", $user->email $user->uid, "settings", "email", $user->email
@@ -103,7 +103,7 @@ class EmailSync implements IUserAction
$result = true; $result = true;
break; break;
case App::EMAIL_FORCE_NC: case App::SYNC_FORCE_NC:
if (!empty($ncMail) && $user->email !== $ncMail) { if (!empty($ncMail) && $user->email !== $ncMail) {
$user = $this->userRepository->findByUid($user->uid); $user = $this->userRepository->findByUid($user->uid);
if (!($user instanceof User)) { if (!($user instanceof User)) {
@@ -115,7 +115,7 @@ class EmailSync implements IUserAction
} }
break; break;
case App::EMAIL_FORCE_SQL: case App::SYNC_FORCE_SQL:
if (!empty($user->email) && $user->email !== $ncMail) { if (!empty($user->email) && $user->email !== $ncMail) {
$this->config->setUserValue( $this->config->setUserValue(
$user->uid, "settings", "email", $user->email $user->uid, "settings", "email", $user->email

137
lib/Action/QuotaSync.php Normal file
View File

@@ -0,0 +1,137 @@
<?php
/**
* Nextcloud - user_sql
*
* @copyright 2018 Marcin Łojewski <dev@mlojewski.me>
* @author Marcin Łojewski <dev@mlojewski.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace OCA\UserSQL\Action;
use OCA\UserSQL\Constant\App;
use OCA\UserSQL\Constant\Opt;
use OCA\UserSQL\Model\User;
use OCA\UserSQL\Properties;
use OCA\UserSQL\Repository\UserRepository;
use OCP\IConfig;
use OCP\ILogger;
/**
* Synchronizes the user quota.
*
* @author Marcin Łojewski <dev@mlojewski.me>
*/
class QuotaSync implements IUserAction
{
/**
* @var string The application name.
*/
private $appName;
/**
* @var ILogger The logger instance.
*/
private $logger;
/**
* @var Properties The properties array.
*/
private $properties;
/**
* @var IConfig The config instance.
*/
private $config;
/**
* @var UserRepository The user repository.
*/
private $userRepository;
/**
* The default constructor.
*
* @param string $appName The application name.
* @param ILogger $logger The logger instance.
* @param Properties $properties The properties array.
* @param IConfig $config The config instance.
* @param UserRepository $userRepository The user repository.
*/
public function __construct(
$appName, ILogger $logger, Properties $properties, IConfig $config,
UserRepository $userRepository
) {
$this->appName = $appName;
$this->logger = $logger;
$this->properties = $properties;
$this->config = $config;
$this->userRepository = $userRepository;
}
/**
* @inheritdoc
* @throws \OCP\PreConditionNotMetException
*/
public function doAction(User $user)
{
$this->logger->debug(
"Entering QuotaSync#doAction($user->uid)", ["app" => $this->appName]
);
$ncQuota = $this->config->getUserValue(
$user->uid, "files", "quota", ""
);
$result = false;
switch ($this->properties[Opt::QUOTA_SYNC]) {
case App::SYNC_INITIAL:
if (empty($ncQuota) && !empty($user->quota)) {
$this->config->setUserValue(
$user->uid, "files", "quota", $user->quota
);
}
$result = true;
break;
case App::SYNC_FORCE_NC:
if (!empty($ncQuota) && $user->quota !== $ncQuota) {
$user = $this->userRepository->findByUid($user->uid);
if (!($user instanceof User)) {
break;
}
$user->quota = $ncQuota;
$result = $this->userRepository->save($user);
}
break;
case App::SYNC_FORCE_SQL:
if (!empty($user->quota) && $user->quota !== $ncQuota) {
$this->config->setUserValue(
$user->uid, "files", "quota", $user->quota
);
}
$result = true;
break;
}
$this->logger->debug(
"Returning QuotaSync#doAction($user->uid): " . ($result ? "true"
: "false"),
["app" => $this->appName]
);
return $result;
}
}

View File

@@ -23,6 +23,7 @@ namespace OCA\UserSQL\Backend;
use OCA\UserSQL\Action\EmailSync; use OCA\UserSQL\Action\EmailSync;
use OCA\UserSQL\Action\IUserAction; use OCA\UserSQL\Action\IUserAction;
use OCA\UserSQL\Action\QuotaSync;
use OCA\UserSQL\Cache; use OCA\UserSQL\Cache;
use OCA\UserSQL\Constant\App; use OCA\UserSQL\Constant\App;
use OCA\UserSQL\Constant\DB; use OCA\UserSQL\Constant\DB;
@@ -130,6 +131,14 @@ final class UserBackend extends ABackend implements
$this->userRepository $this->userRepository
); );
} }
if (!empty($this->properties[Opt::QUOTA_SYNC])
&& !empty($this->properties[DB::USER_QUOTA_COLUMN])
) {
$this->actions[] = new QuotaSync(
$this->appName, $this->logger, $this->properties, $this->config,
$this->userRepository
);
}
} }
/** /**

View File

@@ -34,7 +34,7 @@ final class App
const HOME_QUERY = "query"; const HOME_QUERY = "query";
const HOME_STATIC = "static"; const HOME_STATIC = "static";
const EMAIL_FORCE_NC = "force_nc"; const SYNC_FORCE_NC = "force_nc";
const EMAIL_FORCE_SQL = "force_sql"; const SYNC_FORCE_SQL = "force_sql";
const EMAIL_INITIAL = "initial"; const SYNC_INITIAL = "initial";
} }

View File

@@ -51,6 +51,7 @@ final class DB
const USER_HOME_COLUMN = "db.table.user.column.home"; const USER_HOME_COLUMN = "db.table.user.column.home";
const USER_NAME_COLUMN = "db.table.user.column.name"; const USER_NAME_COLUMN = "db.table.user.column.name";
const USER_PASSWORD_COLUMN = "db.table.user.column.password"; const USER_PASSWORD_COLUMN = "db.table.user.column.password";
const USER_QUOTA_COLUMN = "db.table.user.column.quota";
const USER_SALT_COLUMN = "db.table.user.column.salt"; const USER_SALT_COLUMN = "db.table.user.column.salt";
const USER_UID_COLUMN = "db.table.user.column.uid"; const USER_UID_COLUMN = "db.table.user.column.uid";
} }

View File

@@ -34,5 +34,6 @@ final class Opt
const HOME_MODE = "opt.home_mode"; const HOME_MODE = "opt.home_mode";
const NAME_CHANGE = "opt.name_change"; const NAME_CHANGE = "opt.name_change";
const PASSWORD_CHANGE = "opt.password_change"; const PASSWORD_CHANGE = "opt.password_change";
const QUOTA_SYNC = "opt.quota_sync";
const USE_CACHE = "opt.use_cache"; const USE_CACHE = "opt.use_cache";
} }

View File

@@ -39,9 +39,11 @@ final class Query
const FIND_USERS = "find_users"; const FIND_USERS = "find_users";
const SAVE_USER = "save_user"; const SAVE_USER = "save_user";
const EMAIL_PARAM = "email";
const GID_PARAM = "gid"; const GID_PARAM = "gid";
const NAME_PARAM = "name"; const NAME_PARAM = "name";
const PASSWORD_PARAM = "password"; const PASSWORD_PARAM = "password";
const QUOTA_PARAM = "quota";
const SEARCH_PARAM = "search"; const SEARCH_PARAM = "search";
const UID_PARAM = "uid"; const UID_PARAM = "uid";
} }

View File

@@ -22,8 +22,8 @@
namespace OCA\UserSQL\Crypto; namespace OCA\UserSQL\Crypto;
/** /**
* Abstract Unix Crypt hashing implementation. * Abstract Unix Crypt hash implementation.
* The hashing algorithm depends on the chosen salt. * The hash algorithm depends on the chosen salt.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
@@ -52,12 +52,9 @@ abstract class AbstractCrypt extends AbstractAlgorithm
} }
/** /**
* Generate a salt string for the hashing algorithm. * Generate a salt string for the hash algorithm.
* *
* @return string The salt string. * @return string The salt string.
*/ */
protected function getSalt() protected abstract function getSalt();
{
return "";
}
} }

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Courier MD5 hashing implementation. * Courier MD5 hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Courier MD5 RAW hashing implementation. * Courier MD5 RAW hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Courier SHA1 hashing implementation. * Courier SHA1 hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Courier SHA256 hashing implementation. * Courier SHA256 hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Unix Crypt hashing implementation. * Unix Crypt hash implementation.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
@@ -56,4 +56,12 @@ class Crypt extends AbstractCrypt
{ {
return "Unix (Crypt)"; return "Unix (Crypt)";
} }
/**
* Not used.
*/
protected function getSalt()
{
return null;
}
} }

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Argon2 Crypt hashing implementation. * Argon2 Crypt hash implementation.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Blowfish Crypt hashing implementation. * Blowfish Crypt hash implementation.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Extended DES Crypt hashing implementation. * Extended DES Crypt hash implementation.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* MD5 Crypt hashing implementation. * MD5 Crypt hash implementation.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* SHA256 Crypt hashing implementation. * SHA256 Crypt hash implementation.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* SHA512 Crypt hashing implementation. * SHA512 Crypt hash implementation.
* *
* @see crypt() * @see crypt()
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Standard DES Crypt hashing implementation. * Standard DES Crypt hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* Joomla hashing implementation. * Joomla hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* MD5 hashing implementation. * MD5 hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* phpass hashing implementation. * phpass hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* SHA1 hashing implementation. * SHA1 hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* SHA512 Whirlpool hashing implementation. * SHA512 Whirlpool hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* SSHA* hashing implementation. * SSHA* hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* SSHA256 hashing implementation. * SSHA256 hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

View File

@@ -24,7 +24,7 @@ namespace OCA\UserSQL\Crypto;
use OCP\IL10N; use OCP\IL10N;
/** /**
* SSHA512 hashing implementation. * SSHA512 hash implementation.
* *
* @author Marcin Łojewski <dev@mlojewski.me> * @author Marcin Łojewski <dev@mlojewski.me>
*/ */

63
lib/Crypto/WCF2.php Normal file
View File

@@ -0,0 +1,63 @@
<?php
/**
* Nextcloud - user_sql
*
* @copyright 2018 Marcin Łojewski <dev@mlojewski.me>
* @author Marcin Łojewski <dev@mlojewski.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace OCA\UserSQL\Crypto;
/**
* WCF2 hash implementation.
*
* @author Marcin Łojewski <dev@mlojewski.me>
*/
class WCF2 extends AbstractCrypt
{
/**
* @inheritdoc
*/
public function checkPassword($password, $dbHash)
{
return hash_equals($dbHash, crypt(crypt($password, $dbHash), $dbHash));
}
/**
* @inheritdoc
*/
public function getPasswordHash($password)
{
$salt = $this->getSalt();
return crypt(crypt($password, $salt), $salt);
}
/**
* @inheritdoc
*/
protected function getSalt()
{
return "$2a$08$" . Utils::randomString(22, self::SALT_ALPHABET) . "$";
}
/**
* @inheritdoc
*/
protected function getAlgorithmName()
{
return "WoltLab Community Framework 2.x";
}
}

View File

@@ -36,6 +36,10 @@ class User
* @var string The user's email address. * @var string The user's email address.
*/ */
public $email; public $email;
/**
* @var string The user quota.
*/
public $quota;
/** /**
* @var string The user's display name. * @var string The user's display name.
*/ */

View File

@@ -71,15 +71,18 @@ class QueryProvider implements \ArrayAccess
$uHome = $this->properties[DB::USER_HOME_COLUMN]; $uHome = $this->properties[DB::USER_HOME_COLUMN];
$uName = $this->properties[DB::USER_NAME_COLUMN]; $uName = $this->properties[DB::USER_NAME_COLUMN];
$uPassword = $this->properties[DB::USER_PASSWORD_COLUMN]; $uPassword = $this->properties[DB::USER_PASSWORD_COLUMN];
$uQuota = $this->properties[DB::USER_QUOTA_COLUMN];
$uSalt = $this->properties[DB::USER_SALT_COLUMN]; $uSalt = $this->properties[DB::USER_SALT_COLUMN];
$uUID = $this->properties[DB::USER_UID_COLUMN]; $uUID = $this->properties[DB::USER_UID_COLUMN];
$ugGID = $this->properties[DB::USER_GROUP_GID_COLUMN]; $ugGID = $this->properties[DB::USER_GROUP_GID_COLUMN];
$ugUID = $this->properties[DB::USER_GROUP_UID_COLUMN]; $ugUID = $this->properties[DB::USER_GROUP_UID_COLUMN];
$emailParam = Query::EMAIL_PARAM;
$gidParam = Query::GID_PARAM; $gidParam = Query::GID_PARAM;
$nameParam = Query::NAME_PARAM; $nameParam = Query::NAME_PARAM;
$passwordParam = Query::PASSWORD_PARAM; $passwordParam = Query::PASSWORD_PARAM;
$quotaParam = Query::QUOTA_PARAM;
$searchParam = Query::SEARCH_PARAM; $searchParam = Query::SEARCH_PARAM;
$uidParam = Query::UID_PARAM; $uidParam = Query::UID_PARAM;
@@ -91,6 +94,7 @@ class QueryProvider implements \ArrayAccess
= "$uUID AS uid, " . = "$uUID AS uid, " .
(empty($uName) ? "null" : $uName) . " AS name, " . (empty($uName) ? "null" : $uName) . " AS name, " .
(empty($uEmail) ? "null" : $uEmail) . " AS email, " . (empty($uEmail) ? "null" : $uEmail) . " AS email, " .
(empty($uQuota) ? "null" : $uQuota) . " AS quota, " .
(empty($uHome) ? "null" : $uHome) . " AS home, " . (empty($uHome) ? "null" : $uHome) . " AS home, " .
(empty($uActive) ? "true" : $uActive) . " AS active, " . (empty($uActive) ? "true" : $uActive) . " AS active, " .
(empty($uAvatar) ? "false" : $uAvatar) . " AS avatar, " . (empty($uAvatar) ? "false" : $uAvatar) . " AS avatar, " .
@@ -156,7 +160,9 @@ class QueryProvider implements \ArrayAccess
Query::SAVE_USER => Query::SAVE_USER =>
"UPDATE $user " . "UPDATE $user " .
"SET $uPassword = :$passwordParam, " . "SET $uPassword = :$passwordParam, " .
"$uName = :$nameParam " . "$uName = :$nameParam, " .
"$uEmail = :$emailParam, " .
"$uQuota = :$quotaParam " .
"WHERE $uUID = :$uidParam", "WHERE $uUID = :$uidParam",
]; ];
} }

View File

@@ -107,6 +107,8 @@ class UserRepository
Query::SAVE_USER, [ Query::SAVE_USER, [
Query::NAME_PARAM => $user->name, Query::NAME_PARAM => $user->name,
Query::PASSWORD_PARAM => $user->password, Query::PASSWORD_PARAM => $user->password,
Query::EMAIL_PARAM => $user->email,
Query::QUOTA_PARAM => $user->quota,
Query::UID_PARAM => $user->uid Query::UID_PARAM => $user->uid
] ]
); );

View File

@@ -71,6 +71,16 @@ function print_select_options(
echo "</option>"; echo "</option>";
} }
#54: Merge develop-14 into develop Conflicts
Resolved all conflicts
2 conflicting files
CHANGELOG.md
CHANGELOG.md
admin.php
templates/admin.php
templates/admin.php
Resolved
echo "</select>"; echo "</select>";
echo "</label></div>"; echo "</label></div>";
} }
@@ -115,7 +125,7 @@ function print_select_options(
<input type="submit" id="user_sql-clear_cache" value="<?php p($l->t("Clear cache")); ?>"> <input type="submit" id="user_sql-clear_cache" value="<?php p($l->t("Clear cache")); ?>">
</div> </div>
<?php <?php
$hashing = []; $hashes = [];
foreach (glob(__DIR__ . "/../lib/Crypto/*.php") as $filename) { foreach (glob(__DIR__ . "/../lib/Crypto/*.php") as $filename) {
$class = "OCA\\UserSQL\\Crypto\\" . basename(substr($filename, 0, -4)); $class = "OCA\\UserSQL\\Crypto\\" . basename(substr($filename, 0, -4));
try { try {
@@ -123,14 +133,15 @@ function print_select_options(
if ($passwordAlgorithm instanceof if ($passwordAlgorithm instanceof
\OCA\UserSQL\Crypto\IPasswordAlgorithm \OCA\UserSQL\Crypto\IPasswordAlgorithm
) { ) {
$hashing[$class] = $passwordAlgorithm->getVisibleName(); $hashes[$class] = $passwordAlgorithm->getVisibleName();
} }
} catch (Throwable $e) { } catch (Throwable $e) {
} }
} }
print_select_options($l, "opt-crypto_class", "Hashing algorithm", $hashing, $_["opt.crypto_class"]); print_select_options($l, "opt-crypto_class", "Hash algorithm", $hashes, $_["opt.crypto_class"]);
print_select_options($l, "opt-email_sync", "Email sync", ["" => "None", "initial" => "Synchronise only once", "force_nc"=>"Nextcloud always wins", "force_sql"=>"SQL always wins"], $_["opt.email_sync"]); print_select_options($l, "opt-email_sync", "Email sync", ["" => "None", "initial" => "Synchronise only once", "force_nc"=>"Nextcloud always wins", "force_sql"=>"SQL always wins"], $_["opt.email_sync"]);
print_select_options($l, "opt-quota_sync", "Quota sync", ["" => "None", "initial" => "Synchronise only once", "force_nc"=>"Nextcloud always wins", "force_sql"=>"SQL always wins"], $_["opt.quota_sync"]);
print_select_options($l, "opt-home_mode", "Home mode", ["" => "Default", "query" => "Query", "static" => "Static"], $_["opt.home_mode"]); print_select_options($l, "opt-home_mode", "Home mode", ["" => "Default", "query" => "Query", "static" => "Static"], $_["opt.home_mode"]);
print_text_input($l, "opt-home_location", "Home Location", $_["opt.home_location"]); ?> print_text_input($l, "opt-home_location", "Home Location", $_["opt.home_location"]); ?>
</fieldset> </fieldset>
@@ -144,11 +155,12 @@ function print_select_options(
<?php <?php
print_text_input($l, "db-table-user-column-uid", "Username", $_["db.table.user.column.uid"]); print_text_input($l, "db-table-user-column-uid", "Username", $_["db.table.user.column.uid"]);
print_text_input($l, "db-table-user-column-email", "Email", $_["db.table.user.column.email"]); print_text_input($l, "db-table-user-column-email", "Email", $_["db.table.user.column.email"]);
print_text_input($l, "db-table-user-column-quota", "Quota", $_["db.table.user.column.quota"]);
print_text_input($l, "db-table-user-column-home", "Home", $_["db.table.user.column.home"]); print_text_input($l, "db-table-user-column-home", "Home", $_["db.table.user.column.home"]);
print_text_input($l, "db-table-user-column-password", "Password", $_["db.table.user.column.password"]); print_text_input($l, "db-table-user-column-password", "Password", $_["db.table.user.column.password"]);
print_text_input($l, "db-table-user-column-name", "Display name", $_["db.table.user.column.name"]); print_text_input($l, "db-table-user-column-name", "Display name", $_["db.table.user.column.name"]);
print_text_input($l, "db-table-user-column-active", "Active", $_["db.table.user.column.active"]); print_text_input($l, "db-table-user-column-active", "Active", $_["db.table.user.column.active"]);
print_text_input($l, "db-table-user-column-avatar", "Can change avatar", $_["db.table.user.column.avatar"]); print_text_input($l, "db-table-user-column-avatar", "Provide avatar", $_["db.table.user.column.avatar"]);
print_text_input($l, "db-table-user-column-salt", "Salt", $_["db.table.user.column.salt"]); ?> print_text_input($l, "db-table-user-column-salt", "Salt", $_["db.table.user.column.salt"]); ?>
</fieldset> </fieldset>
</div> </div>

View File

@@ -43,6 +43,12 @@ class CleartextTest extends TestCase
$this->assertTrue($this->crypto->checkPassword("password", "password")); $this->assertTrue($this->crypto->checkPassword("password", "password"));
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -47,6 +47,12 @@ class CourierMD5RawTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -47,6 +47,12 @@ class CourierMD5Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -47,6 +47,12 @@ class CourierSHA1Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class CourierSHA256Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class CryptArgon2Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class CryptBlowfishTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -45,6 +45,12 @@ class CryptExtendedDESTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -47,6 +47,12 @@ class CryptMD5Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class CryptSHA256Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class CryptSHA512Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -45,6 +45,12 @@ class CryptStandardDESTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class CryptTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class JoomlaTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -47,6 +47,12 @@ class MD5Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -47,6 +47,12 @@ class PhpassTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -47,6 +47,12 @@ class SHA1Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class SHA512WhirlpoolTest extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class SSHA256Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@@ -48,6 +48,12 @@ class SSHA512Test extends TestCase
); );
} }
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

62
tests/Crypto/WCF2Test.php Normal file
View File

@@ -0,0 +1,62 @@
<?php
/**
* Nextcloud - user_sql
*
* @copyright 2018 Marcin Łojewski <dev@mlojewski.me>
* @author Marcin Łojewski <dev@mlojewski.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Tests\UserSQL\Crypto;
use OCA\UserSQL\Crypto\IPasswordAlgorithm;
use OCA\UserSQL\Crypto\WCF2;
use OCP\IL10N;
use Test\TestCase;
/**
* Unit tests for class <code>WCF2</code>.
*
* @author Marcin Łojewski <dev@mlojewski.me>
*/
class WCF2Test extends TestCase
{
/**
* @var IPasswordAlgorithm
*/
private $crypto;
public function testCheckPassword()
{
$this->assertTrue(
$this->crypto->checkPassword(
"password",
"$2a$08\$XEQDKNU/Vbootwxv5Gp7gujxFX/RUFsZLvQPYM435Dd3/p17fto02"
)
);
}
public function testPasswordHash()
{
$hash = $this->crypto->getPasswordHash("password");
$this->assertTrue($this->crypto->checkPassword("password", $hash));
}
protected function setUp()
{
parent::setUp();
$this->crypto = new WCF2($this->createMock(IL10N::class));
}
}