Added: ?admin TOTP show QR code

This commit is contained in:
the-djmaze 2022-08-29 12:17:08 +02:00
parent a80161a316
commit 3808852894
3 changed files with 50 additions and 12 deletions

View file

@ -21,28 +21,47 @@ export class AdminSettingsSecurity extends AbstractViewSettings {
adminPasswordNew: '', adminPasswordNew: '',
adminPasswordNew2: '', adminPasswordNew2: '',
adminPasswordNewError: false, adminPasswordNewError: false,
adminTOTP: SettingsGet('AdminTOTP'), adminTOTP: '',
adminPasswordUpdateError: false, saveError: false,
adminPasswordUpdateSuccess: false, saveSuccess: false,
viewQRCode: '',
capaOpenPGP: SettingsCapa('OpenPGP') capaOpenPGP: SettingsCapa('OpenPGP')
}); });
const reset = () => { const reset = () => {
this.adminPasswordUpdateError(false); this.saveError(false);
this.adminPasswordUpdateSuccess(false); this.saveSuccess(false);
this.adminPasswordNewError(false); this.adminPasswordNewError(false);
}; };
addSubscribablesTo(this, { addSubscribablesTo(this, {
adminPassword: () => { adminPassword: () => {
this.adminPasswordUpdateError(false); this.saveError(false);
this.adminPasswordUpdateSuccess(false); this.saveSuccess(false);
}, },
adminLogin: () => this.adminLoginError(false), adminLogin: () => this.adminLoginError(false),
adminTOTP: value => {
let l = value.length;
if (16 <= l && 0 == value.length * 5 % 8) {
Remote.request('AdminQRCode', (iError, data) => {
if (!iError) {
console.dir({data:data});
this.viewQRCode(data.Result);
}
}, {
'username': this.adminLogin(),
'TOTP': this.adminTOTP()
});
} else {
this.viewQRCode('');
}
},
adminPasswordNew: reset, adminPasswordNew: reset,
adminPasswordNew2: reset, adminPasswordNew2: reset,
@ -50,6 +69,8 @@ export class AdminSettingsSecurity extends AbstractViewSettings {
capaOpenPGP: value => Remote.saveSetting('CapaOpenPGP', value) capaOpenPGP: value => Remote.saveSetting('CapaOpenPGP', value)
}); });
this.adminTOTP(SettingsGet('AdminTOTP'));
decorateKoCommands(this, { decorateKoCommands(this, {
saveNewAdminPasswordCommand: self => self.adminLogin().trim() && self.adminPassword() saveNewAdminPasswordCommand: self => self.adminLogin().trim() && self.adminPassword()
}); });
@ -66,18 +87,18 @@ export class AdminSettingsSecurity extends AbstractViewSettings {
return false; return false;
} }
this.adminPasswordUpdateError(false); this.saveError(false);
this.adminPasswordUpdateSuccess(false); this.saveSuccess(false);
Remote.request('AdminPasswordUpdate', (iError, data) => { Remote.request('AdminPasswordUpdate', (iError, data) => {
if (iError) { if (iError) {
this.adminPasswordUpdateError(true); this.saveError(true);
} else { } else {
this.adminPassword(''); this.adminPassword('');
this.adminPasswordNew(''); this.adminPasswordNew('');
this.adminPasswordNew2(''); this.adminPasswordNew2('');
this.adminPasswordUpdateSuccess(true); this.saveSuccess(true);
this.weakPassword(!!data.Result.Weak); this.weakPassword(!!data.Result.Weak);
} }

View file

@ -668,6 +668,19 @@ class ActionsAdmin extends Actions
return $this->DefaultResponse(__FUNCTION__, true); return $this->DefaultResponse(__FUNCTION__, true);
} }
public function DoAdminQRCode() : array
{
$user = (string) $this->GetActionParam('username', '');
$secret = (string) $this->GetActionParam('TOTP', '');
$issuer = \rawurlencode(\RainLoop\API::Config()->Get('webmail', 'title', 'SnappyMail'));
$QR = \SnappyMail\QRCode::getMinimumQRCode(
"otpauth://totp/{$issuer}:{$user}?secret={$secret}&issuer={$issuer}",
// "otpauth://totp/{$user}?secret={$secret}",
\SnappyMail\QRCode::ERROR_CORRECT_LEVEL_M
);
return $this->DefaultResponse(__FUNCTION__, $QR->__toString());
}
private function setAdminAuthToken(string $sToken) : void private function setAdminAuthToken(string $sToken) : void
{ {
Utils::SetCookie(static::$AUTH_ADMIN_TOKEN_KEY, $sToken, 0); Utils::SetCookie(static::$AUTH_ADMIN_TOKEN_KEY, $sToken, 0);

View file

@ -49,7 +49,11 @@
data-bind="textInput: adminTOTP"> data-bind="textInput: adminTOTP">
</div> </div>
<div class="control-group"> <div class="control-group">
<a class="btn" data-bind="command: saveNewAdminPasswordCommand, css: { 'btn-success': adminPasswordUpdateSuccess, 'btn-danger': adminPasswordUpdateError }" <label></label>
<pre data-bind="text: viewQRCode" style="font-family:var(--fontMono);font-size:11px;letter-spacing:-1px;line-height:1;"></pre>
</div>
<div class="control-group">
<a class="btn" data-bind="command: saveNewAdminPasswordCommand, css: { 'btn-success': saveSuccess, 'btn-danger': saveError }"
data-icon="🔑" data-i18n="GLOBAL/SAVE"></a> data-icon="🔑" data-i18n="GLOBAL/SAVE"></a>
</div> </div>
</div> </div>