aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Marien Fressinaud <dev@marienfressinaud.fr> 2019-12-03 23:11:06 +0100
committerGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2019-12-03 23:11:06 +0100
commitd0f1f9f141a58e090d210c221a7c1745378b96a3 (patch)
tree5d538ee048a14d29f8091d9e85cf391ada48ae83
parent15b8ef8f40f249ace343696df216f2d61f8249d0 (diff)
Separate the update API password endpoint (#2675)
* Extract hashPassword method from userController * Extract and refactor fever key-related methods * Move update of API password to dedicated action * Simplify the controller by refactoring feverUtil * Add locales
-rw-r--r--app/Controllers/apiController.php47
-rwxr-xr-xapp/Controllers/javascriptController.php2
-rw-r--r--app/Controllers/userController.php61
-rw-r--r--app/Utils/feverUtil.php80
-rw-r--r--app/Utils/passwordUtil.php27
-rw-r--r--app/i18n/cz/conf.php1
-rw-r--r--app/i18n/cz/feedback.php6
-rw-r--r--app/i18n/de/conf.php1
-rw-r--r--app/i18n/de/feedback.php6
-rw-r--r--app/i18n/en/conf.php1
-rw-r--r--app/i18n/en/feedback.php6
-rwxr-xr-xapp/i18n/es/conf.php1
-rwxr-xr-xapp/i18n/es/feedback.php6
-rw-r--r--app/i18n/fr/conf.php1
-rw-r--r--app/i18n/fr/feedback.php6
-rw-r--r--app/i18n/he/conf.php1
-rw-r--r--app/i18n/he/feedback.php6
-rw-r--r--app/i18n/it/conf.php1
-rw-r--r--app/i18n/it/feedback.php6
-rw-r--r--app/i18n/kr/conf.php1
-rw-r--r--app/i18n/kr/feedback.php6
-rw-r--r--app/i18n/nl/conf.php1
-rw-r--r--app/i18n/nl/feedback.php6
-rw-r--r--app/i18n/oc/conf.php1
-rw-r--r--app/i18n/oc/feedback.php6
-rw-r--r--app/i18n/pt-br/conf.php1
-rw-r--r--app/i18n/pt-br/feedback.php6
-rw-r--r--app/i18n/ru/conf.php1
-rw-r--r--app/i18n/ru/feedback.php6
-rw-r--r--app/i18n/sk/conf.php1
-rw-r--r--app/i18n/sk/feedback.php6
-rw-r--r--app/i18n/tr/conf.php1
-rw-r--r--app/i18n/tr/feedback.php6
-rw-r--r--app/i18n/zh-cn/conf.php1
-rw-r--r--app/i18n/zh-cn/feedback.php6
-rw-r--r--app/install.php1
-rw-r--r--app/views/user/profile.phtml37
-rw-r--r--cli/_update-or-create-user.php3
-rwxr-xr-xcli/create-user.php1
-rwxr-xr-xcli/update-user.php1
40 files changed, 292 insertions, 73 deletions
diff --git a/app/Controllers/apiController.php b/app/Controllers/apiController.php
new file mode 100644
index 000000000..d096ba83f
--- /dev/null
+++ b/app/Controllers/apiController.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * This controller manage API-related features.
+ */
+class FreshRSS_api_Controller extends Minz_ActionController {
+ /**
+ * This action updates the user API password.
+ *
+ * Parameter is:
+ * - apiPasswordPlain: the new user password
+ */
+ public function updatePasswordAction() {
+ if (!FreshRSS_Auth::hasAccess()) {
+ Minz_Error::error(403);
+ }
+
+ $return_url = array('c' => 'user', 'a' => 'profile');
+
+ if (!Minz_Request::isPost()) {
+ Minz_Request::forward($return_url, true);
+ }
+
+ $apiPasswordPlain = Minz_Request::param('apiPasswordPlain', '', true);
+ if ($apiPasswordPlain == '') {
+ Minz_Request::forward($return_url, true);
+ }
+
+ $username = Minz_Session::param('currentUser');
+ $userConfig = FreshRSS_Context::$user_conf;
+
+ $apiPasswordHash = FreshRSS_password_Util::hash($apiPasswordPlain);
+ $userConfig->apiPasswordHash = $apiPasswordHash;
+
+ $feverKey = FreshRSS_fever_Util::updateKey($username, $apiPasswordPlain);
+ if (!$feverKey) {
+ Minz_Request::bad(_t('feedback.api.password.failed'), $return_url);
+ }
+
+ $userConfig->feverKey = $feverKey;
+ if ($userConfig->save()) {
+ Minz_Request::good(_t('feedback.api.password.updated'), $return_url);
+ } else {
+ Minz_Request::bad(_t('feedback.api.password.failed'), $return_url);
+ }
+ }
+}
diff --git a/app/Controllers/javascriptController.php b/app/Controllers/javascriptController.php
index c84e5483b..b22e2c127 100755
--- a/app/Controllers/javascriptController.php
+++ b/app/Controllers/javascriptController.php
@@ -47,7 +47,7 @@ class FreshRSS_javascript_Controller extends Minz_ActionController {
Minz_Log::notice('Nonce failure due to invalid username!');
}
//Failure: Return random data.
- $this->view->salt1 = sprintf('$2a$%02d$', FreshRSS_user_Controller::BCRYPT_COST);
+ $this->view->salt1 = sprintf('$2a$%02d$', FreshRSS_password_Util::BCRYPT_COST);
$alphabet = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for ($i = 22; $i > 0; $i--) {
$this->view->salt1 .= $alphabet[mt_rand(0, 63)];
diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php
index 05e7475e7..3a48e65e3 100644
--- a/app/Controllers/userController.php
+++ b/app/Controllers/userController.php
@@ -4,17 +4,6 @@
* Controller to handle user actions.
*/
class FreshRSS_user_Controller extends Minz_ActionController {
- // Will also have to be computed client side on mobile devices,
- // so do not use a too high cost
- const BCRYPT_COST = 9;
-
- public static function hashPassword($passwordPlain) {
- $passwordHash = password_hash($passwordPlain, PASSWORD_BCRYPT, array('cost' => self::BCRYPT_COST));
- $passwordPlain = '';
- $passwordHash = preg_replace('/^\$2[xy]\$/', '\$2a\$', $passwordHash); //Compatibility with bcrypt.js
- return $passwordHash == '' ? '' : $passwordHash;
- }
-
/**
* The username is also used as folder name, file name, and part of SQL table name.
* '_' is a reserved internal username.
@@ -25,15 +14,7 @@ class FreshRSS_user_Controller extends Minz_ActionController {
return preg_match('/^' . self::USERNAME_PATTERN . '$/', $username) === 1;
}
- public static function deleteFeverKey($username) {
- $userConfig = get_user_configuration($username);
- if ($userConfig !== null && ctype_xdigit($userConfig->feverKey)) {
- return @unlink(DATA_PATH . '/fever/.key-' . sha1(FreshRSS_Context::$system_conf->salt) . '-' . $userConfig->feverKey . '.txt');
- }
- return false;
- }
-
- public static function updateUser($user, $email, $passwordPlain, $apiPasswordPlain, $userConfigUpdated = array()) {
+ public static function updateUser($user, $email, $passwordPlain, $userConfigUpdated = array()) {
$userConfig = get_user_configuration($user);
if ($userConfig === null) {
return false;
@@ -51,33 +32,10 @@ class FreshRSS_user_Controller extends Minz_ActionController {
}
if ($passwordPlain != '') {
- $passwordHash = self::hashPassword($passwordPlain);
+ $passwordHash = FreshRSS_password_Util::hash($passwordPlain);
$userConfig->passwordHash = $passwordHash;
}
- if ($apiPasswordPlain != '') {
- $apiPasswordHash = self::hashPassword($apiPasswordPlain);
- $userConfig->apiPasswordHash = $apiPasswordHash;
-
- $feverPath = DATA_PATH . '/fever/';
-
- if (!file_exists($feverPath)) {
- @mkdir($feverPath, 0770, true);
- }
-
- if (!is_writable($feverPath)) {
- Minz_Log::error("Could not save Fever API credentials. The directory does not have write access.");
- } else {
- self::deleteFeverKey($user);
- $userConfig->feverKey = strtolower(md5("{$user}:{$apiPasswordPlain}"));
- $ok = file_put_contents($feverPath . '.key-' . sha1(FreshRSS_Context::$system_conf->salt) . '-' . $userConfig->feverKey . '.txt', $user) !== false;
-
- if (!$ok) {
- Minz_Log::warning('Could not save Fever API credentials. Unknown error.', ADMIN_LOG);
- }
- }
- }
-
if (is_array($userConfigUpdated)) {
foreach ($userConfigUpdated as $configName => $configValue) {
if ($configValue !== null) {
@@ -100,10 +58,8 @@ class FreshRSS_user_Controller extends Minz_ActionController {
Minz_Request::_param('newPasswordPlain'); //Discard plain-text password ASAP
$_POST['newPasswordPlain'] = '';
- $apiPasswordPlain = Minz_Request::param('apiPasswordPlain', '', true);
-
$username = Minz_Request::param('username');
- $ok = self::updateUser($username, null, $passwordPlain, $apiPasswordPlain, array(
+ $ok = self::updateUser($username, null, $passwordPlain, array(
'token' => Minz_Request::param('token', null),
));
@@ -150,8 +106,6 @@ class FreshRSS_user_Controller extends Minz_ActionController {
Minz_Request::_param('newPasswordPlain'); //Discard plain-text password ASAP
$_POST['newPasswordPlain'] = '';
- $apiPasswordPlain = Minz_Request::param('apiPasswordPlain', '', true);
-
if ($system_conf->force_email_validation && empty($email)) {
Minz_Request::bad(
_t('user.email.feedback.required'),
@@ -170,7 +124,6 @@ class FreshRSS_user_Controller extends Minz_ActionController {
Minz_Session::param('currentUser'),
$email,
$passwordPlain,
- $apiPasswordPlain,
array(
'token' => Minz_Request::param('token', null),
)
@@ -239,7 +192,7 @@ class FreshRSS_user_Controller extends Minz_ActionController {
}
}
- public static function createUser($new_user_name, $email, $passwordPlain, $apiPasswordPlain = '', $userConfigOverride = [], $insertDefaultFeeds = true) {
+ public static function createUser($new_user_name, $email, $passwordPlain, $userConfigOverride = [], $insertDefaultFeeds = true) {
$userConfig = [];
$customUserConfigPath = join_path(DATA_PATH, 'config-user.custom.php');
@@ -291,7 +244,7 @@ class FreshRSS_user_Controller extends Minz_ActionController {
}
}
- $ok &= self::updateUser($new_user_name, $email, $passwordPlain, $apiPasswordPlain);
+ $ok &= self::updateUser($new_user_name, $email, $passwordPlain);
}
return $ok;
}
@@ -346,7 +299,7 @@ class FreshRSS_user_Controller extends Minz_ActionController {
);
}
- $ok = self::createUser($new_user_name, $email, $passwordPlain, '', array('language' => $new_user_language));
+ $ok = self::createUser($new_user_name, $email, $passwordPlain, array('language' => $new_user_language));
Minz_Request::_param('new_user_passwordPlain'); //Discard plain-text password ASAP
$_POST['new_user_passwordPlain'] = '';
invalidateHttpCache();
@@ -386,7 +339,7 @@ class FreshRSS_user_Controller extends Minz_ActionController {
$user_data = join_path(DATA_PATH, 'users', $username);
$ok &= is_dir($user_data);
if ($ok) {
- self::deleteFeverKey($username);
+ FreshRSS_fever_Util::deleteKey($username);
$oldUserDAO = FreshRSS_Factory::createUserDao($username);
$ok &= $oldUserDAO->deleteUser();
$ok &= recursive_unlink($user_data);
diff --git a/app/Utils/feverUtil.php b/app/Utils/feverUtil.php
new file mode 100644
index 000000000..83921943c
--- /dev/null
+++ b/app/Utils/feverUtil.php
@@ -0,0 +1,80 @@
+<?php
+
+class FreshRSS_fever_Util {
+ const FEVER_PATH = DATA_PATH . '/fever';
+
+ /**
+ * Make sure the fever path exists and is writable.
+ *
+ * @return boolean true if the path is writable, else false.
+ */
+ public static function checkFeverPath() {
+ if (!file_exists(self::FEVER_PATH)) {
+ @mkdir(self::FEVER_PATH, 0770, true);
+ }
+
+ $ok = is_writable(self::FEVER_PATH);
+ if (!$ok) {
+ Minz_Log::error("Could not save Fever API credentials. The directory does not have write access.");
+ }
+ return $ok;
+ }
+
+ /**
+ * Return the corresponding path for a fever key.
+ *
+ * @param string
+ * @return string
+ */
+ public static function getKeyPath($feverKey) {
+ $salt = sha1(FreshRSS_Context::$system_conf->salt);
+ return self::FEVER_PATH . '/.key-' . $salt . '-' . $feverKey . '.txt';
+ }
+
+ /**
+ * Update the fever key of a user.
+ *
+ * @param string
+ * @param string
+ * @return string the Fever key, or false if the update failed
+ */
+ public static function updateKey($username, $passwordPlain) {
+ $ok = self::checkFeverPath();
+ if (!$ok) {
+ return false;
+ }
+
+ self::deleteKey($username);
+
+ $feverKey = strtolower(md5("{$username}:{$passwordPlain}"));
+ $feverKeyPath = self::getKeyPath($feverKey);
+ $res = file_put_contents($feverKeyPath, $username);
+ if ($res !== false) {
+ return $feverKey;
+ } else {
+ Minz_Log::warning('Could not save Fever API credentials. Unknown error.', ADMIN_LOG);
+ return false;
+ }
+ }
+
+ /**
+ * Delete the Fever key of a user.
+ *
+ * @param string
+ * @return boolean true if the deletion succeeded, else false.
+ */
+ public static function deleteKey($username) {
+ $userConfig = get_user_configuration($username);
+ if ($userConfig === null) {
+ return false;
+ }
+
+ $feverKey = $userConfig->feverKey;
+ if (!ctype_xdigit($feverKey)) {
+ return false;
+ }
+
+ $feverKeyPath = self::getKeyPath($feverKey);
+ return @unlink($feverKeyPath);
+ }
+}
diff --git a/app/Utils/passwordUtil.php b/app/Utils/passwordUtil.php
new file mode 100644
index 000000000..fd71d4b72
--- /dev/null
+++ b/app/Utils/passwordUtil.php
@@ -0,0 +1,27 @@
+<?php
+
+class FreshRSS_password_Util {
+ // Will also have to be computed client side on mobile devices,
+ // so do not use a too high cost
+ const BCRYPT_COST = 9;
+
+ /**
+ * Return a hash of a plain password, using BCRYPT
+ *
+ * @param string
+ * @return string
+ */
+ public static function hash($passwordPlain) {
+ $passwordHash = password_hash(
+ $passwordPlain,
+ PASSWORD_BCRYPT,
+ array('cost' => self::BCRYPT_COST)
+ );
+ $passwordPlain = '';
+
+ // Compatibility with bcrypt.js
+ $passwordHash = preg_replace('/^\$2[xy]\$/', '\$2a\$', $passwordHash);
+
+ return $passwordHash == '' ? '' : $passwordHash;
+ }
+}
diff --git a/app/i18n/cz/conf.php b/app/i18n/cz/conf.php
index 056e895a7..f066ac9a4 100644
--- a/app/i18n/cz/conf.php
+++ b/app/i18n/cz/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Správa profilu',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Smazání účtu',
'warn' => 'Váš účet bude smazán spolu se všemi souvisejícími daty',
diff --git a/app/i18n/cz/feedback.php b/app/i18n/cz/feedback.php
index 3d0dcbc96..ad3d38cf0 100644
--- a/app/i18n/cz/feedback.php
+++ b/app/i18n/cz/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Nemáte oprávnění přistupovat na tuto stránku',
'not_found' => 'Tato stránka neexistuje',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Nastal problém s konfigurací přihlašovacího systému. Zkuste to prosím později.',
diff --git a/app/i18n/de/conf.php b/app/i18n/de/conf.php
index b08694eee..2d9b91260 100644
--- a/app/i18n/de/conf.php
+++ b/app/i18n/de/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Profil-Verwaltung',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Accountlöschung',
'warn' => 'Dein Account und alle damit bezogenen Daten werden gelöscht.',
diff --git a/app/i18n/de/feedback.php b/app/i18n/de/feedback.php
index 269069162..446aa2a04 100644
--- a/app/i18n/de/feedback.php
+++ b/app/i18n/de/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Sie haben nicht die Berechtigung, diese Seite aufzurufen',
'not_found' => 'Sie suchen nach einer Seite, die nicht existiert',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Während der Konfiguration des Authentifikationssystems trat ein Fehler auf. Bitte versuchen Sie es später erneut.',
diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php
index 2d4e06550..f01de649a 100644
--- a/app/i18n/en/conf.php
+++ b/app/i18n/en/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Profile management',
+ 'api' => 'API management',
'delete' => array(
'_' => 'Account deletion',
'warn' => 'Your account and all related data will be deleted.',
diff --git a/app/i18n/en/feedback.php b/app/i18n/en/feedback.php
index 2322a62cc..89bbd4154 100644
--- a/app/i18n/en/feedback.php
+++ b/app/i18n/en/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'You don’t have permission to access this page',
'not_found' => 'You are looking for a page which doesn’t exist',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified',
+ 'updated' => 'Your password has been modified',
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'A problem occured during authentication system configuration. Please retry later.',
diff --git a/app/i18n/es/conf.php b/app/i18n/es/conf.php
index 7a93a87de..fcbe9b984 100755
--- a/app/i18n/es/conf.php
+++ b/app/i18n/es/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Administración de perfiles',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Borrar cuenta',
'warn' => 'Tu cuenta y todos los datos asociados serán eliminados.',
diff --git a/app/i18n/es/feedback.php b/app/i18n/es/feedback.php
index d70ccfe8a..5a7358b0d 100755
--- a/app/i18n/es/feedback.php
+++ b/app/i18n/es/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'No dispones de permiso para acceder a esta página',
'not_found' => 'La página que buscas no existe',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Hubo un problema durante la configuración del sistema de idenfificación. Por favor, inténtalo más tarde.',
diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php
index 020c94085..b51d123f1 100644
--- a/app/i18n/fr/conf.php
+++ b/app/i18n/fr/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Gestion du profil',
+ 'api' => 'Gestion de l’API',
'delete' => array(
'_' => 'Suppression du compte',
'warn' => 'Le compte et toutes les données associées vont être supprimées.',
diff --git a/app/i18n/fr/feedback.php b/app/i18n/fr/feedback.php
index 328113c25..f4b3ba245 100644
--- a/app/i18n/fr/feedback.php
+++ b/app/i18n/fr/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Vous n’avez pas le droit d’accéder à cette page !',
'not_found' => 'La page que vous cherchez n’existe pas !',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Votre mot de passe n’a pas pu être mis à jour',
+ 'updated' => 'Votre mot de passe a été mis à jour',
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Un problème est survenu lors de la configuration de votre système d’authentification. Veuillez réessayer plus tard.',
diff --git a/app/i18n/he/conf.php b/app/i18n/he/conf.php
index b987f21f4..d83d688d5 100644
--- a/app/i18n/he/conf.php
+++ b/app/i18n/he/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Profile management', //TODO - Translation
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Account deletion', //TODO - Translation
'warn' => 'Your account and all related data will be deleted.', //TODO - Translation
diff --git a/app/i18n/he/feedback.php b/app/i18n/he/feedback.php
index f972173cb..026e93450 100644
--- a/app/i18n/he/feedback.php
+++ b/app/i18n/he/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'אין לך הרשאות לצפות בדף זה',
'not_found' => 'הדף הזה לא נמצא',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'אירעה שגיאה במהלך הגדרת מערכת האימיות. אנא נסו שוב מאוחר יותר.',
diff --git a/app/i18n/it/conf.php b/app/i18n/it/conf.php
index 4bdaad33d..6dd390ebd 100644
--- a/app/i18n/it/conf.php
+++ b/app/i18n/it/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Gestione profili',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Cancellazione account',
'warn' => 'Il tuo account e tutti i dati associati saranno cancellati.',
diff --git a/app/i18n/it/feedback.php b/app/i18n/it/feedback.php
index ca7879904..f137de9e8 100644
--- a/app/i18n/it/feedback.php
+++ b/app/i18n/it/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Non hai i permessi per accedere a questa pagina',
'not_found' => 'Pagina non disponibile',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Si è verificato un problema alla configurazione del sistema di autenticazione. Per favore riprova più tardi.',
diff --git a/app/i18n/kr/conf.php b/app/i18n/kr/conf.php
index 1e77d0098..219feab49 100644
--- a/app/i18n/kr/conf.php
+++ b/app/i18n/kr/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => '프로필 관리',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => '계정 삭제',
'warn' => '당신의 계정과 관련된 모든 데이터가 삭제됩니다.',
diff --git a/app/i18n/kr/feedback.php b/app/i18n/kr/feedback.php
index 0e31536f8..1ea58388b 100644
--- a/app/i18n/kr/feedback.php
+++ b/app/i18n/kr/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => '이 페이지에 접근할 수 있는 권한이 없습니다',
'not_found' => '이 페이지는 존재하지 않습니다',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => '인증 시스템을 설정하는 동안 문제가 발생했습니다. 잠시 후 다시 시도하세요.',
diff --git a/app/i18n/nl/conf.php b/app/i18n/nl/conf.php
index ca6627cbb..fdd82f7c2 100644
--- a/app/i18n/nl/conf.php
+++ b/app/i18n/nl/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Profiel beheer',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Account verwijderen',
'warn' => 'Uw account en alle gerelateerde gegvens worden verwijderd.',
diff --git a/app/i18n/nl/feedback.php b/app/i18n/nl/feedback.php
index 97e1a71b8..dafbb9d68 100644
--- a/app/i18n/nl/feedback.php
+++ b/app/i18n/nl/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'U hebt geen rechten om deze pagina te bekijken.',
'not_found' => 'Deze pagina bestaat niet',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Er is een probleem opgetreden tijdens de controle van de systeemconfiguratie. Probeer het later nog eens.',
diff --git a/app/i18n/oc/conf.php b/app/i18n/oc/conf.php
index e123c03c5..98758be28 100644
--- a/app/i18n/oc/conf.php
+++ b/app/i18n/oc/conf.php
@@ -51,6 +51,7 @@ return array(
),
'profile' => array(
'_' => 'Gestion del perfil',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Supression del compte',
'warn' => 'Lo compte e totas las donadas ligadas seràn suprimits.',
diff --git a/app/i18n/oc/feedback.php b/app/i18n/oc/feedback.php
index 7f7d05dbd..a37ad2ae2 100644
--- a/app/i18n/oc/feedback.php
+++ b/app/i18n/oc/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Avètz pas l’autorizacion d’accedir a aquesta pagina',
'not_found' => 'La pagina que cercatz existís pas',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Un problèma es aparegut pendent la configuracion del sistèma d’autentificacion. Tonatz ensajar ai tard.',
diff --git a/app/i18n/pt-br/conf.php b/app/i18n/pt-br/conf.php
index 5e43cc373..d2a60aba8 100644
--- a/app/i18n/pt-br/conf.php
+++ b/app/i18n/pt-br/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Gerenciamento de perfil',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Remover conta',
'warn' => 'Sua conta e todos os dados relacionados serão removidos.',
diff --git a/app/i18n/pt-br/feedback.php b/app/i18n/pt-br/feedback.php
index 816bbf43b..d15080964 100644
--- a/app/i18n/pt-br/feedback.php
+++ b/app/i18n/pt-br/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Você não tem permissão para acessar esta página',
'not_found' => 'VocÊ está buscando por uma página que não existe',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Um problema ocorreu durante o sistema de configuração para autenticação. Por favor tente mais tarde.',
diff --git a/app/i18n/ru/conf.php b/app/i18n/ru/conf.php
index 7a80587f8..96a307976 100644
--- a/app/i18n/ru/conf.php
+++ b/app/i18n/ru/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Profile management', //TODO - Translation
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Account deletion', //TODO - Translation
'warn' => 'Your account and all the related data will be deleted.', //TODO - Translation
diff --git a/app/i18n/ru/feedback.php b/app/i18n/ru/feedback.php
index 7b859fcdd..449d01ee4 100644
--- a/app/i18n/ru/feedback.php
+++ b/app/i18n/ru/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'You don’t have permission to access this page', //TODO - Translation
'not_found' => 'You are looking for a page which doesn’t exist', //TODO - Translation
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'A problem occured during authentication system configuration. Please retry later.', //TODO - Translation
diff --git a/app/i18n/sk/conf.php b/app/i18n/sk/conf.php
index 2e2289b79..be6fdce4f 100644
--- a/app/i18n/sk/conf.php
+++ b/app/i18n/sk/conf.php
@@ -42,6 +42,7 @@ return array(
),
'profile' => array(
'_' => 'Správca profilu',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Vymazanie účtu',
'warn' => 'Váš účet a všetky údaje v ňom budú vymazané.',
diff --git a/app/i18n/sk/feedback.php b/app/i18n/sk/feedback.php
index 9aee79068..5bccd8259 100644
--- a/app/i18n/sk/feedback.php
+++ b/app/i18n/sk/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Na prístup k tejto stránke nemáte oprávnenie',
'not_found' => 'Hľadáte stránku, ktorá neexistuje',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Nastavl problém pri nastavovaní prihlasovacieho systému. Prosím, skúste to znova neskôr.',
diff --git a/app/i18n/tr/conf.php b/app/i18n/tr/conf.php
index c8ea78efa..25eaedc55 100644
--- a/app/i18n/tr/conf.php
+++ b/app/i18n/tr/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => 'Profil yönetimi',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => 'Hesap silme',
'warn' => 'Hesabınız ve tüm verileriniz silinecek.',
diff --git a/app/i18n/tr/feedback.php b/app/i18n/tr/feedback.php
index fc1e59bbc..73489c723 100644
--- a/app/i18n/tr/feedback.php
+++ b/app/i18n/tr/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => 'Bu sayfaya erişim yetkiniz yok',
'not_found' => 'Varolmayan bir sayfa arıyorsunuz',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => 'Sistem yapılandırma kimlik doğrulaması sırasında hata oldu. Lütfen daha sonra tekrar deneyin.',
diff --git a/app/i18n/zh-cn/conf.php b/app/i18n/zh-cn/conf.php
index a7404bc58..485da16f2 100644
--- a/app/i18n/zh-cn/conf.php
+++ b/app/i18n/zh-cn/conf.php
@@ -50,6 +50,7 @@ return array(
),
'profile' => array(
'_' => '帐户管理',
+ 'api' => 'API management', // TODO - Translation
'delete' => array(
'_' => '账户删除',
'warn' => '你的帐户和所有相关数据都将被删除。',
diff --git a/app/i18n/zh-cn/feedback.php b/app/i18n/zh-cn/feedback.php
index e8ee969b0..9dbc45cf5 100644
--- a/app/i18n/zh-cn/feedback.php
+++ b/app/i18n/zh-cn/feedback.php
@@ -8,6 +8,12 @@ return array(
'denied' => '你无权访问此页面',
'not_found' => '你寻找的页面不存在',
),
+ 'api' => array(
+ 'password' => array(
+ 'failed' => 'Your password cannot be modified', // TODO - Translation
+ 'updated' => 'Your password has been modified', // TODO - Translation
+ ),
+ ),
'auth' => array(
'form' => array(
'not_set' => '配置认证方式时出错。请稍后重试。',
diff --git a/app/install.php b/app/install.php
index 557ae9eab..3737e2ccc 100644
--- a/app/install.php
+++ b/app/install.php
@@ -221,7 +221,6 @@ function saveStep3() {
$_SESSION['default_user'],
'', //TODO: Add e-mail
$password_plain,
- '',
[
'language' => $_SESSION['language'],
]
diff --git a/app/views/user/profile.phtml b/app/views/user/profile.phtml
index b8bb5cee9..5357c2bfd 100644
--- a/app/views/user/profile.phtml
+++ b/app/views/user/profile.phtml
@@ -48,19 +48,6 @@
</div>
</div>
- <?php if (FreshRSS_Context::$system_conf->api_enabled) { ?>
- <div class="form-group">
- <label class="group-name" for="apiPasswordPlain"><?= _t('conf.profile.password_api') ?></label>
- <div class="group-controls">
- <div class="stick">
- <input type="password" id="apiPasswordPlain" name="apiPasswordPlain" autocomplete="new-password" pattern=".{7,}" <?= cryptAvailable() ? '' : 'disabled="disabled" ' ?>/>
- <a class="btn toggle-password" data-toggle="apiPasswordPlain"><?= _i('key') ?></a>
- </div>
- <?= _i('help') ?> <kbd><a href="../api/"><?= Minz_Url::display('/api/', 'html', true) ?></a></kbd>
- </div>
- </div>
- <?php } ?>
-
<?php if (FreshRSS_Auth::accessNeedsAction()) { ?>
<div class="form-group">
<label class="group-name" for="token"><?= _t('admin.auth.token') ?></label>
@@ -82,6 +69,30 @@
</div>
</form>
+ <?php if (FreshRSS_Context::$system_conf->api_enabled) { ?>
+ <form method="post" action="<?= _url('api', 'updatePassword') ?>">
+ <input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
+ <legend><?= _t('conf.profile.api') ?></legend>
+
+ <div class="form-group">
+ <label class="group-name" for="apiPasswordPlain"><?= _t('conf.profile.password_api') ?></label>
+ <div class="group-controls">
+ <div class="stick">
+ <input type="password" id="apiPasswordPlain" name="apiPasswordPlain" autocomplete="new-password" pattern=".{7,}" <?= cryptAvailable() ? '' : 'disabled="disabled" ' ?>/>
+ <a class="btn toggle-password" data-toggle="apiPasswordPlain"><?= _i('key') ?></a>
+ </div>
+ <?= _i('help') ?> <kbd><a href="../api/"><?= Minz_Url::display('/api/', 'html', true) ?></a></kbd>
+ </div>
+ </div>
+
+ <div class="form-group form-actions">
+ <div class="group-controls">
+ <button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
+ </div>
+ </div>
+ </form>
+ <?php } ?>
+
<?php if (!FreshRSS_Auth::hasAccess('admin')) { ?>
<form id="crypto-form" method="post" action="<?= _url('user', 'delete') ?>">
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
diff --git a/cli/_update-or-create-user.php b/cli/_update-or-create-user.php
index 43b86a4a9..3217a07ea 100644
--- a/cli/_update-or-create-user.php
+++ b/cli/_update-or-create-user.php
@@ -4,7 +4,6 @@ require(__DIR__ . '/_cli.php');
$params = array(
'user:',
'password:',
- 'api_password:',
'language:',
'email:',
'token:',
@@ -24,7 +23,7 @@ $options = getopt('', $params);
if (!validateOptions($argv, $params) || empty($options['user'])) {
fail('Usage: ' . basename($_SERVER['SCRIPT_FILENAME']) .
- " --user username ( --password 'password' --api_password 'api_password'" .
+ " --user username ( --password 'password'" .
" --language en --email user@example.net --token 'longRandomString'" .
($isUpdate ? '' : '--no_default_feeds') .
" --purge_after_months 3 --feed_min_articles_default 50 --feed_ttl_default 3600" .
diff --git a/cli/create-user.php b/cli/create-user.php
index 7e0a031d9..9e978ee3c 100755
--- a/cli/create-user.php
+++ b/cli/create-user.php
@@ -20,7 +20,6 @@ $ok = FreshRSS_user_Controller::createUser(
$username,
empty($options['mail_login']) ? '' : $options['mail_login'],
empty($options['password']) ? '' : $options['password'],
- empty($options['api_password']) ? '' : $options['api_password'],
$values,
!isset($options['no_default_feeds'])
);
diff --git a/cli/update-user.php b/cli/update-user.php
index 8067dadd3..02da16d5a 100755
--- a/cli/update-user.php
+++ b/cli/update-user.php
@@ -11,7 +11,6 @@ $ok = FreshRSS_user_Controller::updateUser(
$username,
empty($options['mail_login']) ? null : $options['mail_login'],
empty($options['password']) ? '' : $options['password'],
- empty($options['api_password']) ? '' : $options['api_password'],
$values);
if (!$ok) {