Add HOTP counter field to Edit form

This commit is contained in:
Bubka 2020-01-24 12:56:38 +01:00
parent 6ed67ad895
commit a4a780b14f
5 changed files with 72 additions and 3 deletions

View File

@ -34,7 +34,7 @@ class TwoFAccountController extends Controller
// for otpauth uri format validation // for otpauth uri format validation
$this->validate($request, [ $this->validate($request, [
'service' => 'required', 'service' => 'required',
'uri' => 'required|starts_with:otpauth://totp/', 'uri' => 'required|regex:/^otpauth:\/\/[h,t]otp\//i',
]); ]);
$twofaccount = TwoFAccount::create([ $twofaccount = TwoFAccount::create([

View File

@ -2,6 +2,8 @@
namespace App; namespace App;
use OTPHP\HOTP;
use OTPHP\Factory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Encryption\DecryptException;
@ -24,6 +26,14 @@ class TwoFAccount extends Model
protected $table = 'twofaccounts'; protected $table = 'twofaccounts';
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = ['type', 'counter'];
/** /**
* Null empty icon resource has gone * Null empty icon resource has gone
* *
@ -42,6 +52,35 @@ class TwoFAccount extends Model
return $value; return $value;
} }
/**
* Get the account type.
*
* @return string
*/
public function getTypeAttribute()
{
return substr( $this->uri, 0, 15 ) === "otpauth://totp/" ? 'totp' : 'hotp';
}
/**
* Get the account counter in case of HOTP.
*
* @return integer
*/
public function getCounterAttribute()
{
if( $this->type === 'hotp' ) {
$otp = Factory::loadFromProvisioningUri($this->uri);
return $otp->getCounter();
}
return null;
}
/** /**
* Set the user's first name. * Set the user's first name.
* *

View File

@ -25,7 +25,7 @@ export default {
"change_password": "Change password", "change_password": "Change password",
"send_password_reset_link": "Send password reset link", "send_password_reset_link": "Send password reset link",
"change_your_password": "Change your password", "change_your_password": "Change your password",
"your_password_has_been_changed": "Your password has been successfully changed ", "password_successfully_changed": "Password successfully changed ",
"profile_saved": "Profile successfully updated!" "profile_saved": "Profile successfully updated!"
} }
}, },
@ -79,6 +79,7 @@ export default {
"new_account": "New account", "new_account": "New account",
"edit_account": "Edit account", "edit_account": "Edit account",
"totp_uri": "TOTP Uri", "totp_uri": "TOTP Uri",
"hotp_counter": "HOTP Counter",
"use_qrcode": { "use_qrcode": {
"val": "Use a qrcode", "val": "Use a qrcode",
"title": "Use a QR code to fill the form magically" "title": "Use a QR code to fill the form magically"

View File

@ -18,6 +18,31 @@
</div> </div>
<field-error :form="form" field="account" /> <field-error :form="form" field="account" />
</div> </div>
<div v-if="form.counter">
<div class="field" style="margin-bottom: 0.5rem;">
<label class="label">{{ $t('twofaccounts.forms.hotp_counter') }}</label>
</div>
<div class="field has-addons">
<div class="control is-expanded">
<input class="input" type="text" placeholder="" v-model="form.counter" :disabled="counterIsLocked" />
</div>
<div class="control" v-if="counterIsLocked">
<a class="button is-dark field-lock" @click="counterIsLocked = false" :title="$t('twofaccounts.forms.unlock.title')">
<span class="icon">
<font-awesome-icon :icon="['fas', 'lock']" />
</span>
</a>
</div>
<div class="control" v-else>
<a class="button is-dark field-unlock" @click="counterIsLocked = true" :title="$t('twofaccounts.forms.lock.title')">
<span class="icon has-text-danger">
<font-awesome-icon :icon="['fas', 'lock-open']" />
</span>
</a>
</div>
</div>
<field-error :form="form" field="uri" class="help-for-file" />
</div>
<div class="field"> <div class="field">
<label class="label">{{ $t('twofaccounts.icon') }}</label> <label class="label">{{ $t('twofaccounts.icon') }}</label>
<div class="file is-dark"> <div class="file is-dark">
@ -58,6 +83,7 @@
export default { export default {
data() { data() {
return { return {
counterIsLocked: true,
twofaccountExists: false, twofaccountExists: false,
tempIcon: '', tempIcon: '',
form: new Form({ form: new Form({
@ -65,7 +91,9 @@
account: '', account: '',
uri: '', uri: '',
icon: '', icon: '',
qrcode: null qrcode: null,
type: '',
counter: null
}) })
} }
}, },

View File

@ -31,6 +31,7 @@ return [
'new_account' => 'New account', 'new_account' => 'New account',
'edit_account' => 'Edit account', 'edit_account' => 'Edit account',
'totp_uri' => 'TOTP Uri', 'totp_uri' => 'TOTP Uri',
'hotp_counter' => 'HOTP Counter',
'use_qrcode' => [ 'use_qrcode' => [
'val' => 'Use a qrcode', 'val' => 'Use a qrcode',
'title' => 'Use a QR code to fill the form magically', 'title' => 'Use a QR code to fill the form magically',