mirror of
https://gitee.com/dromara/MaxKey.git
synced 2025-12-06 17:08:29 +08:00
213 lines
6.6 KiB
TypeScript
213 lines
6.6 KiB
TypeScript
/*
|
|
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import {
|
|
ChangeDetectionStrategy,
|
|
ChangeDetectorRef,
|
|
Component,
|
|
Inject,
|
|
inject,
|
|
OnInit,
|
|
OnDestroy,
|
|
AfterViewInit,
|
|
Optional
|
|
} from '@angular/core';
|
|
import { AbstractControl, ReactiveFormsModule, FormBuilder, FormGroup, Validators, FormsModule } from '@angular/forms';
|
|
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
|
import { ReuseTabService } from '@delon/abc/reuse-tab';
|
|
import { SettingsService, _HttpClient, I18nPipe } from '@delon/theme';
|
|
import { environment } from '@env/environment';
|
|
import { NzAlertModule } from 'ng-zorro-antd/alert';
|
|
import { NzButtonModule } from 'ng-zorro-antd/button';
|
|
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
|
|
import { NzSafeAny } from 'ng-zorro-antd/core/types';
|
|
import { NzFormModule } from 'ng-zorro-antd/form';
|
|
import { NzIconModule } from 'ng-zorro-antd/icon';
|
|
import { NzInputModule } from 'ng-zorro-antd/input';
|
|
import { NzMessageService } from 'ng-zorro-antd/message';
|
|
import { NzRadioModule } from 'ng-zorro-antd/radio';
|
|
import { NzTabChangeEvent, NzTabsModule } from 'ng-zorro-antd/tabs';
|
|
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
|
|
import { finalize } from 'rxjs/operators';
|
|
|
|
import { AuthnService } from '../../../service/authn.service';
|
|
import { ImageCaptchaService } from '../../../service/image-captcha.service';
|
|
import { CONSTS } from '../../../shared/consts';
|
|
|
|
@Component({
|
|
selector: 'app-tfa',
|
|
templateUrl: './tfa.component.html',
|
|
styleUrls: ['./tfa.component.less'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class TfaComponent implements OnInit {
|
|
form: FormGroup;
|
|
error = '';
|
|
secretKey = '';
|
|
secretPublicKey = '';
|
|
captchaType = '';
|
|
twoFactorType = '0';
|
|
twoFactorJwt = '';
|
|
isFirstPasswordModify = 'N';
|
|
state = '';
|
|
defualtRedirectUri = '';
|
|
count = 0;
|
|
interval$: any;
|
|
loading = false;
|
|
constructor(
|
|
fb: FormBuilder,
|
|
private router: Router,
|
|
private settingsService: SettingsService,
|
|
private authnService: AuthnService,
|
|
private imageCaptchaService: ImageCaptchaService,
|
|
private route: ActivatedRoute,
|
|
private msg: NzMessageService,
|
|
@Optional()
|
|
@Inject(ReuseTabService)
|
|
private reuseTabService: ReuseTabService,
|
|
private cdr: ChangeDetectorRef
|
|
) {
|
|
this.form = fb.group({
|
|
userName: [null, [Validators.required]],
|
|
password: [null, [Validators.required]],
|
|
captcha: [null, [Validators.required]],
|
|
mobile: [null, [Validators.required, Validators.pattern(/^1\d{10}$/)]],
|
|
twoFactorMobile: [null, [Validators.required, Validators.pattern(/^1\d{10}$/)]],
|
|
twoFactorEmail: [null, [Validators.required, Validators.pattern(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/)]],
|
|
otpCaptcha: [null, [Validators.required]],
|
|
remember: [false]
|
|
});
|
|
}
|
|
|
|
ngOnInit(): void {
|
|
this.authnService
|
|
.get({ remember_me: localStorage.getItem(CONSTS.REMEMBER) })
|
|
.pipe(
|
|
finalize(() => {
|
|
this.loading = false;
|
|
this.cdr.detectChanges();
|
|
})
|
|
)
|
|
.subscribe(res => {
|
|
this.loading = true;
|
|
if (res.code !== 0) {
|
|
this.error = res.msg;
|
|
} else {
|
|
this.state = res.data.state;
|
|
this.defualtRedirectUri = res.data.redirectUri;
|
|
this.captchaType = res.data.captcha;
|
|
this.secretKey = res.data.secretKey;
|
|
this.secretPublicKey = res.data.secretPublicKey;
|
|
this.isFirstPasswordModify = res.data.isFirstPasswordModify;
|
|
}
|
|
});
|
|
let twoFactorData = JSON.parse(localStorage.getItem(CONSTS.TWO_FACTOR_DATA) || '');
|
|
this.twoFactorType = twoFactorData.twoFactor;
|
|
this.twoFactorJwt = twoFactorData.token;
|
|
this.twoFactorMobile.setValue(twoFactorData.mobile);
|
|
this.twoFactorEmail.setValue(twoFactorData.email);
|
|
}
|
|
|
|
get userName(): AbstractControl {
|
|
return this.form.get('userName')!;
|
|
}
|
|
get password(): AbstractControl {
|
|
return this.form.get('password')!;
|
|
}
|
|
get mobile(): AbstractControl {
|
|
return this.form.get('mobile')!;
|
|
}
|
|
get captcha(): AbstractControl {
|
|
return this.form.get('captcha')!;
|
|
}
|
|
|
|
get otpCaptcha(): AbstractControl {
|
|
return this.form.get('otpCaptcha')!;
|
|
}
|
|
|
|
get remember(): AbstractControl {
|
|
return this.form.get('remember')!;
|
|
}
|
|
|
|
get twoFactorMobile(): AbstractControl {
|
|
return this.form.get('twoFactorMobile')!;
|
|
}
|
|
|
|
get twoFactorEmail(): AbstractControl {
|
|
return this.form.get('twoFactorEmail')!;
|
|
}
|
|
|
|
sendTwoFactorOtpCode(): void {
|
|
this.authnService.sendTwoFactorCode({ jwtToken: this.twoFactorJwt }).subscribe(res => {
|
|
if (res.code !== 0) {
|
|
this.msg.success(`发送失败`);
|
|
}
|
|
});
|
|
this.count = 59;
|
|
this.interval$ = setInterval(() => {
|
|
this.count -= 1;
|
|
if (this.count <= 0) {
|
|
clearInterval(this.interval$);
|
|
}
|
|
this.cdr.detectChanges();
|
|
}, 1000);
|
|
}
|
|
|
|
submit(): void {
|
|
this.error = '';
|
|
|
|
this.otpCaptcha.markAsDirty();
|
|
this.otpCaptcha.updateValueAndValidity();
|
|
|
|
localStorage.setItem(CONSTS.REMEMBER, this.form.get(CONSTS.REMEMBER)?.value);
|
|
|
|
this.loading = true;
|
|
this.cdr.detectChanges();
|
|
this.authnService
|
|
.login({
|
|
authType: 'twoFactor',
|
|
state: this.state,
|
|
jwtToken: this.twoFactorJwt,
|
|
otpCaptcha: this.otpCaptcha.value,
|
|
remeberMe: this.remember.value
|
|
})
|
|
.pipe(
|
|
finalize(() => {
|
|
this.loading = false;
|
|
this.cdr.detectChanges();
|
|
})
|
|
)
|
|
.subscribe(res => {
|
|
this.loading = true;
|
|
if (res.code !== 0) {
|
|
this.error = res.msg;
|
|
} else {
|
|
localStorage.removeItem(CONSTS.TWO_FACTOR_DATA);
|
|
// 清空路由复用信息
|
|
this.reuseTabService?.clear();
|
|
// 设置用户Token信息
|
|
this.authnService.auth(res.data);
|
|
this.authnService.navigate({
|
|
defualtRedirectUri: this.defualtRedirectUri,
|
|
isFirstPasswordModify: this.isFirstPasswordModify,
|
|
passwordSetType: res.data.passwordSetType
|
|
});
|
|
}
|
|
this.cdr.detectChanges();
|
|
});
|
|
}
|
|
}
|