2018-06-27 04:51:58 +02:00
|
|
|
import {
|
|
|
|
Component,
|
2018-06-27 15:20:09 +02:00
|
|
|
ComponentFactoryResolver,
|
2018-06-27 04:51:58 +02:00
|
|
|
OnInit,
|
2018-06-27 15:20:09 +02:00
|
|
|
Type,
|
|
|
|
ViewChild,
|
|
|
|
ViewContainerRef,
|
2018-06-27 04:51:58 +02:00
|
|
|
} from '@angular/core';
|
|
|
|
|
|
|
|
import { ApiService } from 'jslib/abstractions/api.service';
|
2018-07-18 15:21:23 +02:00
|
|
|
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
2020-02-27 19:07:33 +01:00
|
|
|
import { PolicyService } from 'jslib/abstractions/policy.service';
|
2018-08-29 05:17:58 +02:00
|
|
|
import { UserService } from 'jslib/abstractions/user.service';
|
2018-06-27 04:51:58 +02:00
|
|
|
|
|
|
|
import { TwoFactorProviders } from 'jslib/services/auth.service';
|
|
|
|
|
2020-02-27 19:07:33 +01:00
|
|
|
import { PolicyType } from 'jslib/enums/policyType';
|
2018-06-27 04:51:58 +02:00
|
|
|
import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType';
|
|
|
|
|
2018-06-27 15:20:09 +02:00
|
|
|
import { ModalComponent } from '../modal.component';
|
|
|
|
|
|
|
|
import { TwoFactorAuthenticatorComponent } from './two-factor-authenticator.component';
|
2018-06-27 21:27:59 +02:00
|
|
|
import { TwoFactorDuoComponent } from './two-factor-duo.component';
|
2018-06-27 22:56:11 +02:00
|
|
|
import { TwoFactorEmailComponent } from './two-factor-email.component';
|
2018-06-28 15:40:11 +02:00
|
|
|
import { TwoFactorRecoveryComponent } from './two-factor-recovery.component';
|
2021-03-16 17:44:31 +01:00
|
|
|
import { TwoFactorWebAuthnComponent } from './two-factor-webauthn.component';
|
2018-06-27 19:45:11 +02:00
|
|
|
import { TwoFactorYubiKeyComponent } from './two-factor-yubikey.component';
|
2018-06-27 15:20:09 +02:00
|
|
|
|
2018-06-27 04:51:58 +02:00
|
|
|
@Component({
|
|
|
|
selector: 'app-two-factor-setup',
|
|
|
|
templateUrl: 'two-factor-setup.component.html',
|
|
|
|
})
|
|
|
|
export class TwoFactorSetupComponent implements OnInit {
|
2020-08-17 16:04:38 +02:00
|
|
|
@ViewChild('recoveryTemplate', { read: ViewContainerRef, static: true }) recoveryModalRef: ViewContainerRef;
|
|
|
|
@ViewChild('authenticatorTemplate', { read: ViewContainerRef, static: true }) authenticatorModalRef: ViewContainerRef;
|
|
|
|
@ViewChild('yubikeyTemplate', { read: ViewContainerRef, static: true }) yubikeyModalRef: ViewContainerRef;
|
|
|
|
@ViewChild('duoTemplate', { read: ViewContainerRef, static: true }) duoModalRef: ViewContainerRef;
|
|
|
|
@ViewChild('emailTemplate', { read: ViewContainerRef, static: true }) emailModalRef: ViewContainerRef;
|
2021-03-16 17:44:31 +01:00
|
|
|
@ViewChild('webAuthnTemplate', { read: ViewContainerRef, static: true }) webAuthnModalRef: ViewContainerRef;
|
2018-06-27 15:20:09 +02:00
|
|
|
|
2018-07-18 23:20:35 +02:00
|
|
|
organizationId: string;
|
2018-06-27 04:51:58 +02:00
|
|
|
providers: any[] = [];
|
2018-08-29 05:17:58 +02:00
|
|
|
canAccessPremium: boolean;
|
2020-02-27 19:07:33 +01:00
|
|
|
showPolicyWarning = false;
|
2018-06-27 04:51:58 +02:00
|
|
|
loading = true;
|
|
|
|
|
2018-06-27 15:20:09 +02:00
|
|
|
private modal: ModalComponent = null;
|
|
|
|
|
2018-08-29 05:17:58 +02:00
|
|
|
constructor(protected apiService: ApiService, protected userService: UserService,
|
2020-02-27 19:07:33 +01:00
|
|
|
protected componentFactoryResolver: ComponentFactoryResolver, protected messagingService: MessagingService,
|
|
|
|
protected policyService: PolicyService) { }
|
2018-06-27 04:51:58 +02:00
|
|
|
|
|
|
|
async ngOnInit() {
|
2018-08-29 05:17:58 +02:00
|
|
|
this.canAccessPremium = await this.userService.canAccessPremium();
|
2018-06-27 04:51:58 +02:00
|
|
|
|
|
|
|
for (const key in TwoFactorProviders) {
|
|
|
|
if (!TwoFactorProviders.hasOwnProperty(key)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const p = (TwoFactorProviders as any)[key];
|
2018-07-18 23:10:26 +02:00
|
|
|
if (this.filterProvider(p.type)) {
|
2018-06-27 04:51:58 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.providers.push({
|
|
|
|
type: p.type,
|
|
|
|
name: p.name,
|
|
|
|
description: p.description,
|
|
|
|
enabled: false,
|
|
|
|
premium: p.premium,
|
|
|
|
sort: p.sort,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.providers.sort((a: any, b: any) => a.sort - b.sort);
|
|
|
|
await this.load();
|
|
|
|
}
|
|
|
|
|
|
|
|
async load() {
|
|
|
|
this.loading = true;
|
2018-07-18 23:10:26 +02:00
|
|
|
const providerList = await this.getTwoFactorProviders();
|
2021-02-03 18:41:33 +01:00
|
|
|
providerList.data.forEach(p => {
|
|
|
|
this.providers.forEach(p2 => {
|
2018-06-27 04:51:58 +02:00
|
|
|
if (p.type === p2.type) {
|
|
|
|
p2.enabled = p.enabled;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2020-02-27 19:07:33 +01:00
|
|
|
this.evaluatePolicies();
|
2018-06-27 04:51:58 +02:00
|
|
|
this.loading = false;
|
|
|
|
}
|
2018-06-27 15:20:09 +02:00
|
|
|
|
|
|
|
manage(type: TwoFactorProviderType) {
|
|
|
|
switch (type) {
|
|
|
|
case TwoFactorProviderType.Authenticator:
|
2018-06-27 19:45:11 +02:00
|
|
|
const authComp = this.openModal(this.authenticatorModalRef, TwoFactorAuthenticatorComponent);
|
|
|
|
authComp.onUpdated.subscribe((enabled: boolean) => {
|
2018-06-27 21:27:59 +02:00
|
|
|
this.updateStatus(enabled, TwoFactorProviderType.Authenticator);
|
2018-06-27 15:20:09 +02:00
|
|
|
});
|
|
|
|
break;
|
2018-06-27 19:45:11 +02:00
|
|
|
case TwoFactorProviderType.Yubikey:
|
|
|
|
const yubiComp = this.openModal(this.yubikeyModalRef, TwoFactorYubiKeyComponent);
|
|
|
|
yubiComp.onUpdated.subscribe((enabled: boolean) => {
|
2018-06-27 21:27:59 +02:00
|
|
|
this.updateStatus(enabled, TwoFactorProviderType.Yubikey);
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
case TwoFactorProviderType.Duo:
|
|
|
|
const duoComp = this.openModal(this.duoModalRef, TwoFactorDuoComponent);
|
|
|
|
duoComp.onUpdated.subscribe((enabled: boolean) => {
|
|
|
|
this.updateStatus(enabled, TwoFactorProviderType.Duo);
|
2018-06-27 19:45:11 +02:00
|
|
|
});
|
|
|
|
break;
|
2018-06-27 22:56:11 +02:00
|
|
|
case TwoFactorProviderType.Email:
|
|
|
|
const emailComp = this.openModal(this.emailModalRef, TwoFactorEmailComponent);
|
|
|
|
emailComp.onUpdated.subscribe((enabled: boolean) => {
|
|
|
|
this.updateStatus(enabled, TwoFactorProviderType.Email);
|
|
|
|
});
|
|
|
|
break;
|
2021-03-16 17:44:31 +01:00
|
|
|
case TwoFactorProviderType.WebAuthn:
|
|
|
|
const webAuthnComp = this.openModal(this.webAuthnModalRef, TwoFactorWebAuthnComponent);
|
|
|
|
webAuthnComp.onUpdated.subscribe((enabled: boolean) => {
|
|
|
|
this.updateStatus(enabled, TwoFactorProviderType.WebAuthn);
|
2018-06-27 23:50:31 +02:00
|
|
|
});
|
|
|
|
break;
|
2018-06-27 15:20:09 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 15:40:11 +02:00
|
|
|
recoveryCode() {
|
|
|
|
this.openModal(this.recoveryModalRef, TwoFactorRecoveryComponent);
|
|
|
|
}
|
|
|
|
|
2018-07-18 15:21:23 +02:00
|
|
|
async premiumRequired() {
|
2018-08-29 05:17:58 +02:00
|
|
|
if (!this.canAccessPremium) {
|
2018-07-18 15:21:23 +02:00
|
|
|
this.messagingService.send('premiumRequired');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-18 23:10:26 +02:00
|
|
|
protected getTwoFactorProviders() {
|
|
|
|
return this.apiService.getTwoFactorProviders();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected filterProvider(type: TwoFactorProviderType) {
|
|
|
|
return type === TwoFactorProviderType.OrganizationDuo;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected openModal<T>(ref: ViewContainerRef, type: Type<T>): T {
|
2018-06-27 15:20:09 +02:00
|
|
|
if (this.modal != null) {
|
|
|
|
this.modal.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
|
|
|
|
this.modal = ref.createComponent(factory).instance;
|
|
|
|
const childComponent = this.modal.show<T>(type, ref);
|
|
|
|
|
|
|
|
this.modal.onClosed.subscribe(() => {
|
|
|
|
this.modal = null;
|
|
|
|
});
|
|
|
|
return childComponent;
|
|
|
|
}
|
|
|
|
|
2018-07-18 23:10:26 +02:00
|
|
|
protected updateStatus(enabled: boolean, type: TwoFactorProviderType) {
|
2018-06-27 15:20:09 +02:00
|
|
|
if (!enabled && this.modal != null) {
|
|
|
|
this.modal.close();
|
|
|
|
}
|
2021-02-03 18:41:33 +01:00
|
|
|
this.providers.forEach(p => {
|
2018-06-27 15:20:09 +02:00
|
|
|
if (p.type === type) {
|
|
|
|
p.enabled = enabled;
|
|
|
|
}
|
|
|
|
});
|
2020-02-27 19:07:33 +01:00
|
|
|
this.evaluatePolicies();
|
|
|
|
}
|
|
|
|
|
|
|
|
private async evaluatePolicies() {
|
2021-02-03 18:41:33 +01:00
|
|
|
if (this.organizationId == null && this.providers.filter(p => p.enabled).length === 1) {
|
2020-02-27 19:07:33 +01:00
|
|
|
const policies = await this.policyService.getAll(PolicyType.TwoFactorAuthentication);
|
2021-02-03 18:41:33 +01:00
|
|
|
this.showPolicyWarning = policies != null && policies.some(p => p.enabled);
|
2020-02-27 19:07:33 +01:00
|
|
|
} else {
|
|
|
|
this.showPolicyWarning = false;
|
|
|
|
}
|
2018-06-27 15:20:09 +02:00
|
|
|
}
|
2018-06-27 04:51:58 +02:00
|
|
|
}
|