Signed-off-by: Joas Schilling <coding@schilljs.com>tags/v11.0RC2
@@ -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, |
@@ -983,3 +983,34 @@ fieldset.warning legend + p, fieldset.update legend + p { | |||
opacity: 0; | |||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; | |||
} | |||
#sudo-login-background { | |||
position: absolute; | |||
width: 100%; | |||
height: 100%; | |||
background-color: #1d2d44; | |||
opacity:0.4; | |||
z-index: 999; | |||
} | |||
#sudo-login-form { | |||
position: absolute; | |||
top: 45%; | |||
left: 40%; | |||
border: 1px solid #e9322d; | |||
z-index: 1000; | |||
background: #e4b9c0; | |||
border-radius: 10px; | |||
opacity:1; | |||
padding: 25px; | |||
} | |||
#sudo-login-form .question { | |||
width: 250px; | |||
} | |||
#sudo-login-form .confirm { | |||
position: absolute; | |||
top: 25px; | |||
right: 25px; | |||
} |
@@ -1512,8 +1512,72 @@ function initCore() { | |||
$(this).text(OC.Util.relativeModifiedDate(parseInt($(this).attr('data-timestamp'), 10))); | |||
}); | |||
}, 30 * 1000); | |||
OC.PasswordConfirmation.init(); | |||
} | |||
OC.PasswordConfirmation = { | |||
$form: null, | |||
$background: null, | |||
$input: null, | |||
$submit: null, | |||
init: function() { | |||
this.$form = $('#sudo-login-form'); | |||
this.$background = $('#sudo-login-background'); | |||
this.$input = this.$form.find('.question'); | |||
this.$submit = this.$form.find('.confirm'); | |||
this.$background.on('click', _.bind(this._fadeOut, this)); | |||
$('.password-confirm-required').on('click', _.bind(this.requirePasswordConfirmation, this)); | |||
this.$submit.on('click', _.bind(this._submitPasswordConfirmation, this)); | |||
}, | |||
requirePasswordConfirmation: function() { | |||
var timeSinceLogin = moment.now() - nc_lastLogin * 1000; | |||
if (timeSinceLogin > 30 * 60 * 1000) { // 30 minutes | |||
this.$form.removeClass('hidden'); | |||
this.$background.removeClass('hidden'); | |||
// Hack against firefox ignoring autocomplete="off" | |||
if (this.$input.val() === ' ') { | |||
this.$input.val(''); | |||
} | |||
} | |||
}, | |||
_submitPasswordConfirmation: function() { | |||
var self = this; | |||
self.$submit.removeClass('icon-confirm').addClass('icon-loading-small'); | |||
$.ajax({ | |||
url: OC.generateUrl('/login/confirm'), | |||
data: { | |||
password: this.$input.val() | |||
}, | |||
type: 'POST', | |||
success: function(response) { | |||
nc_lastLogin = response.lastLogin; | |||
self.$submit.addClass('icon-confirm').removeClass('icon-loading-small'); | |||
self.$form.addClass('hidden'); | |||
self.$background.addClass('hidden'); | |||
}, | |||
error: function() { | |||
OC.Notification.showTemporary(t('core', 'Failed to authenticate, try again')); | |||
self.$submit.addClass('icon-confirm').removeClass('icon-loading-small'); | |||
} | |||
}); | |||
}, | |||
_fadeOut: function() { | |||
this.$form.addClass('hidden'); | |||
this.$background.addClass('hidden'); | |||
this.$input.value = ''; | |||
} | |||
}; | |||
$(document).ready(initCore); | |||
/** |
@@ -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,13 @@ | |||
</div> | |||
</div></nav> | |||
<div id="sudo-login-background" class="hidden"></div> | |||
<div id="sudo-login-form" class="hidden"> | |||
<input type="password" class="question" autocomplete="off" name="question" value=" " | |||
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']); ?> |
@@ -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(), |