diff --git a/.github/workflows/dispatch_storybook_release.yaml b/.github/workflows/dispatch_storybook_release.yaml index 78dc4a3b2e..7b37ae36a1 100644 --- a/.github/workflows/dispatch_storybook_release.yaml +++ b/.github/workflows/dispatch_storybook_release.yaml @@ -48,7 +48,7 @@ jobs: aws-region: ap-northeast-2 - name: Deploy to s3 - run: aws s3 sync apps/storybook/storybook-static/ s3://${{ secrets.STORYBOOK_S3_BUCKET }} --delete + run: aws s3 sync apps/mirinae-storybook/storybook-static/ s3://${{ secrets.STORYBOOK_S3_BUCKET }} --delete - name: Invalidate CloudFront Cache run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CDN_DISTRIBUTION_ID }} --paths "/*" diff --git a/apps/web/package.json b/apps/web/package.json index bed1108cff..0940cfe084 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "web", - "version": "2.0.0-dev377", + "version": "2.0.0-dev378", "private": true, "description": "Cloudforet Console Web Application", "author": "Cloudforet", diff --git a/apps/web/src/api-clients/identity/user-profile/composables/use-user-profile-api.ts b/apps/web/src/api-clients/identity/user-profile/composables/use-user-profile-api.ts index b155920e69..c08aa42a31 100644 --- a/apps/web/src/api-clients/identity/user-profile/composables/use-user-profile-api.ts +++ b/apps/web/src/api-clients/identity/user-profile/composables/use-user-profile-api.ts @@ -1,16 +1,16 @@ import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { UserProfileConfirmEmailParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/confirm-email'; import type { UserProfileConfirmMfaParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/confirm-mfa'; +import type { UserProfileDisableMfaParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/disable-mfa'; import type { UserProfileEnableMfaParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/enable-mfa'; import type { UserProfileGetWorkspacesParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/get-workspaces'; import type { UserProfileResetPasswordParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/reset-password'; import type { UserProfileUpdateParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/update'; import type { UserProfileUpdatePasswordParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/update-password'; import type { UserProfileVerifyEmailParameters } from '@/api-clients/identity/user-profile/schema/api-verbs/verify-email'; -import type { WorkspaceGroupModel } from '@/api-clients/identity/workspace-group/schema/model'; -import type { WorkspaceModel } from '@/api-clients/identity/workspace/schema/model'; +import type { UserModel } from '@/api-clients/identity/user/schema/model'; + export const useUserProfileApi = () => { @@ -19,12 +19,11 @@ export const useUserProfileApi = () => { updatePassword: SpaceConnector.clientV2.identity.userProfile.updatePassword, resetPassword: SpaceConnector.clientV2.identity.userProfile.resetPassword, verifyEmail: SpaceConnector.clientV2.identity.userProfile.verifyEmail, - confirmEmail: SpaceConnector.clientV2.identity.userProfile.confirmEmail, - enableMfa: SpaceConnector.clientV2.identity.userProfile.enableMfa, - confirmMfa: SpaceConnector.clientV2.identity.userProfile.confirmMfa, - getWorkspaces: SpaceConnector.clientV2.identity.userProfile.getWorkspaces>, - getWorkspaceGroups: SpaceConnector.clientV2.identity.userProfile.getWorkspaceGroups>, - + confirmEmail: SpaceConnector.clientV2.identity.userProfile.confirmEmail, + disableMfa: SpaceConnector.clientV2.identity.userProfile.disableMfa, + enableMfa: SpaceConnector.clientV2.identity.userProfile.enableMfa, + confirmMfa: SpaceConnector.clientV2.identity.userProfile.confirmMfa, + getWorkspaces: SpaceConnector.clientV2.identity.userProfile.getWorkspaces, }; return { diff --git a/apps/web/src/api-clients/identity/user-profile/schema/api-verbs/disable-mfa.ts b/apps/web/src/api-clients/identity/user-profile/schema/api-verbs/disable-mfa.ts new file mode 100644 index 0000000000..619b9e7e9f --- /dev/null +++ b/apps/web/src/api-clients/identity/user-profile/schema/api-verbs/disable-mfa.ts @@ -0,0 +1,4 @@ +/* eslint-disable @typescript-eslint/no-empty-interface */ +export interface UserProfileDisableMfaParameters { + // No parameters +} diff --git a/apps/web/src/api-clients/identity/user-profile/schema/constant.ts b/apps/web/src/api-clients/identity/user-profile/schema/constant.ts index 2eb11920bf..be88fccd66 100644 --- a/apps/web/src/api-clients/identity/user-profile/schema/constant.ts +++ b/apps/web/src/api-clients/identity/user-profile/schema/constant.ts @@ -2,3 +2,8 @@ export const MULTI_FACTOR_AUTH_TYPE = { OTP: 'OTP', EMAIL: 'EMAIL', } as const; + +export const MFA_STATE = { + ENABLED: 'ENABLED', + DISABLED: 'DISABLED', +} as const; diff --git a/apps/web/src/api-clients/identity/user-profile/schema/type.ts b/apps/web/src/api-clients/identity/user-profile/schema/type.ts index 1c6a813feb..d1d614f889 100644 --- a/apps/web/src/api-clients/identity/user-profile/schema/type.ts +++ b/apps/web/src/api-clients/identity/user-profile/schema/type.ts @@ -1,3 +1,4 @@ -import type { MULTI_FACTOR_AUTH_TYPE } from '@/api-clients/identity/user-profile/schema/constant'; +import type { MFA_STATE, MULTI_FACTOR_AUTH_TYPE } from '@/api-clients/identity/user-profile/schema/constant'; export type MultiFactorAuthType = typeof MULTI_FACTOR_AUTH_TYPE[keyof typeof MULTI_FACTOR_AUTH_TYPE]; +export type MfaState = typeof MFA_STATE[keyof typeof MFA_STATE]; diff --git a/apps/web/src/api-clients/identity/user/schema/api-verbs/create.ts b/apps/web/src/api-clients/identity/user/schema/api-verbs/create.ts index 7ad83faf97..e55cbc6693 100644 --- a/apps/web/src/api-clients/identity/user/schema/api-verbs/create.ts +++ b/apps/web/src/api-clients/identity/user/schema/api-verbs/create.ts @@ -1,4 +1,5 @@ import type { Tags } from '@/api-clients/_common/schema/model'; +import type { MfaState, MultiFactorAuthType } from '@/api-clients/identity/user-profile/schema/type'; import type { AuthType } from '@/api-clients/identity/user/schema/type'; @@ -12,4 +13,6 @@ export interface UserCreateParameters { timezone?: string; tags?: Tags; reset_password?: boolean; + enforce_mfa_state?: MfaState; + enforce_mfa_type?: MultiFactorAuthType; // only when enforce_mfa_state is ENABLED, this field is required } diff --git a/apps/web/src/api-clients/identity/user/schema/api-verbs/update.ts b/apps/web/src/api-clients/identity/user/schema/api-verbs/update.ts index c7278cc482..dd46464b3c 100644 --- a/apps/web/src/api-clients/identity/user/schema/api-verbs/update.ts +++ b/apps/web/src/api-clients/identity/user/schema/api-verbs/update.ts @@ -1,4 +1,5 @@ import type { Tags } from '@/api-clients/_common/schema/model'; +import type { MfaState, MultiFactorAuthType } from '@/api-clients/identity/user-profile/schema/type'; export interface UserUpdateParameters { @@ -10,4 +11,6 @@ export interface UserUpdateParameters { timezone?: string; tags?: Tags; reset_password?: boolean; + enforce_mfa_state?: MfaState; + enforce_mfa_type?: MultiFactorAuthType; // only when enforce_mfa_state is ENABLED, this field is required } diff --git a/apps/web/src/api-clients/identity/user/schema/model.ts b/apps/web/src/api-clients/identity/user/schema/model.ts index 7edf82ba1d..3cfb3c6e10 100644 --- a/apps/web/src/api-clients/identity/user/schema/model.ts +++ b/apps/web/src/api-clients/identity/user/schema/model.ts @@ -14,7 +14,7 @@ export interface UserModel { auth_type: AuthType; // backend role_type: RoleType; role_id?: string; - mfa: UserMfa; + mfa?: UserMfa; language: string; timezone: string; api_key_count: number; @@ -26,11 +26,13 @@ export interface UserModel { } export interface UserMfa { - state: UserMfaState, - mfa_type: MultiFactorAuthType, - options: { + state?: UserMfaState, + mfa_type?: MultiFactorAuthType, + options?: { + enforce?: boolean, // if true, mfa_type is required email?: string, user_secret_id?: string, + otp_qrcode_uri?: string, // response from 'enable-mfa' verb only } } diff --git a/apps/web/src/api-clients/identity/workspace-user/schema/api-verbs/create.ts b/apps/web/src/api-clients/identity/workspace-user/schema/api-verbs/create.ts index ed17d6383a..5a36caaa45 100644 --- a/apps/web/src/api-clients/identity/workspace-user/schema/api-verbs/create.ts +++ b/apps/web/src/api-clients/identity/workspace-user/schema/api-verbs/create.ts @@ -1,4 +1,5 @@ import type { Tags } from '@/api-clients/_common/schema/model'; +import type { MfaState, MultiFactorAuthType } from '@/api-clients/identity/user-profile/schema/type'; import type { AuthType } from '@/api-clients/identity/user/schema/type'; export interface WorkspaceUserCreateParameters { @@ -11,5 +12,7 @@ export interface WorkspaceUserCreateParameters { timezone?: string; tags?: Tags; reset_password?: boolean; + enforce_mfa_state?: MfaState; + enforce_mfa_type?: MultiFactorAuthType; role_id: string; } diff --git a/apps/web/src/common/components/info-tooltip/InfoTooltip.vue b/apps/web/src/common/components/info-tooltip/InfoTooltip.vue index 5274de29c2..03550df8f2 100644 --- a/apps/web/src/common/components/info-tooltip/InfoTooltip.vue +++ b/apps/web/src/common/components/info-tooltip/InfoTooltip.vue @@ -1,9 +1,11 @@ @@ -62,7 +82,7 @@ const handleClickSendEmailButton = async () => { {{ $t('COMMON.MFA_MODAL.COLLAPSE_DESC') }} {{ $t('COMMON.MFA_MODAL.SEND_NEW_CODE') }} diff --git a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue b/apps/web/src/common/components/mfa/components/EmailInfo.vue similarity index 92% rename from apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue rename to apps/web/src/common/components/mfa/components/EmailInfo.vue index 18d1d2024b..0330e6f4d7 100644 --- a/apps/web/src/services/my-page/components/UserAccountMultiFactorAuthModalEmailInfo.vue +++ b/apps/web/src/common/components/mfa/components/EmailInfo.vue @@ -16,25 +16,22 @@ import { emailValidator } from '@/lib/helper/user-validation-helper'; import { useFormValidator } from '@/common/composables/form-validator'; import { useProxyValue } from '@/common/composables/proxy-state'; -import { useMultiFactorAuthStore } from '@/services/my-page/stores/multi-factor-auth-store'; - interface Props { - isSentCode?: boolean + isSentCode?: boolean; + isForm?: boolean; } const props = withDefaults(defineProps(), { isSentCode: false, + isForm: false, }); -const multiFactorAuthStore = useMultiFactorAuthStore(); -const multiFactorAuthState = multiFactorAuthStore.state; const userStore = useUserStore(); const emit = defineEmits<{(e: 'update:is-sent-code'): void }>(); const storeState = reactive({ email: computed(() => userStore.state.mfa?.options?.email), - isFormModal: computed(() => multiFactorAuthState.modalType === 'FORM'), }); const state = reactive({ loading: false, @@ -58,7 +55,7 @@ const { const handleClickSendCodeButton = async () => { state.loading = true; try { - if (storeState.isFormModal) { + if (props.isForm) { await postEnableMfa({ mfa_type: MULTI_FACTOR_AUTH_TYPE.EMAIL, options: { @@ -82,9 +79,9 @@ const handleClickSendCodeButton = async () => {