listing YubiKeys on the open view

This commit is contained in:
antelle 2020-05-24 20:02:49 +02:00
parent f215c26a63
commit 93310eb029
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
7 changed files with 126 additions and 11 deletions

View File

@ -80,9 +80,13 @@ const YubiKey = {
const yubiKeysIncludingEmpty = stdout
.trim()
.split(/\n/g)
.map(line => (line.match(/\d{5,}$/g) || [])[0]);
.map(line => {
const fullName = line;
const serial = (line.match(/\d{5,}$/g) || [])[0];
return { fullName, serial };
});
const yubiKeys = yubiKeysIncludingEmpty.filter(s => s);
const yubiKeys = yubiKeysIncludingEmpty.filter(s => s.serial);
if (
yubiKeysIncludingEmpty.length === 1 &&

View File

@ -233,6 +233,12 @@
"openListErrorBody": "There was an error loading file list",
"openShowAllFiles": "Show all files",
"openFileNoCacheError": "File not found in the cache storage. This can happen because browser storage was cleaned up. To open the file, remove it from KeeWeb and add it again.",
"openChalRespHeader": "Challenge-Response",
"openChalRespLoading": "Loading the list of YubiKeys",
"openChalRespSelectYubiKey": "Select a YubiKey that you would like to use",
"openChalRespErrorNotInstalled": "YubiKey integration is not configured, please go to settings to set it up",
"openChalRespErrorEmpty": "No YubiKeys found",
"openChalRespSlot": "slot",
"detAttDownload": "Shift-click the attachment button to download it or",
"detAttDelToRemove": "Delete to remove",

View File

@ -35,7 +35,7 @@ class YubiKeyOtpModel extends ExternalOtpDeviceModel {
const openErrors = [];
const openNextYubiKey = () => {
const yubiKey = yubiKeys.shift();
this._addYubiKey(yubiKey, err => {
this._addYubiKey(yubiKey.serial, err => {
if (YubiKey.aborted) {
return callback('Aborted');
}

View File

@ -0,0 +1,65 @@
import { View } from 'framework/views/view';
import { YubiKey } from 'comp/app/yubikey';
import { Locale } from 'util/locale';
import template from 'templates/open-chal-resp.hbs';
class OpenChalRespView extends View {
template = template;
events = {
'click .open-chal-resp__item': 'itemClick'
};
constructor() {
super();
YubiKey.checkToolStatus().then(status => {
if (this.removed) {
return;
}
if (status === 'ok') {
YubiKey.list((err, yubiKeys) => {
this.error = err;
this.yubiKeys = [];
for (const { fullName, serial } of yubiKeys) {
for (const slot of [1, 2]) {
this.yubiKeys.push({
fullName,
serial,
slot
});
}
}
this.render();
});
} else {
this.render();
}
});
}
render() {
let error = this.error;
if (YubiKey.ykmanStatus === 'error') {
error = Locale.openChalRespErrorNotInstalled.replace('{}', 'ykman');
}
if (this.yubiKeys && !this.yubiKeys.length) {
error = Locale.openChalRespErrorEmpty;
}
super.render({
error,
yubiKeys: this.yubiKeys,
loading: !YubiKey.ykmanStatus || YubiKey.ykmanStatus === 'checking'
});
}
itemClick(e) {
const el = e.target.closest('[data-serial]');
const { serial, slot } = el.dataset;
this.emit('select', { serial, slot });
}
}
export { OpenChalRespView };

View File

@ -19,6 +19,7 @@ import { Logger } from 'util/logger';
import { InputFx } from 'util/ui/input-fx';
import { OpenConfigView } from 'views/open-config-view';
import { StorageFileListView } from 'views/storage-file-list-view';
import { OpenChalRespView } from 'views/open-chal-resp-view';
import { omit } from 'util/fn';
import { GeneratorView } from 'views/generator-view';
import template from 'templates/open.hbs';
@ -1043,16 +1044,19 @@ class OpenView extends View {
if (this.busy) {
return;
}
this.busy = true;
YubiKey.checkToolStatus().then(status => {
if (status !== 'ok') {
this.busy = false;
return Events.emit('toggle-settings', 'devices');
}
this.busy = false;
const chalRespView = new OpenChalRespView();
chalRespView.on('select', e => {
// console.log('e', e.serial, e.slot);
});
Alerts.notImplemented();
Alerts.alert({
header: Locale.openChalRespHeader,
icon: 'exchange',
buttons: [{ result: '', title: Locale.alertCancel }],
esc: '',
click: '',
view: chalRespView
});
}
}

View File

@ -388,3 +388,19 @@
display: inline-block;
}
}
.open-chal-resp {
&__head {
padding: $base-padding;
}
&__icon {
margin-right: $small-spacing;
}
&__item {
padding: $base-padding;
cursor: pointer;
&:hover {
background-color: var(--action-background-color-focus-tr);
}
}
}

View File

@ -0,0 +1,20 @@
<div class="open-chal-resp">
{{#if loading}}
<div class="open-chal-resp__head">
<i class="open-chal-resp__icon fa fa-spinner fa-spin"></i> {{res 'openChalRespLoading'}}
</div>
{{else if error}}
<div class="open-chal-resp__head">
<i class="open-chal-resp__icon fa fa-ban"></i> {{error}}
</div>
{{else}}
<div class="open-chal-resp__head">{{res 'openChalRespSelectYubiKey'}}:</div>
<div>
{{#each yubiKeys as |yk|}}
<div class="open-chal-resp__item" data-serial="{{yk.serial}}" data-slot="{{yk.slot}}">
{{yk.fullName}}, {{res 'openChalRespSlot'}} {{yk.slot}}
</div>
{{/each}}
</div>
{{/if}}
</div>