allow users to enable/disable U2F via their personal settings

This commit is contained in:
Christoph Wurst 2016-08-26 15:26:23 +02:00
Родитель b2ecea2c82
Коммит 022e8ea063
4 изменённых файлов: 123 добавлений и 26 удалений

Просмотреть файл

@ -19,16 +19,26 @@
*
*/
return [
'routes' => [
[
'name' => 'settings#startRegister',
'url' => '/settings/startregister',
'verb' => 'POST'
],
[
'name' => 'settings#finishRegister',
'url' => '/settings/finishregister',
'verb' => 'POST'
],
]
'routes' => [
[
'name' => 'settings#state',
'url' => '/settings/state',
'verb' => 'GET'
],
[
'name' => 'settings#disable',
'url' => '/settings/disable',
'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 */
(function (OC, Backbone, Handlebars, $, u2f) {
(function(OC, Backbone, Handlebars, $, u2f) {
'use strict';
OC.Settings = OC.Settings || {};
OC.Settings.TwoFactorU2F = OC.Settings.TwoFactorU2F || {};
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>';
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: {
'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) {
this.$el.html(this.template(data));
},
onRegister: function () {
_onRegister: function() {
this._loading = true;
console.log('start register…');
var url = OC.generateUrl('apps/twofactor_u2f/settings/startregister');
$.ajax(url, {
method: 'POST'
}).done(function (data) {
}).done(function(data) {
this.doRegister(data.req, data.sigs);
}.bind(this)).fail(function() {
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);
u2f.register([req], sigs, function (data) {
u2f.register([req], sigs, function(data) {
console.log(data.errorCode);
if (data.errorCode && data.errorCode !== 0) {
OC.Notification.showTemporary('U2F device registration failed (error code ' + data.errorCode + ')');
this._enabled = false;
this.render();
return;
}
this.finishRegister(data);
}.bind(this));
},
finishRegister: function (data) {
finishRegister: function(data) {
console.log('finish register…', data);
var url = OC.generateUrl('apps/twofactor_u2f/settings/finishregister');
$.ajax(url, {

Просмотреть файл

@ -27,12 +27,34 @@ class SettingsController extends Controller {
/** @var IUserSession */
private $userSession;
/**
* @param string $appName
* @param IRequest $request
* @param U2FManager $manager
* @param IUserSession $userSession
*/
public function __construct($appName, IRequest $request, U2FManager $manager, IUserSession $userSession) {
parent::__construct($appName, $request);
$this->manager = $manager;
$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
* @UseSession

Просмотреть файл

@ -62,6 +62,13 @@ class U2FManager {
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) {
$u2f = $this->getU2f();
$data = $u2f->getRegisterData($this->getRegistrations($user));