From 31153b52bf96ba72c6636d383cb7d0b7076547b3 Mon Sep 17 00:00:00 2001 From: Richard Park Date: Fri, 29 Nov 2019 14:26:59 +0900 Subject: [PATCH 1/6] change password is modified --- .../change-password.dialog.component.html | 3 + .../change-password.dialog.component.ts | 181 ++---------------- .../app/services/authentication.service.ts | 12 +- .../store/account/authentication/actions.ts | 17 ++ .../store/account/authentication/effects.ts | 44 ++++- .../src/app/store/messenger/index.ts | 7 - .../app/store/messenger/service/actions.ts | 23 --- .../app/store/messenger/service/effects.ts | 47 ----- .../src/app/store/messenger/service/index.ts | 4 - .../app/store/messenger/service/reducers.ts | 4 - .../src/app/store/messenger/service/state.ts | 9 - .../src/lib/utils/password.util.ts | 137 +++++++++++++ .../ucap-webmessenger-pi/src/public-api.ts | 2 + .../components/change-password.component.html | 134 +++++++++++-- .../components/change-password.component.ts | 137 ++++++++++--- 15 files changed, 443 insertions(+), 318 deletions(-) delete mode 100644 projects/ucap-webmessenger-app/src/app/store/messenger/service/actions.ts delete mode 100644 projects/ucap-webmessenger-app/src/app/store/messenger/service/effects.ts delete mode 100644 projects/ucap-webmessenger-app/src/app/store/messenger/service/index.ts delete mode 100644 projects/ucap-webmessenger-app/src/app/store/messenger/service/reducers.ts delete mode 100644 projects/ucap-webmessenger-app/src/app/store/messenger/service/state.ts create mode 100644 projects/ucap-webmessenger-pi/src/lib/utils/password.util.ts diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.html index 31d82e21..dc33fc29 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.html +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.html @@ -5,6 +5,9 @@
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.ts index bf2cc7d3..1a403a40 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/account/change-password.dialog.component.ts @@ -1,24 +1,18 @@ import { Component, OnInit, Inject, OnDestroy } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type'; -import { KEY_VER_INFO } from '@app/types/ver-info.type'; -import { SessionStorageService } from '@ucap-webmessenger/web-storage'; - -import { Store } from '@ngrx/store'; import { DialogService } from '@ucap-webmessenger/ui'; -import { VersionInfo2Response } from '@ucap-webmessenger/api-public'; -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 { + loginId: string; + phoneNumber?: string; + encryptedLoginPw?: string; +} export interface ChangePasswordDialogResult { choice: boolean; + currentLoginPw?: string; + newLoginPw?: string; } @Component({ @@ -27,170 +21,25 @@ export interface ChangePasswordDialogResult { styleUrls: ['./change-password.dialog.component.scss'] }) export class ChangePasswordDialogComponent implements OnInit, OnDestroy { - loginRes: LoginResponse; - sessionVerinfo: VersionInfo2Response; - isMe: boolean; - constructor( public dialogRef: MatDialogRef< ChangePasswordDialogData, ChangePasswordDialogResult >, @Inject(MAT_DIALOG_DATA) public data: ChangePasswordDialogData, - private dialogService: DialogService, - private sessionStorageService: SessionStorageService, - private appAuthenticationService: AppAuthenticationService, - private store: Store - ) { - this.sessionVerinfo = this.sessionStorageService.get( - KEY_VER_INFO - ); - this.loginRes = this.sessionStorageService.get( - KEY_LOGIN_RES_INFO - ); - } + private dialogService: DialogService + ) {} ngOnInit() {} 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 }); + onChangePassword(info: { currentLoginPw: string; newLoginPw: string }): void { + this.dialogRef.close({ + choice: true, + currentLoginPw: info.currentLoginPw, + newLoginPw: info.newLoginPw + }); } onClickChoice(choice: boolean): void { diff --git a/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts b/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts index 91d22349..65e38deb 100644 --- a/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts +++ b/projects/ucap-webmessenger-app/src/app/services/authentication.service.ts @@ -1,7 +1,5 @@ import { Injectable } from '@angular/core'; -import CryptoJS from 'crypto-js'; - import { SessionStorageService, LocalStorageService @@ -10,6 +8,7 @@ import { LocaleCode } from '@ucap-webmessenger/core'; import { LoginInfo, KEY_LOGIN_INFO } from '../types'; import { KEY_VER_INFO } from '@app/types/ver-info.type'; import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type'; +import { PasswordUtil } from '@ucap-webmessenger/pi'; @Injectable({ providedIn: 'root' @@ -33,7 +32,7 @@ export class AppAuthenticationService { this.sessionStorageService.set(KEY_LOGIN_INFO, { ...loginInfo, initPw: loginInfo.loginId === loginInfo.loginPw, - loginPw: CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(loginInfo.loginPw)) + loginPw: PasswordUtil.encrypt(loginInfo.loginPw) }); if (rememberMe) { @@ -51,11 +50,4 @@ export class AppAuthenticationService { this.sessionStorageService.remove(KEY_VER_INFO); this.sessionStorageService.remove(KEY_LOGIN_INFO); } - - isSameForPassword(pw: string): boolean { - const loginInfo = this.sessionStorageService.get(KEY_LOGIN_INFO); - return ( - loginInfo.loginPw === CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(pw)) - ); - } } diff --git a/projects/ucap-webmessenger-app/src/app/store/account/authentication/actions.ts b/projects/ucap-webmessenger-app/src/app/store/account/authentication/actions.ts index b61192f1..26c09e5c 100644 --- a/projects/ucap-webmessenger-app/src/app/store/account/authentication/actions.ts +++ b/projects/ucap-webmessenger-app/src/app/store/account/authentication/actions.ts @@ -96,3 +96,20 @@ export const privacyAgreeFailure = createAction( export const privacyDisagree = createAction( '[Account::Authentication] Privacy Disagree' ); + +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 }>() +); diff --git a/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts b/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts index e4fb861f..595f862a 100644 --- a/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts +++ b/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts @@ -34,7 +34,10 @@ import { privacyAgreeSuccess, increaseLoginFailCount, initialLoginFailCount, - logoutInitialize + logoutInitialize, + userPasswordSet, + userPasswordSetSuccess, + userPasswordSetFailure } from './actions'; import { LoginInfo, @@ -60,6 +63,10 @@ import { ChangePasswordDialogData, ChangePasswordDialogResult } from '@app/layouts/messenger/dialogs/account/change-password.dialog.component'; +import { + ServiceProtocolService, + UserPasswordSetResponse +} from '@ucap-webmessenger/protocol-service'; @Injectable() export class Effects { @@ -273,10 +280,24 @@ export class Effects { width: '500px', height: '500px', disableClose: false, - data: {} + 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 { return; } @@ -324,6 +345,23 @@ 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 ngZone: NgZone, @@ -334,7 +372,7 @@ export class Effects { private appAuthenticationService: AppAuthenticationService, private protocolService: ProtocolService, private authenticationProtocolService: AuthenticationProtocolService, - + private serviceProtocolService: ServiceProtocolService, private dialogService: DialogService, @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, private logger: NGXLogger diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/index.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/index.ts index 3d4d543f..44ba4d69 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/index.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/index.ts @@ -6,7 +6,6 @@ import * as EventStore from './event'; import * as OptionStore from './option'; import * as QueryStore from './query'; import * as RoomStore from './room'; -import * as ServiceStore from './service'; import * as StatusStore from './status'; import * as SyncStore from './sync'; import * as SettingsStore from './settings'; @@ -17,7 +16,6 @@ export interface State { option: OptionStore.State; query: QueryStore.State; room: RoomStore.State; - service: ServiceStore.State; status: StatusStore.State; sync: SyncStore.State; settings: SettingsStore.State; @@ -29,7 +27,6 @@ export const effects: Type[] = [ OptionStore.Effects, QueryStore.Effects, RoomStore.Effects, - ServiceStore.Effects, StatusStore.Effects, SyncStore.Effects, SettingsStore.Effects @@ -42,7 +39,6 @@ export function reducers(state: State | undefined, action: Action) { option: OptionStore.reducer, query: QueryStore.reducer, room: RoomStore.reducer, - service: ServiceStore.reducer, status: StatusStore.reducer, sync: SyncStore.reducer, settings: SettingsStore.reducer @@ -66,9 +62,6 @@ export function selectors(selector: Selector) { QuerySelector: QueryStore.selectors( createSelector(selector, (state: State) => state.query) ), - ServiceSelector: ServiceStore.selectors( - createSelector(selector, (state: State) => state.service) - ), StatusSelector: StatusStore.selectors( createSelector(selector, (state: State) => state.status) ), diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/service/actions.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/service/actions.ts deleted file mode 100644 index f6956adb..00000000 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/service/actions.ts +++ /dev/null @@ -1,23 +0,0 @@ -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 }>() -); diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/service/effects.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/service/effects.ts deleted file mode 100644 index 175351cd..00000000 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/service/effects.ts +++ /dev/null @@ -1,47 +0,0 @@ -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, - private logger: NGXLogger - ) {} -} diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/service/index.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/service/index.ts deleted file mode 100644 index 2663cade..00000000 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/service/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './actions'; -export * from './effects'; -export * from './reducers'; -export * from './state'; diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/service/reducers.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/service/reducers.ts deleted file mode 100644 index 70e7e209..00000000 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/service/reducers.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createReducer, on } from '@ngrx/store'; -import { initialState } from './state'; - -export const reducer = createReducer(initialState); diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/service/state.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/service/state.ts deleted file mode 100644 index 1e05bd08..00000000 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/service/state.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Selector, createSelector } from '@ngrx/store'; - -export interface State {} - -export const initialState: State = {}; - -export function selectors(selector: Selector) { - return {}; -} diff --git a/projects/ucap-webmessenger-pi/src/lib/utils/password.util.ts b/projects/ucap-webmessenger-pi/src/lib/utils/password.util.ts new file mode 100644 index 00000000..e95d24b2 --- /dev/null +++ b/projects/ucap-webmessenger-pi/src/lib/utils/password.util.ts @@ -0,0 +1,137 @@ +import CryptoJS from 'crypto-js'; +import { StringUtil, CharactorType } from '@ucap-webmessenger/core'; + +export interface PasswordValidationOption { + userId?: string; + phoneNumber?: string; +} + +export enum PasswordValidationResult { + Valid = 'Valid', + Empty = 'Empty', + IncludeUserId = 'IncludeUserId', + IncludePhoneNumber = 'IncludePhoneNumber', + IncludeSpace = 'IncludeSpace', + IncludeRepeated = 'IncludeRepeated', + IncludeIncrements = 'IncludeIncrements', + IncludeDecrements = 'IncludeDecrements', + LackOfCombination = 'LackOfCombination', + TooShortCombinationLength = 'TooShortCombinationLength' +} + +export class PasswordUtil { + static encrypt(password: string): string { + return CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(password)); + } + + static validate( + password: string, + option?: PasswordValidationOption + ): { code: PasswordValidationResult; extra?: any } { + if (!password || '' === password.trim()) { + return { + code: PasswordValidationResult.Empty + }; + } + + if (!!option && !!option.userId) { + if (-1 < password.indexOf(option.userId)) { + return { + code: PasswordValidationResult.IncludeUserId + }; + } + } + + if (!!option && !!option.phoneNumber) { + const phoneNumberOnly = option.phoneNumber + .trim() + .replace(new RegExp('-', 'g'), ''); + + switch (phoneNumberOnly.length) { + case 11: + if (-1 < password.indexOf(phoneNumberOnly.substr(3, 4))) { + return { + code: PasswordValidationResult.IncludePhoneNumber + }; + } + if (-1 < password.indexOf(phoneNumberOnly.substr(7, 4))) { + return { + code: PasswordValidationResult.IncludePhoneNumber + }; + } + break; + case 10: + if (-1 < password.indexOf(phoneNumberOnly.substr(3, 3))) { + return { + code: PasswordValidationResult.IncludePhoneNumber + }; + } + if (-1 < password.indexOf(phoneNumberOnly.substr(6, 4))) { + return { + code: PasswordValidationResult.IncludePhoneNumber + }; + } + break; + default: + break; + } + } + + if (0 < StringUtil.includes(password, CharactorType.Space)) { + return { + code: PasswordValidationResult.IncludeSpace + }; + } + if (StringUtil.isRepeat(password, 3)) { + return { + code: PasswordValidationResult.IncludeRepeated + }; + } + if (StringUtil.isIncrements(password, 3)) { + return { + code: PasswordValidationResult.IncludeIncrements + }; + } + if (StringUtil.isDecrements(password, 3)) { + return { + code: PasswordValidationResult.IncludeDecrements + }; + } + + let combinationCount = 0; + if (0 < StringUtil.includes(password, CharactorType.Special)) { + combinationCount++; + } + if (0 < StringUtil.includes(password, CharactorType.Number)) { + combinationCount++; + } + if (0 < StringUtil.includes(password, CharactorType.Charactor)) { + combinationCount++; + } + + let minPwLen = 0; + if (2 < combinationCount) { + minPwLen = 8; + } else if (2 === combinationCount) { + minPwLen = 10; + } else if (2 > combinationCount) { + return { + code: PasswordValidationResult.LackOfCombination + }; + } + + if (password.length < minPwLen) { + return { + code: PasswordValidationResult.TooShortCombinationLength, + extra: { + combinationCount, + minPwLen + } + }; + } + + return { + code: PasswordValidationResult.Valid + }; + } +} diff --git a/projects/ucap-webmessenger-pi/src/public-api.ts b/projects/ucap-webmessenger-pi/src/public-api.ts index 4fee4a46..6bb87dda 100644 --- a/projects/ucap-webmessenger-pi/src/public-api.ts +++ b/projects/ucap-webmessenger-pi/src/public-api.ts @@ -12,6 +12,8 @@ export * from './lib/types/response-status.type'; export * from './lib/services/pi.service'; +export * from './lib/utils/password.util'; + export * from './lib/ucap-pi.module'; export * from './lib/config/urls'; diff --git a/projects/ucap-webmessenger-ui-account/src/lib/components/change-password.component.html b/projects/ucap-webmessenger-ui-account/src/lib/components/change-password.component.html index 61744c94..47c1ca22 100644 --- a/projects/ucap-webmessenger-ui-account/src/lib/components/change-password.component.html +++ b/projects/ucap-webmessenger-ui-account/src/lib/components/change-password.component.html @@ -5,43 +5,137 @@ - - 현재 패스워드를 입력해 주세요 - 신규 패스워드 - - - 신규 패스워드를 입력해 주세요 - + 신규 패스워드 확인 - - 신규 패스워드 확인을 입력해 주세요 - +
+ + 현재 비밀번호를 입력해 주세요 + + + 현재 비밀번호와 일치하지 않습니다 + + + + 신규 비밀번호를 입력해 주세요 + + + 현재 비밀번호와 동일합니다 + + + + + 비밀번호에는 공백을 입력할 수 없습니다 + + + 사용자 ID를 비밀번호에 포함할 수 없습니다 + + + 사용자 휴대폰번호를 비밀번호에 포함할 수 없습니다 + + + 숫자나 문자를 3번이상 반복적으로 사용할 수 없습니다 + + + 연속되는 숫자나 문자를 3번이상 사용할 수 없습니다 + + + 연속되는 숫자나 문자를 3번이상 사용할 수 없습니다 + + + 2종류 이상 조합을 해야 합니다 + + + 비밀번호에는 공백을 입력할 수 없습니다 + + + 비밀번호는{{ + newLoginPwFormControl.getError('ucapPassword').result.extra + .combinationCount + }}가지가 조합된 경우{{ + newLoginPwFormControl.getError('ucapPassword').result.extra + .minPwLen + }}자를 넘어야 합니다 + + + + + 신규 비밀번호 확인을 입력해 주세요 + + + 신규 비밀번호와 신규 비밀번호 확인이 다릅니다 + +
+ +
diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.scss b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.scss index 60953038..2a1c3ef6 100644 --- a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.scss +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.scss @@ -12,12 +12,12 @@ word-wrap: break-word; } } -::ng-deep .mat-card-header-text{ - width:100%; - .mat-card-subtitle{ +::ng-deep .mat-card-header-text { + width: 100%; + .mat-card-subtitle { color: rgb(256, 256, 256, 0.7) !important; - text-align:center; - margin-top:10px !important; + text-align: center; + margin-top: 10px !important; } } @@ -25,78 +25,90 @@ width: 400px; padding: 0 0 20px; position: relative; - .mat-card-header{ + .mat-card-header { justify-content: center; padding-bottom: 40px; background: #76d9c5; /*background: linear-gradient(to right, #345385, #ef4c73);*/ color: #ffffff; padding-top: 20px; - width:100%; - .mat-card-title{ + width: 100%; + .mat-card-title { margin-bottom: 12px; max-width: 100%; justify-content: center; display: flex; - margin:0 20px; - span{ + margin: 0 20px; + span { @include ellipsis(1); } } } - .mat-card-content{ - margin-top:-40px; - .profile-img{ - display:flex; - height:80px; + .mat-card-content { + margin-top: -40px; + .profile-img { + display: flex; + height: 80px; justify-content: center; - margin-bottom:20px; - img{ + margin-bottom: 20px; + img { widows: 80px; height: 80px; border-radius: 50%; - background-color:#efefef; - border:2px solid #ffffff; + background-color: #efefef; + border: 2px solid #ffffff; + } + + .upload-profile-image-spinner { + position: absolute; + top: 90px; + left: 160px; + } + + .upload-profile-image-btn { + position: absolute; + top: 140px; + left: 210px; } } - .profile-option{ - display:flex; - padding:0 20px; - color:#ffffff; + .profile-option { + display: flex; + padding: 0 20px; + color: #ffffff; margin-top: -100px; height: 120px; - .btn-favorite{ + .btn-favorite { cursor: pointer; - .on{ - fill:yellow; + .on { + fill: yellow; } } - .btn-groupadd{ - margin-left:auto; + .btn-groupadd { + margin-left: auto; cursor: pointer; - svg{ - display:none; - &.on{ - display:block; + svg { + display: none; + &.on { + display: block; } } } } - ul{ - padding:0 20px; - display:flex; + ul { + padding: 0 20px; + display: flex; flex-flow: column; - margin-top:-20px; - li{ - display:inline-flex; - height:30px; + margin-top: -20px; + li { + display: inline-flex; + height: 30px; align-items: center; - flex-flow:row; - margin-bottom:20px; + flex-flow: row; + margin-bottom: 20px; - svg{ - margin-right:10px; - color:#777777; + svg { + margin-right: 10px; + color: #777777; } } } diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.ts b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.ts index a7612d97..e1a84944 100644 --- a/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.ts +++ b/projects/ucap-webmessenger-ui-profile/src/lib/components/profile.component.ts @@ -1,11 +1,16 @@ -import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core'; +import { + Component, + OnInit, + Input, + EventEmitter, + Output, + ViewChild, + ElementRef +} from '@angular/core'; import { UserInfo } from '@ucap-webmessenger/protocol-sync'; -import { - UserInfoSS, - UserInfoF, - UserInfoDN -} from '@ucap-webmessenger/protocol-query'; +import { UserInfoF } from '@ucap-webmessenger/protocol-query'; +import { FileUploadItem } from '@ucap-webmessenger/api-common'; @Component({ selector: 'ucap-profile-profile', @@ -37,6 +42,14 @@ export class ProfileComponent implements OnInit { isBuddy: boolean; }>(); + @Output() + uploadProfileImage = new EventEmitter(); + + @ViewChild('profileImageFileInput', { static: false }) + profileImageFileInput: ElementRef; + + profileImageFileUploadItem: FileUploadItem; + constructor() {} ngOnInit() {} @@ -73,4 +86,14 @@ export class ProfileComponent implements OnInit { isBuddy: false }); } + + onChangeFileInput() { + this.profileImageFileUploadItem = FileUploadItem.fromFiles( + this.profileImageFileInput.nativeElement.files + )[0]; + + this.uploadProfileImage.emit(this.profileImageFileUploadItem); + + this.profileImageFileInput.nativeElement.value = ''; + } } diff --git a/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts b/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts index 1849a2ad..feb12152 100644 --- a/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts +++ b/projects/ucap-webmessenger-ui-profile/src/lib/ucap-ui-profile.module.ts @@ -8,6 +8,7 @@ import { FlexLayoutModule } from '@angular/flex-layout'; import { MatRippleModule, MatCheckboxModule } from '@angular/material'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { UCapUiModule } from '@ucap-webmessenger/ui'; @@ -35,6 +36,7 @@ const SERVICES = []; MatCheckboxModule, MatCardModule, MatTooltipModule, + MatProgressSpinnerModule, UCapUiModule ], diff --git a/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts b/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts index 412f15fb..64d91329 100644 --- a/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts +++ b/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts @@ -5,15 +5,19 @@ import { Output, Input, AfterViewInit, - OnInit + OnInit, + OnChanges, + SimpleChanges } from '@angular/core'; import { NGXLogger } from 'ngx-logger'; +const PATH = 'path'; + @Directive({ selector: 'img[ucapImage]' }) -export class ImageDirective implements OnInit, AfterViewInit { +export class ImageDirective implements OnInit, AfterViewInit, OnChanges { @Input() base: string; @@ -50,6 +54,19 @@ export class ImageDirective implements OnInit, AfterViewInit { } ngAfterViewInit(): void { + this.loadImage(); + } + + ngOnChanges(changes: SimpleChanges): void { + const pathChanges = changes[PATH]; + + if (!!pathChanges && !pathChanges.firstChange) { + this.loadImage(); + this.logger.debug('ucapImage.ngOnChanges', changes); + } + } + + private loadImage(): void { if (this.imageSrc === this.default) { this.elementRef.nativeElement.src = this.default; this.loaded.emit(this.elementRef.nativeElement); From bf333785b9fd1728745f7781bf25d17119348981 Mon Sep 17 00:00:00 2001 From: Richard Park Date: Fri, 29 Nov 2019 18:32:30 +0900 Subject: [PATCH 6/6] bug fixed --- .../components/left-side.component.ts | 23 +++++++++++++------ .../src/lib/directives/image.directive.ts | 1 - 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts index 3736dde9..467165be 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts @@ -16,7 +16,7 @@ import { CreateChatDialogData, CreateChatDialogResult } from '@app/layouts/messenger/dialogs/chat/create-chat.dialog.component'; -import { Observable, Subscription, of } from 'rxjs'; +import { Subscription, of } from 'rxjs'; import { Store, select } from '@ngrx/store'; import * as AppStore from '@app/store'; @@ -28,8 +28,7 @@ import { UserInfoF, UserInfoDN } from '@ucap-webmessenger/protocol-query'; -import { MatTabChangeEvent, MatTabGroup } from '@angular/material'; -import { RightDrawer } from '@app/types'; +import { MatTabChangeEvent } from '@angular/material'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { SessionStorageService } from '@ucap-webmessenger/web-storage'; import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type'; @@ -38,7 +37,7 @@ import { KEY_VER_INFO } from '@app/types/ver-info.type'; import { MessageApiService } from '@ucap-webmessenger/api-message'; import { DeviceType } from '@ucap-webmessenger/core'; import { UnreadCountRequest } from 'projects/ucap-webmessenger-api-message/src/lib/apis/unread-count'; -import { map, catchError } from 'rxjs/operators'; +import { map, catchError, tap } from 'rxjs/operators'; import { MessageStatusCode } from '@ucap-webmessenger/api'; export enum MainMenu { @@ -82,6 +81,7 @@ export class LeftSideComponent implements OnInit, OnDestroy { sessionVerinfo: VersionInfo2Response; loginRes: LoginResponse; + loginResSubscription: Subscription; constructor( private store: Store, @@ -90,9 +90,6 @@ export class LeftSideComponent implements OnInit, OnDestroy { private messageApiService: MessageApiService, private logger: NGXLogger ) { - this.loginRes = this.sessionStorageService.get( - KEY_LOGIN_RES_INFO - ); this.sessionVerinfo = this.sessionStorageService.get( KEY_VER_INFO ); @@ -107,6 +104,15 @@ export class LeftSideComponent implements OnInit, OnDestroy { this.badgeChatUnReadCount = count; }); + this.loginResSubscription = this.store + .pipe( + select(AppStore.AccountSelector.AuthenticationSelector.loginRes), + tap(loginRes => { + this.loginRes = loginRes; + }) + ) + .subscribe(); + this.getMessageUnreadCount(); this.badgeMessageInterval = setInterval( () => this.getMessageUnreadCount(), @@ -124,6 +130,9 @@ export class LeftSideComponent implements OnInit, OnDestroy { if (!!this.badgeMessageUnReadCountSubscription) { this.badgeMessageUnReadCountSubscription.unsubscribe(); } + if (!!this.loginResSubscription) { + this.loginResSubscription.unsubscribe(); + } if (!!this.badgeMessageInterval) { clearInterval(this.badgeMessageInterval); diff --git a/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts b/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts index 64d91329..0ce4bdfa 100644 --- a/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts +++ b/projects/ucap-webmessenger-ui/src/lib/directives/image.directive.ts @@ -62,7 +62,6 @@ export class ImageDirective implements OnInit, AfterViewInit, OnChanges { if (!!pathChanges && !pathChanges.firstChange) { this.loadImage(); - this.logger.debug('ucapImage.ngOnChanges', changes); } }