change password is implemented
This commit is contained in:
parent
c5d61417f3
commit
b72e2adc8b
|
@ -1 +1,21 @@
|
||||||
<ucap-account-change-password></ucap-account-change-password>
|
<mat-card class="confirm-card mat-elevation-z setting-frame">
|
||||||
|
<mat-card-header cdkDrag cdkDragRootElement=".cdk-overlay-pane" cdkDragHandle>
|
||||||
|
<mat-card-title>패스워드 변경</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<div fxFlex class="setting-tab">
|
||||||
|
<ucap-account-change-password
|
||||||
|
(changePassword)="onChangePassword($event)"
|
||||||
|
></ucap-account-change-password>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
<mat-card-actions class="button-farm flex-row">
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
(click)="onClickChoice(false)"
|
||||||
|
class="mat-primary"
|
||||||
|
>
|
||||||
|
취소
|
||||||
|
</button>
|
||||||
|
</mat-card-actions>
|
||||||
|
</mat-card>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
::ng-deep .setting-frame {
|
||||||
|
padding: 16px;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 400px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.mat-dialog-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-card-header {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid #dddddd;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-card-content {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
height: calc(100% - 100px);
|
||||||
|
border-bottom: 1px solid #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-farm {
|
||||||
|
text-align: right;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 10px;
|
||||||
|
.mat-primary {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,15 +6,14 @@ import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
|
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
import { UserInfo } from '@ucap-webmessenger/protocol-sync';
|
|
||||||
import {
|
|
||||||
UserInfoSS,
|
|
||||||
UserInfoF,
|
|
||||||
UserInfoDN
|
|
||||||
} from '@ucap-webmessenger/protocol-query';
|
|
||||||
import { DialogService } from '@ucap-webmessenger/ui';
|
import { DialogService } from '@ucap-webmessenger/ui';
|
||||||
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
||||||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
|
import { AppAuthenticationService } from '@app/services/authentication.service';
|
||||||
|
import { StringUtil, CharactorType } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
|
import * as ServiceStore from '@app/store/messenger/service';
|
||||||
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
export interface ChangePasswordDialogData {}
|
export interface ChangePasswordDialogData {}
|
||||||
|
|
||||||
|
@ -40,6 +39,7 @@ export class ChangePasswordDialogComponent implements OnInit, OnDestroy {
|
||||||
@Inject(MAT_DIALOG_DATA) public data: ChangePasswordDialogData,
|
@Inject(MAT_DIALOG_DATA) public data: ChangePasswordDialogData,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
private store: Store<any>
|
private store: Store<any>
|
||||||
) {
|
) {
|
||||||
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
|
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
|
||||||
|
@ -53,4 +53,147 @@ export class ChangePasswordDialogComponent implements OnInit, OnDestroy {
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
|
|
||||||
ngOnDestroy(): void {}
|
ngOnDestroy(): void {}
|
||||||
|
|
||||||
|
onChangePassword(info: {
|
||||||
|
currentLoginPw: string;
|
||||||
|
newLoginPw: string;
|
||||||
|
newConfirmLoginPw: string;
|
||||||
|
notValid: () => void;
|
||||||
|
}): void {
|
||||||
|
if (!info.currentLoginPw || '' === info.currentLoginPw.trim()) {
|
||||||
|
// 현재 비밀번호를 입력해주세요
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.appAuthenticationService.isSameForPassword(info.currentLoginPw)) {
|
||||||
|
// "현재 비밀번호가 다릅니다"
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!info.newLoginPw || '' === info.newLoginPw.trim()) {
|
||||||
|
// 신규 비밀번호를 입력해주세요
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (-1 < info.newLoginPw.indexOf(this.loginRes.userId)) {
|
||||||
|
// "사용자 ID를 비밀번호에 포함할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const phoneNumberOnly = !!this.loginRes.userInfo.hpNumber
|
||||||
|
? this.loginRes.userInfo.hpNumber.trim().replace(new RegExp('-', 'g'), '')
|
||||||
|
: '';
|
||||||
|
|
||||||
|
switch (phoneNumberOnly.length) {
|
||||||
|
case 11:
|
||||||
|
if (-1 < info.newLoginPw.indexOf(phoneNumberOnly.substr(3, 4))) {
|
||||||
|
// "사용자 휴대폰번호를 비밀번호에 포함할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (-1 < info.newLoginPw.indexOf(phoneNumberOnly.substr(7, 4))) {
|
||||||
|
// "사용자 휴대폰번호를 비밀번호에 포함할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
if (-1 < info.newLoginPw.indexOf(phoneNumberOnly.substr(3, 3))) {
|
||||||
|
// "사용자 휴대폰번호를 비밀번호에 포함할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (-1 < info.newLoginPw.indexOf(phoneNumberOnly.substr(6, 4))) {
|
||||||
|
// "사용자 휴대폰번호를 비밀번호에 포함할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.newConfirmLoginPw || '' === info.newConfirmLoginPw.trim()) {
|
||||||
|
// "신규 비밀번호 확인을 입력해주세요"
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (info.newLoginPw !== info.newConfirmLoginPw.trim()) {
|
||||||
|
// "신규 비밀번호와 신규 비밀번호 확인이 다릅니다"
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (info.currentLoginPw === info.newLoginPw.trim()) {
|
||||||
|
// "현재 비밀번호와 새로운 비밀번호가 같습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (0 < StringUtil.includes(info.newLoginPw, CharactorType.Space)) {
|
||||||
|
// "비밀번호에는 공백을 입력할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtil.isRepeat(info.newLoginPw, 3)) {
|
||||||
|
// "숫자나 문자를 3번이상 반복적으로 사용할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
StringUtil.isIncrements(info.newLoginPw, 3) ||
|
||||||
|
StringUtil.isDecrements(info.newLoginPw, 3)
|
||||||
|
) {
|
||||||
|
// "연속되는 숫자나 문자를 3번이상 사용할 수 없습니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let combinationCount = 0;
|
||||||
|
if (0 < StringUtil.includes(info.newLoginPw, CharactorType.Special)) {
|
||||||
|
combinationCount++;
|
||||||
|
}
|
||||||
|
if (0 < StringUtil.includes(info.newLoginPw, CharactorType.Number)) {
|
||||||
|
combinationCount++;
|
||||||
|
}
|
||||||
|
if (0 < StringUtil.includes(info.newLoginPw, CharactorType.Charactor)) {
|
||||||
|
combinationCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
let minPwLen = 0;
|
||||||
|
if (2 < combinationCount) {
|
||||||
|
minPwLen = 8;
|
||||||
|
} else if (2 === combinationCount) {
|
||||||
|
minPwLen = 10;
|
||||||
|
} else if (2 > combinationCount) {
|
||||||
|
// "2종류 이상 조합을 해야 합니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.newLoginPw.length < minPwLen) {
|
||||||
|
// "비밀번호는 %d가지가 조합된 경우 %d자를 넘어야 합니다."
|
||||||
|
info.notValid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.store.dispatch(
|
||||||
|
ServiceStore.userPasswordSet({
|
||||||
|
req: {
|
||||||
|
loginId: this.loginRes.userId,
|
||||||
|
companyCode: this.loginRes.companyCode,
|
||||||
|
oldLoginPw: CryptoJS.enc.Hex.stringify(
|
||||||
|
CryptoJS.SHA256(info.currentLoginPw)
|
||||||
|
),
|
||||||
|
newLoginPw: CryptoJS.enc.Hex.stringify(
|
||||||
|
CryptoJS.SHA256(info.newLoginPw)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.dialogRef.close({ choice: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickChoice(choice: boolean): void {
|
||||||
|
this.dialogRef.close({ choice });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,4 +51,11 @@ export class AppAuthenticationService {
|
||||||
this.sessionStorageService.remove(KEY_VER_INFO);
|
this.sessionStorageService.remove(KEY_VER_INFO);
|
||||||
this.sessionStorageService.remove(KEY_LOGIN_INFO);
|
this.sessionStorageService.remove(KEY_LOGIN_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSameForPassword(pw: string): boolean {
|
||||||
|
const loginInfo = this.sessionStorageService.get<LoginInfo>(KEY_LOGIN_INFO);
|
||||||
|
return (
|
||||||
|
loginInfo.loginPw === CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(pw))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,20 +96,3 @@ export const privacyAgreeFailure = createAction(
|
||||||
export const privacyDisagree = createAction(
|
export const privacyDisagree = createAction(
|
||||||
'[Account::Authentication] Privacy Disagree'
|
'[Account::Authentication] Privacy Disagree'
|
||||||
);
|
);
|
||||||
|
|
||||||
export const changePassword = createAction(
|
|
||||||
'[Account::Authentication] Change Password',
|
|
||||||
props<{ req: UserPasswordSetRequest }>()
|
|
||||||
);
|
|
||||||
|
|
||||||
export const changePasswordSuccess = createAction(
|
|
||||||
'[Account::Authentication] Change Password Success',
|
|
||||||
props<{
|
|
||||||
res: UserPasswordSetResponse;
|
|
||||||
}>()
|
|
||||||
);
|
|
||||||
|
|
||||||
export const changePasswordFailure = createAction(
|
|
||||||
'[Account::Authentication] Change Password Failure',
|
|
||||||
props<{ error: any }>()
|
|
||||||
);
|
|
||||||
|
|
|
@ -32,9 +32,6 @@ import {
|
||||||
privacyDisagree,
|
privacyDisagree,
|
||||||
privacyAgreeFailure,
|
privacyAgreeFailure,
|
||||||
privacyAgreeSuccess,
|
privacyAgreeSuccess,
|
||||||
changePassword,
|
|
||||||
changePasswordFailure,
|
|
||||||
changePasswordSuccess,
|
|
||||||
increaseLoginFailCount,
|
increaseLoginFailCount,
|
||||||
initialLoginFailCount,
|
initialLoginFailCount,
|
||||||
logoutInitialize
|
logoutInitialize
|
||||||
|
@ -49,10 +46,7 @@ import { AppAuthenticationService } from '@app/services/authentication.service';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
import {
|
|
||||||
ServiceProtocolService,
|
|
||||||
UserPasswordSetResponse
|
|
||||||
} from '@ucap-webmessenger/protocol-service';
|
|
||||||
import {
|
import {
|
||||||
AuthenticationProtocolService,
|
AuthenticationProtocolService,
|
||||||
LoginResponse
|
LoginResponse
|
||||||
|
@ -330,23 +324,6 @@ export class Effects {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
changePassword$ = createEffect(() =>
|
|
||||||
this.actions$.pipe(
|
|
||||||
ofType(changePassword),
|
|
||||||
map(action => action.req),
|
|
||||||
exhaustMap(req =>
|
|
||||||
this.serviceProtocolService.userPasswordSet(req).pipe(
|
|
||||||
map((res: UserPasswordSetResponse) => {
|
|
||||||
return changePasswordSuccess({
|
|
||||||
res
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
catchError(error => of(changePasswordFailure({ error })))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private actions$: Actions,
|
private actions$: Actions,
|
||||||
private ngZone: NgZone,
|
private ngZone: NgZone,
|
||||||
|
@ -357,7 +334,7 @@ export class Effects {
|
||||||
private appAuthenticationService: AppAuthenticationService,
|
private appAuthenticationService: AppAuthenticationService,
|
||||||
private protocolService: ProtocolService,
|
private protocolService: ProtocolService,
|
||||||
private authenticationProtocolService: AuthenticationProtocolService,
|
private authenticationProtocolService: AuthenticationProtocolService,
|
||||||
private serviceProtocolService: ServiceProtocolService,
|
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
|
|
|
@ -6,6 +6,7 @@ import * as EventStore from './event';
|
||||||
import * as OptionStore from './option';
|
import * as OptionStore from './option';
|
||||||
import * as QueryStore from './query';
|
import * as QueryStore from './query';
|
||||||
import * as RoomStore from './room';
|
import * as RoomStore from './room';
|
||||||
|
import * as ServiceStore from './service';
|
||||||
import * as StatusStore from './status';
|
import * as StatusStore from './status';
|
||||||
import * as SyncStore from './sync';
|
import * as SyncStore from './sync';
|
||||||
import * as SettingsStore from './settings';
|
import * as SettingsStore from './settings';
|
||||||
|
@ -16,6 +17,7 @@ export interface State {
|
||||||
option: OptionStore.State;
|
option: OptionStore.State;
|
||||||
query: QueryStore.State;
|
query: QueryStore.State;
|
||||||
room: RoomStore.State;
|
room: RoomStore.State;
|
||||||
|
service: ServiceStore.State;
|
||||||
status: StatusStore.State;
|
status: StatusStore.State;
|
||||||
sync: SyncStore.State;
|
sync: SyncStore.State;
|
||||||
settings: SettingsStore.State;
|
settings: SettingsStore.State;
|
||||||
|
@ -27,6 +29,7 @@ export const effects: Type<any>[] = [
|
||||||
OptionStore.Effects,
|
OptionStore.Effects,
|
||||||
QueryStore.Effects,
|
QueryStore.Effects,
|
||||||
RoomStore.Effects,
|
RoomStore.Effects,
|
||||||
|
ServiceStore.Effects,
|
||||||
StatusStore.Effects,
|
StatusStore.Effects,
|
||||||
SyncStore.Effects,
|
SyncStore.Effects,
|
||||||
SettingsStore.Effects
|
SettingsStore.Effects
|
||||||
|
@ -39,6 +42,7 @@ export function reducers(state: State | undefined, action: Action) {
|
||||||
option: OptionStore.reducer,
|
option: OptionStore.reducer,
|
||||||
query: QueryStore.reducer,
|
query: QueryStore.reducer,
|
||||||
room: RoomStore.reducer,
|
room: RoomStore.reducer,
|
||||||
|
service: ServiceStore.reducer,
|
||||||
status: StatusStore.reducer,
|
status: StatusStore.reducer,
|
||||||
sync: SyncStore.reducer,
|
sync: SyncStore.reducer,
|
||||||
settings: SettingsStore.reducer
|
settings: SettingsStore.reducer
|
||||||
|
@ -62,6 +66,9 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
QuerySelector: QueryStore.selectors(
|
QuerySelector: QueryStore.selectors(
|
||||||
createSelector(selector, (state: State) => state.query)
|
createSelector(selector, (state: State) => state.query)
|
||||||
),
|
),
|
||||||
|
ServiceSelector: ServiceStore.selectors(
|
||||||
|
createSelector(selector, (state: State) => state.service)
|
||||||
|
),
|
||||||
StatusSelector: StatusStore.selectors(
|
StatusSelector: StatusStore.selectors(
|
||||||
createSelector(selector, (state: State) => state.status)
|
createSelector(selector, (state: State) => state.status)
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { createAction, props } from '@ngrx/store';
|
||||||
|
|
||||||
|
import {
|
||||||
|
UserPasswordSetRequest,
|
||||||
|
UserPasswordSetResponse
|
||||||
|
} from '@ucap-webmessenger/protocol-service';
|
||||||
|
|
||||||
|
export const userPasswordSet = createAction(
|
||||||
|
'[Account::Authentication] User Password Set',
|
||||||
|
props<{ req: UserPasswordSetRequest }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const userPasswordSetSuccess = createAction(
|
||||||
|
'[Account::Authentication] User Password Set Success',
|
||||||
|
props<{
|
||||||
|
res: UserPasswordSetResponse;
|
||||||
|
}>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const userPasswordSetFailure = createAction(
|
||||||
|
'[Account::Authentication] User Password Set Failure',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { Actions, ofType, createEffect } from '@ngrx/effects';
|
||||||
|
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { NGXLogger } from 'ngx-logger';
|
||||||
|
import { catchError, exhaustMap, map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
|
import {
|
||||||
|
userPasswordSet,
|
||||||
|
userPasswordSetSuccess,
|
||||||
|
userPasswordSetFailure
|
||||||
|
} from './actions';
|
||||||
|
import {
|
||||||
|
ServiceProtocolService,
|
||||||
|
UserPasswordSetResponse
|
||||||
|
} from '@ucap-webmessenger/protocol-service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class Effects {
|
||||||
|
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 })))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private actions$: Actions,
|
||||||
|
private serviceProtocolService: ServiceProtocolService,
|
||||||
|
private store: Store<any>,
|
||||||
|
private logger: NGXLogger
|
||||||
|
) {}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export * from './actions';
|
||||||
|
export * from './effects';
|
||||||
|
export * from './reducers';
|
||||||
|
export * from './state';
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { createReducer, on } from '@ngrx/store';
|
||||||
|
import { initialState } from './state';
|
||||||
|
|
||||||
|
export const reducer = createReducer(initialState);
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Selector, createSelector } from '@ngrx/store';
|
||||||
|
|
||||||
|
export interface State {}
|
||||||
|
|
||||||
|
export const initialState: State = {};
|
||||||
|
|
||||||
|
export function selectors<S>(selector: Selector<any, State>) {
|
||||||
|
return {};
|
||||||
|
}
|
|
@ -1,3 +1,13 @@
|
||||||
|
export enum CharactorType {
|
||||||
|
Number = 'Number',
|
||||||
|
Charactor = 'Charactor',
|
||||||
|
Space = 'Space',
|
||||||
|
Special = 'Special'
|
||||||
|
}
|
||||||
|
|
||||||
|
const CharCodeZero = '0'.charCodeAt(0);
|
||||||
|
const CharCodeNine = '9'.charCodeAt(0);
|
||||||
|
|
||||||
export class StringUtil {
|
export class StringUtil {
|
||||||
/**
|
/**
|
||||||
* prefix zero fill
|
* prefix zero fill
|
||||||
|
@ -15,4 +25,160 @@ export class StringUtil {
|
||||||
return StringUtil.zeroFill(str.toString(), len);
|
return StringUtil.zeroFill(str.toString(), len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* includes
|
||||||
|
*/
|
||||||
|
public static includes(target: string, charactorType: CharactorType): number {
|
||||||
|
let nNum = 0;
|
||||||
|
let nChar = 0;
|
||||||
|
let nSpace = 0;
|
||||||
|
let nElse = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < target.length; i++) {
|
||||||
|
const char = target.charCodeAt(i);
|
||||||
|
// 숫자
|
||||||
|
if (char >= 48 && char <= 57) {
|
||||||
|
nNum++;
|
||||||
|
} else if (char >= 65 && char <= 90) {
|
||||||
|
// 영어(대문자)
|
||||||
|
nChar++;
|
||||||
|
} else if (char >= 97 && char <= 122) {
|
||||||
|
// 영어(소문자)
|
||||||
|
nChar++;
|
||||||
|
} else if (target.charAt(i) === ' ') {
|
||||||
|
// 공백
|
||||||
|
nSpace++;
|
||||||
|
} else {
|
||||||
|
// 특수기호
|
||||||
|
nElse++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (charactorType) {
|
||||||
|
case CharactorType.Number:
|
||||||
|
return nNum;
|
||||||
|
case CharactorType.Charactor:
|
||||||
|
return nChar;
|
||||||
|
case CharactorType.Space:
|
||||||
|
return nSpace;
|
||||||
|
case CharactorType.Special:
|
||||||
|
return nElse;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isRepeat
|
||||||
|
*/
|
||||||
|
public static isRepeat(target: string, repeatTime: number) {
|
||||||
|
let old = '';
|
||||||
|
let rptCnt = 1;
|
||||||
|
for (let i = 0; i < target.length; i++) {
|
||||||
|
const s = target.charAt(i);
|
||||||
|
if (old === s) {
|
||||||
|
rptCnt++;
|
||||||
|
if (rptCnt === repeatTime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
old = s;
|
||||||
|
rptCnt = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isIncrements
|
||||||
|
*/
|
||||||
|
public static isIncrements(target: string, repeatTime: number) {
|
||||||
|
for (let i = 0; i < target.length - (repeatTime - 1); i++) {
|
||||||
|
let notNeed = false;
|
||||||
|
const ary: number[] = [];
|
||||||
|
for (let j = 0; j < repeatTime; j++) {
|
||||||
|
const char = target.charCodeAt(i + j);
|
||||||
|
if (!StringUtil.isAlphaNumeric(char)) {
|
||||||
|
notNeed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ary.push(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notNeed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let k = 1; k < ary.length; k++) {
|
||||||
|
if (ary[0] !== ary[k] - k) {
|
||||||
|
notNeed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notNeed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isIncrements
|
||||||
|
*/
|
||||||
|
public static isDecrements(target: string, repeatTime: number) {
|
||||||
|
for (let i = 0; i < target.length - (repeatTime - 1); i++) {
|
||||||
|
let notNeed = false;
|
||||||
|
const ary: number[] = [];
|
||||||
|
for (let j = 0; j < repeatTime; j++) {
|
||||||
|
const char = target.charCodeAt(i + j);
|
||||||
|
if (!StringUtil.isAlphaNumeric(char)) {
|
||||||
|
notNeed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ary.push(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notNeed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let k = 1; k < ary.length; k++) {
|
||||||
|
if (ary[0] !== ary[k] + k) {
|
||||||
|
notNeed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notNeed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isAlphabet
|
||||||
|
*/
|
||||||
|
public static isAlphabet(char: number): boolean {
|
||||||
|
return (char >= 65 && char <= 90) || (char >= 97 && char <= 122);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* isNumeric
|
||||||
|
*/
|
||||||
|
public static isNumeric(char: number): boolean {
|
||||||
|
return char >= 48 && char <= 57;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* isAlphaNumeric
|
||||||
|
*/
|
||||||
|
public static isAlphaNumeric(char: number): boolean {
|
||||||
|
return StringUtil.isAlphabet(char) || StringUtil.isNumeric(char);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<div class="change-password-form">
|
<div class="change-password-form">
|
||||||
<div class="mat-title">비밀번호 변경</div>
|
|
||||||
|
|
||||||
<form name="changePasswordForm" [formGroup]="changePasswordForm" novalidate>
|
<form name="changePasswordForm" [formGroup]="changePasswordForm" novalidate>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>현재 패스워드</mat-label>
|
<mat-label>현재 패스워드</mat-label>
|
||||||
|
@ -44,7 +42,7 @@
|
||||||
class="submit-button bg-accent-dark"
|
class="submit-button bg-accent-dark"
|
||||||
aria-label="패스워드 변경"
|
aria-label="패스워드 변경"
|
||||||
[disabled]="changePasswordForm.invalid || !changePasswordBtnEnable"
|
[disabled]="changePasswordForm.invalid || !changePasswordBtnEnable"
|
||||||
(click)="onClickLogin()"
|
(click)="onClickChangePassword()"
|
||||||
>
|
>
|
||||||
패스워드 변경
|
패스워드 변경
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
.change-password-form {
|
.change-password-form {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 384px;
|
width: 100%;
|
||||||
max-width: 384px;
|
min-width: 380px;
|
||||||
padding: 50px;
|
padding: 0px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
|
||||||
border-radius: 0px;
|
|
||||||
box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
.mat-title {
|
.mat-title {
|
||||||
margin: 16px 0 32px 0;
|
margin: 16px 0 32px 0;
|
||||||
|
|
|
@ -54,7 +54,7 @@ export class ChangePasswordComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickLogin() {
|
onClickChangePassword() {
|
||||||
this.changePassword.emit({
|
this.changePassword.emit({
|
||||||
currentLoginPw: this.changePasswordForm.get('currentLoginPw').value,
|
currentLoginPw: this.changePasswordForm.get('currentLoginPw').value,
|
||||||
newLoginPw: this.changePasswordForm.get('newLoginPw').value,
|
newLoginPw: this.changePasswordForm.get('newLoginPw').value,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user