Implémentation de l'indentification par mot de passe

Implémentation de
https://github.com/marienfressinaud/FreshRSS/issues/104
pull/384/head
Alexandre Alapetite 11 years ago
parent 43f1b227b4
commit d58886a937
  1. 3
      CHANGELOG
  2. 52
      app/Controllers/indexController.php
  3. 12
      app/Controllers/javascriptController.php
  4. 26
      app/Controllers/usersController.php
  5. 27
      app/FreshRSS.php
  6. 7
      app/i18n/en.php
  7. 7
      app/i18n/fr.php
  8. 51
      app/layout/header.phtml
  9. 16
      app/views/configure/users.phtml
  10. 4
      app/views/helpers/javascript_vars.phtml
  11. 43
      app/views/helpers/view/login.phtml
  12. 14
      app/views/index/index.phtml
  13. 3
      lib/Minz/Configuration.php
  14. 2
      lib/Minz/FrontController.php
  15. 57
      p/scripts/main.js

@ -5,6 +5,8 @@
* Nouveau mode multi-utilisateur
* L’utilisateur par défaut (administrateur) peut créer et supprimer d’autres utilisateurs
* Nécessite un contrôle d’accès, soit :
* par le nouveau mode de connexion par formulaire (nom d’utilisateur + mot de passe)
* relativement sûr même sans HTTPS (le mot de passe n’est pas transmis en clair)
* par HTTP (par exemple sous Apache en créant un fichier ./p/i/.htaccess et .htpasswd)
* le nom d’utilisateur HTTP doit correspondre au nom d’utilisateur FreshRSS
* par Mozilla Persona, en renseignant l’adresse courriel des utilisateurs
@ -68,6 +70,7 @@
* Réorganisation des fichiers et répertoires, en particulier :
* Tous les fichiers utilisateur sont dans “./data/” (y compris “cache”, “favicons”, et “log”)
* Déplacement de “./app/configuration/application.ini” vers “./data/config.php”
* Meilleure sécurité et compatibilité
* Déplacement de “./public/data/Configuration.array.php” vers “./data/*_user.php”
* Déplacement de “./public/” vers “./p/”
* Déplacement de “./public/index.php” vers “./p/i/index.php” (voir cookie ci-dessous)

@ -47,8 +47,6 @@ class FreshRSS_index_Controller extends Minz_ActionController {
$this->view->_useLayout (false);
header('Content-Type: application/rss+xml; charset=utf-8');
} else {
Minz_View::appendScript (Minz_Url::display ('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js')));
if ($output === 'global') {
Minz_View::appendScript (Minz_Url::display ('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js')));
}
@ -290,8 +288,56 @@ class FreshRSS_index_Controller extends Minz_ActionController {
}
public function logoutAction () {
$this->view->_useLayout(false);
invalidateHttpCache();
Minz_Session::_param('currentUser');
Minz_Session::_param('mail');
Minz_Session::_param('passwordHash');
}
public function formLoginAction () {
$this->view->_useLayout (false);
Minz_Session::_param ('mail');
if (Minz_Request::isPost()) {
$ok = false;
$nonce = Minz_Session::param('nonce');
$username = Minz_Request::param('username', '');
$c = Minz_Request::param('challenge', '');
if (ctype_alnum($username) && ctype_graph($c) && ctype_alnum($nonce)) {
if (!function_exists('password_verify')) {
include_once(LIB_PATH . '/password_compat.php');
}
try {
$conf = new FreshRSS_Configuration($username);
$s = $conf->passwordHash;
$ok = password_verify($nonce . $s, $c);
if ($ok) {
Minz_Session::_param('currentUser', $username);
Minz_Session::_param('passwordHash', $s);
} else {
Minz_Log::record('Password mismatch for user ' . $username . ', nonce=' . $nonce . ', c=' . $c, Minz_Log::WARNING);
}
} catch (Minz_Exception $me) {
Minz_Log::record('Login failure: ' . $me->getMessage(), Minz_Log::WARNING);
}
}
if (!$ok) {
$notif = array(
'type' => 'bad',
'content' => Minz_Translate::t('invalid_login')
);
Minz_Session::_param('notification', $notif);
}
}
invalidateHttpCache();
Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true);
}
public function formLogoutAction () {
$this->view->_useLayout(false);
invalidateHttpCache();
Minz_Session::_param('currentUser');
Minz_Session::_param('mail');
Minz_Session::_param('passwordHash');
Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true);
}
}

@ -17,7 +17,7 @@ class FreshRSS_javascript_Controller extends Minz_ActionController {
$this->view->categories = $catDAO->listCategories(true, false);
}
// For Web-form login
//For Web-form login
public function nonceAction() {
header('Content-Type: application/json; charset=UTF-8');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T'));
@ -29,15 +29,15 @@ class FreshRSS_javascript_Controller extends Minz_ActionController {
if (ctype_alnum($user)) {
try {
$conf = new FreshRSS_Configuration($user);
$hash = $conf->passwordHash; //CRYPT_BLOWFISH - Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z".
if (strlen($hash) >= 60) {
$this->view->salt1 = substr($hash, 0, 29);
$s = $conf->passwordHash;
if (strlen($s) >= 60) {
$this->view->salt1 = substr($s, 0, 29); //CRYPT_BLOWFISH Salt: "$2a$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z".
$this->view->nonce = sha1(Minz_Configuration::salt() . uniqid(mt_rand(), true));
Minz_Session::_param ('nonce', $this->view->nonce);
Minz_Session::_param('nonce', $this->view->nonce);
return; //Success
}
} catch (Minz_Exception $me) {
Minz_Log::record ('Login failure: ' . $me->getMessage(), Minz_Log::WARNING);
Minz_Log::record('Login failure: ' . $me->getMessage(), Minz_Log::WARNING);
}
}
$this->view->nonce = ''; //Failure

@ -21,18 +21,20 @@ class FreshRSS_users_Controller extends Minz_ActionController {
if (!function_exists('password_hash')) {
include_once(LIB_PATH . '/password_compat.php');
}
$passwordHash = password_hash($passwordPlain, PASSWORD_BCRYPT); //A bit expensive, on purpose
$passwordHash = password_hash($passwordPlain, PASSWORD_BCRYPT, array('cost' => 8)); //This will also have to be computed client side on mobile devices, so do not use a too high cost
$passwordPlain = '';
$passwordHash = preg_replace('/^\$2[xy]\$/', '\$2a\$', $passwordHash); //Compatibility with bcrypt.js
$this->view->conf->_passwordHash($passwordHash);
}
$mail = Minz_Request::param('mail_login', false);
$this->view->conf->_mail_login($mail);
$email = Minz_Request::param('mail_login', false);
$this->view->conf->_mail_login($email);
$ok &= $this->view->conf->save();
$email = $this->view->conf->mail_login;
Minz_Session::_param('mail', $email);
Minz_Session::_param('passwordHash', $this->view->conf->passwordHash);
if ($email != '') {
$personaFile = DATA_PATH . '/persona/' . $email . '.txt';
@ -89,10 +91,25 @@ class FreshRSS_users_Controller extends Minz_ActionController {
$ok &= !file_exists($configPath);
}
if ($ok) {
$passwordPlain = Minz_Request::param('new_user_passwordPlain', false);
$passwordHash = '';
if ($passwordPlain != '') {
Minz_Request::_param('new_user_passwordPlain'); //Discard plain-text password ASAP
$_POST['new_user_passwordPlain'] = '';
if (!function_exists('password_hash')) {
include_once(LIB_PATH . '/password_compat.php');
}
$passwordHash = password_hash($passwordPlain, PASSWORD_BCRYPT, array('cost' => 8));
$passwordPlain = '';
}
if (empty($passwordHash)) {
$passwordHash = '';
}
$new_user_email = filter_var($_POST['new_user_email'], FILTER_VALIDATE_EMAIL);
if (empty($new_user_email)) {
$new_user_email = '';
$ok &= Minz_Configuration::authType() !== 'persona';
} else {
$personaFile = DATA_PATH . '/persona/' . $new_user_email . '.txt';
@unlink($personaFile);
@ -102,6 +119,7 @@ class FreshRSS_users_Controller extends Minz_ActionController {
if ($ok) {
$config_array = array(
'language' => $new_user_language,
'passwordHash' => $passwordHash,
'mail_login' => $new_user_email,
);
$ok &= (file_put_contents($configPath, "<?php\n return " . var_export($config_array, true) . ';') !== false);

@ -4,15 +4,20 @@ class FreshRSS extends Minz_FrontController {
if (!isset($_SESSION)) {
Minz_Session::init('FreshRSS');
}
$this->accessControl(Minz_Session::param('currentUser', ''));
$loginOk = $this->accessControl(Minz_Session::param('currentUser', ''));
$this->loadParamsView();
$this->loadStylesAndScripts(); //TODO: Do not load that when not needed, e.g. some Ajax requests
$this->loadStylesAndScripts($loginOk); //TODO: Do not load that when not needed, e.g. some Ajax requests
$this->loadNotifications();
}
private function accessControl($currentUser) {
if ($currentUser == '') {
switch (Minz_Configuration::authType()) {
case 'form':
$currentUser = Minz_Configuration::defaultUser();
Minz_Session::_param('passwordHash');
$loginOk = false;
break;
case 'http_auth':
$currentUser = httpAuthUser();
$loginOk = $currentUser != '';
@ -73,6 +78,9 @@ class FreshRSS extends Minz_FrontController {
if ($loginOk) {
switch (Minz_Configuration::authType()) {
case 'form':
$loginOk = Minz_Session::param('passwordHash') === $this->conf->passwordHash;
break;
case 'http_auth':
$loginOk = strcasecmp($currentUser, httpAuthUser()) === 0;
break;
@ -92,6 +100,7 @@ class FreshRSS extends Minz_FrontController {
}
}
Minz_View::_param ('loginOk', $loginOk);
return $loginOk;
}
private function loadParamsView () {
@ -104,7 +113,7 @@ class FreshRSS extends Minz_FrontController {
}
}
private function loadStylesAndScripts () {
private function loadStylesAndScripts ($loginOk) {
$theme = FreshRSS_Themes::get_infos($this->conf->theme);
if ($theme) {
foreach($theme['files'] as $file) {
@ -112,14 +121,22 @@ class FreshRSS extends Minz_FrontController {
}
}
if (Minz_Configuration::authType() === 'persona') {
Minz_View::appendScript ('https://login.persona.org/include.js');
switch (Minz_Configuration::authType()) {
case 'form':
if (!$loginOk) {
Minz_View::appendScript(Minz_Url::display ('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js')));
}
break;
case 'persona':
Minz_View::appendScript('https://login.persona.org/include.js');
break;
}
$includeLazyLoad = $this->conf->lazyload && ($this->conf->display_posts || Minz_Request::param ('output') === 'reader');
Minz_View::appendScript (Minz_Url::display ('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')), false, !$includeLazyLoad, !$includeLazyLoad);
if ($includeLazyLoad) {
Minz_View::appendScript (Minz_Url::display ('/scripts/jquery.lazyload.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.lazyload.min.js')));
}
Minz_View::appendScript (Minz_Url::display ('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js')));
Minz_View::appendScript (Minz_Url::display ('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js')));
}

@ -170,6 +170,9 @@ return array (
'is_admin' => 'is administrator',
'auth_type' => 'Authentication method',
'auth_none' => 'None (dangerous)',
'auth_form' => 'Web form (traditional, requires JavaScript)',
'http_auth' => 'HTTP (for advanced users with HTTPS)',
'auth_persona' => 'Mozilla Persona (modern, requires JavaScript)',
'users_list' => 'List of users',
'create_user' => 'Create new user',
'username' => 'Username',
@ -258,8 +261,8 @@ return array (
'logs_empty' => 'Log file is empty',
'clear_logs' => 'Clear the logs',
'forbidden_access' => 'Forbidden access',
'forbidden_access_description' => 'Access is password protected, please <a class="signin" href="#">sign in</a> to read your feeds.',
'forbidden_access' => 'Access forbidden! (%s)',
'login_required' => 'Login required:',
'confirm_action' => 'Are you sure you want to perform this action? It cannot be cancelled!',

@ -170,6 +170,9 @@ return array (
'is_admin' => 'est administrateur',
'auth_type' => 'Méthode d’authentification',
'auth_none' => 'Aucune (dangereux)',
'auth_form' => 'Formulaire (traditionnel, requiert JavaScript)',
'http_auth' => 'HTTP (pour utilisateurs avancés avec HTTPS)',
'auth_persona' => 'Mozilla Persona (moderne, requiert JavaScript)',
'users_list' => 'Liste des utilisateurs',
'create_user' => 'Créer un nouvel utilisateur',
'username' => 'Nom d’utilisateur',
@ -258,8 +261,8 @@ return array (
'logs_empty' => 'Les logs sont vides',
'clear_logs' => 'Effacer les logs',
'forbidden_access' => 'Accès interdit',
'forbidden_access_description' => 'L’accès est protégé par un mot de passe, veuillez <a class="signin" href="#">vous connecter</a> pour accéder aux flux.',
'forbidden_access' => 'Accès interdit ! (%s)',
'login_required' => 'Accès protégé par mot de passe :',
'confirm_action' => 'Êtes-vous sûr(e) de vouloir continuer ? Cette action ne peut être annulée !',

@ -1,12 +1,25 @@
<?php if (Minz_Configuration::canLogIn()) { ?>
<ul class="nav nav-head nav-login">
<?php if ($this->loginOk) { ?>
<li class="item"><?php echo FreshRSS_Themes::icon('logout'); ?> <a class="signout" href="#"><?php echo Minz_Translate::t ('logout'); ?></a></li>
<?php } else { ?>
<li class="item"><?php echo FreshRSS_Themes::icon('login'); ?> <a class="signin" href="#"><?php echo Minz_Translate::t ('login'); ?></a></li>
<?php } ?>
</ul>
<?php } ?>
<?php
if (Minz_Configuration::canLogIn()) {
?><ul class="nav nav-head nav-login"><?php
switch (Minz_Configuration::authType()) {
case 'form':
if ($this->loginOk) {
?><li class="item"><?php echo FreshRSS_Themes::icon('logout'); ?> <a class="signout" href="<?php echo _url ('index', 'formLogout'); ?>"><?php echo Minz_Translate::t ('logout'); ?></a></li><?php
} else {
?><li class="item"><?php echo FreshRSS_Themes::icon('login'); ?> <a class="signin" href="<?php echo _url ('index', 'formLogin'); ?>"><?php echo Minz_Translate::t ('login'); ?></a></li><?php
}
break;
case 'persona':
if ($this->loginOk) {
?><li class="item"><?php echo FreshRSS_Themes::icon('logout'); ?> <a class="signout" href="#"><?php echo Minz_Translate::t ('logout'); ?></a></li><?php
} else {
?><li class="item"><?php echo FreshRSS_Themes::icon('login'); ?> <a class="signin" href="#"><?php echo Minz_Translate::t ('login'); ?></a></li><?php
}
break;
}
?></ul><?php
}
?>
<div class="header">
<div class="item title">
@ -62,16 +75,24 @@
<li class="separator"></li>
<li class="item"><a href="<?php echo _url ('index', 'about'); ?>"><?php echo Minz_Translate::t ('about'); ?></a></li>
<li class="item"><a href="<?php echo _url ('index', 'logs'); ?>"><?php echo Minz_Translate::t ('logs'); ?></a></li>
<?php if (Minz_Configuration::canLogIn()) { ?>
<li class="separator"></li>
<li class="item"><a class="signout" href="#"><?php echo FreshRSS_Themes::icon('logout'); ?> <?php echo Minz_Translate::t ('logout'); ?></a></li>
<?php } ?>
<?php
if (Minz_Configuration::canLogIn()) {
?><li class="separator"></li><?php
switch (Minz_Configuration::authType()) {
case 'form':
?><li class="item"><a class="signout" href="<?php echo _url ('index', 'formLogout'); ?>"><?php echo FreshRSS_Themes::icon('logout'), ' ', Minz_Translate::t ('logout'); ?></a></li><?php
break;
case 'persona':
?><li class="item"><a class="signout" href="#"><?php echo FreshRSS_Themes::icon('logout'), ' ', Minz_Translate::t ('logout'); ?></a></li><?php
break;
}
} ?>
</ul>
</div>
</div>
<?php } elseif (Minz_Configuration::canLogIn()) { ?>
<?php }/* elseif (Minz_Configuration::authType() === 'persona') { ?>
<div class="item configure">
<?php echo FreshRSS_Themes::icon('login'); ?> <a class="signin" href="#"><?php echo Minz_Translate::t ('login'); ?></a>
</div>
<?php } ?>
<?php }*/ ?>
</div>

