allow users to enable/disable U2F via their personal settings
This commit is contained in:
Родитель
b2ecea2c82
Коммит
022e8ea063
|
@ -19,16 +19,26 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
return [
|
return [
|
||||||
'routes' => [
|
'routes' => [
|
||||||
[
|
[
|
||||||
'name' => 'settings#startRegister',
|
'name' => 'settings#state',
|
||||||
'url' => '/settings/startregister',
|
'url' => '/settings/state',
|
||||||
'verb' => 'POST'
|
'verb' => 'GET'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'settings#finishRegister',
|
'name' => 'settings#disable',
|
||||||
'url' => '/settings/finishregister',
|
'url' => '/settings/disable',
|
||||||
'verb' => 'POST'
|
'verb' => 'POST'
|
||||||
],
|
],
|
||||||
]
|
[
|
||||||
|
'name' => 'settings#startRegister',
|
||||||
|
'url' => '/settings/startregister',
|
||||||
|
'verb' => 'POST'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'settings#finishRegister',
|
||||||
|
'url' => '/settings/finishregister',
|
||||||
|
'verb' => 'POST'
|
||||||
|
],
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,49 +1,107 @@
|
||||||
/* global Backbone, Handlebars, OC, u2f */
|
/* global Backbone, Handlebars, OC, u2f */
|
||||||
|
|
||||||
(function (OC, Backbone, Handlebars, $, u2f) {
|
(function(OC, Backbone, Handlebars, $, u2f) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
OC.Settings = OC.Settings || {};
|
OC.Settings = OC.Settings || {};
|
||||||
OC.Settings.TwoFactorU2F = OC.Settings.TwoFactorU2F || {};
|
OC.Settings.TwoFactorU2F = OC.Settings.TwoFactorU2F || {};
|
||||||
|
|
||||||
var TEMPLATE = '<div>'
|
var TEMPLATE = '<div>'
|
||||||
+ ' <button id="u2f-register">Register</button>'
|
+ ' <input type="checkbox" class="checkbox" id="u2f-enabled" {{#if enabled}}checked{{/if}}>'
|
||||||
|
+ ' <label for="u2f-enabled">' + t('twofactor_u2f', 'Use U2F device') + '</label>'
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
|
|
||||||
var View = Backbone.View.extend({
|
var View = Backbone.View.extend({
|
||||||
template: Handlebars.compile(TEMPLATE),
|
_template: undefined,
|
||||||
|
_enabled: undefined,
|
||||||
|
template: function(data) {
|
||||||
|
if (!this._template) {
|
||||||
|
this._template = Handlebars.compile(TEMPLATE);
|
||||||
|
}
|
||||||
|
return this._template(data);
|
||||||
|
},
|
||||||
events: {
|
events: {
|
||||||
'click #u2f-register': 'onRegister'
|
'change #u2f-enabled': '_onToggleEnabled',
|
||||||
},
|
},
|
||||||
initialize: function () {
|
initialize: function() {
|
||||||
|
this._load();
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
this.$el.html(this.template({
|
||||||
|
enabled: this._enabled
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
_load: function() {
|
||||||
|
var url = OC.generateUrl('/apps/twofactor_u2f/settings/state');
|
||||||
|
$.ajax(url, {
|
||||||
|
method: 'GET',
|
||||||
|
}).done(function(data) {
|
||||||
|
this._enabled = data.enabled;
|
||||||
|
this.render();
|
||||||
|
}.bind(this)).fail(function() {
|
||||||
|
OC.Notification.showTemporary('Could not get U2F enabled/disabled state.');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_onToggleEnabled: function() {
|
||||||
|
if (this._loading) {
|
||||||
|
// Ignore event
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var enabled = this.$('#u2f-enabled').is(':checked');
|
||||||
|
|
||||||
|
if (enabled === this._enabled) {
|
||||||
|
console.log('ign');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._enabled = enabled;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
this._onRegister();
|
||||||
|
} else {
|
||||||
|
this._onDisable();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
render: function (data) {
|
_onRegister: function() {
|
||||||
this.$el.html(this.template(data));
|
this._loading = true;
|
||||||
},
|
|
||||||
onRegister: function () {
|
|
||||||
console.log('start register…');
|
console.log('start register…');
|
||||||
var url = OC.generateUrl('apps/twofactor_u2f/settings/startregister');
|
var url = OC.generateUrl('apps/twofactor_u2f/settings/startregister');
|
||||||
$.ajax(url, {
|
$.ajax(url, {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}).done(function (data) {
|
}).done(function(data) {
|
||||||
this.doRegister(data.req, data.sigs);
|
this.doRegister(data.req, data.sigs);
|
||||||
}.bind(this)).fail(function() {
|
}.bind(this)).fail(function() {
|
||||||
OC.Notification.showTemporary('server error while trying to add U2F device');
|
OC.Notification.showTemporary('server error while trying to add U2F device');
|
||||||
});
|
}).always(function() {
|
||||||
|
this._loading = false;
|
||||||
|
}.bind(this));
|
||||||
},
|
},
|
||||||
doRegister: function (req, sigs) {
|
_onDisable: function() {
|
||||||
|
this._loading = true;
|
||||||
|
console.log('disabling U2F…');
|
||||||
|
var url = OC.generateUrl('apps/twofactor_u2f/settings/disable');
|
||||||
|
$.ajax(url, {
|
||||||
|
method: 'POST'
|
||||||
|
}).fail(function() {
|
||||||
|
OC.Notification.showTemporary('Could not disable U2F');
|
||||||
|
}.bind(this)).always(function() {
|
||||||
|
this._loading = false;
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
doRegister: function(req, sigs) {
|
||||||
console.log('doRegister', req, sigs);
|
console.log('doRegister', req, sigs);
|
||||||
u2f.register([req], sigs, function (data) {
|
u2f.register([req], sigs, function(data) {
|
||||||
console.log(data.errorCode);
|
console.log(data.errorCode);
|
||||||
if (data.errorCode && data.errorCode !== 0) {
|
if (data.errorCode && data.errorCode !== 0) {
|
||||||
OC.Notification.showTemporary('U2F device registration failed (error code ' + data.errorCode + ')');
|
OC.Notification.showTemporary('U2F device registration failed (error code ' + data.errorCode + ')');
|
||||||
|
this._enabled = false;
|
||||||
|
this.render();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.finishRegister(data);
|
this.finishRegister(data);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
finishRegister: function (data) {
|
finishRegister: function(data) {
|
||||||
console.log('finish register…', data);
|
console.log('finish register…', data);
|
||||||
var url = OC.generateUrl('apps/twofactor_u2f/settings/finishregister');
|
var url = OC.generateUrl('apps/twofactor_u2f/settings/finishregister');
|
||||||
$.ajax(url, {
|
$.ajax(url, {
|
||||||
|
|
|
@ -27,12 +27,34 @@ class SettingsController extends Controller {
|
||||||
/** @var IUserSession */
|
/** @var IUserSession */
|
||||||
private $userSession;
|
private $userSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $appName
|
||||||
|
* @param IRequest $request
|
||||||
|
* @param U2FManager $manager
|
||||||
|
* @param IUserSession $userSession
|
||||||
|
*/
|
||||||
public function __construct($appName, IRequest $request, U2FManager $manager, IUserSession $userSession) {
|
public function __construct($appName, IRequest $request, U2FManager $manager, IUserSession $userSession) {
|
||||||
parent::__construct($appName, $request);
|
parent::__construct($appName, $request);
|
||||||
$this->manager = $manager;
|
$this->manager = $manager;
|
||||||
$this->userSession = $userSession;
|
$this->userSession = $userSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoAdminRequired
|
||||||
|
*/
|
||||||
|
public function state() {
|
||||||
|
return [
|
||||||
|
'enabled' => $this->manager->isEnabled($this->userSession->getUser())
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoAdminRequired
|
||||||
|
*/
|
||||||
|
public function disable() {
|
||||||
|
$this->manager->disableU2F($this->userSession->getUser());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @UseSession
|
* @UseSession
|
||||||
|
|
|
@ -62,6 +62,13 @@ class U2FManager {
|
||||||
return count($registrations) > 0;
|
return count($registrations) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function disableU2F(IUser $user) {
|
||||||
|
// TODO: use single query instead
|
||||||
|
foreach ($this->mapper->findRegistrations($user) as $registration) {
|
||||||
|
$this->mapper->delete($registration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function startRegistration(IUser $user) {
|
public function startRegistration(IUser $user) {
|
||||||
$u2f = $this->getU2f();
|
$u2f = $this->getU2f();
|
||||||
$data = $u2f->getRegisterData($this->getRegistrations($user));
|
$data = $u2f->getRegisterData($this->getRegistrations($user));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче