Merge branch 'release/v4.3.0'

This commit is contained in:
Marcin Łojewski
2018-12-30 20:48:14 +01:00
22 changed files with 391 additions and 31 deletions

View File

@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [4.3.0] - 2018-12-30
### Added
- Reverse active column option
- Support for Nextcloud 16
- Set default value for "provide avatar" option
- Set hash algorithm parameters
## [4.2.1] - 2018-12-22 ## [4.2.1] - 2018-12-22
### Fixed ### Fixed
- SQL error when same column names given in several tables - SQL error when same column names given in several tables
@@ -112,6 +119,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed ### Changed
- Supported version of ownCloud, Nextcloud: ownCloud 10, Nextcloud 12 - Supported version of ownCloud, Nextcloud: ownCloud 10, Nextcloud 12
[4.3.0]: https://github.com/nextcloud/user_sql/compare/v4.2.1...v4.3.0
[4.2.1]: https://github.com/nextcloud/user_sql/compare/v4.2.0...v4.2.1 [4.2.1]: https://github.com/nextcloud/user_sql/compare/v4.2.0...v4.2.1
[4.2.0]: https://github.com/nextcloud/user_sql/compare/v4.1.0...v4.2.0 [4.2.0]: https://github.com/nextcloud/user_sql/compare/v4.1.0...v4.2.0
[4.1.0]: https://github.com/nextcloud/user_sql/compare/v4.0.1...v4.1.0 [4.1.0]: https://github.com/nextcloud/user_sql/compare/v4.0.1...v4.1.0

View File