@ -20,7 +20,7 @@
<div class="form-group">
<label class="group-name" for="passwordPlain"><?php echo Minz_Translate::t('password'); ?></label>
<div class="group-controls">
<input type="password" id="passwordPlain" name="passwordPlain" />
<input type="password" id="passwordPlain" name="passwordPlain" pattern=".{7,}" />
<noscript><b><?php echo Minz_Translate::t('javascript_should_be_activated'); ?></b></noscript>
</div>
</div>
@ -52,11 +52,11 @@
<div class="group-controls">
<select id="auth_type" name="auth_type" required="required">
<option value=""></option>
<option value="form"<?php echo Minz_Configuration::authType() === 'form' ? ' selected="selected"' : ''; ?>><?php echo Minz_Translate::t('auth_form'); ?></option>
<option value="persona"<?php echo Minz_Configuration::authType() === 'persona' ? ' selected="selected"' : '', $this->conf->mail_login == '' ? ' disabled="disabled"' : ''; ?>><?php echo Minz_Translate::t('auth_persona'); ?></option>
<option value="http_auth"<?php echo Minz_Configuration::authType() === 'http_auth' ? ' selected="selected"' : '', httpAuthUser() == '' ? ' disabled="disabled"' : ''; ?>><?php echo Minz_Translate::t('http_auth'); ?> (REMOTE_USER = '<?php echo httpAuthUser(); ?>')</option>
<option value="none"<?php echo Minz_Configuration::authType() === 'none' ? ' selected="selected"' : ''; ?>><?php echo Minz_Translate::t('auth_none'); ?></option>
<option value="http_auth"<?php echo Minz_Configuration::authType() === 'http_auth' ? ' selected="selected"' : '', httpAuthUser() == '' ? ' disabled="disabled"' : ''; ?>>HTTP Auth</option>
<option value="persona"<?php echo Minz_Configuration::authType() === 'persona' ? ' selected="selected"' : '', $this->conf->mail_login == '' ? ' disabled="disabled"' : ''; ?>>Mozilla Persona</option>
</select>
<code>$_SERVER['REMOTE_USER'] = `<?php echo httpAuthUser(); ?>`</code>
</div>
</div>
@ -141,6 +141,14 @@
</div>
</div>
<div class="form-group">
<label class="group-name" for="new_user_passwordPlain"><?php echo Minz_Translate::t('password'); ?></label>
<div class="group-controls">
<input type="password" id="new_user_passwordPlain" name="new_user_passwordPlain" pattern=".{7,}" />
<noscript><b><?php echo Minz_Translate::t('javascript_should_be_activated'); ?></b></noscript>
</div>
</div>
<div class="form-group">
<label class="group-name" for="new_user_email"><?php echo Minz_Translate::t('persona_connection_email'); ?></label>
<?php $mail = $this->conf->mail_login; ?>

