Merge pull request #1447 from nextcloud/password-confirmation-for-some-actions
Password confirmation for some actions
This commit is contained in:
commit
332eaec4c0
|
@ -89,6 +89,11 @@
|
|||
}.bind(this));
|
||||
},
|
||||
_onGenerateBackupCodes: function () {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this._onGenerateBackupCodes, this));
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide old codes
|
||||
this._enabled = false;
|
||||
this.render();
|
||||
|
|
|
@ -59,15 +59,17 @@ class SettingsController extends Controller {
|
|||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @return JSONResponse
|
||||
*/
|
||||
public function createCodes() {
|
||||
$user = $this->userSession->getUser();
|
||||
$codes = $this->storage->createCodes($user);
|
||||
return [
|
||||
'codes' => $codes,
|
||||
'state' => $this->storage->getBackupCodesState($user),
|
||||
];
|
||||
return new JSONResponse([
|
||||
'codes' => $codes,
|
||||
'state' => $this->storage->getBackupCodesState($user),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace OCA\TwoFactorBackupCodes\Tests\Unit\Controller;
|
|||
|
||||
use OCA\TwoFactorBackupCodes\Controller\SettingsController;
|
||||
use OCA\TwoFactorBackupCodes\Service\BackupCodeStorage;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
|
@ -89,7 +90,9 @@ class SettingsControllerTest extends TestCase {
|
|||
'codes' => $codes,
|
||||
'state' => 'state',
|
||||
];
|
||||
$this->assertEquals($expected, $this->controller->createCodes());
|
||||
$response = $this->controller->createCodes();
|
||||
$this->assertInstanceOf(JSONResponse::class, $response);
|
||||
$this->assertEquals($expected, $response->getData());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -163,6 +163,11 @@
|
|||
}
|
||||
},
|
||||
delete: function() {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.delete, this));
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.destroy();
|
||||
this.remove();
|
||||
},
|
||||
|
@ -173,6 +178,11 @@
|
|||
this.render();
|
||||
},
|
||||
save: function() {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.save, this));
|
||||
return;
|
||||
}
|
||||
|
||||
var success = function(model, response, options) {
|
||||
this.saving = false;
|
||||
this.originalModel = JSON.parse(JSON.stringify(this.model));
|
||||
|
|
|
@ -58,6 +58,8 @@ class FlowOperations extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param array[] $checks
|
||||
|
@ -75,6 +77,8 @@ class FlowOperations extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $name
|
||||
* @param array[] $checks
|
||||
|
@ -92,6 +96,8 @@ class FlowOperations extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param int $id
|
||||
* @return JSONResponse
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Christoph Wurst <christoph@owncloud.com>
|
||||
|
@ -31,6 +32,8 @@ use OC\User\Session;
|
|||
use OC_App;
|
||||
use OC_Util;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\Authentication\TwoFactorAuth\IProvider;
|
||||
|
@ -242,6 +245,8 @@ class LoginController extends Controller {
|
|||
// User has successfully logged in, now remove the password reset link, when it is available
|
||||
$this->config->deleteUserValue($loginResult->getUID(), 'core', 'lostpassword');
|
||||
|
||||
$this->session->set('last-password-confirm', $loginResult->getLastLogin());
|
||||
|
||||
if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) {
|
||||
$this->twoFactorManager->prepareTwoFactorLogin($loginResult, $remember_login);
|
||||
|
||||
|
@ -273,4 +278,36 @@ class LoginController extends Controller {
|
|||
return $this->generateRedirect($redirect_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @UseSession
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* @param string $password
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function confirmPassword($password) {
|
||||
$currentDelay = $this->throttler->getDelay($this->request->getRemoteAddress());
|
||||
$this->throttler->sleepDelay($this->request->getRemoteAddress());
|
||||
|
||||
$user = $this->userSession->getUser();
|
||||
if (!$user instanceof IUser) {
|
||||
return new DataResponse([], Http::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$loginResult = $this->userManager->checkPassword($user->getUID(), $password);
|
||||
if ($loginResult === false) {
|
||||
$this->throttler->registerAttempt('sudo', $this->request->getRemoteAddress(), ['user' => $user->getUID()]);
|
||||
if ($currentDelay === 0) {
|
||||
$this->throttler->sleepDelay($this->request->getRemoteAddress());
|
||||
}
|
||||
|
||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
$confirmTimestamp = time();
|
||||
$this->session->set('last-password-confirm', $confirmTimestamp);
|
||||
return new DataResponse(['lastLogin' => $confirmTimestamp], Http::STATUS_OK);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ use OCP\IConfig;
|
|||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserSession;
|
||||
|
||||
|
@ -48,7 +49,8 @@ class OCJSController extends Controller {
|
|||
* @param IL10N $l
|
||||
* @param \OC_Defaults $defaults
|
||||
* @param IAppManager $appManager
|
||||
* @param IUserSession $session
|
||||
* @param ISession $session
|
||||
* @param IUserSession $userSession
|
||||
* @param IConfig $config
|
||||
* @param IGroupManager $groupManager
|
||||
* @param IniGetWrapper $iniWrapper
|
||||
|
@ -59,7 +61,8 @@ class OCJSController extends Controller {
|
|||
IL10N $l,
|
||||
\OC_Defaults $defaults,
|
||||
IAppManager $appManager,
|
||||
IUserSession $session,
|
||||
ISession $session,
|
||||
IUserSession $userSession,
|
||||
IConfig $config,
|
||||
IGroupManager $groupManager,
|
||||
IniGetWrapper $iniWrapper,
|
||||
|
@ -70,7 +73,8 @@ class OCJSController extends Controller {
|
|||
$l,
|
||||
$defaults,
|
||||
$appManager,
|
||||
$session->getUser(),
|
||||
$session,
|
||||
$userSession->getUser(),
|
||||
$config,
|
||||
$groupManager,
|
||||
$iniWrapper,
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
.oc-dialog-buttonrow {
|
||||
display: block;
|
||||
background: transparent;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 10px;
|
||||
|
|
|
@ -1512,8 +1512,80 @@ function initCore() {
|
|||
$(this).text(OC.Util.relativeModifiedDate(parseInt($(this).attr('data-timestamp'), 10)));
|
||||
});
|
||||
}, 30 * 1000);
|
||||
|
||||
OC.PasswordConfirmation.init();
|
||||
}
|
||||
|
||||
OC.PasswordConfirmation = {
|
||||
callback: null,
|
||||
|
||||
init: function() {
|
||||
$('.password-confirm-required').on('click', _.bind(this.requirePasswordConfirmation, this));
|
||||
},
|
||||
|
||||
requiresPasswordConfirmation: function() {
|
||||
var timeSinceLogin = moment.now() - nc_lastLogin * 1000;
|
||||
return timeSinceLogin > 10 * 1000; // 30 minutes
|
||||
return timeSinceLogin > 30 * 60 * 1000; // 30 minutes
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {function} callback
|
||||
*/
|
||||
requirePasswordConfirmation: function(callback) {
|
||||
var self = this;
|
||||
|
||||
if (this.requiresPasswordConfirmation()) {
|
||||
OC.dialogs.prompt(
|
||||
t(
|
||||
'core',
|
||||
'This action requires you to confirm your password'
|
||||
),
|
||||
t('core','Authentication required'),
|
||||
function (result, password) {
|
||||
if (result && password !== '') {
|
||||
self._confirmPassword(password);
|
||||
}
|
||||
},
|
||||
true,
|
||||
t('core','Password'),
|
||||
true
|
||||
).then(function() {
|
||||
var $dialog = $('.oc-dialog:visible');
|
||||
$dialog.find('.ui-icon').remove();
|
||||
|
||||
var $buttons = $dialog.find('button');
|
||||
$buttons.eq(0).text(t('core', 'Cancel'));
|
||||
$buttons.eq(1).text(t('core', 'Confirm'));
|
||||
});
|
||||
}
|
||||
|
||||
this.callback = callback;
|
||||
},
|
||||
|
||||
_confirmPassword: function(password) {
|
||||
var self = this;
|
||||
|
||||
$.ajax({
|
||||
url: OC.generateUrl('/login/confirm'),
|
||||
data: {
|
||||
password: password
|
||||
},
|
||||
type: 'POST',
|
||||
success: function(response) {
|
||||
nc_lastLogin = response.lastLogin;
|
||||
|
||||
if (_.isFunction(self.callback)) {
|
||||
self.callback();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
OC.Notification.showTemporary(t('core', 'Failed to authenticate, try again'));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(initCore);
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,6 +33,10 @@ OCP.AppConfig = {
|
|||
* @internal
|
||||
*/
|
||||
_call: function(method, endpoint, options) {
|
||||
if ((method === 'post' || method === 'delete') && OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this._call, this, method, endpoint, options));
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: method.toUpperCase(),
|
||||
|
|
|
@ -46,6 +46,7 @@ $application->registerRoutes($this, [
|
|||
['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
|
||||
['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
|
||||
['name' => 'login#tryLogin', 'url' => '/login', 'verb' => 'POST'],
|
||||
['name' => 'login#confirmPassword', 'url' => '/login/confirm', 'verb' => 'POST'],
|
||||
['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
|
||||
['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
|
||||
['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
|
||||
|
|
|
@ -146,6 +146,14 @@
|
|||
</div>
|
||||
</div></nav>
|
||||
|
||||
<div id="sudo-login-background" class="hidden"></div>
|
||||
<div id="sudo-login-form" class="hidden">
|
||||
<?php p($l->t('This action requires you to confirm your password:')); ?><br>
|
||||
<input type="password" class="question" autocomplete="off" name="question" value=" <?php /* Hack against firefox ignoring autocomplete="off" */ ?>"
|
||||
placeholder="<?php p($l->t('Confirm your password')); ?>" />
|
||||
<input class="confirm icon-confirm" title="<?php p($l->t('Confirm')); ?>" value="" type="submit">
|
||||
</div>
|
||||
|
||||
<div id="content-wrapper">
|
||||
<div id="content" class="app-<?php p($_['appid']) ?>" role="main">
|
||||
<?php print_unescaped($_['content']); ?>
|
||||
|
|
|
@ -265,6 +265,7 @@ return array(
|
|||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\AppNotEnabledException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\CrossSiteRequestForgeryException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotAdminException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotConfirmedException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotLoggedInException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\SecurityException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\StrictCookieMissingException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php',
|
||||
|
|
|
@ -295,6 +295,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\AppNotEnabledException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\CrossSiteRequestForgeryException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotAdminException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotConfirmedException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotLoggedInException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\SecurityException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php',
|
||||
'OC\\AppFramework\\Middleware\\Security\\Exceptions\\StrictCookieMissingException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php',
|
||||
|
|
|
@ -383,6 +383,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
|
|||
$app->getServer()->getNavigationManager(),
|
||||
$app->getServer()->getURLGenerator(),
|
||||
$app->getServer()->getLogger(),
|
||||
$app->getServer()->getSession(),
|
||||
$c['AppName'],
|
||||
$app->isLoggedIn(),
|
||||
$app->isAdminUser(),
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\AppFramework\Middleware\Security\Exceptions;
|
||||
|
||||
use OCP\AppFramework\Http;
|
||||
|
||||
/**
|
||||
* Class NotConfirmedException is thrown when a resource has been requested by a
|
||||
* user that has not confirmed their password in the last 30 minutes.
|
||||
*
|
||||
* @package OC\AppFramework\Middleware\Security\Exceptions
|
||||
*/
|
||||
class NotConfirmedException extends SecurityException {
|
||||
public function __construct() {
|
||||
parent::__construct('Password confirmation is required', Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ namespace OC\AppFramework\Middleware\Security;
|
|||
use OC\AppFramework\Middleware\Security\Exceptions\AppNotEnabledException;
|
||||
use OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException;
|
||||
use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException;
|
||||
use OC\AppFramework\Middleware\Security\Exceptions\NotConfirmedException;
|
||||
use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException;
|
||||
use OC\AppFramework\Middleware\Security\Exceptions\StrictCookieMissingException;
|
||||
use OC\AppFramework\Utility\ControllerMethodReflector;
|
||||
|
@ -47,6 +48,7 @@ use OCP\AppFramework\Http\Response;
|
|||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\INavigationManager;
|
||||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IRequest;
|
||||
use OCP\ILogger;
|
||||
|
@ -73,6 +75,8 @@ class SecurityMiddleware extends Middleware {
|
|||
private $urlGenerator;
|
||||
/** @var ILogger */
|
||||
private $logger;
|
||||
/** @var ISession */
|
||||
private $session;
|
||||
/** @var bool */
|
||||
private $isLoggedIn;
|
||||
/** @var bool */
|
||||
|
@ -90,6 +94,7 @@ class SecurityMiddleware extends Middleware {
|
|||
* @param INavigationManager $navigationManager
|
||||
* @param IURLGenerator $urlGenerator
|
||||
* @param ILogger $logger
|
||||
* @param ISession $session
|
||||
* @param string $appName
|
||||
* @param bool $isLoggedIn
|
||||
* @param bool $isAdminUser
|
||||
|
@ -102,6 +107,7 @@ class SecurityMiddleware extends Middleware {
|
|||
INavigationManager $navigationManager,
|
||||
IURLGenerator $urlGenerator,
|
||||
ILogger $logger,
|
||||
ISession $session,
|
||||
$appName,
|
||||
$isLoggedIn,
|
||||
$isAdminUser,
|
||||
|
@ -114,6 +120,7 @@ class SecurityMiddleware extends Middleware {
|
|||
$this->appName = $appName;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->logger = $logger;
|
||||
$this->session = $session;
|
||||
$this->isLoggedIn = $isLoggedIn;
|
||||
$this->isAdminUser = $isAdminUser;
|
||||
$this->contentSecurityPolicyManager = $contentSecurityPolicyManager;
|
||||
|
@ -150,6 +157,13 @@ class SecurityMiddleware extends Middleware {
|
|||
}
|
||||
}
|
||||
|
||||
if ($this->reflector->hasAnnotation('PasswordConfirmationRequired')) {
|
||||
$lastConfirm = (int) $this->session->get('last-password-confirm');
|
||||
if ($lastConfirm < (time() - (30 * 60 + 15))) { // allow 15 seconds delay
|
||||
throw new NotConfirmedException();
|
||||
}
|
||||
}
|
||||
|
||||
// Check for strict cookie requirement
|
||||
if($this->reflector->hasAnnotation('StrictCookieRequired') || !$this->reflector->hasAnnotation('NoCSRFRequired')) {
|
||||
if(!$this->request->passesStrictCookieCheck()) {
|
||||
|
|
|
@ -27,6 +27,7 @@ use OCP\App\IAppManager;
|
|||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
|
||||
|
@ -41,7 +42,10 @@ class JSConfigHelper {
|
|||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
|
||||
/** @var IUser */
|
||||
/** @var ISession */
|
||||
private $session;
|
||||
|
||||
/** @var IUser|null */
|
||||
private $currentUser;
|
||||
|
||||
/** @var IConfig */
|
||||
|
@ -60,6 +64,7 @@ class JSConfigHelper {
|
|||
* @param IL10N $l
|
||||
* @param \OC_Defaults $defaults
|
||||
* @param IAppManager $appManager
|
||||
* @param ISession $session
|
||||
* @param IUser|null $currentUser
|
||||
* @param IConfig $config
|
||||
* @param IGroupManager $groupManager
|
||||
|
@ -69,6 +74,7 @@ class JSConfigHelper {
|
|||
public function __construct(IL10N $l,
|
||||
\OC_Defaults $defaults,
|
||||
IAppManager $appManager,
|
||||
ISession $session,
|
||||
$currentUser,
|
||||
IConfig $config,
|
||||
IGroupManager $groupManager,
|
||||
|
@ -77,6 +83,7 @@ class JSConfigHelper {
|
|||
$this->l = $l;
|
||||
$this->defaults = $defaults;
|
||||
$this->appManager = $appManager;
|
||||
$this->session = $session;
|
||||
$this->currentUser = $currentUser;
|
||||
$this->config = $config;
|
||||
$this->groupManager = $groupManager;
|
||||
|
@ -119,6 +126,16 @@ class JSConfigHelper {
|
|||
$dataLocation = false;
|
||||
}
|
||||
|
||||
if ($this->currentUser instanceof IUser) {
|
||||
$lastConfirmTimestamp = $this->currentUser->getLastLogin();
|
||||
$sessionTime = $this->session->get('last-password-confirm');
|
||||
if (is_int($sessionTime)) {
|
||||
$lastConfirmTimestamp = $sessionTime;
|
||||
}
|
||||
} else {
|
||||
$lastConfirmTimestamp = 0;
|
||||
}
|
||||
|
||||
$array = [
|
||||
"oc_debug" => $this->config->getSystemValue('debug', false) ? 'true' : 'false',
|
||||
"oc_isadmin" => $this->groupManager->isAdmin($uid) ? 'true' : 'false',
|
||||
|
@ -126,6 +143,7 @@ class JSConfigHelper {
|
|||
"oc_webroot" => "\"".\OC::$WEBROOT."\"",
|
||||
"oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution
|
||||
"datepickerFormatDate" => json_encode($this->l->l('jsdate', null)),
|
||||
'nc_lastLogin' => $lastConfirmTimestamp,
|
||||
"dayNames" => json_encode([
|
||||
(string)$this->l->t('Sunday'),
|
||||
(string)$this->l->t('Monday'),
|
||||
|
|
|
@ -148,6 +148,7 @@ class TemplateLayout extends \OC_Template {
|
|||
\OC::$server->getL10N('core'),
|
||||
\OC::$server->getThemingDefaults(),
|
||||
\OC::$server->getAppManager(),
|
||||
\OC::$server->getSession(),
|
||||
\OC::$server->getUserSession()->getUser(),
|
||||
\OC::$server->getConfig(),
|
||||
\OC::$server->getGroupManager(),
|
||||
|
|
|
@ -111,7 +111,9 @@ class AuthSettingsController extends Controller {
|
|||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoSubadminRequired
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $name
|
||||
* @return JSONResponse
|
||||
*/
|
||||
public function create($name) {
|
||||
|
@ -138,11 +140,11 @@ class AuthSettingsController extends Controller {
|
|||
$tokenData = $deviceToken->jsonSerialize();
|
||||
$tokenData['canDelete'] = true;
|
||||
|
||||
return [
|
||||
return new JSONResponse([
|
||||
'token' => $token,
|
||||
'loginName' => $loginName,
|
||||
'deviceToken' => $tokenData
|
||||
];
|
||||
'deviceToken' => $tokenData,
|
||||
]);
|
||||
}
|
||||
|
||||
private function getServiceNotAvailableResponse() {
|
||||
|
|
|
@ -131,6 +131,7 @@ class ChangePasswordController extends Controller {
|
|||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
|
|
|
@ -95,6 +95,7 @@ class GroupsController extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* @PasswordConfirmationRequired
|
||||
* @param string $id
|
||||
* @return DataResponse
|
||||
*/
|
||||
|
@ -128,6 +129,7 @@ class GroupsController extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* @PasswordConfirmationRequired
|
||||
* @param string $id
|
||||
* @return DataResponse
|
||||
*/
|
||||
|
|
|
@ -73,6 +73,9 @@ class MailSettingsController extends Controller {
|
|||
|
||||
/**
|
||||
* Sets the email settings
|
||||
*
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $mail_domain
|
||||
* @param string $mail_from_address
|
||||
* @param string $mail_smtpmode
|
||||
|
@ -116,6 +119,9 @@ class MailSettingsController extends Controller {
|
|||
|
||||
/**
|
||||
* Store the credentials used for SMTP in the config
|
||||
*
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $mail_smtpname
|
||||
* @param string $mail_smtppassword
|
||||
* @return array
|
||||
|
|
|
@ -301,6 +301,7 @@ class UsersController extends Controller {
|
|||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
|
@ -433,6 +434,7 @@ class UsersController extends Controller {
|
|||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $id
|
||||
* @return DataResponse
|
||||
|
@ -495,6 +497,7 @@ class UsersController extends Controller {
|
|||
*
|
||||
* @NoAdminRequired
|
||||
* @NoSubadminRequired
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $mailAddress
|
||||
|
@ -615,6 +618,7 @@ class UsersController extends Controller {
|
|||
*
|
||||
* @NoAdminRequired
|
||||
* @NoSubadminRequired
|
||||
* @PasswordConfirmationRequired
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $displayName
|
||||
|
|
|
@ -32,6 +32,13 @@
|
|||
OC_JSON::checkSubAdminUser();
|
||||
OCP\JSON::callCheck();
|
||||
|
||||
$lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
|
||||
if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
|
||||
$l = \OC::$server->getL10N('core');
|
||||
OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
|
||||
exit();
|
||||
}
|
||||
|
||||
$username = isset($_POST["username"]) ? (string)$_POST["username"] : '';
|
||||
|
||||
$isUserAccessible = false;
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
OC_JSON::checkSubAdminUser();
|
||||
OCP\JSON::callCheck();
|
||||
|
||||
$lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
|
||||
if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
|
||||
$l = \OC::$server->getL10N('core');
|
||||
OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
|
||||
exit();
|
||||
}
|
||||
|
||||
$success = true;
|
||||
$username = (string)$_POST['username'];
|
||||
$group = (string)$_POST['group'];
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
OC_JSON::checkAdminUser();
|
||||
OCP\JSON::callCheck();
|
||||
|
||||
$lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
|
||||
if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
|
||||
$l = \OC::$server->getL10N('core');
|
||||
OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
|
||||
exit();
|
||||
}
|
||||
|
||||
$username = (string)$_POST['username'];
|
||||
$group = (string)$_POST['group'];
|
||||
|
||||
|
|
|
@ -172,21 +172,48 @@ $(document).ready(function(){
|
|||
}
|
||||
});
|
||||
|
||||
$('#mail_general_settings_form').change(function(){
|
||||
OC.msg.startSaving('#mail_settings_msg');
|
||||
var post = $( "#mail_general_settings_form" ).serialize();
|
||||
$.post(OC.generateUrl('/settings/admin/mailsettings'), post, function(data){
|
||||
OC.msg.finishedSaving('#mail_settings_msg', data);
|
||||
});
|
||||
});
|
||||
var changeEmailSettings = function() {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(changeEmailSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
$('#mail_credentials_settings_submit').click(function(){
|
||||
OC.msg.startSaving('#mail_settings_msg');
|
||||
var post = $( "#mail_credentials_settings" ).serialize();
|
||||
$.post(OC.generateUrl('/settings/admin/mailsettings/credentials'), post, function(data){
|
||||
OC.msg.finishedSaving('#mail_settings_msg', data);
|
||||
$.ajax({
|
||||
url: OC.generateUrl('/settings/admin/mailsettings'),
|
||||
type: 'POST',
|
||||
data: $('#mail_general_settings_form').serialize(),
|
||||
success: function(data){
|
||||
OC.msg.finishedSaving('#mail_settings_msg', data);
|
||||
},
|
||||
error: function(data){
|
||||
OC.msg.finishedError('#mail_settings_msg', data.responseJSON.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var toggleEmailCredentials = function() {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(toggleEmailCredentials);
|
||||
return;
|
||||
}
|
||||
|
||||
OC.msg.startSaving('#mail_settings_msg');
|
||||
$.ajax({
|
||||
url: OC.generateUrl('/settings/admin/mailsettings/credentials'),
|
||||
type: 'POST',
|
||||
data: $('#mail_credentials_settings').serialize(),
|
||||
success: function(data){
|
||||
OC.msg.finishedSaving('#mail_settings_msg', data);
|
||||
},
|
||||
error: function(data){
|
||||
OC.msg.finishedError('#mail_settings_msg', data.responseJSON.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#mail_general_settings_form').change(changeEmailSettings);
|
||||
$('#mail_credentials_settings_submit').click(toggleEmailCredentials);
|
||||
|
||||
$('#sendtestemail').click(function(event){
|
||||
event.preventDefault();
|
||||
|
|
|
@ -299,6 +299,11 @@
|
|||
},
|
||||
|
||||
_addAppPassword: function () {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this._addAppPassword, this));
|
||||
return;
|
||||
}
|
||||
|
||||
var _this = this;
|
||||
this._toggleAddingToken(true);
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ function changeEmailAddress () {
|
|||
// for failure the first parameter is the result object
|
||||
OC.msg.finishedSaving('#lostpassword .msg', result);
|
||||
}).fail(function(result){
|
||||
OC.msg.finishedSaving('#lostpassword .msg', result.responseJSON);
|
||||
OC.msg.finishedError('#lostpassword .msg', result.responseJSON.message);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,11 @@ GroupList = {
|
|||
},
|
||||
|
||||
createGroup: function (groupname) {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.createGroup, this, groupname));
|
||||
return;
|
||||
}
|
||||
|
||||
$.post(
|
||||
OC.generateUrl('/settings/users/groups'),
|
||||
{
|
||||
|
@ -278,10 +283,16 @@ GroupList = {
|
|||
GroupList.show);
|
||||
|
||||
//when to mark user for delete
|
||||
$userGroupList.on('click', '.delete', function () {
|
||||
var deleteAction = function () {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(deleteAction, this));
|
||||
return;
|
||||
}
|
||||
|
||||
// Call function for handling delete/undo
|
||||
GroupDeleteHandler.mark(GroupList.getElementGID(this));
|
||||
});
|
||||
};
|
||||
$userGroupList.on('click', '.delete', deleteAction);
|
||||
|
||||
//delete a marked user when leaving the page
|
||||
$(window).on('beforeunload', function () {
|
||||
|
|
|
@ -353,6 +353,14 @@ var UserList = {
|
|||
$userListBody.on('click', '.delete', function () {
|
||||
// Call function for handling delete/undo
|
||||
var uid = UserList.getUID(this);
|
||||
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(function() {
|
||||
UserDeleteHandler.mark(uid);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
UserDeleteHandler.mark(uid);
|
||||
});
|
||||
|
||||
|
@ -405,6 +413,11 @@ var UserList = {
|
|||
},
|
||||
|
||||
applyGroupSelect: function (element, user, checked) {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.applySubadminSelect, this, element, user, checked));
|
||||
return;
|
||||
}
|
||||
|
||||
var $element = $(element);
|
||||
|
||||
var checkHandler = null;
|
||||
|
@ -467,6 +480,11 @@ var UserList = {
|
|||
},
|
||||
|
||||
applySubadminSelect: function (element, user, checked) {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.applySubadminSelect, this, element, user, checked));
|
||||
return;
|
||||
}
|
||||
|
||||
var $element = $(element);
|
||||
var checkHandler = function (group) {
|
||||
if (group === 'admin') {
|
||||
|
@ -478,7 +496,10 @@ var UserList = {
|
|||
username: user,
|
||||
group: group
|
||||
},
|
||||
function () {
|
||||
function (response) {
|
||||
if (response.data.message) {
|
||||
OC.Notification.show(response.data.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -518,7 +539,7 @@ var UserList = {
|
|||
OC.Notification.showTemporary(t('core', 'Invalid quota value "{val}"', {val: quota}));
|
||||
return;
|
||||
}
|
||||
UserList._updateQuota(uid, quota, function(returnedQuota){
|
||||
UserList._updateQuota(uid, quota, function(returnedQuota) {
|
||||
if (quota !== returnedQuota) {
|
||||
$select.find(':selected').text(returnedQuota);
|
||||
}
|
||||
|
@ -532,12 +553,21 @@ var UserList = {
|
|||
* @param {Function} ready callback after save
|
||||
*/
|
||||
_updateQuota: function(uid, quota, ready) {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this._updateQuota, this, uid, quota, ready));
|
||||
return;
|
||||
}
|
||||
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'setquota.php'),
|
||||
{username: uid, quota: quota},
|
||||
function (result) {
|
||||
if (ready) {
|
||||
ready(result.data.quota);
|
||||
if (result.status === 'error') {
|
||||
OC.Notification.showTemporary(result.data.message);
|
||||
} else {
|
||||
if (ready) {
|
||||
ready(result.data.quota);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -635,6 +665,28 @@ $(document).ready(function () {
|
|||
// TODO: move other init calls inside of initialize
|
||||
UserList.initialize($('#userlist'));
|
||||
|
||||
var _submitPasswordChange = function(uid, password, recoveryPasswordVal, blurFunction) {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(function() {
|
||||
_submitPasswordChange(uid, password, recoveryPasswordVal, blurFunction);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$.post(
|
||||
OC.generateUrl('/settings/users/changepassword'),
|
||||
{username: uid, password: password, recoveryPassword: recoveryPasswordVal},
|
||||
function (result) {
|
||||
blurFunction();
|
||||
if (result.status === 'success') {
|
||||
OC.Notification.showTemporary(t('admin', 'Password successfully changed'));
|
||||
} else {
|
||||
OC.Notification.showTemporary(t('admin', result.data.message));
|
||||
}
|
||||
}
|
||||
).fail(blurFunction);
|
||||
};
|
||||
|
||||
$userListBody.on('click', '.password', function (event) {
|
||||
event.stopPropagation();
|
||||
|
||||
|
@ -643,6 +695,12 @@ $(document).ready(function () {
|
|||
var uid = UserList.getUID($td);
|
||||
var $input = $('<input type="password">');
|
||||
var isRestoreDisabled = UserList.getRestoreDisabled($td) === true;
|
||||
var blurFunction = function () {
|
||||
$(this).replaceWith($('<span>●●●●●●●</span>'));
|
||||
$td.find('img').show();
|
||||
// remove highlight class from users without recovery ability
|
||||
$tr.removeClass('row-warning');
|
||||
};
|
||||
if(isRestoreDisabled) {
|
||||
$tr.addClass('row-warning');
|
||||
// add tipsy if the password change could cause data loss - no recovery enabled
|
||||
|
@ -657,34 +715,51 @@ $(document).ready(function () {
|
|||
if (event.keyCode === 13) {
|
||||
if ($(this).val().length > 0) {
|
||||
var recoveryPasswordVal = $('input:password[id="recoveryPassword"]').val();
|
||||
$.post(
|
||||
OC.generateUrl('/settings/users/changepassword'),
|
||||
{username: uid, password: $(this).val(), recoveryPassword: recoveryPasswordVal},
|
||||
function (result) {
|
||||
if (result.status === 'success') {
|
||||
OC.Notification.showTemporary(t('admin', 'Password successfully changed'));
|
||||
} else {
|
||||
OC.Notification.showTemporary(t('admin', result.data.message));
|
||||
}
|
||||
}
|
||||
);
|
||||
$input.blur();
|
||||
$input.off('blur');
|
||||
_submitPasswordChange(uid, $(this).val(), recoveryPasswordVal, blurFunction);
|
||||
} else {
|
||||
$input.blur();
|
||||
}
|
||||
}
|
||||
})
|
||||
.blur(function () {
|
||||
$(this).replaceWith($('<span>●●●●●●●</span>'));
|
||||
$td.find('img').show();
|
||||
// remove highlight class from users without recovery ability
|
||||
$tr.removeClass('row-warning');
|
||||
});
|
||||
.blur(blurFunction);
|
||||
});
|
||||
$('input:password[id="recoveryPassword"]').keyup(function() {
|
||||
OC.Notification.hide();
|
||||
});
|
||||
|
||||
var _submitDisplayNameChange = function($tr, uid, displayName, blurFunction) {
|
||||
var $div = $tr.find('div.avatardiv');
|
||||
if ($div.length) {
|
||||
$div.imageplaceholder(uid, displayName);
|
||||
}
|
||||
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(function() {
|
||||
_submitDisplayNameChange($tr, uid, displayName, blurFunction);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: OC.generateUrl('/settings/users/{id}/displayName', {id: uid}),
|
||||
data: {
|
||||
username: uid,
|
||||
displayName: displayName
|
||||
}
|
||||
}).success(function (result) {
|
||||
if (result && result.status==='success' && $div.length){
|
||||
$div.avatar(result.data.username, 32);
|
||||
}
|
||||
$tr.data('displayname', displayName);
|
||||
blurFunction();
|
||||
}).fail(function (result) {
|
||||
OC.Notification.showTemporary(result.responseJSON.message);
|
||||
$tr.find('.displayName input').blur(blurFunction);
|
||||
});
|
||||
};
|
||||
|
||||
$userListBody.on('click', '.displayName', function (event) {
|
||||
event.stopPropagation();
|
||||
var $td = $(this).closest('td');
|
||||
|
@ -692,6 +767,11 @@ $(document).ready(function () {
|
|||
var uid = UserList.getUID($td);
|
||||
var displayName = escapeHTML(UserList.getDisplayName($td));
|
||||
var $input = $('<input type="text" value="' + displayName + '">');
|
||||
var blurFunction = function() {
|
||||
var displayName = $tr.data('displayname');
|
||||
$input.replaceWith('<span>' + escapeHTML(displayName) + '</span>');
|
||||
$td.find('img').show();
|
||||
};
|
||||
$td.find('img').hide();
|
||||
$td.children('span').replaceWith($input);
|
||||
$input
|
||||
|
@ -699,34 +779,53 @@ $(document).ready(function () {
|
|||
.keypress(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
if ($(this).val().length > 0) {
|
||||
var $div = $tr.find('div.avatardiv');
|
||||
if ($div.length) {
|
||||
$div.imageplaceholder(uid, displayName);
|
||||
}
|
||||
$.post(
|
||||
OC.generateUrl('/settings/users/{id}/displayName', {id: uid}),
|
||||
{username: uid, displayName: $(this).val()},
|
||||
function (result) {
|
||||
if (result && result.status==='success' && $div.length){
|
||||
$div.avatar(result.data.username, 32);
|
||||
}
|
||||
}
|
||||
);
|
||||
var displayName = $input.val();
|
||||
$tr.data('displayname', displayName);
|
||||
$input.blur();
|
||||
$input.off('blur');
|
||||
_submitDisplayNameChange($tr, uid, $(this).val(), blurFunction);
|
||||
} else {
|
||||
$input.blur();
|
||||
}
|
||||
}
|
||||
})
|
||||
.blur(function () {
|
||||
var displayName = $tr.data('displayname');
|
||||
$input.replaceWith('<span>' + escapeHTML(displayName) + '</span>');
|
||||
$td.find('img').show();
|
||||
});
|
||||
.blur(blurFunction);
|
||||
});
|
||||
|
||||
var _submitEmailChange = function($tr, $td, $input, uid, mailAddress, blurFunction) {
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(function() {
|
||||
_submitEmailChange($tr, $td, $input, uid, mailAddress, blurFunction);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: 'PUT',
|
||||
url: OC.generateUrl('/settings/users/{id}/mailAddress', {id: uid}),
|
||||
data: {
|
||||
mailAddress: mailAddress
|
||||
}
|
||||
}).success(function () {
|
||||
// set data attribute to new value
|
||||
// will in blur() be used to show the text instead of the input field
|
||||
$tr.data('mailAddress', mailAddress);
|
||||
$td.find('.loading-small').css('display', '');
|
||||
$input.removeAttr('disabled')
|
||||
.triggerHandler('blur'); // needed instead of $input.blur() for Firefox
|
||||
blurFunction();
|
||||
}).fail(function (result) {
|
||||
if (!_.isUndefined(result.responseJSON.data)) {
|
||||
OC.Notification.showTemporary(result.responseJSON.data.message);
|
||||
} else if (!_.isUndefined(result.responseJSON.message)) {
|
||||
OC.Notification.showTemporary(result.responseJSON.message);
|
||||
} else {
|
||||
OC.Notification.showTemporary(t('settings', 'Could not change the users email'));
|
||||
}
|
||||
$td.find('.loading-small').css('display', '');
|
||||
$input.removeAttr('disabled')
|
||||
.css('padding-right', '6px');
|
||||
$input.blur(blurFunction);
|
||||
});
|
||||
};
|
||||
|
||||
$userListBody.on('click', '.mailAddress', function (event) {
|
||||
event.stopPropagation();
|
||||
var $td = $(this).closest('td');
|
||||
|
@ -734,6 +833,15 @@ $(document).ready(function () {
|
|||
var uid = UserList.getUID($td);
|
||||
var mailAddress = escapeHTML(UserList.getMailAddress($td));
|
||||
var $input = $('<input type="text">').val(mailAddress);
|
||||
var blurFunction = function() {
|
||||
if($td.find('.loading-small').css('display') === 'inline-block') {
|
||||
// in Chrome the blur event is fired too early by the browser - even if the request is still running
|
||||
return;
|
||||
}
|
||||
var $span = $('<span>').text($tr.data('mailAddress'));
|
||||
$input.replaceWith($span);
|
||||
$td.find('img').show();
|
||||
};
|
||||
$td.children('span').replaceWith($input);
|
||||
$td.find('img').hide();
|
||||
$input
|
||||
|
@ -742,40 +850,14 @@ $(document).ready(function () {
|
|||
if (event.keyCode === 13) {
|
||||
// enter key
|
||||
|
||||
var mailAddress = $input.val();
|
||||
$td.find('.loading-small').css('display', 'inline-block');
|
||||
$input.css('padding-right', '26px');
|
||||
$input.attr('disabled', 'disabled');
|
||||
$.ajax({
|
||||
type: 'PUT',
|
||||
url: OC.generateUrl('/settings/users/{id}/mailAddress', {id: uid}),
|
||||
data: {
|
||||
mailAddress: $(this).val()
|
||||
}
|
||||
}).success(function () {
|
||||
// set data attribute to new value
|
||||
// will in blur() be used to show the text instead of the input field
|
||||
$tr.data('mailAddress', mailAddress);
|
||||
$td.find('.loading-small').css('display', '');
|
||||
$input.removeAttr('disabled')
|
||||
.triggerHandler('blur'); // needed instead of $input.blur() for Firefox
|
||||
}).fail(function (result) {
|
||||
OC.Notification.showTemporary(result.responseJSON.data.message);
|
||||
$td.find('.loading-small').css('display', '');
|
||||
$input.removeAttr('disabled')
|
||||
.css('padding-right', '6px');
|
||||
});
|
||||
$input.off('blur');
|
||||
_submitEmailChange($tr, $td, $input, uid, $(this).val(), blurFunction);
|
||||
}
|
||||
})
|
||||
.blur(function () {
|
||||
if($td.find('.loading-small').css('display') === 'inline-block') {
|
||||
// in Chrome the blur event is fired too early by the browser - even if the request is still running
|
||||
return;
|
||||
}
|
||||
var $span = $('<span>').text($tr.data('mailAddress'));
|
||||
$input.replaceWith($span);
|
||||
$td.find('img').show();
|
||||
});
|
||||
.blur(blurFunction);
|
||||
});
|
||||
|
||||
$('#newuser .groupsListContainer').on('click', function (event) {
|
||||
|
@ -796,8 +878,15 @@ $(document).ready(function () {
|
|||
});
|
||||
|
||||
UserList._updateGroupListLabel($('#newuser .groups'), []);
|
||||
$('#newuser').submit(function (event) {
|
||||
var _submitNewUserForm = function (event) {
|
||||
event.preventDefault();
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(function() {
|
||||
_submitNewUserForm(event);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var username = $('#newusername').val();
|
||||
var password = $('#newuserpassword').val();
|
||||
var email = $('#newemail').val();
|
||||
|
@ -866,7 +955,8 @@ $(document).ready(function () {
|
|||
$('#newuser').get(0).reset();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
$('#newuser').submit(_submitNewUserForm);
|
||||
|
||||
if ($('#CheckboxStorageLocation').is(':checked')) {
|
||||
$("#userlist .storageLocation").show();
|
||||
|
@ -874,11 +964,17 @@ $(document).ready(function () {
|
|||
// Option to display/hide the "Storage location" column
|
||||
$('#CheckboxStorageLocation').click(function() {
|
||||
if ($('#CheckboxStorageLocation').is(':checked')) {
|
||||
$("#userlist .storageLocation").show();
|
||||
OCP.AppConfig.setValue('core', 'umgmt_show_storage_location', 'true');
|
||||
OCP.AppConfig.setValue('core', 'umgmt_show_storage_location', 'true', {
|
||||
success: function () {
|
||||
$("#userlist .storageLocation").show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$("#userlist .storageLocation").hide();
|
||||
OCP.AppConfig.setValue('core', 'umgmt_show_storage_location', 'false');
|
||||
OCP.AppConfig.setValue('core', 'umgmt_show_storage_location', 'false', {
|
||||
success: function () {
|
||||
$("#userlist .storageLocation").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ if($_['displayNameChangeSupported']) {
|
|||
<h2>
|
||||
<label for="displayName"><?php echo $l->t('Full name');?></label>
|
||||
</h2>
|
||||
<input type="text" id="displayName" name="displayName"
|
||||
<input type="text" id="displayName" name="displayName" class="password-confirm-required"
|
||||
value="<?php p($_['displayName'])?>"
|
||||
autocomplete="on" autocapitalize="off" autocorrect="off" />
|
||||
<span class="msg"></span>
|
||||
|
@ -91,6 +91,7 @@ if($_['displayNameChangeSupported']) {
|
|||
</h2>
|
||||
<input type="email" name="email" id="email" value="<?php p($_['email']); ?>"
|
||||
placeholder="<?php p($l->t('Your email address'));?>"
|
||||
class="password-confirm-required"
|
||||
autocomplete="on" autocapitalize="off" autocorrect="off" />
|
||||
<span class="msg"></span><br />
|
||||
<em><?php p($l->t('For password recovery and notifications'));?></em>
|
||||
|
|
|
@ -153,7 +153,9 @@ class AuthSettingsControllerTest extends TestCase {
|
|||
'deviceToken' => ['dummy' => 'dummy', 'canDelete' => true],
|
||||
'loginName' => 'User13',
|
||||
];
|
||||
$this->assertEquals($expected, $this->controller->create($name));
|
||||
$response = $this->controller->create($name);
|
||||
$this->assertInstanceOf(JSONResponse::class, $response);
|
||||
$this->assertEquals($expected, $response->getData());
|
||||
}
|
||||
|
||||
public function testCreateSessionNotAvailable() {
|
||||
|
|
|
@ -49,6 +49,7 @@ use OCP\IConfig;
|
|||
use OCP\ILogger;
|
||||
use OCP\INavigationManager;
|
||||
use OCP\IRequest;
|
||||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Security\ISecureRandom;
|
||||
|
||||
|
@ -63,6 +64,8 @@ class SecurityMiddlewareTest extends \Test\TestCase {
|
|||
private $secException;
|
||||
/** @var SecurityException */
|
||||
private $secAjaxException;
|
||||
/** @var ISession|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $session;
|
||||
/** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $request;
|
||||
/** @var ControllerMethodReflector */
|
||||
|
@ -88,6 +91,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
|
|||
$this->logger = $this->createMock(ILogger::class);
|
||||
$this->navigationManager = $this->createMock(INavigationManager::class);
|
||||
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
||||
$this->session = $this->createMock(ISession::class);
|
||||
$this->request = $this->createMock(IRequest::class);
|
||||
$this->contentSecurityPolicyManager = $this->createMock(ContentSecurityPolicyManager::class);
|
||||
$this->csrfTokenManager = $this->createMock(CsrfTokenManager::class);
|
||||
|
@ -109,6 +113,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
|
|||
$this->navigationManager,
|
||||
$this->urlGenerator,
|
||||
$this->logger,
|
||||
$this->session,
|
||||
'files',
|
||||
$isLoggedIn,
|
||||
$isAdminUser,
|
||||
|
|
Loading…
Reference in New Issue