@@ -49,7 +49,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.
**Allow providing avatar** | Can user provide its avatar. The value is used when column *Provide avatar* is not set. | Optional.<br/>Default: false.
**Case-insensitive username** | Whether user query should be case-sensitive or case-insensitive. | Optional.<br/>Default: false. **Case-insensitive username** | Whether user query should be case-sensitive or case-insensitive. | Optional.<br/>Default: false.
**Reverse active column** | Reverse value of active column in user table. | 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.
**Hash 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 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. **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.
@@ -186,12 +188,12 @@ Courier hexadecimal MD5 | No salt supported. | {MD5}X03MO1qnZdYdgyfeuILPmQ==
Courier base64-encoded SHA1 | No salt supported. | {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g= Courier base64-encoded SHA1 | No salt supported. | {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
Courier base64-encoded SHA256 | No salt supported. | {SHA256}XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg= Courier base64-encoded SHA256 | No salt supported. | {SHA256}XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=
Unix (Crypt) | See [crypt](http://php.net/manual/en/function.crypt.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq Unix (Crypt) | See [crypt](http://php.net/manual/en/function.crypt.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq
Argon2 (Crypt) | Requires PHP >= 7.2.<br/>Uses default parameters. See [password_hash](http://php.net/manual/en/function.password-hash.php). | $argon2i$v=19$m=1024,t=2,p=2$NnpSNlRNLlZobnJHUDh0Sw$oW5E1cfdPzLWfkTvQFUyzTR00R0aLwEdYwldcqW6Pmo Argon2 (Crypt) | Requires PHP >= 7.2. See [password_hash](http://php.net/manual/en/function.password-hash.php). | $argon2i$v=19$m=1024,t=2,p=2$NnpSNlRNLlZobnJHUDh0Sw$oW5E1cfdPzLWfkTvQFUyzTR00R0aLwEdYwldcqW6Pmo
Blowfish (Crypt) | Uses default parameters. See [password_hash](http://php.net/manual/en/function.password-hash.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq Blowfish (Crypt) | See [password_hash](http://php.net/manual/en/function.password-hash.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq
Extended DES (Crypt) | | cDRpdxPmHpzS. Extended DES (Crypt) | | cDRpdxPmHpzS.
MD5 (Crypt) | | $1$RzaFbNcU$u9adfTY/Q6za6nu0Ogrl1/ MD5 (Crypt) | | $1$RzaFbNcU$u9adfTY/Q6za6nu0Ogrl1/
SHA256 (Crypt) | Generates hash with 5000 rounds. | $5$rounds=5000$VIYD0iHkg7uY9SRc$v2XLS/9dvfFN84mzGvW9wxnVt9Xd/urXaaTkpW8EwD1 SHA256 (Crypt) | | $5$rounds=5000$VIYD0iHkg7uY9SRc$v2XLS/9dvfFN84mzGvW9wxnVt9Xd/urXaaTkpW8EwD1
SHA512 (Crypt) | Generates hash with 5000 rounds. | $6$rounds=5000$yH.Q0OL4qbCOUJ3q$Xry5EVFva3wKnfo8/ktrugmBd8tcl34NK6rXInv1HhmdSUNLEm0La9JnA57rqwQ.9/Bz513MD4tvmmISLUIHs/ SHA512 (Crypt) | | $6$rounds=5000$yH.Q0OL4qbCOUJ3q$Xry5EVFva3wKnfo8/ktrugmBd8tcl34NK6rXInv1HhmdSUNLEm0La9JnA57rqwQ.9/Bz513MD4tvmmISLUIHs/
Standard DES (Crypt) | | yTBnb7ab/N072 Standard DES (Crypt) | | yTBnb7ab/N072
Drupal 7 | See [phpass](http://www.openwall.com/phpass/). | $S$DC7eCpJQ3SUQtW4Bp.vKb2rpeaffi4iqk9OpYwJyEoSMsezn67Sl Drupal 7 | See [phpass](http://www.openwall.com/phpass/). | $S$DC7eCpJQ3SUQtW4Bp.vKb2rpeaffi4iqk9OpYwJyEoSMsezn67Sl
Joomla MD5 Encryption | Generates 32 chars salt. | 14d21b49b0f13e2acba962b6b0039edd:haJK0yTvBXTNMh76xwEw5RYEVpJsN8us Joomla MD5 Encryption | Generates 32 chars salt. | 14d21b49b0f13e2acba962b6b0039edd:haJK0yTvBXTNMh76xwEw5RYEVpJsN8us

View File

@@ -8,7 +8,7 @@
Retrieve the users and groups info. Allow the users to change their passwords. Retrieve the users and groups info. Allow the users to change their passwords.
Sync the users' email addresses with the addresses stored by Nextcloud. Sync the users' email addresses with the addresses stored by Nextcloud.
</description> </description>
<version>4.2.1</version> <version>4.3.0</version>
<licence>agpl</licence> <licence>agpl</licence>
<author>Marcin Łojewski</author> <author>Marcin Łojewski</author>
<author>Andreas Böhler</author> <author>Andreas Böhler</author>
@@ -22,7 +22,7 @@
<category>auth</category> <category>auth</category>
<dependencies> <dependencies>
<php min-version="7.0"/> <php min-version="7.0"/>
<nextcloud min-version="14" max-version="15"/> <nextcloud min-version="14" max-version="16"/>
</dependencies> </dependencies>
<settings> <settings>
<admin>\OCA\UserSQL\Settings\Admin</admin> <admin>\OCA\UserSQL\Settings\Admin</admin>

View File

@@ -61,6 +61,11 @@ $application->registerRoutes(
"url" => "/settings/autocomplete/table/group", "url" => "/settings/autocomplete/table/group",
"verb" => "POST" "verb" => "POST"
], ],
[
"name" => "settings#cryptoParams",
"url" => "/settings/crypto/params",
"verb" => "GET"
],
] ]
] ]
); );

View File

@@ -33,6 +33,13 @@
float: right; float: right;
} }
#user_sql .main .inner-fieldset {
border-bottom: 1px solid var(--color-border);
border-top: 1px solid var(--color-border);
margin: 8px 0;
padding: 8px 0 8px 16px;
}
#user_sql .msg { #user_sql .msg {
left: 0; left: 0;
padding: 3px; padding: 3px;
@@ -43,16 +50,23 @@
} }
#user_sql .msg.error { #user_sql .msg.error {
background-color: #d2322d; background-color: var(--color-error);
color: #fff; color: var(--color-primary-text);
} }
#user_sql .msg.success { #user_sql .msg.success {
background-color: #47a447; background-color: var(--color-success);
color: #fff; color: var(--color-primary-text);
} }
#user_sql .msg.waiting { #user_sql .msg.waiting {
background-color: #ff8f00; background-color: var(--color-warning);
color: #fff; color: var(--color-primary-text);
}
#user_sql .loading {
display: inline-block;
height: 32px;
margin: 5px 0;
width: 32px;
} }