@ -30,8 +30,8 @@
if ($mail != 'null') {
$mail = '"' . $mail . '"';
}
echo 'use_persona=', Minz_Configuration::authType() === 'persona' ? 'true' : 'false',
',url_freshrss="', _url ('index', 'index'), '",',
echo 'authType="', Minz_Configuration::authType(), '",',
'url_freshrss="', _url ('index', 'index'), '",',
'url_login="', _url ('index', 'login'), '",',
'url_logout="', _url ('index', 'logout'), '",',
'current_user_mail=', $mail, ",\n";

@ -0,0 +1,43 @@
<div class="post content">
<?php
if (Minz_Configuration::canLogIn()) {
?><h1><?php echo Minz_Translate::t('login'); ?></h1><?php
switch (Minz_Configuration::authType()) {
case 'form':
?><form id="loginForm" method="post" action="<?php echo _url('index', 'formLogin'); ?>">
<div class="form-group">
<label class="group-name" for="username"><?php echo Minz_Translate::t('username'); ?></label>
<div class="group-controls">
<input type="text" id="username" name="username" size="16" required="required" maxlength="16" pattern="[0-9a-zA-Z]{1,16}" />
</div>
</div>
<div class="form-group">
<label class="group-name" for="passwordPlain"><?php echo Minz_Translate::t('password'); ?></label>
<div class="group-controls">
<input type="password" id="passwordPlain" required="required" />
<input type="hidden" id="challenge" name="challenge" />
<noscript><strong><?php echo Minz_Translate::t('javascript_should_be_activated'); ?></strong></noscript>
</div>
</div>
<div class="form-group form-actions">
<div class="group-controls">
<button id="loginButton" type="submit" class="btn btn-important"><?php echo Minz_Translate::t('login'); ?></button>
</div>
</div>
</form><?php
break;
case 'persona':
?><p><?php echo FreshRSS_Themes::icon('login'); ?> <a class="signin" href="#"><?php echo Minz_Translate::t('login'); ?></a></p><?php
break;
}
} else {
?><h1>FreshRSS</h1>
<p><?php echo Minz_Translate::t('forbidden_access', Minz_Configuration::authType()); ?></p><?php
}
?>
<p><a href="<?php echo _url('index', 'about'); ?>"><?php echo Minz_Translate::t('about_freshrss'); ?></a></p>
</div>

