From 00dc55281baa42dd97b698ec8a5484db4898bd50 Mon Sep 17 00:00:00 2001 From: "NaYeong,Kim" Date: Wed, 11 Sep 2024 10:07:49 +0900 Subject: [PATCH 01/26] feat(my-page): apply base mark-up at mfa (#4688) * chore: update translation Signed-off-by: NaYeong,Kim * chore: changed section position Signed-off-by: NaYeong,Kim * feat: changed base role data Signed-off-by: NaYeong,Kim * feat: apply mark-up at mfa section Signed-off-by: NaYeong,Kim --------- Signed-off-by: NaYeong,Kim --- .../components/UserAccountBaseInformation.vue | 15 +- .../components/UserAccountMultiFactorAuth.vue | 222 ++++-------------- .../UserAccountMultiFactorAuthItems.vue | 89 +++++++ .../my-page/pages/UserAccountPage.vue | 2 +- .../console-translation-2.8.babel | 126 ++++++++++ packages/language-pack/en.json | 6 + packages/language-pack/ja.json | 6 + packages/language-pack/ko.json | 6 + 8 files changed, 285 insertions(+), 187 deletions(-) create mode 100644 apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue diff --git a/apps/web/src/services/my-page/components/UserAccountBaseInformation.vue b/apps/web/src/services/my-page/components/UserAccountBaseInformation.vue index d4b76e2210..2a5deb5a8e 100644 --- a/apps/web/src/services/my-page/components/UserAccountBaseInformation.vue +++ b/apps/web/src/services/my-page/components/UserAccountBaseInformation.vue @@ -9,6 +9,8 @@ import { import type { MenuItem } from '@cloudforet/mirinae/types/inputs/context-menu/type'; import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/types/inputs/dropdown/select-dropdown/type'; +import { ROLE_TYPE } from '@/schema/identity/role/constant'; +import type { RoleType } from '@/schema/identity/role/type'; import { store } from '@/store'; import { i18n } from '@/translations'; @@ -22,16 +24,19 @@ import ErrorHandler from '@/common/composables/error/errorHandler'; import UserAccountModuleContainer from '@/services/my-page/components/UserAccountModuleContainer.vue'; - const state = reactive({ userId: computed(() => store.state.user.userId), - userRole: computed(() => store.getters['user/getCurrentRoleInfo']?.roleType || 'USER'), + userRole: computed(() => store.state.user.roleType), languages: map(languages, (d, k) => ({ type: 'item', label: k === 'en' ? `${d} (default)` : d, name: k, })) as MenuItem[], timezones: map(timezoneList, (d) => ({ type: 'item', label: d === 'UTC' ? `${d} (default)` : d, name: d, })) as SelectDropdownMenuItem[], + roleType: computed(() => { + if (state.userRole === ROLE_TYPE.DOMAIN_ADMIN) return 'Admin'; + return 'User'; + }), }); const formState = reactive({ userName: '' as string | undefined, @@ -113,12 +118,12 @@ watch(() => store.state.user.language, (language) => { - import { - computed, reactive, watch, + computed, reactive, } from 'vue'; -import { - PI, PTextInput, PFieldGroup, PToggleButton, PSelectDropdown, PFieldTitle, -} from '@cloudforet/mirinae'; - import { store } from '@/store'; -import { i18n } from '@/translations'; - -import { postEnableMfa } from '@/lib/helper/multi-factor-auth-helper'; -import { emailValidator } from '@/lib/helper/user-validation-helper'; - -import { useFormValidator } from '@/common/composables/form-validator'; -import VerifyButton from '@/common/modules/button/verify-button/VerifyButton.vue'; import UserAccountModuleContainer from '@/services/my-page/components/UserAccountModuleContainer.vue'; +import UserAccountMultiFactorAuthItems from '@/services/my-page/components/UserAccountMultiFactorAuthItems.vue'; import UserAccountMultiFactorAuthModal from '@/services/my-page/components/UserAccountMultiFactorAuthModal.vue'; -// Currently, only email is supported. -const contextMenuItems = [ - { label: 'Email', name: 'EMAIL' }, -]; - const state = reactive({ - loading: false, userId: computed(() => store.state.user.userId), - // mfa: computed(() => store.state.user.mfa || undefined), isVerified: computed(() => state.mfa?.state === 'ENABLED'), - enableMfa: false, - // Currently, only email is supported. - selectedItem: contextMenuItems[0].name, }); const modalState = reactive({ isModalVisible: false, - modalType: '' as 'verify' | 'disabled' | 'change' | 'new', + modalType: '' as 'confirm' | 'form', }); -/* Components */ -const handleSelectDropdownItem = (selected: string) => { - state.selectedItem = selected; -}; -const initState = () => { - state.enableMfa = state.mfa?.state === 'ENABLED'; -}; - -/* API */ -const handleChangeToggle = async () => { - if (state.isVerified && !state.enableMfa) { - modalState.isModalVisible = true; - modalState.modalType = 'disabled'; - } -}; -const handleClickVerifyButton = async () => { - if (state.isVerified) { - modalState.modalType = 'change'; - } else { - state.loading = true; - try { - await postEnableMfa({ - mfa_type: state.selectedItem, - options: { - email: email.value, - }, - }, true); - modalState.modalType = 'verify'; - } finally { - state.loading = false; - } - } - modalState.isModalVisible = true; -}; - -const { - forms: { - email, - }, - setForm, - invalidState, - invalidTexts, -} = useFormValidator({ - email: '', -}, { - email(value: string) { return !emailValidator(value) ? '' : i18n.t('MY_PAGE.NOTIFICATION_EMAIL.EMAIL_INVALID'); }, -}); - -/* Watcher */ -watch(() => state.mfa, (mfa) => { - setForm('email', mfa?.options?.email || ''); -}, { immediate: true }); - -(() => { - initState(); -})(); +// const handleClickVerifyButton = async () => { +// if (state.isVerified) { +// modalState.modalType = 'change'; +// } else { +// state.loading = true; +// try { +// await postEnableMfa({ +// mfa_type: state.selectedItem, +// options: { +// email: email.value, +// }, +// }, true); +// modalState.modalType = 'verify'; +// } finally { +// state.loading = false; +// } +// } +// modalState.isModalVisible = true; +// }; + +// const { +// forms: { +// email, +// }, +// setForm, +// invalidState, +// invalidTexts, +// } = useFormValidator({ +// email: '', +// }, { +// email(value: string) { return !emailValidator(value) ? '' : i18n.t('MY_PAGE.NOTIFICATION_EMAIL.EMAIL_INVALID'); }, +// }); +// +// /* Watcher */ +// watch(() => state.mfa, (mfa) => { +// setForm('email', mfa?.options?.email || ''); +// }, { immediate: true }); -
- - {{ $t('MY_PAGE.MFA.ENABLE_MFA') }} - - -
-
- - - - - -
+ @@ -200,38 +92,6 @@ watch(() => state.mfa, (mfa) => { @apply text-display-md; margin-bottom: 0; } - .verify-status-wrapper { - margin-left: 0.5rem; - .verified { - @apply flex items-center text-label-md text-green-600; - gap: 0.25rem; - } - .not-verified { - @apply bg-yellow-200 text-label-sm; - padding: 0.15rem 0.5rem; - border-radius: 6.25rem; - } - } - } - .enable-toggle { - @apply flex items-center; - gap: 1rem; - } - .enable-mfa-wrapper { - @apply flex items-end; - max-width: 47.5rem; - margin-bottom: 1rem; - .type-dropdown { - min-width: 13rem; - } - .email-input { - flex: 1; - margin-left: 1rem; - } - } - - .verify-button { - @apply flex items-end; } } diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue new file mode 100644 index 0000000000..c4f2b72d29 --- /dev/null +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/apps/web/src/services/my-page/pages/UserAccountPage.vue b/apps/web/src/services/my-page/pages/UserAccountPage.vue index 89fd2d4988..d599b47b7f 100644 --- a/apps/web/src/services/my-page/pages/UserAccountPage.vue +++ b/apps/web/src/services/my-page/pages/UserAccountPage.vue @@ -70,9 +70,9 @@ const state = reactive({ diff --git a/packages/language-pack/console-translation-2.8.babel b/packages/language-pack/console-translation-2.8.babel index 867d960626..b9b7b028db 100644 --- a/packages/language-pack/console-translation-2.8.babel +++ b/packages/language-pack/console-translation-2.8.babel @@ -73024,6 +73024,27 @@ + + ADMIN_ROLE + false + + + + + + en-US + true + + + ja-JP + true + + + ko-KR + true + + + BASE_INFORMATION false @@ -73155,6 +73176,48 @@ + + EMAIL + false + + + + + + en-US + false + + + ja-JP + false + + + ko-KR + false + + + + + EMAIL_DESC + false + + + + + + en-US + false + + + ja-JP + false + + + ko-KR + false + + + ENABLE_MFA false @@ -73176,6 +73239,48 @@ + + MS_DESC + false + + + + + + en-US + false + + + ja-JP + false + + + ko-KR + false + + + + + MS_TITLE + false + + + + + + en-US + false + + + ja-JP + false + + + ko-KR + false + + + STATE_NOT_VERIFIED false @@ -73218,6 +73323,27 @@ + + SYNC + false + + + + + + en-US + false + + + ja-JP + false + + + ko-KR + false + + + TITLE false diff --git a/packages/language-pack/en.json b/packages/language-pack/en.json index 3a1a6a0cdd..0a14aa0f81 100644 --- a/packages/language-pack/en.json +++ b/packages/language-pack/en.json @@ -4027,6 +4027,7 @@ "MY_PAGE": { "ACCOUNT": { "ACCOUNT_N_PROFILE": "Account & Profile", + "ADMIN_ROLE": "Admin Role", "BASE_INFORMATION": "Base Information", "SAVE_CHANGES": "Save Changes", "TIMEZONE_INVALID": "The time zone is set incorrectly." @@ -4035,9 +4036,14 @@ "MFA": { "BTN_CHANGE": "Change", "BTN_SEND_MAIL": "Send Verification Code", + "EMAIL": "Email", + "EMAIL_DESC": "Receive a code by Email", "ENABLE_MFA": "Enable MFA", + "MS_DESC": "Receive a code with the Microsoft Authenticator app", + "MS_TITLE": "Microsoft Authenticator App", "STATE_NOT_VERIFIED": "Not Verified", "STATE_VERIFIED": "Verified", + "SYNC": "In-Sync", "TITLE": "Multi-factor Authentication", "TYPE": "MFA Type" }, diff --git a/packages/language-pack/ja.json b/packages/language-pack/ja.json index c81790f8fd..3927150fdf 100644 --- a/packages/language-pack/ja.json +++ b/packages/language-pack/ja.json @@ -4027,6 +4027,7 @@ "MY_PAGE": { "ACCOUNT": { "ACCOUNT_N_PROFILE": "アカウント&情報", + "ADMIN_ROLE": "Admin役割", "BASE_INFORMATION": "基本情報", "SAVE_CHANGES": "変更事項を保存", "TIMEZONE_INVALID": "タイムゾーンが正しく設定されました。" @@ -4035,9 +4036,14 @@ "MFA": { "BTN_CHANGE": "変更", "BTN_SEND_MAIL": "認証コード送信", + "EMAIL": "", + "EMAIL_DESC": "", "ENABLE_MFA": "MFA有効化", + "MS_DESC": "", + "MS_TITLE": "", "STATE_NOT_VERIFIED": "認証されていません", "STATE_VERIFIED": "認証済みです", + "SYNC": "", "TITLE": "マルチファクタ認証", "TYPE": "MFAタイプ" }, diff --git a/packages/language-pack/ko.json b/packages/language-pack/ko.json index ad76151680..c5e12c56d7 100644 --- a/packages/language-pack/ko.json +++ b/packages/language-pack/ko.json @@ -4027,6 +4027,7 @@ "MY_PAGE": { "ACCOUNT": { "ACCOUNT_N_PROFILE": "계정 & 프로필", + "ADMIN_ROLE": "Admin 역할(Role)", "BASE_INFORMATION": "기본 정보", "SAVE_CHANGES": "변경사항 저장 ", "TIMEZONE_INVALID": "타임존이 잘못 설정되었습니다." @@ -4035,9 +4036,14 @@ "MFA": { "BTN_CHANGE": "변경", "BTN_SEND_MAIL": "인증 코드 전송", + "EMAIL": "", + "EMAIL_DESC": "", "ENABLE_MFA": "MFA 활성화", + "MS_DESC": "", + "MS_TITLE": "", "STATE_NOT_VERIFIED": "인증되지 않음", "STATE_VERIFIED": "인증됨", + "SYNC": "", "TITLE": "멀티 팩터 인증", "TYPE": "MFA 타입" }, From 9afab66696e295946220412e1ace556d4488e3e7 Mon Sep 17 00:00:00 2001 From: HeeYoung Anna <73812528+heeyoung1332@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:00:14 +0900 Subject: [PATCH 02/26] upload 'ic_microsoft_auth' (#4692) upload 'ic_microsoft_auth' Signed-off-by: HeeYoung Anna <73812528+heeyoung1332@users.noreply.github.com> --- .../foundation/icons/icon-assets/ic_microsoft_auth.svg | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 packages/mirinae/src/foundation/icons/icon-assets/ic_microsoft_auth.svg diff --git a/packages/mirinae/src/foundation/icons/icon-assets/ic_microsoft_auth.svg b/packages/mirinae/src/foundation/icons/icon-assets/ic_microsoft_auth.svg new file mode 100644 index 0000000000..29fe2b97e6 --- /dev/null +++ b/packages/mirinae/src/foundation/icons/icon-assets/ic_microsoft_auth.svg @@ -0,0 +1,9 @@ + + + + + + + + + From c1d3bdc357a9c5863fe5ad3ea2a354b6e7fcd4f7 Mon Sep 17 00:00:00 2001 From: HeeYoung Anna <73812528+heeyoung1332@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:02:58 +0900 Subject: [PATCH 03/26] upload 'ic_notification-protocol_envelope' (#4693) upload 'ic_notification-protocol_envelope' Signed-off-by: HeeYoung Anna <73812528+heeyoung1332@users.noreply.github.com> --- .../icons/icon-assets/ic_notification-protocol_envelope.svg | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/mirinae/src/foundation/icons/icon-assets/ic_notification-protocol_envelope.svg diff --git a/packages/mirinae/src/foundation/icons/icon-assets/ic_notification-protocol_envelope.svg b/packages/mirinae/src/foundation/icons/icon-assets/ic_notification-protocol_envelope.svg new file mode 100644 index 0000000000..aa7e9fbbf5 --- /dev/null +++ b/packages/mirinae/src/foundation/icons/icon-assets/ic_notification-protocol_envelope.svg @@ -0,0 +1,3 @@ + + + From a4ebb50c49b3b150032cce6fd34f223fecbb0121 Mon Sep 17 00:00:00 2001 From: "NaYeong,Kim" Date: Mon, 23 Sep 2024 10:44:35 +0900 Subject: [PATCH 04/26] feat: update package.json/ translations/ icon (#4727) * feat: install useQRCode / update jwt-decode Signed-off-by: NaYeong,Kim * chore: run icon Signed-off-by: NaYeong,Kim * chore: update translations Signed-off-by: NaYeong,Kim * chore: update translations Signed-off-by: NaYeong,Kim --------- Signed-off-by: NaYeong,Kim --- apps/web/package.json | 6 +- apps/web/src/router/helpers/route-helper.ts | 2 +- .../src/services/auth/pages/PasswordPage.vue | 2 +- apps/web/src/store/modules/user/actions.ts | 2 +- package-lock.json | 490 ++++++++++++++++-- packages/core-lib/package.json | 2 +- .../core-lib/src/space-connector/token-api.ts | 2 +- .../console-translation-2.8.babel | 116 ++++- packages/language-pack/en.json | 10 +- packages/language-pack/ja.json | 10 +- packages/language-pack/ko.json | 10 +- .../icons/p-icons/ic_microsoft_auth.js | 12 + .../ic_notification-protocol_envelope.js | 12 + .../src/foundation/icons/p-icons/index.js | 2 + 14 files changed, 616 insertions(+), 62 deletions(-) create mode 100644 packages/mirinae/src/foundation/icons/p-icons/ic_microsoft_auth.js create mode 100644 packages/mirinae/src/foundation/icons/p-icons/ic_notification-protocol_envelope.js diff --git a/apps/web/package.json b/apps/web/package.json index d8b52d0a28..5735c7e63a 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -40,6 +40,7 @@ "@vercel/edge-config": "^0.2.1", "@vueuse/components": "^9.0.2", "@vueuse/core": "^10.7.2", + "@vueuse/integrations": "^11.1.0", "@vvo/tzdb": "^6.4.1", "animated-number-vue": "^1.0.0", "axios": "^1.7.4", @@ -57,7 +58,7 @@ "html-to-image": "^1.9.0", "js-yaml": "^4.1.0", "jsonwebtoken": "^9.0.0", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "keycloak-js": "^10.0.2", "lodash": "^4.17.21", "numeral": "^2.0.6", @@ -80,7 +81,8 @@ "vue-selecto": "^1.6.4", "vuedraggable": "^2.24.3", "vuex": "^3.6.2", - "webfontloader": "^1.6.28" + "webfontloader": "^1.6.28", + "qrcode": "^1.5.4" }, "devDependencies": { "@babel/preset-env": "^7.21.4", diff --git a/apps/web/src/router/helpers/route-helper.ts b/apps/web/src/router/helpers/route-helper.ts index c4cee27e16..0bd39dc297 100644 --- a/apps/web/src/router/helpers/route-helper.ts +++ b/apps/web/src/router/helpers/route-helper.ts @@ -1,7 +1,7 @@ import type { Route, NavigationGuardNext } from 'vue-router'; import type { JwtPayload } from 'jwt-decode'; -import jwtDecode from 'jwt-decode'; +import { jwtDecode } from 'jwt-decode'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; diff --git a/apps/web/src/services/auth/pages/PasswordPage.vue b/apps/web/src/services/auth/pages/PasswordPage.vue index cb11e2af6d..bd61279500 100644 --- a/apps/web/src/services/auth/pages/PasswordPage.vue +++ b/apps/web/src/services/auth/pages/PasswordPage.vue @@ -94,7 +94,7 @@ import type { Vue } from 'vue/types/vue'; import dayjs from 'dayjs'; import type { JwtPayload } from 'jwt-decode'; -import jwtDecode from 'jwt-decode'; +import { jwtDecode } from 'jwt-decode'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; import { PButton, PDataLoader, PIconButton } from '@cloudforet/mirinae'; diff --git a/apps/web/src/store/modules/user/actions.ts b/apps/web/src/store/modules/user/actions.ts index c150a35f8f..26e4540b4a 100644 --- a/apps/web/src/store/modules/user/actions.ts +++ b/apps/web/src/store/modules/user/actions.ts @@ -1,6 +1,6 @@ import type { Action } from 'vuex'; -import jwtDecode from 'jwt-decode'; +import { jwtDecode } from 'jwt-decode'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; import { getCancellableFetcher } from '@cloudforet/core-lib/space-connector/cancallable-fetcher'; diff --git a/package-lock.json b/package-lock.json index 086d328361..fbed7191d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -188,6 +188,7 @@ "@vercel/edge-config": "^0.2.1", "@vueuse/components": "^9.0.2", "@vueuse/core": "^10.7.2", + "@vueuse/integrations": "^11.1.0", "@vvo/tzdb": "^6.4.1", "animated-number-vue": "^1.0.0", "axios": "^1.7.4", @@ -205,7 +206,7 @@ "html-to-image": "^1.9.0", "js-yaml": "^4.1.0", "jsonwebtoken": "^9.0.0", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "keycloak-js": "^10.0.2", "lodash": "^4.17.21", "numeral": "^2.0.6", @@ -216,6 +217,7 @@ "prosemirror-state": "^1.4.3", "prosemirror-transform": "^1.7.3", "prosemirror-view": "^1.31.5", + "qrcode": "^1.5.4", "uuid": "^8.3.2", "v-click-outside": "^3.0.1", "v-tooltip": "^2.0.3", @@ -886,6 +888,129 @@ } } }, + "apps/web/node_modules/@vueuse/integrations": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-11.1.0.tgz", + "integrity": "sha512-O2ZgrAGPy0qAjpoI2YR3egNgyEqwG85fxfwmA9BshRIGjV4G6yu6CfOPpMHAOoCD+UfsIl7Vb1bXJ6ifrHYDDA==", + "dependencies": { + "@vueuse/core": "11.1.0", + "@vueuse/shared": "11.1.0", + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "apps/web/node_modules/@vueuse/integrations/node_modules/@vueuse/core": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.1.0.tgz", + "integrity": "sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "11.1.0", + "@vueuse/shared": "11.1.0", + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "apps/web/node_modules/@vueuse/integrations/node_modules/@vueuse/metadata": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.1.0.tgz", + "integrity": "sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "apps/web/node_modules/@vueuse/integrations/node_modules/@vueuse/shared": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.1.0.tgz", + "integrity": "sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==", + "dependencies": { + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "apps/web/node_modules/@vueuse/integrations/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "apps/web/node_modules/@vueuse/metadata": { "version": "10.7.2", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.2.tgz", @@ -1003,6 +1128,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "apps/web/node_modules/fuse.js": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz", + "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==", + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, "apps/web/node_modules/istanbul-lib-instrument": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", @@ -12487,7 +12622,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -16349,6 +16483,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -19076,7 +19215,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -21455,9 +21593,12 @@ } }, "node_modules/jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } }, "node_modules/keycloak-js": { "version": "10.0.2", @@ -25276,7 +25417,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -25554,6 +25694,14 @@ "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/polished": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", @@ -28657,6 +28805,136 @@ "teleport": ">=0.2.0" } }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/qrcode/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qrcode/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/qrcode/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/qrcode/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.12.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", @@ -31310,7 +31588,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -31353,14 +31630,12 @@ "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/string-width/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -31450,7 +31725,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -35277,7 +35551,7 @@ "axios-auth-refresh": "^3.2.2", "bytes": "^3.1.2", "dayjs": "^1.10.7", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "lodash": "^4.17.21" }, "devDependencies": { @@ -37777,7 +38051,7 @@ "cross-env": "^7.0.3", "dayjs": "^1.10.7", "eslint-config-custom": "*", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "lodash": "^4.17.21", "rimraf": "^3.0.2", "tsc-alias": "^1.6.11", @@ -44507,8 +44781,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -47433,6 +47706,11 @@ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, + "dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==" + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -49516,8 +49794,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-func-name": { "version": "2.0.2", @@ -51230,9 +51507,9 @@ } }, "jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==" }, "keycloak-js": { "version": "10.0.2", @@ -53969,8 +54246,7 @@ "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "path-is-absolute": { "version": "1.0.1", @@ -54181,6 +54457,11 @@ "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" }, + "pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==" + }, "polished": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", @@ -56743,6 +57024,108 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" }, + "qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "requires": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "dependencies": { + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "qs": { "version": "6.12.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", @@ -58910,7 +59293,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -58920,14 +59302,12 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" } } }, @@ -59019,7 +59399,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -61485,6 +61864,7 @@ "@vue/test-utils": "^1.3.3", "@vueuse/components": "^9.0.2", "@vueuse/core": "^10.7.2", + "@vueuse/integrations": "^11.1.0", "@vvo/tzdb": "^6.4.1", "animated-number-vue": "^1.0.0", "axios": "^1.7.4", @@ -61506,7 +61886,7 @@ "js-yaml": "^4.1.0", "jsdom": "^20.0.1", "jsonwebtoken": "^9.0.0", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "keycloak-js": "^10.0.2", "lodash": "^4.17.21", "numeral": "^2.0.6", @@ -61519,6 +61899,7 @@ "prosemirror-state": "^1.4.3", "prosemirror-transform": "^1.7.3", "prosemirror-view": "^1.31.5", + "qrcode": "^1.5.4", "rollup-plugin-visualizer": "^5.9.0", "tsconfig": "*", "uuid": "^8.3.2", @@ -61846,6 +62227,48 @@ } } }, + "@vueuse/integrations": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-11.1.0.tgz", + "integrity": "sha512-O2ZgrAGPy0qAjpoI2YR3egNgyEqwG85fxfwmA9BshRIGjV4G6yu6CfOPpMHAOoCD+UfsIl7Vb1bXJ6ifrHYDDA==", + "requires": { + "@vueuse/core": "11.1.0", + "@vueuse/shared": "11.1.0", + "vue-demi": ">=0.14.10" + }, + "dependencies": { + "@vueuse/core": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.1.0.tgz", + "integrity": "sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==", + "requires": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "11.1.0", + "@vueuse/shared": "11.1.0", + "vue-demi": ">=0.14.10" + } + }, + "@vueuse/metadata": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.1.0.tgz", + "integrity": "sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==" + }, + "@vueuse/shared": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.1.0.tgz", + "integrity": "sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==", + "requires": { + "vue-demi": ">=0.14.10" + } + }, + "vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "requires": {} + } + } + }, "@vueuse/metadata": { "version": "10.7.2", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.2.tgz", @@ -61917,6 +62340,13 @@ "dev": true, "optional": true }, + "fuse.js": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz", + "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==", + "optional": true, + "peer": true + }, "istanbul-lib-instrument": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", diff --git a/packages/core-lib/package.json b/packages/core-lib/package.json index 59689cd1a7..5488ca5190 100644 --- a/packages/core-lib/package.json +++ b/packages/core-lib/package.json @@ -21,7 +21,7 @@ "axios-auth-refresh": "^3.2.2", "bytes": "^3.1.2", "dayjs": "^1.10.7", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "lodash": "^4.17.21" }, "devDependencies": { diff --git a/packages/core-lib/src/space-connector/token-api.ts b/packages/core-lib/src/space-connector/token-api.ts index fef1a060cb..5bf8dd29fa 100644 --- a/packages/core-lib/src/space-connector/token-api.ts +++ b/packages/core-lib/src/space-connector/token-api.ts @@ -3,7 +3,7 @@ import type { } from 'axios'; import axios from 'axios'; import type { JwtPayload } from 'jwt-decode'; -import jwtDecode from 'jwt-decode'; +import { jwtDecode } from 'jwt-decode'; import { LocalStorageAccessor } from '@/local-storage-accessor'; import type { diff --git a/packages/language-pack/console-translation-2.8.babel b/packages/language-pack/console-translation-2.8.babel index b9b7b028db..b272fe4847 100644 --- a/packages/language-pack/console-translation-2.8.babel +++ b/packages/language-pack/console-translation-2.8.babel @@ -21770,15 +21770,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -73033,15 +73033,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -73177,7 +73177,7 @@ - EMAIL + EMAIL_DESC false @@ -73198,7 +73198,28 @@ - EMAIL_DESC + ENABLE_MFA + false + + + + + + en-US + true + + + ja-JP + true + + + ko-KR + true + + + + + MS_DESC false @@ -73219,7 +73240,49 @@ - ENABLE_MFA + RESYNC_DESC + false + + + + + + en-US + false + + + ja-JP + false + + + ko-KR + false + + + + + RESYNC_TITLE + false + + + + + + en-US + false + + + ja-JP + false + + + ko-KR + false + + + + + STATE_NOT_VERIFIED false @@ -73240,7 +73303,28 @@ - MS_DESC + STATE_VERIFIED + false + + + + + + en-US + true + + + ja-JP + true + + + ko-KR + true + + + + + STEP1 false @@ -73261,7 +73345,7 @@ - MS_TITLE + STEP2 false @@ -73282,7 +73366,7 @@ - STATE_NOT_VERIFIED + STEP3 false @@ -73290,20 +73374,20 @@ en-US - true + false ja-JP - true + false ko-KR - true + false - STATE_VERIFIED + STEP_DESC false diff --git a/packages/language-pack/en.json b/packages/language-pack/en.json index 0a14aa0f81..6940e46e67 100644 --- a/packages/language-pack/en.json +++ b/packages/language-pack/en.json @@ -1230,7 +1230,7 @@ "SEND_NEW_CODE": "Send new code", "SENT_DESC": "A verification code has been sent to", "SUCCESS": "A verification code has been sent to your notification email.", - "TITLE": "Verify your Email Address", + "TITLE": "Set up {type}", "VERIFICATION_CODE": "Verification Code", "VERIFY": "Verify" }, @@ -4036,13 +4036,17 @@ "MFA": { "BTN_CHANGE": "Change", "BTN_SEND_MAIL": "Send Verification Code", - "EMAIL": "Email", "EMAIL_DESC": "Receive a code by Email", "ENABLE_MFA": "Enable MFA", "MS_DESC": "Receive a code with the Microsoft Authenticator app", - "MS_TITLE": "Microsoft Authenticator App", + "RESYNC_DESC": "To re-sync, your existing authentication records will be deleted.", + "RESYNC_TITLE": "Are you sure you want to resync this multi-factor authentication?", "STATE_NOT_VERIFIED": "Not Verified", "STATE_VERIFIED": "Verified", + "STEP1": "Download the Microsoft Authenticator app to your phone.", + "STEP2": "Scan this QR code or Enter the secret key with the Microsoft Authenticator app.", + "STEP3": "Enter the code below that the Microsoft Authenticator app generated.", + "STEP_DESC": "To set up two-step verification using {type}", "SYNC": "In-Sync", "TITLE": "Multi-factor Authentication", "TYPE": "MFA Type" diff --git a/packages/language-pack/ja.json b/packages/language-pack/ja.json index 3927150fdf..4ebbe0e418 100644 --- a/packages/language-pack/ja.json +++ b/packages/language-pack/ja.json @@ -1230,7 +1230,7 @@ "SEND_NEW_CODE": "再送信", "SENT_DESC": "認証コードが入力したメールアドレスに送信されました:", "SUCCESS": "確認コードが通知メールに送信されました。", - "TITLE": "メールアドレス認証", + "TITLE": "", "VERIFICATION_CODE": "認証コード", "VERIFY": "認証" }, @@ -4036,13 +4036,17 @@ "MFA": { "BTN_CHANGE": "変更", "BTN_SEND_MAIL": "認証コード送信", - "EMAIL": "", "EMAIL_DESC": "", "ENABLE_MFA": "MFA有効化", "MS_DESC": "", - "MS_TITLE": "", + "RESYNC_DESC": "", + "RESYNC_TITLE": "", "STATE_NOT_VERIFIED": "認証されていません", "STATE_VERIFIED": "認証済みです", + "STEP1": "", + "STEP2": "", + "STEP3": "", + "STEP_DESC": "", "SYNC": "", "TITLE": "マルチファクタ認証", "TYPE": "MFAタイプ" diff --git a/packages/language-pack/ko.json b/packages/language-pack/ko.json index c5e12c56d7..98f1b47d0b 100644 --- a/packages/language-pack/ko.json +++ b/packages/language-pack/ko.json @@ -1230,7 +1230,7 @@ "SEND_NEW_CODE": "인증 코드 재전송", "SENT_DESC": "인증코드가 입력한 이메일로 발송 되었습니다: ", "SUCCESS": "인증 코드가 알림 이메일로 전송되었습니다.", - "TITLE": "이메일 주소 인증", + "TITLE": "", "VERIFICATION_CODE": "인증 코드", "VERIFY": "인증" }, @@ -4036,13 +4036,17 @@ "MFA": { "BTN_CHANGE": "변경", "BTN_SEND_MAIL": "인증 코드 전송", - "EMAIL": "", "EMAIL_DESC": "", "ENABLE_MFA": "MFA 활성화", "MS_DESC": "", - "MS_TITLE": "", + "RESYNC_DESC": "", + "RESYNC_TITLE": "", "STATE_NOT_VERIFIED": "인증되지 않음", "STATE_VERIFIED": "인증됨", + "STEP1": "", + "STEP2": "", + "STEP3": "", + "STEP_DESC": "", "SYNC": "", "TITLE": "멀티 팩터 인증", "TYPE": "MFA 타입" diff --git a/packages/mirinae/src/foundation/icons/p-icons/ic_microsoft_auth.js b/packages/mirinae/src/foundation/icons/p-icons/ic_microsoft_auth.js new file mode 100644 index 0000000000..cdb13ae941 --- /dev/null +++ b/packages/mirinae/src/foundation/icons/p-icons/ic_microsoft_auth.js @@ -0,0 +1,12 @@ +/* eslint-disable */ +/* tslint:disable */ +// @ts-ignore +import icon from 'vue-svgicon' +icon.register({ + 'ic_microsoft_auth': { + width: 32, + height: 32, + viewBox: '0 0 32 32', + data: '' + } +}) diff --git a/packages/mirinae/src/foundation/icons/p-icons/ic_notification-protocol_envelope.js b/packages/mirinae/src/foundation/icons/p-icons/ic_notification-protocol_envelope.js new file mode 100644 index 0000000000..e749f75abf --- /dev/null +++ b/packages/mirinae/src/foundation/icons/p-icons/ic_notification-protocol_envelope.js @@ -0,0 +1,12 @@ +/* eslint-disable */ +/* tslint:disable */ +// @ts-ignore +import icon from 'vue-svgicon' +icon.register({ + 'ic_notification-protocol_envelope': { + width: 32, + height: 32, + viewBox: '0 0 32 32', + data: '' + } +}) diff --git a/packages/mirinae/src/foundation/icons/p-icons/index.js b/packages/mirinae/src/foundation/icons/p-icons/index.js index b495add1ec..9de70f112b 100644 --- a/packages/mirinae/src/foundation/icons/p-icons/index.js +++ b/packages/mirinae/src/foundation/icons/p-icons/index.js @@ -159,6 +159,7 @@ import './ic_main-filled' import './ic_marketplace' import './ic_megaphone-filled' import './ic_member' +import './ic_microsoft_auth' import './ic_minus_circle' import './ic_minus' import './ic_money-bag' @@ -168,6 +169,7 @@ import './ic_my-page_account-and-profile' import './ic_my-page_notifications-channel' import './ic_no-edit' import './ic_no-image' +import './ic_notification-protocol_envelope' import './ic_paper-airplane' import './ic_peacock-gradient-circle' import './ic_performance-filled' From 3ac3d1d06cd3a523095eab1e02df655ee7c2ee9d Mon Sep 17 00:00:00 2001 From: "NaYeong,Kim" Date: Mon, 23 Sep 2024 11:07:35 +0900 Subject: [PATCH 05/26] feat: add mfa type (MS) - only Mark up (#4735) * chore: add type Signed-off-by: NaYeong,Kim * feat: changed mfa section Signed-off-by: NaYeong,Kim * feat: chaged mfa modal Signed-off-by: NaYeong,Kim * chore: changed function name Signed-off-by: NaYeong,Kim --------- Signed-off-by: NaYeong,Kim --- .../components/UserAccountMultiFactorAuth.vue | 53 ++--- .../UserAccountMultiFactorAuthItems.vue | 63 ++++-- .../UserAccountMultiFactorAuthModal.vue | 208 +++++++++--------- ...erAccountMultiFactorAuthModalEmailInfo.vue | 49 +---- ...UserAccountMultiFactorAuthModalFolding.vue | 11 +- .../my-page/types/multi-factor-auth-type.ts | 31 +++ 6 files changed, 206 insertions(+), 209 deletions(-) create mode 100644 apps/web/src/services/my-page/types/multi-factor-auth-type.ts diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue index 9ddc32ec9c..a17a0649c5 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue @@ -8,6 +8,8 @@ import { store } from '@/store'; import UserAccountModuleContainer from '@/services/my-page/components/UserAccountModuleContainer.vue'; import UserAccountMultiFactorAuthItems from '@/services/my-page/components/UserAccountMultiFactorAuthItems.vue'; import UserAccountMultiFactorAuthModal from '@/services/my-page/components/UserAccountMultiFactorAuthModal.vue'; +import type { MultiFactorAuthModalType } from '@/services/my-page/types/multi-factor-auth-type'; +import { MULTI_FACTOR_AUTH_MODAL_TYPE } from '@/services/my-page/types/multi-factor-auth-type'; const state = reactive({ userId: computed(() => store.state.user.userId), @@ -17,46 +19,17 @@ const state = reactive({ const modalState = reactive({ isModalVisible: false, - modalType: '' as 'confirm' | 'form', + modalType: MULTI_FACTOR_AUTH_MODAL_TYPE.EMAIL as MultiFactorAuthModalType, }); -// const handleClickVerifyButton = async () => { -// if (state.isVerified) { -// modalState.modalType = 'change'; -// } else { -// state.loading = true; -// try { -// await postEnableMfa({ -// mfa_type: state.selectedItem, -// options: { -// email: email.value, -// }, -// }, true); -// modalState.modalType = 'verify'; -// } finally { -// state.loading = false; -// } -// } -// modalState.isModalVisible = true; -// }; - -// const { -// forms: { -// email, -// }, -// setForm, -// invalidState, -// invalidTexts, -// } = useFormValidator({ -// email: '', -// }, { -// email(value: string) { return !emailValidator(value) ? '' : i18n.t('MY_PAGE.NOTIFICATION_EMAIL.EMAIL_INVALID'); }, -// }); -// -// /* Watcher */ -// watch(() => state.mfa, (mfa) => { -// setForm('email', mfa?.options?.email || ''); -// }, { immediate: true }); +const handleChangeToggle = (type: MultiFactorAuthModalType, value: boolean) => { + modalState.isModalVisible = true; + if (!value) { + modalState.modalType = MULTI_FACTOR_AUTH_MODAL_TYPE.DISABLED; + } else { + modalState.modalType = type; + } +}; - + -import { reactive } from 'vue'; +import { computed, reactive, watch } from 'vue'; + +import { keyBy, mapValues } from 'lodash'; import { PI, PToggleButton, PBadge } from '@cloudforet/mirinae'; -import { i18n } from '@/translations'; +import { store } from '@/store'; + +import type { MultiFactorAuthType } from '@/services/my-page/types/multi-factor-auth-type'; +import { MULTI_FACTOR_AUTH_ITEMS } from '@/services/my-page/types/multi-factor-auth-type'; -const MULTI_FACTOR_AUTH_ITEMS = [ - { - id: 'ms', - icon: 'microsoft', - title: i18n.t('MY_PAGE.MFA.MS_TITLE'), - desc: i18n.t('MY_PAGE.MFA.MS_DESC'), - }, - { - id: 'email', - icon: 'ic_notification-protocol_envelope', - title: i18n.t('MY_PAGE.MFA.EMAIL'), - desc: i18n.t('MY_PAGE.MFA.EMAIL_DESC'), - }, -]; +interface Props { + modalVisible: boolean; +} + +const props = withDefaults(defineProps(), { + modalVisible: false, +}); +const emit = defineEmits<{(e: 'change-toggle', type: string, value: boolean): void }>(); +const storeState = reactive({ + mfa: computed(() => store.state.user.mfa || undefined), +}); const state = reactive({ - enableMfa: { - ms: false, - email: false, - }, + enableMfa: mapValues(keyBy(MULTI_FACTOR_AUTH_ITEMS, 'type'), () => false) as Record, + isVerified: computed(() => storeState.mfa?.state === 'ENABLED'), + type: computed(() => storeState.mfa?.type), + selectedType: '', }); + +const handleChangeToggle = (type: string, value: boolean) => { + state.selectedType = type; + state.enableMfa[type] = value; + emit('change-toggle', type, value); +}; + +watch(() => props.modalVisible, (modalVisible) => { + if (!modalVisible) { + state.enableMfa[state.selectedType] = state.type === state.selectedType ? state.isVerified : false; + state.selectedType = ''; + } +}, { immediate: true }); diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue index a27f7b6dc1..ce57e6f909 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthItems.vue @@ -3,12 +3,19 @@ import { computed, reactive, watch } from 'vue'; import { keyBy, mapValues } from 'lodash'; -import { PI, PToggleButton, PBadge } from '@cloudforet/mirinae'; +import { + PI, PToggleButton, PBadge, PButton, +} from '@cloudforet/mirinae'; import { store } from '@/store'; -import type { MultiFactorAuthType } from '@/services/my-page/types/multi-factor-auth-type'; -import { MULTI_FACTOR_AUTH_ITEMS } from '@/services/my-page/types/multi-factor-auth-type'; +import type { + MultiFactorAuthType, + MultiFactorAuthModalDataType, +} from '@/services/my-page/types/multi-factor-auth-type'; +import { + MULTI_FACTOR_AUTH_ITEMS, +} from '@/services/my-page/types/multi-factor-auth-type'; interface Props { modalVisible: boolean; @@ -17,7 +24,9 @@ interface Props { const props = withDefaults(defineProps(), { modalVisible: false, }); -const emit = defineEmits<{(e: 'change-toggle', type: string, value: boolean): void }>(); +const emit = defineEmits< + {(e: 'handle-modal', data: MultiFactorAuthModalDataType): void} +>(); const storeState = reactive({ mfa: computed(() => store.state.user.mfa || undefined), @@ -25,16 +34,32 @@ const storeState = reactive({ const state = reactive({ enableMfa: mapValues(keyBy(MULTI_FACTOR_AUTH_ITEMS, 'type'), () => false) as Record, isVerified: computed(() => storeState.mfa?.state === 'ENABLED'), - type: computed(() => storeState.mfa?.type), + type: computed(() => storeState.mfa?.mfa_type), selectedType: '', }); -const handleChangeToggle = (type: string, value: boolean) => { +const handleChangeToggle = (type: MultiFactorAuthType, value: boolean) => { state.selectedType = type; state.enableMfa[type] = value; - emit('change-toggle', type, value); + emit('handle-modal', { + type, + state: value, + }); +}; +const handleClickReSyncButton = (type: MultiFactorAuthType) => { + emit('handle-modal', { + type, + isReSync: true, + }); }; +watch(() => storeState.mfa.mfa_type, (mfa_type) => { + if (mfa_type) { + state.enableMfa[mfa_type] = storeState.mfa.state === 'ENABLED'; + } else { + state.enableMfa = mapValues(keyBy(MULTI_FACTOR_AUTH_ITEMS, 'type'), () => false) as Record; + } +}, { immediate: true }); watch(() => props.modalVisible, (modalVisible) => { if (!modalVisible) { state.enableMfa[state.selectedType] = state.type === state.selectedType ? state.isVerified : false; @@ -62,7 +87,8 @@ watch(() => props.modalVisible, (modalVisible) => {

{{ item.title }}

- @@ -73,6 +99,14 @@ watch(() => props.modalVisible, (modalVisible) => { {{ item.desc }}

+ + {{ $t('MY_PAGE.MFA.RESYNC') }} + @@ -101,6 +135,9 @@ watch(() => props.modalVisible, (modalVisible) => { @apply text-label-md text-gray-600; } } + .re-sync-button { + margin-left: auto; + } } } diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModal.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModal.vue index 3bcff6b79e..d5246f4637 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModal.vue +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModal.vue @@ -1,12 +1,11 @@ @@ -122,7 +124,7 @@ watch(() => state.userId, (userId) => { :header-title="modalState.title" class="mfa-modal-wrapper" size="sm" - :theme-color="props.type === MULTI_FACTOR_AUTH_MODAL_TYPE.DISABLED? 'alert' : 'primary'" + :theme-color="state.isDisabledModal? 'alert' : 'primary'" :disabled="validationState.verificationCode === '' || !state.isSentCode" :loading="state.loading" @confirm="handleClickVerifyButton" @@ -130,56 +132,25 @@ watch(() => state.userId, (userId) => { @close="handleClickCancel" > - @@ -217,33 +189,8 @@ watch(() => state.userId, (userId) => { margin-top: 1.625rem; margin-bottom: 1rem; } - .set-up-desc-wrapper { - @apply flex flex-col text-paragraph-md; - margin-bottom: 0.5rem; - .set-up-desc { - list-style: decimal; - padding-left: 1rem; - } - } - .qrcode { - width: 6.25rem; - height: 6.25rem; - margin: 1rem auto; - } - .passkey-wrapper { - @apply flex; - margin-bottom: 0.5rem; - gap: 0.5rem; - - /* custom design-system component - p-text-input */ - :deep(.p-text-input) { - .input-container.disabled { - background-color: white; - } - } - .refresh-btn { - border-radius: 0.25rem; - } + .re-sync-desc { + margin-top: 1rem; } .validation-code-form { @apply flex items-end; diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue index a8f906570e..c52a58f75b 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue @@ -14,29 +14,29 @@ import { emailValidator } from '@/lib/helper/user-validation-helper'; import { useFormValidator } from '@/common/composables/form-validator'; import { useProxyValue } from '@/common/composables/proxy-state'; -import type { UserListItemType } from '@/services/iam/types/user-type'; -import { MULTI_FACTOR_AUTH_MODAL_TYPE } from '@/services/my-page/types/multi-factor-auth-type'; - interface Props { - email?: string - type?: string + mfaType?: string + isDisabledModal?: boolean isSentCode?: boolean } const props = withDefaults(defineProps(), { - email: '', - type: '', + mfaType: '', + isDisabledModal: false, isSentCode: false, }); const emit = defineEmits<{(e: 'update:is-sent-code'): void }>(); +const storeState = reactive({ + email: computed(() => store.state.user.mfa?.options?.email || undefined), +}); const state = reactive({ loading: false, - data: {} as UserListItemType, - userId: computed(() => store.state.user.userId), + userEmail: computed(() => store.state.user.email), + userId: computed(() => store.state.user.userId), proxyIsSentCode: useProxyValue('isSentCode', props, emit), - originEmail: props.email, + originEmail: storeState.email, }); const { @@ -55,19 +55,16 @@ const { const handleClickSendCodeButton = async () => { state.loading = true; try { - if (props.type === MULTI_FACTOR_AUTH_MODAL_TYPE.EMAIL) { - state.data = await postEnableMfa({ - mfa_type: props.type, + if (!props.isDisabledModal) { + await postEnableMfa({ + mfa_type: props.mfaType, options: { email: email.value, }, - }, false) as UserListItemType; - await store.dispatch('user/setUser', { - email: state.data.email, - }); + }, false); + await store.dispatch('user/setUser', { mfa: { options: { email: email.value } } }); } else { - const response = await postUserProfileDisableMfa(); - await store.dispatch('user/setUser', response); + await postUserProfileDisableMfa(); } state.proxyIsSentCode = true; } finally { @@ -78,7 +75,7 @@ const handleClickSendCodeButton = async () => { @@ -153,22 +168,13 @@ watch(() => store.state.user.email, (value) => { } .verify-status-wrapper { margin-left: 0.5rem; - .verified { - @apply flex items-center text-label-md text-green-600; - gap: 0.25rem; - } - .not-verified { - @apply bg-yellow-200 text-label-sm; - padding: 0.15rem 0.5rem; - border-radius: 6.25rem; - } } } .help-text { @apply text-paragraph-md; } .form { - @apply flex; + @apply flex items-start; max-width: 33.625rem; margin-top: 1rem; @@ -191,5 +197,10 @@ watch(() => store.state.user.email, (value) => { } } } + + .verify-button { + margin-top: 0.25rem; + margin-left: 0.5rem; + } } diff --git a/packages/language-pack/console-translation-2.8.babel b/packages/language-pack/console-translation-2.8.babel index 1ef1dbdc28..f8626e88f6 100644 --- a/packages/language-pack/console-translation-2.8.babel +++ b/packages/language-pack/console-translation-2.8.babel @@ -10636,15 +10636,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false
@@ -22614,15 +22614,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -22635,15 +22635,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -22656,15 +22656,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -22677,15 +22677,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -22788,6 +22788,27 @@ + + CONFIRM_PASSWORD + false + + + + + + en-US + true + + + ja-JP + true + + + ko-KR + true + + + CURRENT_PASSWORD false @@ -25921,15 +25942,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -25942,15 +25963,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -25963,15 +25984,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -25984,15 +26005,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26740,15 +26761,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26761,15 +26782,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26782,15 +26803,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26803,15 +26824,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26824,15 +26845,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26845,15 +26866,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26866,15 +26887,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26887,15 +26908,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26908,15 +26929,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26929,15 +26950,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -26950,15 +26971,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -27099,15 +27120,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -27120,15 +27141,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -27489,15 +27510,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28517,15 +28538,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28538,15 +28559,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28559,15 +28580,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28601,15 +28622,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28622,15 +28643,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28690,15 +28711,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28711,15 +28732,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -28732,15 +28753,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30463,15 +30484,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30510,15 +30531,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30531,15 +30552,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30552,15 +30573,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30594,15 +30615,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30615,15 +30636,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30636,15 +30657,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30683,15 +30704,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -30704,15 +30725,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -31396,15 +31417,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -39877,15 +39898,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -40276,15 +40297,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true @@ -50003,15 +50024,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -50024,15 +50045,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61371,15 +61392,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61560,15 +61581,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61581,15 +61602,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61602,15 +61623,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61623,15 +61644,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61644,15 +61665,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61665,15 +61686,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61686,15 +61707,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61707,15 +61728,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61728,15 +61749,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -61749,15 +61770,15 @@ en-US - true + false ja-JP - true + false ko-KR - true + false @@ -75996,15 +76017,15 @@ en-US - false + true ja-JP - false + true ko-KR - false + true diff --git a/packages/language-pack/en.json b/packages/language-pack/en.json index 1be0598e59..2c979f754d 100644 --- a/packages/language-pack/en.json +++ b/packages/language-pack/en.json @@ -1293,6 +1293,7 @@ "PROFILE": { "ALT_E_UPDATE": "Failed to Update Profile", "ALT_S_UPDATE": "Profile successfully updated ", + "CONFIRM_PASSWORD": "Confirm Password", "CURRENT_PASSWORD": "Current Password", "EMAIL": "E-mail", "EMAIL_REQUIRED": "Please enter email", diff --git a/packages/language-pack/ja.json b/packages/language-pack/ja.json index efb33c698b..7d0eb3d2f7 100644 --- a/packages/language-pack/ja.json +++ b/packages/language-pack/ja.json @@ -1293,6 +1293,7 @@ "PROFILE": { "ALT_E_UPDATE": "個人情報編集に失敗", "ALT_S_UPDATE": "個人情報編集完了", + "CONFIRM_PASSWORD": "パスワード確認", "CURRENT_PASSWORD": "現在のパスワード", "EMAIL": "メールアドレス", "EMAIL_REQUIRED": "メールアドレスを入力してください", diff --git a/packages/language-pack/ko.json b/packages/language-pack/ko.json index cf618510e1..7158d3c05b 100644 --- a/packages/language-pack/ko.json +++ b/packages/language-pack/ko.json @@ -1293,6 +1293,7 @@ "PROFILE": { "ALT_E_UPDATE": "개인 정보 수정 실패", "ALT_S_UPDATE": "개인 정보 수정 완료", + "CONFIRM_PASSWORD": "비밀번호 확인", "CURRENT_PASSWORD": "현재 비밀번호", "EMAIL": "이메일", "EMAIL_REQUIRED": "이메일을 입력해주세요.", From 11c489488a4648ef3061b73962eb71d0b338bfc8 Mon Sep 17 00:00:00 2001 From: "NaYeong,Kim" Date: Wed, 16 Oct 2024 10:56:42 +0900 Subject: [PATCH 10/26] refactor: change to a state store usage approach (#4852) * chore: changed file name Signed-off-by: NaYeong,Kim * feat: apply disabled case and changed style Signed-off-by: NaYeong,Kim * refactor: change to a state store usage approach Signed-off-by: NaYeong,Kim * chore: remove unnecessary code Signed-off-by: NaYeong,Kim --------- Signed-off-by: NaYeong,Kim --- .../components/UserAccountMultiFactorAuth.vue | 75 ++++++------------- ...> UserAccountMultiFactorAuthFormModal.vue} | 72 ++++++++---------- .../UserAccountMultiFactorAuthItems.vue | 75 +++++++++++-------- ...erAccountMultiFactorAuthModalEmailInfo.vue | 10 +-- ...UserAccountMultiFactorAuthModalFolding.vue | 2 - .../multi-factor-authentication-store.ts | 40 ++++++++++ 6 files changed, 141 insertions(+), 133 deletions(-) rename apps/web/src/services/my-page/components/{UserAccountMultiFactorAuthModal.vue => UserAccountMultiFactorAuthFormModal.vue} (75%) create mode 100644 apps/web/src/services/my-page/stores/multi-factor-authentication-store.ts diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue index bb289dee1d..ae04d73e53 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuth.vue @@ -1,71 +1,44 @@ diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModal.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthFormModal.vue similarity index 75% rename from apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModal.vue rename to apps/web/src/services/my-page/components/UserAccountMultiFactorAuthFormModal.vue index d5246f4637..470bcb3a6b 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModal.vue +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthFormModal.vue @@ -13,54 +13,44 @@ import { i18n as _i18n } from '@/translations'; import { postValidationMfaCode } from '@/lib/helper/multi-factor-auth-helper'; -import { useProxyValue } from '@/common/composables/proxy-state'; import UserAccountMultiFactorAuthModalEmailInfo from '@/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue'; import UserAccountMultiFactorAuthModalFolding from '@/services/my-page/components/UserAccountMultiFactorAuthModalFolding.vue'; import UserAccountMultiFactorAuthModalMSInfo from '@/services/my-page/components/UserAccountMultiFactorAuthModalMSInfo.vue'; +import { useMultiFactorAuthenticationStore } from '@/services/my-page/stores/multi-factor-authentication-store'; import type { - MultiFactorAuthModalDataType, - MultiFactorAuthType, UserInfoType, } from '@/services/my-page/types/multi-factor-auth-type'; import { MULTI_FACTOR_AUTH_TYPE } from '@/services/my-page/types/multi-factor-auth-type'; -interface Props { - data: MultiFactorAuthModalDataType - visible: boolean -} - -const props = withDefaults(defineProps(), { - data: undefined, - visible: false, -}); +const multiFactorAuthenticationStore = useMultiFactorAuthenticationStore(); +const multiFactorAuthenticationState = multiFactorAuthenticationStore.state; const emit = defineEmits<{(e: 'refresh'): void }>(); const storeState = reactive({ userId: computed(() => store.state.user.userId), + selectedType: computed(() => multiFactorAuthenticationState.selectedType), + isReSyncModal: computed(() => multiFactorAuthenticationState.modalType === 'RE_SYNC'), + isDisabledModal: computed(() => multiFactorAuthenticationState.modalType === 'DISABLED'), }); const state = reactive({ loading: false, - mfaType: computed(() => props.data?.type), - isReSyncModal: computed(() => props.data.isReSync || false), - isDisabledModal: computed(() => !state.isReSyncModal && !props.data.state), userInfo: {} as UserInfoType, isCollapsed: true, isSentCode: false, }); const modalState = reactive({ - proxyVisible: useProxyValue('visible', props, emit), title: computed(() => { - if (state.isReSyncModal) { + if (storeState.isReSyncModal) { return _i18n.t('MY_PAGE.MFA.RESYNC_TITLE'); } - if (state.isDisabledModal) { + if (storeState.isDisabledModal) { return _i18n.t('COMMON.MFA_MODAL.ALT.TITLE'); } - const type = state.mfaType.toLowerCase() + const type = storeState.selectedType?.toLowerCase() .replace(/_/g, ' ') .replace(/\b\w/g, (char) => char.toUpperCase()); return _i18n.t('COMMON.MFA_MODAL.TITLE', { type }); @@ -83,7 +73,7 @@ const handleChangeInput = (value: string) => { validationState.verificationCode = value; }; const handleClickCancel = async () => { - modalState.proxyVisible = false; + multiFactorAuthenticationStore.setModalVisible(false); await resetFormData(); if (storeState.userId === state.userInfo.user_id) { await store.dispatch('user/setUser', state.userInfo); @@ -100,7 +90,7 @@ const handleClickVerifyButton = async () => { if (storeState.userId === state.userInfo.user_id) { await store.dispatch('user/setUser', state.userInfo); } - modalState.proxyVisible = false; + multiFactorAuthenticationStore.setModalVisible(false); resetFormData(); } catch (e: any) { validationState.isValidationCodeValid = false; @@ -119,20 +109,19 @@ watch(() => storeState.userId, (userId) => { diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthFormModal.vue b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthFormModal.vue index 470bcb3a6b..48cd245b18 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthFormModal.vue +++ b/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthFormModal.vue @@ -18,22 +18,22 @@ import UserAccountMultiFactorAuthModalEmailInfo from '@/services/my-page/compone import UserAccountMultiFactorAuthModalFolding from '@/services/my-page/components/UserAccountMultiFactorAuthModalFolding.vue'; import UserAccountMultiFactorAuthModalMSInfo from '@/services/my-page/components/UserAccountMultiFactorAuthModalMSInfo.vue'; -import { useMultiFactorAuthenticationStore } from '@/services/my-page/stores/multi-factor-authentication-store'; +import { useMultiFactorAuthStore } from '@/services/my-page/stores/multi-factor-auth-store'; import type { UserInfoType, } from '@/services/my-page/types/multi-factor-auth-type'; import { MULTI_FACTOR_AUTH_TYPE } from '@/services/my-page/types/multi-factor-auth-type'; -const multiFactorAuthenticationStore = useMultiFactorAuthenticationStore(); -const multiFactorAuthenticationState = multiFactorAuthenticationStore.state; +const multiFactorAuthStore = useMultiFactorAuthStore(); +const multiFactorAuthState = multiFactorAuthStore.state; const emit = defineEmits<{(e: 'refresh'): void }>(); const storeState = reactive({ userId: computed(() => store.state.user.userId), - selectedType: computed(() => multiFactorAuthenticationState.selectedType), - isReSyncModal: computed(() => multiFactorAuthenticationState.modalType === 'RE_SYNC'), - isDisabledModal: computed(() => multiFactorAuthenticationState.modalType === 'DISABLED'), + selectedType: computed(() => multiFactorAuthState.selectedType), + isReSyncModal: computed(() => multiFactorAuthState.modalType === 'RE_SYNC'), + isDisabledModal: computed(() => multiFactorAuthState.modalType === 'DISABLED'), }); const state = reactive({ loading: false, @@ -71,9 +71,11 @@ const resetFormData = () => { }; const handleChangeInput = (value: string) => { validationState.verificationCode = value; + validationState.isValidationCodeValid = true; + validationState.validationCodeInvalidText = ''; }; const handleClickCancel = async () => { - multiFactorAuthenticationStore.setModalVisible(false); + multiFactorAuthStore.setModalVisible(false); await resetFormData(); if (storeState.userId === state.userInfo.user_id) { await store.dispatch('user/setUser', state.userInfo); @@ -90,8 +92,12 @@ const handleClickVerifyButton = async () => { if (storeState.userId === state.userInfo.user_id) { await store.dispatch('user/setUser', state.userInfo); } - multiFactorAuthenticationStore.setModalVisible(false); resetFormData(); + if (storeState.isReSyncModal) { + multiFactorAuthStore.setModalType('FORM'); + } else { + multiFactorAuthStore.setModalVisible(false); + } } catch (e: any) { validationState.isValidationCodeValid = false; validationState.validationCodeInvalidText = _i18n.t('COMMON.MFA_MODAL.INVALID_CODE'); @@ -106,10 +112,15 @@ watch(() => storeState.userId, (userId) => { state.userInfo = store.state.user; } }, { immediate: true }); +watch(() => multiFactorAuthState.modalType, () => { + state.isSentCode = false; + validationState.isValidationCodeValid = true; + validationState.validationCodeInvalidText = ''; +});