View File

@@ -58,6 +58,49 @@ user_sql.adminSettingsUI = function () {
}); });
}; };
var cryptoParams = function () {
var cryptoChanged = function () {
var content = $("#opt-crypto_params_content");
var loading = $("#opt-crypto_params_loading");
content.hide();
loading.show();
$.get(OC.generateUrl("/apps/user_sql/settings/crypto/params"), {cryptoClass: $("#opt-crypto_class").val()},
function (data) {
content.empty();
loading.hide();
if (data.status === "success") {
for (var index = 0, length = data.data.length; index < length; ++index) {
var param = $("<div></div>");
var label = $("<label></label>").attr({for: "opt-crypto_param_" + index});
var title = $("<span></span>").text(data.data[index]["name"]);
var input = $("<input/>").attr({
type: "number",
id: "opt-crypto_param_" + index,
name: "opt-crypto_param_" + index,
step: 1,
min: data.data[index]["min"],
max: data.data[index]["max"],
value: data.data[index]["value"]
});
label.append(title);
param.append(label);
param.append(input);
content.append(param);
content.show();
}
}
}, "json");
};
$("#opt-crypto_class").change(function () {
cryptoChanged();
});
cryptoChanged();
};
$("#user_sql-db_connection_verify").click(function (event) { $("#user_sql-db_connection_verify").click(function (event) {
return click(event, "/apps/user_sql/settings/db/verify"); return click(event, "/apps/user_sql/settings/db/verify");
}); });
@@ -89,6 +132,8 @@ user_sql.adminSettingsUI = function () {
"#db-table-group-column-admin, #db-table-group-column-name, #db-table-group-column-gid", "#db-table-group-column-admin, #db-table-group-column-name, #db-table-group-column-gid",
"/apps/user_sql/settings/autocomplete/table/group" "/apps/user_sql/settings/autocomplete/table/group"
); );
cryptoParams();
} }
}; };

View File