@ -1,15 +1,5 @@
<?php
function showForbidden() {
?><div class="post content">
<h1><?php echo Minz_Translate::t ('forbidden_access'); ?></h1>
<p><?php echo Minz_Configuration::canLogIn() ?
Minz_Translate::t ('forbidden_access_description') :
Minz_Translate::t ('forbidden_access') . ' (' . Minz_Configuration::authType() . ')'; ?></p>
<p><a href="<?php echo _url ('index', 'about'); ?>"><?php echo Minz_Translate::t ('about_freshrss'); ?></a></p>
</div><?php
}
$output = Minz_Request::param ('output', 'normal');
if ($this->loginOk || Minz_Configuration::allowAnonymous()) {
@ -31,8 +21,8 @@ if ($this->loginOk || Minz_Configuration::allowAnonymous()) {
if ($token_is_ok) {
$this->renderHelper ('view/rss_view');
} else {
showForbidden();
$this->renderHelper ('view/login');
}
} else {
showForbidden();
$this->renderHelper ('view/login');
}

@ -109,7 +109,7 @@ class Minz_Configuration {
return self::$auth_type !== 'none';
}
public static function canLogIn() {
return self::$auth_type === 'persona';
return self::$auth_type === 'form' || self::$auth_type === 'persona';
}
public static function _allowAnonymous($allow = false) {
@ -118,6 +118,7 @@ class Minz_Configuration {
public static function _authType($value) {
$value = strtolower($value);
switch ($value) {
case 'form':
case 'http_auth':
case 'persona':
case 'none':

@ -34,7 +34,7 @@ class Minz_FrontController {
*/
public function __construct () {
if (LOG_PATH === false) {
$this->killApp ('Path doesn’t exist : LOG_PATH');
$this->killApp ('Path not found: LOG_PATH');
}
try {

@ -587,6 +587,54 @@ function init_load_more(box) {
}
//</endless_mode>
//<Web login form>
function poormanSalt() { //If crypto.getRandomValues is not available
var text = '$2a$04$',
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz';
for (var i = 22; i > 0; i--) {
text += base.charAt(Math.floor(Math.random() * 64));
}
return text;
}
function init_loginForm() {
var $loginForm = $('#loginForm');
if ($loginForm.length === 0) {
return;
}
if (!(window.dcodeIO)) {
if (window.console) {
console.log('FreshRSS waiting for bcrypt.js…');
}
window.setTimeout(init_loginForm, 100);
return;
}
$loginForm.on('submit', function() {
$('#loginButton').attr('disabled', '');
var success = false;
$.ajax({
url: './?c=javascript&a=nonce&user=' + $('#username').val(),
dataType: 'json',
async: false
}).done(function (data) {
if (data.salt1 == '' || data.nonce == '') {
alert('Invalid user!');
} else {
var strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function'),
s = dcodeIO.bcrypt.hashSync($('#passwordPlain').val(), data.salt1),
c = dcodeIO.bcrypt.hashSync(data.nonce + s, strong ? 4 : poormanSalt());
$('#challenge').val(c);
success = true;
}
}).fail(function() {
alert('Communication error!');
});
$('#loginButton').removeAttr('disabled');
return success;
});
}
//</Web login form>
//<persona>
function init_persona() {
if (!(navigator.id)) {
@ -696,8 +744,13 @@ function init_all() {
init_notifications();
init_actualize();
init_load_more($stream);
if (use_persona) {
init_persona();
switch (authType) {
case 'form':
init_loginForm();
break;
case 'persona':
init_persona();
break;
}
init_confirm_action();
init_print_action();

Loading…
Cancel
Save