@ -133,8 +133,14 @@ const template = `
< h6 class = "pad-top" > Recovery Codes < / h 6 >
< p > Recovery codes can be used to regain access to your account in the event that you lose access to the device that generates your MFA codes . < / p >
< span v - if = "!has_mfa_recovery" >
< p class = "font-italic" > No recovery codes have been generated for your account . < / p >
< button class = "btn btn-sm btn-success" > Generate Recovery Codes < / b u t t o n >
< button class = "btn btn-sm btn-success" @ click = "on_mfa_recovery_generate" > Generate Recovery Codes < / b u t t o n >
< / s p a n >
< span v - if = "has_mfa_recovery" >
< p class = "font-italic" > Recovery codes were generate for your account on { { mfa _recovery _date } } . < span v - if = "mfa_recovery_codes === 1" > There is only 1 recovery code remaining . < / s p a n > < s p a n v - i f = " m f a _ r e c o v e r y _ c o d e s ! = = 1 " > T h e r e a r e { { m f a _ r e c o v e r y _ c o d e s } } r e c o v e r y c o d e s r e m a i n i n g . < / s p a n > < / p >
< button class = "btn btn-sm btn-success" @ click = "on_mfa_recovery_generate" > Re - generate Recovery Codes < / b u t t o n >
< / s p a n >
< / l i >
< / u l >
< / d i v >
@ -163,6 +169,10 @@ export default class EditProfileComponent extends Component {
last _reset = ''
mfa _enable _date = ''
has _mfa _recovery = false
mfa _recovery _date = ''
mfa _recovery _codes = 0
form _message = 'No changes.'
has _mfa = false
@ -248,7 +258,16 @@ export default class EditProfileComponent extends Component {
const mfa = await auth _api . has _mfa ( )
this . has _mfa = mfa && mfa . mfa _enabled
if ( this . has _mfa ) this . mfa _enable _date = ( new Date ( mfa . mfa _enable _date ) ) . toLocaleDateString ( )
if ( this . has _mfa ) {
this . mfa _enable _date = ( new Date ( mfa . mfa _enable _date ) ) . toLocaleDateString ( )
const result = await auth _api . has _mfa _recovery ( )
if ( result && result . has _recovery ) {
this . has _mfa _recovery = true
this . mfa _recovery _date = ( new Date ( result . generated ) ) . toLocaleDateString ( )
this . mfa _recovery _codes = result . remaining _codes
}
}
await this . load _app _passwords ( )
}
@ -301,5 +320,65 @@ export default class EditProfileComponent extends Component {
] ,
} )
}
async on _mfa _recovery _generate ( $event ) {
if ( ! this . has _mfa ) return
if ( ! this . has _mfa _recovery ) {
await this . generate _mfa _recovery ( )
} else {
message _service . modal ( {
title : 'Are you sure?' ,
message : 'There are already MFA recovery codes associated with your account. If you re-generate them, you will be unable to use the old ones. Continue?' ,
buttons : [
{
text : 'Cancel' ,
type : 'close' ,
} ,
{
text : 'Re-generate' ,
type : 'close' ,
class : [ 'btn' , 'btn-warning' ] ,
on _click : async ( ) => {
await this . generate _mfa _recovery ( )
} ,
} ,
] ,
} )
}
}
async generate _mfa _recovery ( ) {
const codes = await auth _api . generate _mfa _recovery ( )
if ( codes ) {
this . display _mfa _recovery _modal ( codes )
} else {
message _service . alert ( {
type : 'error' ,
message : 'An unknown error occurred while attempting to generate MFA recovery codes.'
} )
}
await this . load ( )
}
display _mfa _recovery _modal ( codes ) {
const code _display = codes . map ( x => ` <li><code> ${ x } </code></li> ` ) . join ( '\n' )
message _service . modal ( {
title : 'MFA Recovery Codes' ,
message : ` We've generated recovery codes for your account. You can use these to recover access to your account in the event that you lose your MFA device.
< br > < br >
Be sure to put these somewhere safe . After you close this modal , they will disappear :
< br > < br >
< ul >
$ { code _display }
< / u l > ` ,
buttons : [
{
text : 'Close' ,
type : 'close' ,
} ,
] ,
} )
}
}