@@ -343,7 +343,12 @@ final class UserBackend extends ABackend implements
private function getPasswordAlgorithm() private function getPasswordAlgorithm()
{ {
$cryptoType = $this->properties[Opt::CRYPTO_CLASS]; $cryptoType = $this->properties[Opt::CRYPTO_CLASS];
$passwordAlgorithm = new $cryptoType($this->localization); $cryptoParam0 = $this->properties[Opt::CRYPTO_PARAM_0];
$cryptoParam1 = $this->properties[Opt::CRYPTO_PARAM_1];
$cryptoParam2 = $this->properties[Opt::CRYPTO_PARAM_2];
$passwordAlgorithm = new $cryptoType(
$this->localization, $cryptoParam0, $cryptoParam1, $cryptoParam2
);
if ($passwordAlgorithm === null) { if ($passwordAlgorithm === null) {
$this->logger->error( $this->logger->error(
@@ -555,7 +560,7 @@ final class UserBackend extends ABackend implements
); );
if (empty($this->properties[DB::USER_AVATAR_COLUMN])) { if (empty($this->properties[DB::USER_AVATAR_COLUMN])) {
return false; return !empty($this->properties[Opt::PROVIDE_AVATAR]);
} }
$user = $this->userRepository->findByUid($uid); $user = $this->userRepository->findByUid($uid);

View File

@@ -31,12 +31,17 @@ final class Opt
const APPEND_SALT = "opt.append_salt"; const APPEND_SALT = "opt.append_salt";
const CASE_INSENSITIVE_USERNAME = "opt.case_insensitive_username"; const CASE_INSENSITIVE_USERNAME = "opt.case_insensitive_username";
const CRYPTO_CLASS = "opt.crypto_class"; const CRYPTO_CLASS = "opt.crypto_class";
const CRYPTO_PARAM_0 = "opt.crypto_param_0";
const CRYPTO_PARAM_1 = "opt.crypto_param_1";
const CRYPTO_PARAM_2 = "opt.crypto_param_2";
const EMAIL_SYNC = "opt.email_sync"; const EMAIL_SYNC = "opt.email_sync";
const HOME_LOCATION = "opt.home_location"; const HOME_LOCATION = "opt.home_location";
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 PREPEND_SALT = "opt.prepend_salt"; const PREPEND_SALT = "opt.prepend_salt";
const PROVIDE_AVATAR = "opt.provide_avatar";
const QUOTA_SYNC = "opt.quota_sync"; const QUOTA_SYNC = "opt.quota_sync";
const REVERSE_ACTIVE = "opt.reverse_active";
const USE_CACHE = "opt.use_cache"; const USE_CACHE = "opt.use_cache";
} }

View File

@@ -28,12 +28,16 @@ use OC\DB\Connection;
use OC\DB\ConnectionFactory; use OC\DB\ConnectionFactory;
use OCA\UserSQL\Cache; use OCA\UserSQL\Cache;
use OCA\UserSQL\Constant\App; use OCA\UserSQL\Constant\App;
use OCA\UserSQL\Constant\Opt;
use OCA\UserSQL\Crypto\IPasswordAlgorithm;
use OCA\UserSQL\Platform\PlatformFactory; use OCA\UserSQL\Platform\PlatformFactory;
use OCA\UserSQL\Properties; use OCA\UserSQL\Properties;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\IL10N; use OCP\IL10N;
use OCP\ILogger; use OCP\ILogger;
use OCP\IRequest; use OCP\IRequest;
use ReflectionClass;
use ReflectionException;
/** /**
* The settings controller. * The settings controller.
@@ -72,7 +76,8 @@ class SettingsController extends Controller
public function __construct( public function __construct(
$appName, IRequest $request, ILogger $logger, IL10N $localization, $appName, IRequest $request, ILogger $logger, IL10N $localization,
Properties $properties, Cache $cache Properties $properties, Cache $cache
) { )
{
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->appName = $appName; $this->appName = $appName;
$this->logger = $logger; $this->logger = $logger;
@@ -193,6 +198,16 @@ class SettingsController extends Controller
]; ];
} }
if (!$this->validateCryptoParams()) {
return [
"status" => "error", "data" => [
"message" => $this->localization->t(
"Hash algorithm parameter is out of range."
)
]
];
}
foreach ($properties as $key => $value) { foreach ($properties as $key => $value) {
$reqValue = $this->request->getParam(str_replace(".", "-", $key)); $reqValue = $this->request->getParam(str_replace(".", "-", $key));
$appValue = $this->properties[$key]; $appValue = $this->properties[$key];
@@ -208,6 +223,9 @@ class SettingsController extends Controller
"Property '$key' has been set to: " . $value, "Property '$key' has been set to: " . $value,
["app" => $this->appName] ["app" => $this->appName]
); );
} elseif (!is_bool($appValue) && !isset($reqValue)) {
unset($this->properties[$key]);
} }
} }
@@ -225,6 +243,48 @@ class SettingsController extends Controller
]; ];
} }
/**
* Validate request crypto params.
*
* @return bool TRUE if crypto params are correct FALSE otherwise.
*/
private function validateCryptoParams()
{
$cryptoClass = $this->request->getParam("opt-crypto_class");
$configuration = $this->cryptoClassConfiguration($cryptoClass);
for ($i = 0; $i < count($configuration); ++$i) {
$reqParam = $this->request->getParam(
"opt-crypto_param_" . $i, null
);
$cryptoParam = $configuration[$i];
if (is_null($reqParam) || $reqParam < $cryptoParam->min
|| $reqParam > $cryptoParam->max
) {
return false;
}
}
return true;
}
/**
* Get a crypto class configuration from request.
*
* @param $cryptoClass string Crypto class name.
*
* @return array A crypto class configuration.
*/
private function cryptoClassConfiguration($cryptoClass)
{
/**
* @var $passwordAlgorithm IPasswordAlgorithm
*/
$passwordAlgorithm = new $cryptoClass($this->localization);
return $passwordAlgorithm->configuration();
}
/** /**
* Clear the application cache memory. * Clear the application cache memory.
* *
@@ -367,4 +427,40 @@ class SettingsController extends Controller
return $columns; return $columns;
} }
/**
* Get parameters for a password algorithm.
*
* @return array Password algorithm parameters.
* @throws ReflectionException Whenever Opt class cannot be initiated.
*/
public function cryptoParams()
{
$this->logger->debug(
"Entering cryptoParams()", ["app" => $this->appName]
);
$cryptoClass = $this->request->getParam("cryptoClass");
$configuration = $this->cryptoClassConfiguration($cryptoClass);
if ($cryptoClass === $this->properties[Opt::CRYPTO_CLASS]) {
foreach ($configuration as $key => $value) {
$opt = new ReflectionClass("OCA\UserSQL\Constant\Opt");
$param = $this->properties[$opt->getConstant(
"CRYPTO_PARAM_" . $key
)];
if (!is_null($param)) {
$value->value = $param;
}
}
}
$this->logger->debug(
"Returning cryptoParams(): count(" . count($configuration) . ")",
["app" => $this->appName]
);
return ["status" => "success", "data" => (array)$configuration];
}
} }

