582 lines
18 KiB
TypeScript

import { Injectable, Inject, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { of, Observable } from 'rxjs';
import { catchError, exhaustMap, map, tap, switchMap } from 'rxjs/operators';
import { Actions, ofType, createEffect } from '@ngrx/effects';
import {
PiService,
Login2Response,
UserTermsActionResponse
} from '@ucap-webmessenger/pi';
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
import {
DialogService,
ConfirmDialogComponent,
ConfirmDialogData,
ConfirmDialogResult,
SnackBarService,
AlertDialogComponent,
AlertDialogData,
AlertDialogResult
} from '@ucap-webmessenger/ui';
import {
loginRedirect,
logout,
logoutConfirmation,
logoutConfirmationDismiss,
webLogin,
webLoginSuccess,
webLoginFailure,
postLogin,
privacyAgree,
privacyDisagree,
privacyAgreeFailure,
privacyAgreeSuccess,
increaseLoginFailCount,
initialLoginFailCount,
logoutInitialize,
userPasswordSet,
userPasswordSetSuccess,
userPasswordSetFailure,
infoUser,
infoUserSuccess,
infoUserFailure
} from './actions';
import {
LoginInfo,
KEY_LOGIN_INFO,
EnvironmentsInfo,
KEY_ENVIRONMENTS_INFO,
KEY_URL_INFO,
LogoutInfo,
KEY_LOGOUT_INFO
} from '@app/types';
import { AppAuthenticationService } from '@app/services/authentication.service';
import { NGXLogger } from 'ngx-logger';
import { Store } from '@ngrx/store';
import {
SessionStorageService,
LocalStorageService
} from '@ucap-webmessenger/web-storage';
import {
AuthenticationProtocolService,
LoginResponse
} from '@ucap-webmessenger/protocol-authentication';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import { ProtocolService } from '@ucap-webmessenger/protocol';
import { environment } from '../../../../environments/environment';
import {
ServiceProtocolService,
UserPasswordSetResponse
} from '@ucap-webmessenger/protocol-service';
import {
DaesangUrlInfoResponse,
ExternalApiService,
CompanyListRequest
} from '@ucap-webmessenger/api-external';
import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type';
import { DaesangCipherService, WebLinkType } from '@ucap-webmessenger/daesang';
import { TranslateService } from '@ngx-translate/core';
import {
InfoProtocolService,
UserResponse
} from '@ucap-webmessenger/protocol-info';
import { StatusCode } from '@ucap-webmessenger/api';
@Injectable()
export class Effects {
retryCount = 0;
retryInterval = 3000; // ms
maxRetryCount = (10 * 60 * 1000) / this.retryInterval; // 200 count due to 10 min.
webLogin$ = createEffect(
() =>
this.actions$.pipe(
ofType(webLogin),
map(action => action),
exhaustMap(
(params: {
loginInfo: LoginInfo;
rememberMe: boolean;
autoLogin: boolean;
}) => {
const selfParam = params;
return this.piService
.login2({
loginId: params.loginInfo.loginId,
loginPw: params.loginInfo.loginPw,
companyCode: params.loginInfo.companyCode
})
.pipe(
map((res: Login2Response) => {
if ('success' !== res.status.toLowerCase()) {
if (!!params.autoLogin) {
// auto login Failure.
this.store.dispatch(increaseLoginFailCount({}));
this.localStorageService.remove(KEY_APP_USER_INFO);
this.router.navigateByUrl('/account/login');
} else {
this.store.dispatch(increaseLoginFailCount({}));
this.store.dispatch(webLoginFailure({ error: 'Failed' }));
}
} else {
this.store.dispatch(initialLoginFailCount({}));
this.store.dispatch(
webLoginSuccess({
loginInfo: params.loginInfo,
rememberMe: params.rememberMe,
autoLogin: params.autoLogin,
login2Response: res
})
);
}
}),
catchError(error => {
if (!!selfParam.autoLogin) {
if (this.maxRetryCount > this.retryCount) {
this.store.dispatch(logoutInitialize());
setTimeout(() => {
// this.store.dispatch(webLogin(selfParam));
this.router.navigateByUrl('/account/login');
}, this.retryInterval);
this.retryCount++;
console.log('retry', this.retryCount, this.maxRetryCount);
return of(webLoginFailure({ error }));
} else {
console.log(
'retry End',
this.retryCount,
this.maxRetryCount
);
}
}
this.ngZone.run(async () => {
const result = await this.dialogService.open<
AlertDialogComponent,
AlertDialogData,
AlertDialogResult
>(AlertDialogComponent, {
width: '360px',
data: {
title: this.translateService.instant(
'accounts.errors.loginFailed'
),
html: this.translateService.instant(
'accounts.errors.networkFailedAndExit'
)
}
});
if (!!result) {
this.nativeService.appExit();
}
});
console.log('not retry');
return of(webLoginFailure({ error }));
})
);
}
)
),
{ dispatch: false }
);
webLoginSuccess$ = createEffect(
() =>
this.actions$.pipe(
ofType(webLoginSuccess),
tap(params => {
this.nativeService.checkForUpdates(params.login2Response.version);
this.appAuthenticationService.login(
params.loginInfo,
params.rememberMe,
params.autoLogin
);
this.router.navigate(['/messenger']);
})
),
{ dispatch: false }
);
loginRedirect$ = createEffect(
() =>
this.actions$.pipe(
ofType(loginRedirect),
tap(authed => {
// this.ngZone.run(() => {
// location.href = this.router.parseUrl('/account/login').toString();
this.protocolService.disconnect();
this.router.navigate(['/account/login']);
this.appAuthenticationService.logout();
this.store.dispatch(logoutInitialize());
// });
})
),
{ dispatch: false }
);
logout$ = createEffect(
() => {
return this.actions$.pipe(
ofType(logout),
switchMap(action => {
return this.authenticationProtocolService.logout({}).pipe(
map(res => {
this.sessionStorageService.set<LogoutInfo>(KEY_LOGOUT_INFO, {
personLogout: true
} as LogoutInfo);
this.store.dispatch(loginRedirect());
}),
catchError(error => of(error))
);
})
);
},
{ dispatch: false }
);
logoutConfirmation$ = createEffect(() =>
this.actions$.pipe(
ofType(logoutConfirmation),
exhaustMap(async () => {
const loginRes = this.sessionStorageService.get<LoginResponse>(
KEY_LOGIN_RES_INFO
);
if (!!loginRes && loginRes.userSeq) {
const result = await this.dialogService.open<
ConfirmDialogComponent,
ConfirmDialogData,
ConfirmDialogResult
>(ConfirmDialogComponent, {
data: {
title: this.translateService.instant('accounts.logout'),
message: this.translateService.instant('accounts.confirmLogout')
}
});
if (!!result && !!result.choice && result.choice) {
return true;
} else {
return false;
}
} else {
return false;
}
}),
map(result => (result ? logout() : logoutConfirmationDismiss()))
)
);
postLogin$ = createEffect(
() =>
this.actions$.pipe(
ofType(postLogin),
map(action => action.loginRes),
tap(async loginRes => {
const loginInfo = this.sessionStorageService.get<LoginInfo>(
KEY_LOGIN_INFO
);
const environmentsInfo = this.sessionStorageService.get<
EnvironmentsInfo
>(KEY_ENVIRONMENTS_INFO);
if (
environment.productConfig.authentication
.usePrivateInformationAgree &&
!loginRes.privateInformationAgree
) {
const privacyTotalUrl = this.piService.privacyTotalUrl({
companyCode: loginInfo.companyCode,
userSeq: loginRes.userSeq,
token: loginRes.tokenString,
deviceType: environmentsInfo.deviceType,
localeCode: loginInfo.localeCode,
textOnly: 'true'
});
const result = await this.dialogService.open<
ConfirmDialogComponent,
ConfirmDialogData,
ConfirmDialogResult
>(ConfirmDialogComponent, {
width: '100%',
height: '500px',
disableClose: true,
data: {
title: this.translateService.instant(
'accounts.consentOfPrivacy'
),
html: `<iframe id="ifm_privacy" src="${privacyTotalUrl}" style="width: 100%;height: 300px;" />`
}
});
if (result.choice) {
this.store.dispatch(privacyAgree({ loginRes }));
} else {
this.store.dispatch(privacyDisagree());
return;
}
}
if (!!loginInfo.initPw) {
this.store.dispatch(logout());
const passwordInitStep1Url = this.piService.passwordInitStep1Url({
localeCode: loginInfo.localeCode
});
const result = await this.dialogService.open<
ConfirmDialogComponent,
ConfirmDialogData,
ConfirmDialogResult
>(ConfirmDialogComponent, {
width: '100%',
height: '500px',
disableClose: true,
data: {
title: this.translateService.instant('accounts.resetPassword'),
html: `<iframe id="ifm_privacy" src="${passwordInitStep1Url}" style="width: 100%;height: 300px;" />`
}
});
if (result.choice) {
} else {
return;
}
}
if (!loginRes.passwordValid) {
// [Daesang]
const urlInfo: DaesangUrlInfoResponse = this.sessionStorageService.get<
DaesangUrlInfoResponse
>(KEY_URL_INFO);
await this.dialogService.open<
AlertDialogComponent,
AlertDialogData,
AlertDialogResult
>(AlertDialogComponent, {
data: {
title: this.translateService.instant(
'accounts.passwordExpired'
),
html: this.translateService.instant(
'accounts.descriptionOfPasswordExpired'
)
}
});
const passwordChangeUrl = urlInfo.webLink.filter(
weblink => weblink.key === WebLinkType.ChgPassword
);
if (passwordChangeUrl.length > 0) {
const appUserInfo = this.localStorageService.encGet<AppUserInfo>(
KEY_APP_USER_INFO,
environment.customConfig.appKey
);
const loginPw = appUserInfo.loginPw;
const loginId = appUserInfo.loginId;
const url = passwordChangeUrl[0].url
.replace(/(\(%USER_ID%\))/g, loginId)
.replace(
/(\(%USER_PASS%\))/g,
this.daesangCipherService.encryptForWebLink(loginPw)
);
this.nativeService.openDefaultBrowser(url);
}
this.store.dispatch(logout());
// // [GROUP]
// const result = await this.dialogService.open<
// ChangePasswordDialogComponent,
// ChangePasswordDialogData,
// ChangePasswordDialogResult
// >(ChangePasswordDialogComponent, {
// width: '500px',
// height: '500px',
// disableClose: false,
// data: {
// loginId: loginInfo.loginId,
// encryptedLoginPw: loginInfo.loginPw,
// phoneNumber: loginRes.userInfo.hpNumber
// }
// });
// if (!!result && result.choice) {
// this.store.dispatch(
// userPasswordSet({
// req: {
// companyCode: loginInfo.companyCode,
// loginId: loginInfo.loginId,
// oldLoginPw: result.currentLoginPw,
// newLoginPw: result.newLoginPw
// }
// })
// );
// } else {
// this.store.dispatch(logout());
// return;
// }
}
})
),
{ dispatch: false }
);
privacyAgree$ = createEffect(() =>
this.actions$.pipe(
ofType(privacyAgree),
map(action => {
const loginInfo = this.sessionStorageService.get<LoginInfo>(
KEY_LOGIN_INFO
);
const environmentsInfo = this.sessionStorageService.get<
EnvironmentsInfo
>(KEY_ENVIRONMENTS_INFO);
return {
loginInfo,
environmentsInfo,
loginResponse: action.loginRes
};
}),
exhaustMap(params =>
this.piService
.userTermsAction({
userSeq: params.loginResponse.userSeq,
token: params.loginResponse.tokenString,
deviceType: params.environmentsInfo.deviceType
})
.pipe(
map((res: UserTermsActionResponse) => {
if ('00' !== res.responseCode) {
return privacyAgreeFailure({ error: 'Failed' });
} else {
return privacyAgreeSuccess();
}
}),
catchError(error => of(privacyAgreeFailure({ error })))
)
)
)
);
userPasswordSet$ = createEffect(() =>
this.actions$.pipe(
ofType(userPasswordSet),
map(action => action.req),
exhaustMap(req =>
this.serviceProtocolService.userPasswordSet(req).pipe(
map((res: UserPasswordSetResponse) => {
return userPasswordSetSuccess({
res
});
}),
catchError(error => of(userPasswordSetFailure({ error })))
)
)
)
);
userPasswordSetSuccess$ = createEffect(
() => {
return this.actions$.pipe(
ofType(userPasswordSetSuccess),
tap(async action => {
await this.dialogService.open<
AlertDialogComponent,
AlertDialogData,
AlertDialogResult
>(AlertDialogComponent, {
width: '360px',
disableClose: true,
data: {
title: this.translateService.instant('accounts.changePassword'),
message: this.translateService.instant(
'accounts.results.changedPassword'
)
}
});
this.store.dispatch(logout());
})
);
},
{ dispatch: false }
);
userPasswordSetFailure$ = createEffect(
() => {
return this.actions$.pipe(
ofType(userPasswordSetFailure),
tap(action => {
this.snackBarService.open(
this.translateService.instant(
'accounts.errors.failToChangePassword'
),
'',
{
duration: 3000,
verticalPosition: 'bottom'
}
);
})
);
},
{ dispatch: false }
);
infoUser$ = createEffect(() =>
this.actions$.pipe(
ofType(infoUser),
map(action => action.req),
exhaustMap(req =>
this.infoProtocolService.user(req).pipe(
map((res: UserResponse) => {
return infoUserSuccess({
res
});
}),
catchError(error => of(infoUserFailure({ error })))
)
)
)
);
constructor(
private actions$: Actions,
private ngZone: NgZone,
private router: Router,
private store: Store<any>,
private localStorageService: LocalStorageService,
private sessionStorageService: SessionStorageService,
private piService: PiService,
private appAuthenticationService: AppAuthenticationService,
private externalApiService: ExternalApiService,
private protocolService: ProtocolService,
private authenticationProtocolService: AuthenticationProtocolService,
private infoProtocolService: InfoProtocolService,
private serviceProtocolService: ServiceProtocolService,
private translateService: TranslateService,
private dialogService: DialogService,
private snackBarService: SnackBarService,
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
private logger: NGXLogger,
private daesangCipherService: DaesangCipherService
) {}
}