Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/user_sql.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Łojewski <marcin.lojewski@mlojewski.me>2018-12-30 22:48:14 +0300
committerMarcin Łojewski <marcin.lojewski@mlojewski.me>2018-12-30 22:48:14 +0300
commitdff2807910c815b2c5316390b069387462d37f54 (patch)
tree33760dff8381e1c40363bdb2f5880fdfb1a21a65
parent06c650be2cf8ab1fa4fb6710ad4564b30c4d3d37 (diff)
parentee4918e8c2ac683ca7a5483666c40feb310043ed (diff)
Merge branch 'release/v4.3.0'v4.3.0
-rw-r--r--CHANGELOG.md8
-rw-r--r--README.md10
-rw-r--r--appinfo/info.xml4
-rw-r--r--appinfo/routes.php5
-rw-r--r--css/settings.css28
-rw-r--r--js/settings.js47
-rw-r--r--lib/Backend/UserBackend.php9
-rw-r--r--lib/Constant/Opt.php5
-rw-r--r--lib/Controller/SettingsController.php98
-rw-r--r--lib/Crypto/AbstractAlgorithm.php8
-rw-r--r--lib/Crypto/CryptArgon2.php17
-rw-r--r--lib/Crypto/CryptBlowfish.php8
-rw-r--r--lib/Crypto/CryptExtendedDES.php8
-rw-r--r--lib/Crypto/CryptSHA256.php8
-rw-r--r--lib/Crypto/CryptSHA512.php8
-rw-r--r--lib/Crypto/CryptoParam.php63
-rw-r--r--lib/Crypto/Drupal7.php8
-rw-r--r--lib/Crypto/IPasswordAlgorithm.php8
-rw-r--r--lib/Crypto/Phpass.php8
-rw-r--r--lib/Properties.php39
-rw-r--r--lib/Query/QueryProvider.php5
-rw-r--r--templates/admin.php20
22 files changed, 391 insertions, 31 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6937e05..4cedb58 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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/)
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
### Fixed
- 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
- 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.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
diff --git a/README.md b/README.md
index 87061c4..5888a6d 100644
--- a/README.md
+++ b/README.md
@@ -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 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.
+**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.
**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.
@@ -186,12 +188,12 @@ Courier hexadecimal MD5 | No salt supported. | {MD5}X03MO1qnZdYdgyfeuILPmQ==
Courier base64-encoded SHA1 | No salt supported. | {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
Courier base64-encoded SHA256 | No salt supported. | {SHA256}XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=
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
-Blowfish (Crypt) | Uses default parameters. See [password_hash](http://php.net/manual/en/function.password-hash.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq
+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) | See [password_hash](http://php.net/manual/en/function.password-hash.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq
Extended DES (Crypt) | | cDRpdxPmHpzS.
MD5 (Crypt) | | $1$RzaFbNcU$u9adfTY/Q6za6nu0Ogrl1/
-SHA256 (Crypt) | Generates hash with 5000 rounds. | $5$rounds=5000$VIYD0iHkg7uY9SRc$v2XLS/9dvfFN84mzGvW9wxnVt9Xd/urXaaTkpW8EwD1
-SHA512 (Crypt) | Generates hash with 5000 rounds. | $6$rounds=5000$yH.Q0OL4qbCOUJ3q$Xry5EVFva3wKnfo8/ktrugmBd8tcl34NK6rXInv1HhmdSUNLEm0La9JnA57rqwQ.9/Bz513MD4tvmmISLUIHs/
+SHA256 (Crypt) | | $5$rounds=5000$VIYD0iHkg7uY9SRc$v2XLS/9dvfFN84mzGvW9wxnVt9Xd/urXaaTkpW8EwD1
+SHA512 (Crypt) | | $6$rounds=5000$yH.Q0OL4qbCOUJ3q$Xry5EVFva3wKnfo8/ktrugmBd8tcl34NK6rXInv1HhmdSUNLEm0La9JnA57rqwQ.9/Bz513MD4tvmmISLUIHs/
Standard DES (Crypt) | | yTBnb7ab/N072
Drupal 7 | See [phpass](http://www.openwall.com/phpass/). | $S$DC7eCpJQ3SUQtW4Bp.vKb2rpeaffi4iqk9OpYwJyEoSMsezn67Sl
Joomla MD5 Encryption | Generates 32 chars salt. | 14d21b49b0f13e2acba962b6b0039edd:haJK0yTvBXTNMh76xwEw5RYEVpJsN8us
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 6652457..0ee2286 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -8,7 +8,7 @@
Retrieve the users and groups info. Allow the users to change their passwords.
Sync the users' email addresses with the addresses stored by Nextcloud.
</description>
- <version>4.2.1</version>
+ <version>4.3.0</version>
<licence>agpl</licence>
<author>Marcin Łojewski</author>
<author>Andreas Böhler</author>
@@ -22,7 +22,7 @@
<category>auth</category>
<dependencies>
<php min-version="7.0"/>
- <nextcloud min-version="14" max-version="15"/>
+ <nextcloud min-version="14" max-version="16"/>
</dependencies>
<settings>
<admin>\OCA\UserSQL\Settings\Admin</admin>
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 8224fa4..dde5395 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -61,6 +61,11 @@ $application->registerRoutes(
"url" => "/settings/autocomplete/table/group",
"verb" => "POST"
],
+ [
+ "name" => "settings#cryptoParams",
+ "url" => "/settings/crypto/params",
+ "verb" => "GET"
+ ],
]
]
);
diff --git a/css/settings.css b/css/settings.css
index 33f454a..9fae0e2 100644
--- a/css/settings.css
+++ b/css/settings.css
@@ -33,6 +33,13 @@
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 {
left: 0;
padding: 3px;
@@ -43,16 +50,23 @@
}
#user_sql .msg.error {
- background-color: #d2322d;
- color: #fff;
+ background-color: var(--color-error);
+ color: var(--color-primary-text);
}
#user_sql .msg.success {
- background-color: #47a447;
- color: #fff;
+ background-color: var(--color-success);
+ color: var(--color-primary-text);
}
#user_sql .msg.waiting {
- background-color: #ff8f00;
- color: #fff;
-} \ No newline at end of file
+ background-color: var(--color-warning);
+ color: var(--color-primary-text);
+}
+
+#user_sql .loading {
+ display: inline-block;
+ height: 32px;
+ margin: 5px 0;
+ width: 32px;
+}
diff --git a/js/settings.js b/js/settings.js
index 0a42eaf..cf49ac5 100644
--- a/js/settings.js
+++ b/js/settings.js
@@ -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) {
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",
"/apps/user_sql/settings/autocomplete/table/group"
);
+
+ cryptoParams();
}
};
@@ -96,4 +141,4 @@ $(document).ready(function () {
if ($(form_id)) {
user_sql.adminSettingsUI();
}
-}); \ No newline at end of file
+});
diff --git a/lib/Backend/UserBackend.php b/lib/Backend/UserBackend.php
index 27927e4..d8c6ae8 100644
--- a/lib/Backend/UserBackend.php
+++ b/lib/Backend/UserBackend.php
@@ -343,7 +343,12 @@ final class UserBackend extends ABackend implements
private function getPasswordAlgorithm()
{
$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) {
$this->logger->error(
@@ -555,7 +560,7 @@ final class UserBackend extends ABackend implements
);
if (empty($this->properties[DB::USER_AVATAR_COLUMN])) {
- return false;
+ return !empty($this->properties[Opt::PROVIDE_AVATAR]);
}
$user = $this->userRepository->findByUid($uid);
diff --git a/lib/Constant/Opt.php b/lib/Constant/Opt.php
index 5093210..9be2eb0 100644
--- a/lib/Constant/Opt.php
+++ b/lib/Constant/Opt.php
@@ -31,12 +31,17 @@ final class Opt
const APPEND_SALT = "opt.append_salt";
const CASE_INSENSITIVE_USERNAME = "opt.case_insensitive_username";
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 HOME_LOCATION = "opt.home_location";
const HOME_MODE = "opt.home_mode";
const NAME_CHANGE = "opt.name_change";
const PASSWORD_CHANGE = "opt.password_change";
const PREPEND_SALT = "opt.prepend_salt";
+ const PROVIDE_AVATAR = "opt.provide_avatar";
const QUOTA_SYNC = "opt.quota_sync";
+ const REVERSE_ACTIVE = "opt.reverse_active";
const USE_CACHE = "opt.use_cache";
}
diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php
index a192daf..ef06b2d 100644
--- a/lib/Controller/SettingsController.php
+++ b/lib/Controller/SettingsController.php
@@ -28,12 +28,16 @@ use OC\DB\Connection;
use OC\DB\ConnectionFactory;
use OCA\UserSQL\Cache;
use OCA\UserSQL\Constant\App;
+use OCA\UserSQL\Constant\Opt;
+use OCA\UserSQL\Crypto\IPasswordAlgorithm;
use OCA\UserSQL\Platform\PlatformFactory;
use OCA\UserSQL\Properties;
use OCP\AppFramework\Controller;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
+use ReflectionClass;
+use ReflectionException;
/**
* The settings controller.
@@ -72,7 +76,8 @@ class SettingsController extends Controller
public function __construct(
$appName, IRequest $request, ILogger $logger, IL10N $localization,
Properties $properties, Cache $cache
- ) {
+ )
+ {
parent::__construct($appName, $request);
$this->appName = $appName;
$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) {
$reqValue = $this->request->getParam(str_replace(".", "-", $key));
$appValue = $this->properties[$key];
@@ -208,6 +223,9 @@ class SettingsController extends Controller
"Property '$key' has been set to: " . $value,
["app" => $this->appName]
);
+ } elseif (!is_bool($appValue) && !isset($reqValue)) {
+ unset($this->properties[$key]);
+
}
}
@@ -226,6 +244,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.
*
* @return array The request status.
@@ -367,4 +427,40 @@ class SettingsController extends Controller
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];
+ }
}
diff --git a/lib/Crypto/AbstractAlgorithm.php b/lib/Crypto/AbstractAlgorithm.php
index 99f344e..6290d7d 100644
--- a/lib/Crypto/AbstractAlgorithm.php
+++ b/lib/Crypto/AbstractAlgorithm.php
@@ -74,4 +74,12 @@ abstract class AbstractAlgorithm implements IPasswordAlgorithm
* @inheritdoc
*/
public abstract function getPasswordHash($password, $salt = null);
+
+ /**
+ * @inheritdoc
+ */
+ public function configuration()
+ {
+ return [];
+ }
}
diff --git a/lib/Crypto/CryptArgon2.php b/lib/Crypto/CryptArgon2.php
index 6e086cc..ddbfe0a 100644
--- a/lib/Crypto/CryptArgon2.php
+++ b/lib/Crypto/CryptArgon2.php
@@ -103,6 +103,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
+ */
protected function getAlgorithmName()
{
return "Argon2 (Crypt)";
diff --git a/lib/Crypto/CryptBlowfish.php b/lib/Crypto/CryptBlowfish.php
index 73a27b1..fb9e28b 100644
--- a/lib/Crypto/CryptBlowfish.php
+++ b/lib/Crypto/CryptBlowfish.php
@@ -68,6 +68,14 @@ class CryptBlowfish extends AbstractAlgorithm
}
/**
+ * @inheritdoc
+ */
+ public function configuration()
+ {
+ return [new CryptoParam("Cost", 10, 4, 31)];
+ }
+
+ /**
* Get the algorithm name.
*
* @return string The algorithm name.
diff --git a/lib/Crypto/CryptExtendedDES.php b/lib/Crypto/CryptExtendedDES.php
index c91e04c..8cde30a 100644
--- a/lib/Crypto/CryptExtendedDES.php
+++ b/lib/Crypto/CryptExtendedDES.php
@@ -51,6 +51,14 @@ class CryptExtendedDES extends AbstractCrypt
/**
* @inheritdoc
*/
+ public function configuration()
+ {
+ return [new CryptoParam("Iterations", 1000, 0, 16777215)];
+ }
+
+ /**
+ * @inheritdoc
+ */
protected function getSalt()
{
return self::encodeIterationCount($this->iterationCount)
diff --git a/lib/Crypto/CryptSHA256.php b/lib/Crypto/CryptSHA256.php
index b4e2b41..91063ef 100644
--- a/lib/Crypto/CryptSHA256.php
+++ b/lib/Crypto/CryptSHA256.php
@@ -52,6 +52,14 @@ class CryptSHA256 extends AbstractCrypt
/**
* @inheritdoc
*/
+ public function configuration()
+ {
+ return [new CryptoParam("Rounds", 5000, 1000, 999999999)];
+ }
+
+ /**
+ * @inheritdoc
+ */
protected function getSalt()
{
return "$5\$rounds=" . $this->rounds . "$" . Utils::randomString(
diff --git a/lib/Crypto/CryptSHA512.php b/lib/Crypto/CryptSHA512.php
index e32238f..1cafee5 100644
--- a/lib/Crypto/CryptSHA512.php
+++ b/lib/Crypto/CryptSHA512.php
@@ -52,6 +52,14 @@ class CryptSHA512 extends AbstractCrypt
/**
* @inheritdoc
*/
+ public function configuration()
+ {
+ return [new CryptoParam("Rounds", 5000, 1000, 999999999)];
+ }
+
+ /**
+ * @inheritdoc
+ */
protected function getSalt()
{
return "$6\$rounds=" . $this->rounds . "$" . Utils::randomString(
diff --git a/lib/Crypto/CryptoParam.php b/lib/Crypto/CryptoParam.php
new file mode 100644
index 0000000..d694cf2
--- /dev/null
+++ b/lib/Crypto/CryptoParam.php
@@ -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;
+ }
+}
diff --git a/lib/Crypto/Drupal7.php b/lib/Crypto/Drupal7.php
index 567e342..85024f4 100644
--- a/lib/Crypto/Drupal7.php
+++ b/lib/Crypto/Drupal7.php
@@ -37,6 +37,14 @@ class Drupal7 extends Phpass
/**
* @inheritdoc
*/
+ public function configuration()
+ {
+ return [];
+ }
+
+ /**
+ * @inheritdoc
+ */
protected function crypt($password, $setting)
{
return substr(parent::crypt($password, $setting), 0, self::DRUPAL_HASH_LENGTH);
diff --git a/lib/Crypto/IPasswordAlgorithm.php b/lib/Crypto/IPasswordAlgorithm.php
index 4c5a160..54c70b1 100644
--- a/lib/Crypto/IPasswordAlgorithm.php
+++ b/lib/Crypto/IPasswordAlgorithm.php
@@ -58,4 +58,12 @@ interface IPasswordAlgorithm
* @return boolean True if the password is correct, false otherwise.
*/
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();
}
diff --git a/lib/Crypto/Phpass.php b/lib/Crypto/Phpass.php
index bea911d..7edd728 100644
--- a/lib/Crypto/Phpass.php
+++ b/lib/Crypto/Phpass.php
@@ -158,6 +158,14 @@ class Phpass extends AbstractAlgorithm
/**
* @inheritdoc
*/
+ public function configuration()
+ {
+ return [new CryptoParam("Iterations (log2)", 8, 4, 31)];
+ }
+
+ /**
+ * @inheritdoc
+ */
protected function getAlgorithmName()
{
return "Portable PHP password";
diff --git a/lib/Properties.php b/lib/Properties.php
index b030b82..36413f5 100644
--- a/lib/Properties.php
+++ b/lib/Properties.php
@@ -99,10 +99,12 @@ class Properties implements \ArrayAccess
foreach ($params as $param) {
$value = $this->config->getAppValue($this->appName, $param, null);
- if ($value === App::FALSE_VALUE) {
- $value = false;
- } elseif ($value === App::TRUE_VALUE) {
- $value = true;
+ if ($this->isBooleanParam($param)) {
+ if ($value === App::FALSE_VALUE) {
+ $value = false;
+ } elseif ($value === App::TRUE_VALUE) {
+ $value = true;
+ }
}
$this->data[$param] = $value;
@@ -142,6 +144,24 @@ class Properties implements \ArrayAccess
}
/**
+ * 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.
*/
private function store()
@@ -186,10 +206,12 @@ class Properties implements \ArrayAccess
{
$this->config->setAppValue($this->appName, $offset, $value);
- if ($value === App::FALSE_VALUE) {
- $value = false;
- } elseif ($value === App::TRUE_VALUE) {
- $value = true;
+ if ($this->isBooleanParam($offset)) {
+ if ($value === App::FALSE_VALUE) {
+ $value = false;
+ } elseif ($value === App::TRUE_VALUE) {
+ $value = true;
+ }
}
$this->data[$offset] = $value;
@@ -206,6 +228,7 @@ class Properties implements \ArrayAccess
*/
public function offsetUnset($offset)
{
+ $this->config->deleteAppValue($this->appName, $offset);
unset($this->data[$offset]);
}
}
diff --git a/lib/Query/QueryProvider.php b/lib/Query/QueryProvider.php
index 0a1bf76..15092cb 100644
--- a/lib/Query/QueryProvider.php
+++ b/lib/Query/QueryProvider.php
@@ -22,6 +22,7 @@
namespace OCA\UserSQL\Query;
use OCA\UserSQL\Constant\DB;
+use OCA\UserSQL\Constant\Opt;
use OCA\UserSQL\Constant\Query;
use OCA\UserSQL\Properties;
@@ -86,6 +87,8 @@ class QueryProvider implements \ArrayAccess
$searchParam = Query::SEARCH_PARAM;
$uidParam = Query::UID_PARAM;
+ $reverseActiveOpt = $this->properties[Opt::REVERSE_ACTIVE];
+
$groupColumns
= "g.$gGID AS gid, " .
(empty($gName) ? "g." . $gGID : "g." . $gName) . " AS name, " .
@@ -96,7 +99,7 @@ class QueryProvider implements \ArrayAccess
(empty($uEmail) ? "null" : "u." . $uEmail) . " AS email, " .
(empty($uQuota) ? "null" : "u." . $uQuota) . " AS quota, " .
(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($uSalt) ? "null" : "u." . $uSalt) . " AS salt";
diff --git a/templates/admin.php b/templates/admin.php
index c00b06e..579fb94 100644
--- a/templates/admin.php
+++ b/templates/admin.php
@@ -110,7 +110,9 @@ function print_select_options(
<fieldset><?php
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-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
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")); ?>">
@@ -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-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"]);
@@ -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-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-salt", "Salt", $_["db.table.user.column.salt"]);
- print_checkbox_input($l, "opt-append_salt", "Append salt", $_["opt.append_salt"]);
- print_checkbox_input($l, "opt-prepend_salt", "Prepend salt", $_["opt.prepend_salt"]); ?>
+ print_text_input($l, "db-table-user-column-salt", "Salt", $_["db.table.user.column.salt"]); ?>
+ <div class="inner-fieldset">
+ <?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>
</div>
<div class="section">