View File

@@ -74,4 +74,12 @@ abstract class AbstractAlgorithm implements IPasswordAlgorithm
* @inheritdoc * @inheritdoc
*/ */
public abstract function getPasswordHash($password, $salt = null); public abstract function getPasswordHash($password, $salt = null);
/**
* @inheritdoc
*/
public function configuration()
{
return [];
}
} }

View File

@@ -100,6 +100,23 @@ class CryptArgon2 extends AbstractAlgorithm
); );
} }
/**
* @inheritdoc
*/
public function configuration()
{
return [
new CryptoParam(
"Memory cost (KiB)", PASSWORD_ARGON2_DEFAULT_MEMORY_COST, 1,
1048576
),
new CryptoParam(
"Time cost", PASSWORD_ARGON2_DEFAULT_TIME_COST, 1, 1024
),
new CryptoParam("Threads", PASSWORD_ARGON2_DEFAULT_THREADS, 1, 1024)
];
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@@ -67,6 +67,14 @@ class CryptBlowfish extends AbstractAlgorithm
); );
} }
/**
* @inheritdoc
*/
public function configuration()
{
return [new CryptoParam("Cost", 10, 4, 31)];
}
/** /**
* Get the algorithm name. * Get the algorithm name.
* *

View File

@@ -48,6 +48,14 @@ class CryptExtendedDES extends AbstractCrypt
$this->iterationCount = $iterationCount; $this->iterationCount = $iterationCount;
} }
/**
* @inheritdoc
*/
public function configuration()
{
return [new CryptoParam("Iterations", 1000, 0, 16777215)];
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@@ -49,6 +49,14 @@ class CryptSHA256 extends AbstractCrypt
$this->rounds = $rounds; $this->rounds = $rounds;
} }
/**
* @inheritdoc
*/
public function configuration()
{
return [new CryptoParam("Rounds", 5000, 1000, 999999999)];
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@@ -49,6 +49,14 @@ class CryptSHA512 extends AbstractCrypt
$this->rounds = $rounds; $this->rounds = $rounds;
} }
/**
* @inheritdoc
*/
public function configuration()
{
return [new CryptoParam("Rounds", 5000, 1000, 999999999)];
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

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;
/**
* A parameter of a hash algorithm.
*
* @author Marcin Łojewski <dev@mlojewski.me>
*/
class CryptoParam
{
/**
* @var string Parameter name.
*/
public $name;
/**
* @var int Parameter default value.
*/
public $value;
/**
* @var int Minimal value for parameter.
*/
public $min;
/**
* @var int Maximum value for parameter.
*/
public $max;
/**
* Class constructor.
*
* @param $name string Parameter name.
* @param $value int Parameter default value.
* @param $min int Minimal value for parameter.
* @param $max int Maximum value for parameter.
*/
public function __construct($name, $value, $min, $max)
{
$this->name = $name;
$this->value = $value;
$this->min = $min;
$this->max = $max;
}
}

View File

@@ -34,6 +34,14 @@ class Drupal7 extends Phpass
*/ */
const DRUPAL_HASH_LENGTH = 55; const DRUPAL_HASH_LENGTH = 55;
/**
* @inheritdoc
*/
public function configuration()
{
return [];
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@@ -58,4 +58,12 @@ interface IPasswordAlgorithm
* @return boolean True if the password is correct, false otherwise. * @return boolean True if the password is correct, false otherwise.
*/ */
public function checkPassword($password, $dbHash, $salt = null); public function checkPassword($password, $dbHash, $salt = null);
/**
* Configuration for the algorithm.
* The return array should contain entries of class <code>CryptoParam</code>
*
* @return array The configuration array.
*/
public function configuration();
} }

