Feature: two-factor authentication (#8012)

This commit is contained in:
shamoon
2024-11-18 10:34:46 -08:00
committed by GitHub
parent 6c3d6d562d
commit e94a92ed59
29 changed files with 1128 additions and 175 deletions

View File

@@ -2,7 +2,11 @@ import { Component, OnDestroy, OnInit } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ProfileService } from 'src/app/services/profile.service'
import { SocialAccount, SocialAccountProvider } from 'src/app/data/user-profile'
import {
TotpSettings,
SocialAccount,
SocialAccountProvider,
} from 'src/app/data/user-profile'
import { ToastService } from 'src/app/services/toast.service'
import { Subject, takeUntil } from 'rxjs'
import { Clipboard } from '@angular/cdk/clipboard'
@@ -25,6 +29,7 @@ export class ProfileEditDialogComponent implements OnInit, OnDestroy {
first_name: new FormControl(''),
last_name: new FormControl(''),
auth_token: new FormControl(''),
totp_code: new FormControl(''),
})
private currentPassword: string
@@ -38,7 +43,14 @@ export class ProfileEditDialogComponent implements OnInit, OnDestroy {
private emailConfirm: string
public showEmailConfirm: boolean = false
public isTotpEnabled: boolean = false
public totpSettings: TotpSettings
public totpSettingsLoading: boolean = false
public totpLoading: boolean = false
public recoveryCodes: string[]
public copied: boolean = false
public codesCopied: boolean = false
public socialAccounts: SocialAccount[] = []
public socialAccountProviders: SocialAccountProvider[] = []
@@ -70,6 +82,7 @@ export class ProfileEditDialogComponent implements OnInit, OnDestroy {
this.onPasswordChange()
})
this.socialAccounts = profile.social_accounts
this.isTotpEnabled = profile.is_mfa_enabled
})
this.profileService
@@ -147,6 +160,7 @@ export class ProfileEditDialogComponent implements OnInit, OnDestroy {
const passwordChanged =
this.newPassword && this.currentPassword !== this.newPassword
const profile = Object.assign({}, this.form.value)
delete profile.totp_code
this.networkActive = true
this.profileService
.update(profile)
@@ -213,4 +227,81 @@ export class ProfileEditDialogComponent implements OnInit, OnDestroy {
},
})
}
public gettotpSettings(): void {
this.totpSettingsLoading = true
this.profileService
.getTotpSettings()
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (totpSettings) => {
this.totpSettingsLoading = false
this.totpSettings = totpSettings
},
error: (error) => {
this.toastService.showError(
$localize`Error fetching TOTP settings`,
error
)
this.totpSettingsLoading = false
},
})
}
public activateTotp(): void {
this.totpLoading = true
this.form.get('totp_code').disable()
this.profileService
.activateTotp(this.totpSettings.secret, this.form.get('totp_code').value)
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (activationResponse) => {
this.totpLoading = false
this.isTotpEnabled = activationResponse.success
this.recoveryCodes = activationResponse.recovery_codes
this.form.get('totp_code').enable()
if (activationResponse.success) {
this.toastService.showInfo($localize`TOTP activated successfully`)
} else {
this.toastService.showError($localize`Error activating TOTP`)
}
},
error: (error) => {
this.totpLoading = false
this.form.get('totp_code').enable()
this.toastService.showError($localize`Error activating TOTP`, error)
},
})
}
public deactivateTotp(): void {
this.totpLoading = true
this.profileService
.deactivateTotp()
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (success) => {
this.totpLoading = false
this.isTotpEnabled = !success
this.recoveryCodes = null
if (success) {
this.toastService.showInfo($localize`TOTP deactivated successfully`)
} else {
this.toastService.showError($localize`Error deactivating TOTP`)
}
},
error: (error) => {
this.totpLoading = false
this.toastService.showError($localize`Error deactivating TOTP`, error)
},
})
}
public copyRecoveryCodes(): void {
this.clipboard.copy(this.recoveryCodes.join('\n'))
this.codesCopied = true
setTimeout(() => {
this.codesCopied = false
}, 3000)
}
}