View File

@@ -155,6 +155,14 @@ class Phpass extends AbstractAlgorithm
return $output; return $output;
} }
/**
* @inheritdoc
*/
public function configuration()
{
return [new CryptoParam("Iterations (log2)", 8, 4, 31)];
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@@ -99,10 +99,12 @@ class Properties implements \ArrayAccess
foreach ($params as $param) { foreach ($params as $param) {
$value = $this->config->getAppValue($this->appName, $param, null); $value = $this->config->getAppValue($this->appName, $param, null);
if ($value === App::FALSE_VALUE) { if ($this->isBooleanParam($param)) {
$value = false; if ($value === App::FALSE_VALUE) {
} elseif ($value === App::TRUE_VALUE) { $value = false;
$value = true; } elseif ($value === App::TRUE_VALUE) {
$value = true;
}
} }
$this->data[$param] = $value; $this->data[$param] = $value;
@@ -141,6 +143,24 @@ class Properties implements \ArrayAccess
return $params; return $params;
} }
/**
* Is given parameter a boolean parameter.
*
* @param $param string Parameter name.
*
* @return bool Is a boolean parameter.
*/
private function isBooleanParam($param)
{
return in_array(
$param, [
Opt::APPEND_SALT, Opt::CASE_INSENSITIVE_USERNAME,
Opt::NAME_CHANGE, Opt::PASSWORD_CHANGE, Opt::PREPEND_SALT,
Opt::PROVIDE_AVATAR, Opt::REVERSE_ACTIVE, Opt::USE_CACHE
]
);
}
/** /**
* Store properties in the cache memory. * Store properties in the cache memory.
*/ */
@@ -186,10 +206,12 @@ class Properties implements \ArrayAccess
{ {
$this->config->setAppValue($this->appName, $offset, $value); $this->config->setAppValue($this->appName, $offset, $value);
if ($value === App::FALSE_VALUE) { if ($this->isBooleanParam($offset)) {
$value = false; if ($value === App::FALSE_VALUE) {
} elseif ($value === App::TRUE_VALUE) { $value = false;
$value = true; } elseif ($value === App::TRUE_VALUE) {
$value = true;
}
} }
$this->data[$offset] = $value; $this->data[$offset] = $value;
@@ -206,6 +228,7 @@ class Properties implements \ArrayAccess
*/ */
public function offsetUnset($offset) public function offsetUnset($offset)
{ {
$this->config->deleteAppValue($this->appName, $offset);
unset($this->data[$offset]); unset($this->data[$offset]);
} }
} }

View File

@@ -22,6 +22,7 @@
namespace OCA\UserSQL\Query; namespace OCA\UserSQL\Query;
use OCA\UserSQL\Constant\DB; use OCA\UserSQL\Constant\DB;
use OCA\UserSQL\Constant\Opt;
use OCA\UserSQL\Constant\Query; use OCA\UserSQL\Constant\Query;
use OCA\UserSQL\Properties; use OCA\UserSQL\Properties;
@@ -86,6 +87,8 @@ class QueryProvider implements \ArrayAccess
$searchParam = Query::SEARCH_PARAM; $searchParam = Query::SEARCH_PARAM;
$uidParam = Query::UID_PARAM; $uidParam = Query::UID_PARAM;
$reverseActiveOpt = $this->properties[Opt::REVERSE_ACTIVE];
$groupColumns $groupColumns
= "g.$gGID AS gid, " . = "g.$gGID AS gid, " .
(empty($gName) ? "g." . $gGID : "g." . $gName) . " AS name, " . (empty($gName) ? "g." . $gGID : "g." . $gName) . " AS name, " .
@@ -96,7 +99,7 @@ class QueryProvider implements \ArrayAccess
(empty($uEmail) ? "null" : "u." . $uEmail) . " AS email, " . (empty($uEmail) ? "null" : "u." . $uEmail) . " AS email, " .
(empty($uQuota) ? "null" : "u." . $uQuota) . " AS quota, " . (empty($uQuota) ? "null" : "u." . $uQuota) . " AS quota, " .
(empty($uHome) ? "null" : "u." . $uHome) . " AS home, " . (empty($uHome) ? "null" : "u." . $uHome) . " AS home, " .
(empty($uActive) ? "true" : "u." . $uActive) . " AS active, " . (empty($uActive) ? "true" : (empty($reverseActiveOpt) ? "" : "NOT ") . "u." . $uActive) . " AS active, " .
(empty($uAvatar) ? "false" : "u." . $uAvatar) . " AS avatar, " . (empty($uAvatar) ? "false" : "u." . $uAvatar) . " AS avatar, " .
(empty($uSalt) ? "null" : "u." . $uSalt) . " AS salt"; (empty($uSalt) ? "null" : "u." . $uSalt) . " AS salt";

View File

@@ -110,7 +110,9 @@ function print_select_options(
<fieldset><?php <fieldset><?php
print_checkbox_input($l, "opt-name_change", "Allow display name change", $_["opt.name_change"]); print_checkbox_input($l, "opt-name_change", "Allow display name change", $_["opt.name_change"]);
print_checkbox_input($l, "opt-password_change", "Allow password change", $_["opt.password_change"]); print_checkbox_input($l, "opt-password_change", "Allow password change", $_["opt.password_change"]);
print_checkbox_input($l, "opt-case_insensitive_username", "Case-insensitive username", $_["opt.case_insensitive_username"]); ?> print_checkbox_input($l, "opt-provide_avatar", "Allow providing avatar", $_["opt.provide_avatar"]);
print_checkbox_input($l, "opt-case_insensitive_username", "Case-insensitive username", $_["opt.case_insensitive_username"]);
print_checkbox_input($l, "opt-reverse_active", "Reverse active column", $_["opt.reverse_active"]); ?>
<div class="button-right"><?php <div class="button-right"><?php
print_checkbox_input($l, "opt-use_cache", "Use cache", $_["opt.use_cache"], false); ?> print_checkbox_input($l, "opt-use_cache", "Use cache", $_["opt.use_cache"], false); ?>
<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")); ?>">
@@ -130,7 +132,12 @@ function print_select_options(
} }
} }
print_select_options($l, "opt-crypto_class", "Hash algorithm", $hashes, $_["opt.crypto_class"]); print_select_options($l, "opt-crypto_class", "Hash algorithm", $hashes, $_["opt.crypto_class"]); ?>
<div id="opt-crypto_params_loading" style="display: none">
<span class="icon loading"></span>
</div>
<fieldset id="opt-crypto_params_content" class="inner-fieldset" style="display: none"></fieldset>
<?php
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-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"]);
@@ -152,9 +159,12 @@ function print_select_options(
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", "Provide 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"]); ?>
print_checkbox_input($l, "opt-append_salt", "Append salt", $_["opt.append_salt"]); <div class="inner-fieldset">
print_checkbox_input($l, "opt-prepend_salt", "Prepend salt", $_["opt.prepend_salt"]); ?> <?php
print_checkbox_input($l, "opt-append_salt", "Append salt", $_["opt.append_salt"]);
print_checkbox_input($l, "opt-prepend_salt", "Prepend salt", $_["opt.prepend_salt"]); ?>
</div>
</fieldset> </fieldset>
</div> </div>
<div class="section"> <div class="section">