diff --git a/apps/web/src/App.vue b/apps/web/src/App.vue index f108ffe136..9402e35ede 100755 --- a/apps/web/src/App.vue +++ b/apps/web/src/App.vue @@ -17,6 +17,7 @@ import { EXTERNAL_PAGE_ROUTE } from '@/router/constant'; import { getRouteScope } from '@/router/helpers/route-helper'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { SIDEBAR_TYPE } from '@/store/display/constant'; import { useDisplayStore } from '@/store/display/display-store'; import { useErrorStore } from '@/store/error/error-store'; @@ -70,6 +71,7 @@ const state = reactive({ }); const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const appContextStore = useAppContextStore(); const errorStore = useErrorStore(); const globalUIStore = useGlobalUIStore(); @@ -88,7 +90,7 @@ const goToSignIn = async () => { name: AUTH_ROUTE.SIGN_OUT._NAME, query: { previousPath: route.fullPath }, }; - userStore.setCurrentGrantInfo(undefined); + authorizationStore.setCurrentGrantInfo(undefined); errorStore.setVisibleSessionExpiredError(false); await router.push(to); diff --git a/apps/web/src/api-clients/api-client-manager.ts b/apps/web/src/api-clients/api-client-manager.ts deleted file mode 100644 index 4ea744e4c0..0000000000 --- a/apps/web/src/api-clients/api-client-manager.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; - -import { ApiClientEndpoint } from '@/lib/config/global-config/schema/api-client-schema'; -import type { ApiClientsSchemaType, GlobalServiceConfig } from '@/lib/config/global-config/types/type'; - - -class APIClientManager { - // eslint-disable-next-line no-undef - [key: string]: any; - - private config: GlobalServiceConfig = {} as GlobalServiceConfig; - - private apiClientsSchema: ApiClientsSchemaType = {} as ApiClientsSchemaType; - - async initialize(mergedConfig) { - this.config = mergedConfig; - - this.apiClientsSchema = JSON.parse(JSON.stringify(ApiClientEndpoint)); - this.defineDynamicServices(); - } - - private defineDynamicServices() { - if (!this.apiClientsSchema) { - throw new Error('[APIClientManager] APIClientManager is not initialized. Call initialize() first.'); - } - - Object.keys(this.apiClientsSchema).forEach((serviceName) => { - const propertyName = serviceName.toLowerCase() - .replace(/_([a-z])/g, (_, char) => char.toUpperCase()); - - Object.defineProperty(this, propertyName, { - get: () => this.createServiceHandler(serviceName), - enumerable: true, - }); - }); - } - - private createServiceHandler(serviceName: string) { - const serviceConfig = this.config?.[serviceName] || null; - if (!serviceConfig || !serviceConfig.ENABLED) { - return null; - } - - const apiClientSchemaByService = this.apiClientsSchema[serviceName]; - if (!apiClientSchemaByService) { - return null; - } - - const version = serviceConfig.VERSION; - const clientEndpoint = apiClientSchemaByService[version]; - if (!clientEndpoint) { - return null; - } - - const endpoint = SpaceConnector.clientV2[clientEndpoint]; - - return { endpoint, version }; - } -} - -export default new APIClientManager(); diff --git a/apps/web/src/common/components/bookmark/BookmarkFolderFormModal.vue b/apps/web/src/common/components/bookmark/BookmarkFolderFormModal.vue index 6b4b6e90f6..58679a5c34 100644 --- a/apps/web/src/common/components/bookmark/BookmarkFolderFormModal.vue +++ b/apps/web/src/common/components/bookmark/BookmarkFolderFormModal.vue @@ -10,7 +10,7 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { BOOKMARK_MODAL_TYPE } from '@/common/components/bookmark/constant/constant'; import { useBookmarkStore } from '@/common/components/bookmark/store/bookmark-store'; @@ -38,13 +38,13 @@ const bookmarkStore = useBookmarkStore(); const bookmarkState = bookmarkStore.state; const appContextStore = useAppContextStore(); const appContextGetters = appContextStore.getters; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const emit = defineEmits<{(e: 'confirm', isEdit?: boolean, name?: string): void; }>(); const storeState = reactive({ isAdminMode: computed(() => appContextGetters.isAdminMode), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), modal: computed(() => bookmarkState.modal), bookmarkType: computed(() => bookmarkState.bookmarkType), diff --git a/apps/web/src/common/components/bookmark/BookmarkLinkFormModal.vue b/apps/web/src/common/components/bookmark/BookmarkLinkFormModal.vue index fb6063854a..99b12f4346 100644 --- a/apps/web/src/common/components/bookmark/BookmarkLinkFormModal.vue +++ b/apps/web/src/common/components/bookmark/BookmarkLinkFormModal.vue @@ -15,7 +15,7 @@ import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; @@ -47,14 +47,14 @@ const userWorkspaceStore = useUserWorkspaceStore(); const userWorkspaceStoreGetters = userWorkspaceStore.getters; const appContextStore = useAppContextStore(); const appContextGetters = appContextStore.getters; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const emit = defineEmits<{(e: 'confirm', selectedFolder?: BookmarkItem, scope?: BookmarkType): void; }>(); const storeState = reactive({ isAdminMode: computed(() => appContextGetters.isAdminMode), currentWorkspaceId: computed(() => userWorkspaceStoreGetters.currentWorkspaceId), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), modal: computed(() => bookmarkState.modal), selectedBookmark: computed(() => bookmarkState.selectedBookmark), diff --git a/apps/web/src/common/composables/contents-accessibility/index.ts b/apps/web/src/common/composables/contents-accessibility/index.ts index 7581899961..09228415af 100644 --- a/apps/web/src/common/composables/contents-accessibility/index.ts +++ b/apps/web/src/common/composables/contents-accessibility/index.ts @@ -1,7 +1,7 @@ import type { Ref } from 'vue'; import { computed, reactive, toRef } from 'vue'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; +import { useMenuStore } from '@/store/menu/menu-store'; import type { MenuId } from '@/lib/menu/config'; @@ -10,10 +10,10 @@ interface UseContentsAccessibilityReturnType { } export const useContentsAccessibility = (menuId: MenuId): UseContentsAccessibilityReturnType => { - const globalConfigSchemaStore = useGlobalConfigSchemaStore(); + const menuStore = useMenuStore(); const state = reactive({ - visibleContents: computed(() => globalConfigSchemaStore.getters.menuList.findIndex((menu) => menu.id === menuId) !== -1), + visibleContents: computed(() => menuStore.getters.menuList.findIndex((menu) => menu.id === menuId) !== -1), }); return { diff --git a/apps/web/src/common/composables/grant-scope-guard/index.ts b/apps/web/src/common/composables/grant-scope-guard/index.ts index ad4d72cf34..66d41b1897 100644 --- a/apps/web/src/common/composables/grant-scope-guard/index.ts +++ b/apps/web/src/common/composables/grant-scope-guard/index.ts @@ -3,8 +3,8 @@ import { computed, reactive, watch } from 'vue'; import type { GrantScope } from '@/api-clients/identity/token/schema/type'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import type { GrantInfo } from '@/store/user/type'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; +import type { GrantInfo } from '@/store/authorization/type'; import ErrorHandler from '@/common/composables/error/errorHandler'; @@ -14,10 +14,10 @@ interface GrantScopeGuardReturnType { } export const useGrantScopeGuard = (requiredScopes: GrantScope[], apiFunction: () => Promise): GrantScopeGuardReturnType => { const appContextStore = useAppContextStore(); - const userStore = useUserStore(); + const authorizationStore = useAuthorizationStore(); const state = reactive({ - currentGrantInfo: computed(() => userStore.state.currentGrantInfo || { scope: 'USER' }), + currentGrantInfo: computed(() => authorizationStore.state.currentGrantInfo || { scope: 'USER' }), isLoading: computed(() => appContextStore.getters.globalGrantLoading), isValidScope: computed(() => requiredScopes.includes(state.currentGrantInfo.scope)), }); diff --git a/apps/web/src/common/composables/page-editable-status/index.ts b/apps/web/src/common/composables/page-editable-status/index.ts index a77d60f18c..b5a3eb803c 100644 --- a/apps/web/src/common/composables/page-editable-status/index.ts +++ b/apps/web/src/common/composables/page-editable-status/index.ts @@ -1,9 +1,7 @@ import type { Ref } from 'vue'; import { computed, reactive, toRef } from 'vue'; -import { useUserStore } from '@/store/user/user-store'; - -import type { PageAccessMap } from '@/lib/access-control/config'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useCurrentMenuId } from '@/common/composables/current-menu-id'; @@ -12,17 +10,11 @@ interface UsePageEditableStatusReturnType { } export const usePageEditableStatus = (): UsePageEditableStatusReturnType => { - const userStore = useUserStore(); - const userGetters = userStore.getters; - + const authorizationStore = useAuthorizationStore(); const { currentMenuId } = useCurrentMenuId(); - const storeState = reactive({ - pageAccessPermissionMap: computed(() => userGetters.pageAccessPermissionMap), - }); - const state = reactive({ - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[currentMenuId.value]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[currentMenuId.value]?.write), }); return { diff --git a/apps/web/src/common/modules/favorites/favorite-button/FavoriteButton.vue b/apps/web/src/common/modules/favorites/favorite-button/FavoriteButton.vue index f0f20c78ef..e7368abb22 100644 --- a/apps/web/src/common/modules/favorites/favorite-button/FavoriteButton.vue +++ b/apps/web/src/common/modules/favorites/favorite-button/FavoriteButton.vue @@ -2,7 +2,7 @@ import { computed, reactive, } from 'vue'; -import { useRoute } from 'vue-router/composables'; +import { useRoute, useRouter } from 'vue-router/composables'; import { PI } from '@cloudforet/mirinae'; @@ -12,7 +12,6 @@ import type { MetricExampleModel } from '@/schema/inventory/metric-example/model import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useDisplayStore } from '@/store/display/display-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CloudServiceTypeReferenceMap } from '@/store/reference/cloud-service-type-reference-store'; import type { CostDataSourceReferenceMap } from '@/store/reference/cost-data-source-reference-store'; @@ -34,6 +33,7 @@ import { convertWorkspaceConfigToReferenceData, convertServiceConfigToReferenceData, } from '@/lib/helper/config-data-helper'; +import { useAllMenuList } from '@/lib/menu/use-all-menu-list'; import { useGlobalDashboardQuery } from '@/common/composables/global-dashboard/use-global-dashboard-query'; import { useFavoriteStore } from '@/common/modules/favorites/favorite-button/store/favorite-store'; @@ -57,6 +57,7 @@ const props = withDefaults(defineProps(), { }); const route = useRoute(); +const router = useRouter(); const allReferenceStore = useAllReferenceStore(); const userWorkspaceStore = useUserWorkspaceStore(); @@ -66,7 +67,8 @@ const favoriteStore = useFavoriteStore(); const favoriteStoreGetters = favoriteStore.getters; const gnbStore = useGnbStore(); const gnbStoreGetters = gnbStore.getters; -const displayStore = useDisplayStore(); +const { getAllMenuList } = useAllMenuList(); + /* Query */ const { @@ -152,7 +154,7 @@ const convertFavoriteToReferenceData = (favoriteConfig: FavoriteConfig): Referen if (itemType === FAVORITE_TYPE.SERVICE) { return convertServiceConfigToReferenceData([favoriteConfig], storeState.service)[0]; } - const allMenuList = displayStore.getAllMenuList(route); + const allMenuList = getAllMenuList(route, router); return convertMenuConfigToReferenceData([favoriteConfig], allMenuList)[0]; }; diff --git a/apps/web/src/common/modules/favorites/favorite-button/store/favorite-store.ts b/apps/web/src/common/modules/favorites/favorite-button/store/favorite-store.ts index d41b32a4a0..daa94a742d 100644 --- a/apps/web/src/common/modules/favorites/favorite-button/store/favorite-store.ts +++ b/apps/web/src/common/modules/favorites/favorite-button/store/favorite-store.ts @@ -1,5 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck import { computed, reactive, watch } from 'vue'; import { defineStore } from 'pinia'; @@ -62,6 +60,10 @@ export const useFavoriteStore = defineStore('favorite', () => { const actions = { fetchFavorite: async () => { + if (!_getters.userId) { + console.error('userId is not found'); + return; + } favoriteListApiQuery.setFilters([ { k: 'user_id', v: _getters.userId, o: '=' }, { k: 'name', v: 'console:favorite:', o: '' }, @@ -79,6 +81,10 @@ export const useFavoriteStore = defineStore('favorite', () => { } }, fetchWorkspaceFavorite: async () => { + if (!_getters.userId) { + console.error('userId is not found'); + return; + } favoriteListApiQuery.setFilters([ { k: 'user_id', v: _getters.userId, o: '=' }, { k: 'name', v: `console:favorite:${FAVORITE_TYPE.WORKSPACE}`, o: '' }, diff --git a/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue b/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue index f4593f0749..16e010e23b 100644 --- a/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue +++ b/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue @@ -14,13 +14,13 @@ import type { ContextMenuType } from '@cloudforet/mirinae/types/controls/context import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useDisplayStore } from '@/store/display/display-store'; -import type { DisplayMenu } from '@/store/display/type'; +import type { DisplayMenu } from '@/store/menu/type'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CostDataSourceReferenceMap } from '@/store/reference/cost-data-source-reference-store'; import type { MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; +import { useAllMenuList } from '@/lib/menu/use-all-menu-list'; import BetaMark from '@/common/components/marks/BetaMark.vue'; import NewMark from '@/common/components/marks/NewMark.vue'; @@ -44,7 +44,7 @@ const gnbStore = useGnbStore(); const gnbGetters = gnbStore.getters; const userWorkspaceStore = useUserWorkspaceStore(); const userWorkspaceGetters = userWorkspaceStore.getters; -const displayStore = useDisplayStore(); +const { getAllMenuList } = useAllMenuList(); const route = useRoute(); const router = useRouter(); @@ -69,7 +69,7 @@ const state = reactive({ isMenuDescription: undefined as boolean | undefined, gnbMenuList: computed(() => { let results = [] as GNBMenuType[]; - const allMenuList = displayStore.getAllMenuList(route); + const allMenuList = getAllMenuList(route, router); const menuList = allMenuList.filter((d) => !d.hideOnGNB); if (state.isInit && isEmpty(storeState.costDataSource)) { results = removeCostExplorerFromMenuList(menuList); diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/TopBarSearchDropdown.vue b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/TopBarSearchDropdown.vue index d6f8b76d00..b2662c3d76 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/TopBarSearchDropdown.vue +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/TopBarSearchDropdown.vue @@ -13,10 +13,9 @@ import type { ValueItem } from '@cloudforet/mirinae/types/controls/search/query- import { useReferenceRouter } from '@/router/composables/use-reference-router'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; -import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { MENU_ID } from '@/lib/menu/config'; import { useRecentStore } from '@/common/modules/navigations/stores/recent-store'; @@ -54,8 +53,8 @@ const BOTTOM_MARGIN = 5.5 * 16; const topBarSearchStore = useTopBarSearchStore(); const recentStore = useRecentStore(); -const userStore = useUserStore(); const windowSize = useWindowSize(); +const authorizationStore = useAuthorizationStore(); const { getReferenceLocation } = useReferenceRouter(); @@ -73,7 +72,6 @@ const getTabHeaderHeight = () => { const storeState = reactive({ activeTab: computed(() => topBarSearchStore.state.activeTab), cloudServiceTypeMap: computed(() => allReferenceStore.getters.cloudServiceType), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const state = reactive({ @@ -86,7 +84,7 @@ const state = reactive({ tabs: computed(() => { const accessMenuList: ValueItem[] = []; state.defaultServiceTabs.forEach((i) => { - if (storeState.pageAccessPermissionMap[i.id]) { + if (authorizationStore.getters.pageAccessPermissionMap[i.id]) { accessMenuList.push({ label: i.label, name: i.name }); } }); diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/modules/TopBarSearchServiceTab.vue b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/modules/TopBarSearchServiceTab.vue index 4ec074ee72..8ae2bc60ae 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/modules/TopBarSearchServiceTab.vue +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/modules/top-bar-search-dropdown/modules/TopBarSearchServiceTab.vue @@ -12,15 +12,15 @@ import { getTextHighlightRegex, PDataLoader, PDivider } from '@cloudforet/mirina import { i18n } from '@/translations'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useDisplayStore } from '@/store/display/display-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; + -import type { PageAccessMap } from '@/lib/access-control/config'; import type { SuggestionMenu } from '@/lib/helper/menu-suggestion-helper'; import { getAllSuggestionMenuList } from '@/lib/helper/menu-suggestion-helper'; import type { MenuInfo } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; +import { useAllMenuList } from '@/lib/menu/use-all-menu-list'; import { useProxyValue } from '@/common/composables/proxy-state'; import { useRecentStore } from '@/common/modules/navigations/stores/recent-store'; @@ -49,8 +49,8 @@ const props = withDefaults(defineProps(), { const userWorkspaceStore = useUserWorkspaceStore(); const topBarSearchStore = useTopBarSearchStore(); const recentStore = useRecentStore(); -const userStore = useUserStore(); -const displayStore = useDisplayStore(); +const authorizationStore = useAuthorizationStore(); +const { getAllMenuList } = useAllMenuList(); const route = useRoute(); const router = useRouter(); @@ -66,12 +66,11 @@ const storeState = reactive({ currentWorkspaceId: computed(() => userWorkspaceStore.getters.currentWorkspaceId), inputText: computed(() => topBarSearchStore.getters.inputText), trimmedInputText: computed(() => topBarSearchStore.getters.trimmedInputText), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const state = reactive({ allMenuList: computed(() => { - const allMenuList = displayStore.getAllMenuList(route); + const allMenuList = getAllMenuList(route, router); return getAllSuggestionMenuList(allMenuList); }), allMenuMap: computed(() => { @@ -99,7 +98,7 @@ const state = reactive({ recentMenuList: computed(() => { const _recentMenuList: RecentItem[] = []; recentStore.state.recentMenuList.forEach((i) => { - if (storeState.pageAccessPermissionMap[i.data.id]) { + if (authorizationStore.getters.pageAccessPermissionMap[i.data.id]) { _recentMenuList.push(i); } }); diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/TopBarToolset.vue b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/TopBarToolset.vue index 2f471bf2ec..b6ca3f9cde 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/TopBarToolset.vue +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/TopBarToolset.vue @@ -7,9 +7,10 @@ import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useDomainStore } from '@/store/domain/domain-store'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; import { useUserStore } from '@/store/user/user-store'; +import { useGlobalConfigUiAffectsSchema } from '@/lib/config/global-config/composables/use-global-config-ui-affects-schema'; + import TopBarAdminToggleButton from '@/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-admin-toggle-button/TopBarAdminToggleButton.vue'; import TopBarFavorite from '@/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-favorite/TopBarFavorite.vue'; @@ -32,13 +33,13 @@ const emit = defineEmits<{(event: 'hide-menu'): void; const appContextStore = useAppContextStore(); const domainStore = useDomainStore(); const userStore = useUserStore(); -const globalConfigSchemaStore = useGlobalConfigSchemaStore(); +const alertManagerUiAffectsSchema = useGlobalConfigUiAffectsSchema('ALERT_MANAGER'); const state = reactive({ isDomainAdmin: computed(() => userStore.getters.isDomainAdmin), isAdminMode: computed(() => appContextStore.getters.isAdminMode), isGrantLoading: computed(() => appContextStore.getters.globalGrantLoading), - visibleAlertIcon: computed(() => globalConfigSchemaStore.state.uiAffectsSchema.ALERT_MANAGER?.visibleAlertIcon), + visibleAlertIcon: computed(() => alertManagerUiAffectsSchema.value?.visibleAlertIcon), tooltipTexts: computed>(() => ({ adminToggle: (state.isAdminMode ? i18n.t('COMMON.GNB.TOOLTIP.EXIT_ADMIN_MODE') : i18n.t('COMMON.GNB.TOOLTIP.ENABLE_ADMIN_MODE')) as string, })), diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-favorite/modules/TopBarFavoriteContextMenu.vue b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-favorite/modules/TopBarFavoriteContextMenu.vue index 43b2cdb851..a3a90c3d17 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-favorite/modules/TopBarFavoriteContextMenu.vue +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-favorite/modules/TopBarFavoriteContextMenu.vue @@ -19,17 +19,14 @@ import { i18n } from '@/translations'; import { useReferenceRouter } from '@/router/composables/use-reference-router'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useDisplayStore } from '@/store/display/display-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CostDataSourceReferenceMap } from '@/store/reference/cost-data-source-reference-store'; import type { MetricReferenceMap } from '@/store/reference/metric-reference-store'; import type { ProjectGroupReferenceMap } from '@/store/reference/project-group-reference-store'; import type { ProjectReferenceMap } from '@/store/reference/project-reference-store'; import type { ServiceReferenceMap } from '@/store/reference/service-reference-store'; -import { useUserStore } from '@/store/user/user-store'; -import { isUserAccessibleToMenu } from '@/lib/access-control'; -import type { PageAccessMap } from '@/lib/access-control/config'; import type { ReferenceData } from '@/lib/helper/config-data-helper'; import { convertCostAnalysisConfigToReferenceData, @@ -39,9 +36,10 @@ import { convertProjectGroupConfigToReferenceData, convertServiceConfigToReferenceData, getParsedKeysWithManagedCostQueryFavoriteKey, } from '@/lib/helper/config-data-helper'; -import type { MenuInfo } from '@/lib/menu/config'; +import type { MenuId, MenuInfo } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; +import { useAllMenuList } from '@/lib/menu/use-all-menu-list'; import { useGlobalDashboardQuery } from '@/common/composables/global-dashboard/use-global-dashboard-query'; import { useGrantScopeGuard } from '@/common/composables/grant-scope-guard'; @@ -78,9 +76,8 @@ const favoriteStore = useFavoriteStore(); const favoriteGetters = favoriteStore.getters; const gnbStore = useGnbStore(); const gnbStoreGetters = gnbStore.getters; -const userStore = useUserStore(); -const displayStore = useDisplayStore(); - +const authorizationStore = useAuthorizationStore(); +const { getAllMenuList } = useAllMenuList(); const { getReferenceLocation } = useReferenceRouter(); /* Query */ @@ -102,13 +99,13 @@ const storeState = reactive({ projectGroups: computed(() => allReferenceStore.getters.projectGroup), service: computed(() => allReferenceStore.getters.service), costQuerySets: computed(() => gnbStoreGetters.costQuerySets), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), + pageAccessPermissionList: computed(() => authorizationStore.getters.pageAccessPermissionList), }); const state = reactive({ loading: true, showAll: false, showAllType: undefined as undefined|FavoriteType, - accessProject: computed(() => !isEmpty(storeState.pageAccessPermissionMap[MENU_ID.PROJECT])), + accessProject: computed(() => !isEmpty(authorizationStore.getters.pageAccessPermissionMap[MENU_ID.PROJECT])), items: computed(() => { const results: FavoriteMenuItem[] = []; if (state.favoriteMenuItems.length) { @@ -186,14 +183,14 @@ const state = reactive({ }), // favoriteMenuItems: computed(() => { - const allMenuList = displayStore.getAllMenuList(route); + const allMenuList = getAllMenuList(route, router); return convertMenuConfigToReferenceData( favoriteGetters.menuItems ?? [], allMenuList, ); }), favoriteCostAnalysisItems: computed(() => { - const isUserAccessible = isUserAccessibleToMenu(MENU_ID.COST_ANALYSIS, userStore.getters.pageAccessPermissionList); + const isUserAccessible = isUserAccessibleToMenu(MENU_ID.COST_ANALYSIS, storeState.pageAccessPermissionList); return isUserAccessible ? convertCostAnalysisConfigToReferenceData( favoriteGetters.costAnalysisItems ?? [], @@ -203,7 +200,7 @@ const state = reactive({ : []; }), favoriteDashboardItems: computed(() => { - const isUserAccessibleToDashboards = isUserAccessibleToMenu(MENU_ID.DASHBOARDS, userStore.getters.pageAccessPermissionList); + const isUserAccessibleToDashboards = isUserAccessibleToMenu(MENU_ID.DASHBOARDS, storeState.pageAccessPermissionList); if (!isUserAccessibleToDashboards) return []; return convertDashboardConfigToReferenceData( favoriteGetters.dashboardItems ?? [], @@ -211,7 +208,7 @@ const state = reactive({ ); }), favoriteMetricItems: computed(() => { - const isUserAccessible = isUserAccessibleToMenu(MENU_ID.METRIC_EXPLORER, userStore.getters.pageAccessPermissionList); + const isUserAccessible = isUserAccessibleToMenu(MENU_ID.METRIC_EXPLORER, storeState.pageAccessPermissionList); if (!isUserAccessible) return []; const favoriteMetricItems = convertMetricConfigToReferenceData(favoriteGetters.metricItems ?? [], storeState.metrics); const favoriteMetricExampleItems = convertMetricExampleConfigToReferenceData(favoriteGetters.metricExampleItems ?? [], storeState.metricExamples); @@ -221,14 +218,14 @@ const state = reactive({ ]; }), favoriteProjects: computed(() => { - const isUserAccessible = isUserAccessibleToMenu(MENU_ID.PROJECT, userStore.getters.pageAccessPermissionList); + const isUserAccessible = isUserAccessibleToMenu(MENU_ID.PROJECT, storeState.pageAccessPermissionList); if (!isUserAccessible) return []; const favoriteProjectItems = convertProjectConfigToReferenceData(favoriteGetters.projectItems ?? [], storeState.projects); const favoriteProjectGroupItems = convertProjectGroupConfigToReferenceData(favoriteGetters.projectGroupItems ?? [], storeState.projectGroups); return [...favoriteProjectGroupItems, ...favoriteProjectItems]; }), favoriteServiceItems: computed(() => { - const isUserAccessible = isUserAccessibleToMenu(MENU_ID.SERVICE, userStore.getters.pageAccessPermissionList); + const isUserAccessible = isUserAccessibleToMenu(MENU_ID.SERVICE, storeState.pageAccessPermissionList); return isUserAccessible ? convertServiceConfigToReferenceData(favoriteGetters.serviceItems ?? [], storeState.service) : []; }), }); @@ -242,6 +239,8 @@ const getItemLength = (type: FavoriteType): number => { if (type === FAVORITE_TYPE.COST_ANALYSIS) return state.favoriteCostAnalysisItems.length; return 0; }; +const isUserAccessibleToMenu = (menuId: MenuId, pageAccessList: MenuId[]): boolean => pageAccessList.some((id) => id === menuId); + /* Event */ const handleClickMenuButton = (type: FavoriteType) => { diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/TopBarNotice.vue b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/TopBarNotice.vue index 0da0b9f797..b381407e77 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/TopBarNotice.vue +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/TopBarNotice.vue @@ -8,7 +8,7 @@ import { PI, PTooltip, } from '@cloudforet/mirinae'; -import { useNoticeStore } from '@/store/notice'; +import { useNoticeStore } from '@/store/notice/notice-store'; import { useUserStore } from '@/store/user/user-store'; import { useGrantScopeGuard } from '@/common/composables/grant-scope-guard'; diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/modules/TopBarNoticeContextMenu.vue b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/modules/TopBarNoticeContextMenu.vue index 49fe0e1185..7a343b675b 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/modules/TopBarNoticeContextMenu.vue +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-notice/modules/TopBarNoticeContextMenu.vue @@ -17,7 +17,7 @@ import { POST_BOARD_TYPE } from '@/schema/board/post/constant'; import type { PostModel } from '@/schema/board/post/model'; import { i18n } from '@/translations'; -import { useNoticeStore } from '@/store/notice'; +import { useNoticeStore } from '@/store/notice/notice-store'; import ErrorHandler from '@/common/composables/error/errorHandler'; import { useGrantScopeGuard } from '@/common/composables/grant-scope-guard'; diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-profile/TopBarProfile.vue b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-profile/TopBarProfile.vue index c6de3c4c1b..cb60b9da4b 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-profile/TopBarProfile.vue +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-toolset/modules/top-bar-profile/TopBarProfile.vue @@ -23,6 +23,7 @@ import WorkspaceOwnerImage from '@/assets/images/role/img_avatar_workspace-owner import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useDomainStore } from '@/store/domain/domain-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { RoleReferenceMap } from '@/store/reference/role-reference-store'; @@ -38,7 +39,6 @@ import { AUTH_ROUTE } from '@/services/auth/routes/route-constant'; import { LANDING_ROUTE } from '@/services/landing/routes/route-constant'; import { MY_PAGE_ROUTE } from '@/services/my-page/routes/route-constant'; - interface Props { visible: boolean } @@ -49,6 +49,7 @@ const props = withDefaults(defineProps(), { const appContextStore = useAppContextStore(); const domainStore = useDomainStore(); const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const emit = defineEmits<{(e: 'update:visible', visible: boolean): void; }>(); @@ -69,7 +70,7 @@ const state = reactive({ return UserImage; }), baseRoleType: computed(() => userStore.state.roleType), - currentRoleType: computed(() => userStore.state.currentRoleInfo?.roleType), + currentRoleType: computed(() => authorizationStore.state.currentRoleInfo?.roleType), visibleRoleType: computed(() => { if (state.baseRoleType === ROLE_TYPE.DOMAIN_ADMIN) return 'Admin'; if (state.currentRoleType === ROLE_TYPE.WORKSPACE_OWNER) return 'Workspace Owner'; diff --git a/apps/web/src/common/modules/popup/notice/NoticePopup.vue b/apps/web/src/common/modules/popup/notice/NoticePopup.vue index 97e8efef27..e3a537bbb6 100644 --- a/apps/web/src/common/modules/popup/notice/NoticePopup.vue +++ b/apps/web/src/common/modules/popup/notice/NoticePopup.vue @@ -15,6 +15,7 @@ import type { PostModel } from '@/schema/board/post/model'; import type { NoticeConfigData } from '@/schema/board/post/type'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useUserStore } from '@/store/user/user-store'; import ErrorHandler from '@/common/composables/error/errorHandler'; @@ -22,9 +23,10 @@ import NoticePopupItem from '@/common/modules/popup/notice/modules/NoticePopupIt const appContextStore = useAppContextStore(); const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const state = reactive({ isSessionExpired: computed(() => !!userStore.state.isSessionExpired), - isNoRoleUser: computed(() => userStore.getters.isNoRoleUser), + isNoRoleUser: computed(() => authorizationStore.getters.isNoRoleUser), popupList: [] as PostModel[], hasLoaded: false, }); @@ -79,7 +81,7 @@ watch([ () => state.isSessionExpired, () => state.isNoRoleUser, () => appContextStore.getters.globalGrantLoading, - () => userStore.state.currentGrantInfo, + () => authorizationStore.state.currentGrantInfo, ], async ([hasLoaded, isSessionExpired, isNoRoleUser, globalGrantLoading, grantInfo]) => { if (hasLoaded) return; if (isNoRoleUser || isSessionExpired) { diff --git a/apps/web/src/common/modules/popup/notice/modules/NoticePopupItem.vue b/apps/web/src/common/modules/popup/notice/modules/NoticePopupItem.vue index 838833dda4..13e4a0056b 100644 --- a/apps/web/src/common/modules/popup/notice/modules/NoticePopupItem.vue +++ b/apps/web/src/common/modules/popup/notice/modules/NoticePopupItem.vue @@ -8,7 +8,7 @@ import { iso8601Formatter } from '@cloudforet/utils'; import type { PostModel } from '@/schema/board/post/model'; -import { useNoticeStore } from '@/store/notice'; +import { useNoticeStore } from '@/store/notice/notice-store'; import { useUserStore } from '@/store/user/user-store'; import { isMobile } from '@/lib/helper/cross-browsing-helper'; diff --git a/apps/web/src/common/modules/widgets/_widget-field-value-manager/constant/validator-registry.ts b/apps/web/src/common/modules/widgets/_widget-field-value-manager/constant/validator-registry.ts index e335d1d35f..620ea444b6 100644 --- a/apps/web/src/common/modules/widgets/_widget-field-value-manager/constant/validator-registry.ts +++ b/apps/web/src/common/modules/widgets/_widget-field-value-manager/constant/validator-registry.ts @@ -1,5 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck import { every } from 'lodash'; import { DATA_TABLE_OPERATOR } from '@/common/modules/widgets/_constants/data-table-constant'; @@ -101,7 +99,7 @@ export const widgetValidatorRegistry: WidgetValidatorRegistry = { const dependentValue: string|string[]|undefined = allValueMap?.[formatRulesOptions.dependentField]?.value?.data; if (!dependentValue) return !!fieldValue.field; if (Array.isArray(dependentValue)) { - return !dependentValue.includes(fieldValue.field); + return typeof fieldValue.field === 'string' && !dependentValue.includes(fieldValue.field); } return dependentValue !== fieldValue.field; } diff --git a/apps/web/src/lib/access-control/index.ts b/apps/web/src/lib/access-control/index.ts deleted file mode 100644 index b6d004d43a..0000000000 --- a/apps/web/src/lib/access-control/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Route } from 'vue-router'; - -import { clone } from 'lodash'; - -import type { MenuId } from '@/lib/menu/config'; - -export const calculateIsAccessibleRoute = (route: Route, pagePermissions: MenuId[]): boolean => { - const closetMenuRoute = clone(route?.matched)?.reverse().find((match) => !!match.meta.menuId); - const menuId = closetMenuRoute?.meta.menuId; - return pagePermissions.some((id) => id === menuId); -}; - -export const isUserAccessibleToMenu = (menuId: MenuId, pageAccessList: MenuId[]): boolean => pageAccessList.some((id) => id === menuId); diff --git a/apps/web/src/lib/access-control/redirect-route-helper.ts b/apps/web/src/lib/access-control/redirect-route-helper.ts index 4bb1998124..06d71777eb 100644 --- a/apps/web/src/lib/access-control/redirect-route-helper.ts +++ b/apps/web/src/lib/access-control/redirect-route-helper.ts @@ -3,28 +3,30 @@ import type { Location } from 'vue-router/types/router'; import { ERROR_ROUTE } from '@/router/constant'; -import { useGlobalConfigSchemaStore, type FlattenedMenuMap } from '@/store/global-config-schema/global-config-schema-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; +import type { FlattenedMenuMap } from '@/store/menu/menu-store'; +import { useMenuStore } from '@/store/menu/menu-store'; import { pinia } from '@/store/pinia'; -import type { PageAccessMap } from '@/lib/access-control/config'; import type { MenuId } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; -const getSubMenuListByMenuId = (menuId: MenuId, flattenedMenu: FlattenedMenuMap): MenuId[] => { +const _getSubMenuListByMenuId = (menuId: MenuId, flattenedMenu: FlattenedMenuMap): MenuId[] => { if (flattenedMenu[menuId]) return flattenedMenu[menuId] || []; return []; }; -export const getRedirectRouteByPagePermission = (route: Route, pagePermissionsMap: PageAccessMap): Location => { +export const getRedirectRouteByPagePermission = (route: Route): Location => { const menuId = route.meta?.menuId; if (!menuId) return { name: ERROR_ROUTE._NAME, params: { statusCode: '404' } }; - const globalConfigSchemaStore = useGlobalConfigSchemaStore(pinia); - const generateFlattenedMenuMap = globalConfigSchemaStore.getters.generateFlattenedMenuMap; - const subMenuIdList = getSubMenuListByMenuId(menuId, generateFlattenedMenuMap); + const menuStore = useMenuStore(pinia); + const authorizationStore = useAuthorizationStore(pinia); + + const subMenuIdList = _getSubMenuListByMenuId(menuId, menuStore.getters.generateFlattenedMenuMap); let redirectMenuId: MenuId|undefined; subMenuIdList.some((subMenuId) => { - if (pagePermissionsMap[subMenuId]) { + if (authorizationStore.getters.pageAccessPermissionMap[subMenuId]) { redirectMenuId = subMenuId; return true; } diff --git a/apps/web/src/lib/config/global-config/api-client-manager.ts b/apps/web/src/lib/config/global-config/api-client-manager.ts new file mode 100644 index 0000000000..99c7ad8fb8 --- /dev/null +++ b/apps/web/src/lib/config/global-config/api-client-manager.ts @@ -0,0 +1,107 @@ +import camelCase from 'lodash/camelCase'; +import kebabCase from 'lodash/kebabCase'; + +import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; + +import { ApiClientEndpoint } from '@/lib/config/global-config/schema/api-client-schema'; +import type { ApiClientsSchemaType, GlobalServiceConfig } from '@/lib/config/global-config/types/type'; + +interface ServiceEndpoint { + endpoint: any; + version: string; +} + +class APIClientManagerError extends Error { + constructor(message: string) { + super(`[APIClientManager] ${message}`); + this.name = 'APIClientManagerError'; + } +} + +class APIClientManager { + // eslint-disable-next-line no-undef + [key: string]: any; + + private config: GlobalServiceConfig | null = null; + + private apiClientsSchema: ApiClientsSchemaType | null = null; + + private serviceEndpoints: Map = new Map(); + + async initialize(mergedConfig: GlobalServiceConfig): Promise { + this.config = mergedConfig; + this.apiClientsSchema = JSON.parse(JSON.stringify(ApiClientEndpoint)); + await this.initializeServiceConfig(); + this.defineDynamicServices(); + } + + private async initializeServiceConfig(): Promise { + if (!this.config || !this.apiClientsSchema) { + throw new APIClientManagerError('Configuration or schema is not initialized'); + } + + const serviceConfig: Record = {}; + + Object.entries(this.config).forEach(([serviceName, config]) => { + if (this.apiClientsSchema?.[serviceName]) { + const version = config.VERSION; + const endpoint = this.apiClientsSchema[serviceName][version]; + if (endpoint) { + const formattedEndpoint = APIClientManager.formatEndpoint(endpoint); + serviceConfig[formattedEndpoint] = { + enabled: config.ENABLED, + }; + } + } + }); + + SpaceConnector.setServiceConfig(serviceConfig); + } + + private static formatEndpoint(endpoint: string): string { + return kebabCase(endpoint); + } + + private defineDynamicServices(): void { + if (!this.apiClientsSchema) { + throw new APIClientManagerError('APIClientManager is not initialized'); + } + + Object.keys(this.apiClientsSchema).forEach((serviceName) => { + const propertyName = APIClientManager.formatPropertyName(serviceName); + Object.defineProperty(this, propertyName, { + get: () => this.getServiceEndpoint(serviceName), + enumerable: true, + configurable: true, + }); + }); + } + + private static formatPropertyName(serviceName: string): string { + return camelCase(serviceName); + } + + private getServiceEndpoint(serviceName: string): ServiceEndpoint | null { + if (this.serviceEndpoints.has(serviceName)) { + return this.serviceEndpoints.get(serviceName) ?? null; + } + + const serviceConfig = this.config?.[serviceName]; + if (!serviceConfig?.ENABLED) return null; + + const apiClientSchemaByService = this.apiClientsSchema?.[serviceName]; + if (!apiClientSchemaByService) return null; + + const version = serviceConfig.VERSION; + const clientEndpoint = apiClientSchemaByService[version]; + if (!clientEndpoint) return null; + + const endpoint = SpaceConnector.clientV2[clientEndpoint]; + const serviceEndpoint: ServiceEndpoint = { endpoint, version }; + + this.serviceEndpoints.set(serviceName, serviceEndpoint); + return serviceEndpoint; + } +} + +export default new APIClientManager(); diff --git a/apps/web/src/lib/config/global-config/composables/use-global-config-ui-affects-schema.ts b/apps/web/src/lib/config/global-config/composables/use-global-config-ui-affects-schema.ts new file mode 100644 index 0000000000..331900bcb4 --- /dev/null +++ b/apps/web/src/lib/config/global-config/composables/use-global-config-ui-affects-schema.ts @@ -0,0 +1,17 @@ +import { computed } from 'vue'; + +import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; + +import type { FeatureKeyType } from '@/lib/config/global-config/types/type'; + +import { SERVICE_FEATURES } from '../constants/constants'; + +export const useGlobalConfigUiAffectsSchema = (featureKey: FeatureKeyType) => { + if (!Object.values(SERVICE_FEATURES).includes(featureKey)) { + throw new Error(`Invalid feature key: ${featureKey}`); + } + + const globalConfigSchemaStore = useGlobalConfigSchemaStore(); + + return computed(() => globalConfigSchemaStore.state.uiAffectsSchema[featureKey]); +}; diff --git a/apps/web/src/lib/config/global-config/constants/constants.ts b/apps/web/src/lib/config/global-config/constants/constants.ts index c10e39b046..914f28347f 100644 --- a/apps/web/src/lib/config/global-config/constants/constants.ts +++ b/apps/web/src/lib/config/global-config/constants/constants.ts @@ -1,4 +1,4 @@ -export const FEATURES = { +export const SERVICE_FEATURES = { DASHBOARDS: 'DASHBOARDS', PROJECT: 'PROJECT', SERVICE_ACCOUNT: 'SERVICE_ACCOUNT', diff --git a/apps/web/src/lib/config/global-config/dynamic-schema-manager.ts b/apps/web/src/lib/config/global-config/dynamic-schema-manager.ts new file mode 100644 index 0000000000..7d81451971 --- /dev/null +++ b/apps/web/src/lib/config/global-config/dynamic-schema-manager.ts @@ -0,0 +1,78 @@ +import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; +import { pinia } from '@/store/pinia'; + +import type { + GeneratedMenuSchema, + GeneratedRouteSchema, + GeneratedRouteMetadataSchema, + GeneratedUiAffectSchema, +} from '@/lib/config/global-config/types/type'; + +type DynamicMenuHandler = (menuSchema: GeneratedMenuSchema) => Promise; + +export class DynamicSchemaManager { + private static instance: DynamicSchemaManager; + + private globalConfigSchemaStore = useGlobalConfigSchemaStore(pinia); + + private dynamicMenuHandlers: Map = new Map(); + + // private constructor() { + // this.initializeHandlers(); + // } + + static getInstance(): DynamicSchemaManager { + if (!DynamicSchemaManager.instance) { + DynamicSchemaManager.instance = new DynamicSchemaManager(); + } + return DynamicSchemaManager.instance; + } + + // private initializeHandlers() { + // // Example + // this.registerDynamicMenuHandler('OPS_FLOW', async (menuSchema: GeneratedMenuSchema) => { + // const updatedMenu = { ...menuSchema }; + // if (!isEmpty(menuSchema?.OPS_FLOW)) {} + // return updatedMenu; + // }); + + // watch(() => this.taskManagementTemplateStore.state, () => { + // const currentMenuSchema = this.globalConfigSchemaStore.state.menuSchema; + // if (!isEmpty(currentMenuSchema?.OPS_FLOW)) { + // this.updateMenuSchema(currentMenuSchema); + // } + // }, { deep: true }); + // } + + registerDynamicMenuHandler(serviceName: string, handler: DynamicMenuHandler) { + this.dynamicMenuHandlers.set(serviceName, handler); + } + + private async updateMenuSchema(menuSchema: GeneratedMenuSchema) { + const updatedMenuSchema = await this.applyDynamicMenu(menuSchema); + this.globalConfigSchemaStore.setMenuSchema(updatedMenuSchema); + } + + private async applyDynamicMenu(menuSchema: GeneratedMenuSchema): Promise { + return Array.from(this.dynamicMenuHandlers.values()).reduce( + async (acc, handler) => handler(await acc), + Promise.resolve(menuSchema), + ); + } + + async updateSchema( + menuSchema: GeneratedMenuSchema, + routeSchema: GeneratedRouteSchema, + routeMetadataSchema: GeneratedRouteMetadataSchema, + uiAffectSchema: GeneratedUiAffectSchema, + ) { + const dynamicMenuSchema = await this.applyDynamicMenu(menuSchema); + + this.globalConfigSchemaStore.setMenuSchema(dynamicMenuSchema); + this.globalConfigSchemaStore.setRouteSchema(routeSchema); + this.globalConfigSchemaStore.setRouteMetadataSchema(routeMetadataSchema); + this.globalConfigSchemaStore.setUiAffectsSchema(uiAffectSchema); + } +} + +export default DynamicSchemaManager.getInstance(); diff --git a/apps/web/src/lib/config/global-config/feature-schema-manager.ts b/apps/web/src/lib/config/global-config/feature-schema-manager.ts index a98d2c889f..46be67762b 100644 --- a/apps/web/src/lib/config/global-config/feature-schema-manager.ts +++ b/apps/web/src/lib/config/global-config/feature-schema-manager.ts @@ -1,6 +1,4 @@ -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; -import { pinia } from '@/store/pinia'; - +import dynamicSchemaManager from '@/lib/config/global-config/dynamic-schema-manager'; import { getFeatureConfigurator } from '@/lib/config/global-config/helpers/get-feature-configurator'; import type { FeatureConfigurator, @@ -22,17 +20,23 @@ export class FeatureSchemaManager { }, }; - initialize(config: GlobalServiceConfig) { - const globalConfigSchemaStore = useGlobalConfigSchemaStore(pinia); + async initialize(config: GlobalServiceConfig) { this.config = { ...this.config, ...config, }; - globalConfigSchemaStore.setMenuSchema(this.createMenuSchema()); - globalConfigSchemaStore.setRouteSchema(this.createRouteSchema()); - globalConfigSchemaStore.setRouteMetadataSchema(this.createRouteMetadata()); - globalConfigSchemaStore.setUiAffectsSchema(this.createUiAffectsSchema()); + const menuSchema = this.createMenuSchema(); + const routeSchema = this.createRouteSchema(); + const routeMetadataSchema = this.createRouteMetadata(); + const uiAffectSchema = this.createUiAffectsSchema(); + + await dynamicSchemaManager.updateSchema( + menuSchema, + routeSchema, + routeMetadataSchema, + uiAffectSchema, + ); } private forEachEnabledFeature(callback: (feature: string, configurator: FeatureConfigurator, currentVersion: FeatureVersion) => T): T[] { diff --git a/apps/web/src/lib/site-initializer/merge-config.ts b/apps/web/src/lib/config/global-config/helpers/merge-config.ts similarity index 100% rename from apps/web/src/lib/site-initializer/merge-config.ts rename to apps/web/src/lib/config/global-config/helpers/merge-config.ts diff --git a/apps/web/src/lib/config/global-config/schema/api-client-schema.ts b/apps/web/src/lib/config/global-config/schema/api-client-schema.ts index 069bd075f5..bb1728c9c0 100644 --- a/apps/web/src/lib/config/global-config/schema/api-client-schema.ts +++ b/apps/web/src/lib/config/global-config/schema/api-client-schema.ts @@ -8,6 +8,9 @@ export const ApiClientEndpoint: ApiClientsSchemaType = { PROJECT: { V1: 'identity', }, + SERVICE_ACCOUNT: { + V1: 'identity', + }, ASSET_INVENTORY: { V1: 'inventory', }, diff --git a/apps/web/src/lib/config/global-config/types/type.ts b/apps/web/src/lib/config/global-config/types/type.ts index ca1eb4a382..fa0ad80510 100644 --- a/apps/web/src/lib/config/global-config/types/type.ts +++ b/apps/web/src/lib/config/global-config/types/type.ts @@ -1,9 +1,9 @@ import type { RouteConfig } from 'vue-router'; -import type { FEATURES } from '@/lib/config/global-config/constants/constants'; +import type { SERVICE_FEATURES } from '@/lib/config/global-config/constants/constants'; import type { Menu } from '@/lib/menu/config'; -export type FeatureKeyType = typeof FEATURES[keyof typeof FEATURES]; +export type FeatureKeyType = typeof SERVICE_FEATURES[keyof typeof SERVICE_FEATURES]; export type FeatureVersion = 'V1' | 'V2'; export type ServiceConfig = { @@ -25,7 +25,7 @@ export interface GeneratedMenuConfig { menu: Menu; adminMenu?: Menu|null; } -export type GeneratedMenuSchema = Record; +export type GeneratedMenuSchema = Record; type UiAffectConfig = { method: string; @@ -35,7 +35,7 @@ export interface GeneratedUiAffectConfig { feature: string; affects: UiAffectConfig[]; } -export type GeneratedUiAffectSchema = Record>; +export type GeneratedUiAffectSchema = Record>; export interface RouteVersionInfo { name: string; @@ -68,6 +68,7 @@ type apiClientType = { export type ApiClientsSchemaType = { DASHBOARDS: apiClientType, PROJECT: apiClientType, + SERVICE_ACCOUNT: apiClientType, ASSET_INVENTORY: apiClientType, COST_ANALYSIS: apiClientType, OPS_FLOW: apiClientType, diff --git a/apps/web/src/lib/helper/menu-suggestion-helper.ts b/apps/web/src/lib/helper/menu-suggestion-helper.ts index 7413566335..3f57bc4cf6 100644 --- a/apps/web/src/lib/helper/menu-suggestion-helper.ts +++ b/apps/web/src/lib/helper/menu-suggestion-helper.ts @@ -1,6 +1,6 @@ import type { TranslateResult } from 'vue-i18n'; -import type { DisplayMenu } from '@/store/display/type'; +import type { DisplayMenu } from '@/store/menu/type'; export interface SuggestionMenu { id: string; diff --git a/apps/web/src/lib/menu/config.ts b/apps/web/src/lib/menu/config.ts index f419e34380..ccb273dd90 100644 --- a/apps/web/src/lib/menu/config.ts +++ b/apps/web/src/lib/menu/config.ts @@ -1,5 +1,7 @@ // Menu Ids' Rule: All menu ids are dot-delimited in depth, up to two depths. -import type { HighlightTagType } from '@/store/display/type'; +import type { TranslateResult } from 'vue-i18n'; + +import type { HighlightTagType } from '@/store/menu/type'; export const MENU_ID = Object.freeze({ @@ -54,6 +56,7 @@ export type MenuId = typeof MENU_ID[keyof typeof MENU_ID]; export interface Menu { id: MenuId; + label?: string|TranslateResult; needPermissionByRole?: boolean; subMenuList?: Menu[]; hideOnGNB?: boolean; diff --git a/apps/web/src/lib/menu/use-all-menu-list.ts b/apps/web/src/lib/menu/use-all-menu-list.ts new file mode 100644 index 0000000000..2cce50d63a --- /dev/null +++ b/apps/web/src/lib/menu/use-all-menu-list.ts @@ -0,0 +1,106 @@ +import { computed } from 'vue'; +import type { RawLocation, Route } from 'vue-router'; +import type VueRouter from 'vue-router'; + +import { i18n } from '@/translations'; + +import { makeAdminRouteName } from '@/router/helpers/route-helper'; + + +import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; +import { useMenuStore } from '@/store/menu/menu-store'; +import type { DisplayMenu } from '@/store/menu/type'; + +import { MENU_ID } from '@/lib/menu/config'; +import type { Menu, MenuId, MenuInfo } from '@/lib/menu/config'; +import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; + + +export const useAllMenuList = () => { + const appContextStore = useAppContextStore(); + const menuStore = useMenuStore(); + const authorizationStore = useAuthorizationStore(); + const userWorkspaceStore = useUserWorkspaceStore(); + + const _isAdminMode = computed(() => appContextStore.getters.isAdminMode); + const _currentWorkspaceId = computed(() => userWorkspaceStore.getters.currentWorkspaceId); + + + const getAllMenuList = (route: Route, router: VueRouter): DisplayMenu[] => { + const isMyPage = route?.path.startsWith('/my-page'); + let _allGnbMenuList: DisplayMenu[]; + + _allGnbMenuList = _getDisplayMenuList(menuStore.getters.menuList, _isAdminMode.value); + _allGnbMenuList = _filterMenuByRoute(_allGnbMenuList, router, _currentWorkspaceId.value); + if (!_isAdminMode.value) { + _allGnbMenuList = _filterMenuByAccessPermission(_allGnbMenuList, authorizationStore.getters.pageAccessPermissionList); + } + + if (!isMyPage) { + _allGnbMenuList.forEach((menu) => { + if (menu.id === MENU_ID.MY_PAGE) { + menu.hideOnGNB = true; + } + }); + } + + return _allGnbMenuList; + }; + + return { + getAllMenuList, + }; +}; + +const _filterMenuByRoute = (menuList: DisplayMenu[], router: VueRouter, targetWorkspaceId?: string): DisplayMenu[] => menuList.reduce((results, _menu) => { + const menu = { ..._menu }; + if (menu.subMenuList) { + menu.subMenuList = _filterMenuByRoute(menu.subMenuList, router, targetWorkspaceId); + if (menu.subMenuList.length) { + results.push(menu); + return results; + } + } + + const to: RawLocation = { + name: menu.to.name, + params: targetWorkspaceId ? { workspaceId: targetWorkspaceId } : {}, + }; + const link = router.resolve(to); + if (link?.href !== '/') results.push(menu); + + return results; +}, [] as DisplayMenu[]); +const _filterMenuByAccessPermission = (menuList: DisplayMenu[], pagePermissionList: MenuId[]): DisplayMenu[] => menuList.reduce((results, _menu) => { + const menu = { ..._menu }; + + if (menu.subMenuList) { + menu.subMenuList = _filterMenuByAccessPermission(menu.subMenuList, pagePermissionList); + } + + if (menu.subMenuList?.length) results.push(menu); + else { + const hasPermission = pagePermissionList.some((menuId) => menuId === menu.id); + if (hasPermission) results.push(menu); + } + + return results; +}, [] as DisplayMenu[]); + +const _getDisplayMenuList = (menuList: Menu[], isAdminMode?: boolean): DisplayMenu[] => menuList.map((d) => { + const menuInfo: MenuInfo = MENU_INFO_MAP[d.id]; + const routeName = isAdminMode ? makeAdminRouteName(MENU_INFO_MAP[d.id].routeName) : MENU_INFO_MAP[d.id].routeName; + const label = d.label || i18n.t(menuInfo.translationId); + + return { + ...d, + id: d.id, + label, + icon: menuInfo.icon, + highlightTag: menuInfo.highlightTag, + to: { name: routeName }, + subMenuList: d.subMenuList ? _getDisplayMenuList(d.subMenuList, isAdminMode) : [], + } as DisplayMenu; +}); diff --git a/apps/web/src/lib/site-initializer/api-client.ts b/apps/web/src/lib/site-initializer/api-connector.ts similarity index 97% rename from apps/web/src/lib/site-initializer/api-client.ts rename to apps/web/src/lib/site-initializer/api-connector.ts index 8f6f503339..cb8e399a4d 100644 --- a/apps/web/src/lib/site-initializer/api-client.ts +++ b/apps/web/src/lib/site-initializer/api-connector.ts @@ -5,6 +5,7 @@ import type { DevConfig, MockConfig, AuthConfig } from '@cloudforet/core-lib/spa import type { TokenGrantParameters } from '@/api-clients/identity/token/schema/api-verbs/grant'; import type { TokenGrantModel } from '@/api-clients/identity/token/schema/model'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useErrorStore } from '@/store/error/error-store'; import { pinia } from '@/store/pinia'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; @@ -390,8 +391,8 @@ const getApiEndpoints = (config) => { return [ENDPOINT_V1, ENDPOINT_V2]; } if (!ENDPOINT_V1) { - throw new Error('ApiClient init failed: There are no endpoint v1.'); - } else throw new Error('ApiClient init failed: There are no endpoint v2.'); + throw new Error('ApiConnector init failed: There are no endpoint v1.'); + } else throw new Error('ApiConnector init failed: There are no endpoint v2.'); }; const getApiSettings = (config) => { const apiV1Timeout = config.get('CONSOLE_API.TIMEOUT'); @@ -414,8 +415,8 @@ const getAuthConfig = (config): AuthConfig => ({ apiKey: config.get('DEV.AUTH.API_KEY'), }); -export const initApiClient = async (config) => { - const userStore = useUserStore(pinia); +export const initApiConnectorAndAuth = async (config) => { + const authorizationStore = useAuthorizationStore(pinia); const endpoints = getApiEndpoints(config); const tokenApi = new TokenAPI(endpoints[1], getSessionTimeoutCallback()); const apiSettings = getApiSettings(config); @@ -424,14 +425,12 @@ export const initApiClient = async (config) => { mockConfig: getMockConfig(config), authConfig: getAuthConfig(config), }; - const serviceConfig = config.get('SERVICES') || {}; await SpaceConnector.init( endpoints, tokenApi, apiSettings, devConfig, getAfterCallApiMap(), - serviceConfig, ); const existingRefreshToken = SpaceConnector.getRefreshToken(); @@ -445,8 +444,8 @@ export const initApiClient = async (config) => { }; const response = await SpaceConnector.clientV2.identity.token.grant(grantRequest); SpaceConnector.setToken(response.access_token); - userStore.setCurrentGrantInfo({ scope: 'USER' }); - userStore.setCurrentRoleInfo(undefined); + authorizationStore.setCurrentGrantInfo({ scope: 'USER' }); + authorizationStore.setCurrentRoleInfo(undefined); } catch (e) { console.error(e); } diff --git a/apps/web/src/lib/site-initializer/index.ts b/apps/web/src/lib/site-initializer/index.ts index f8cfc979e7..e0344085b5 100644 --- a/apps/web/src/lib/site-initializer/index.ts +++ b/apps/web/src/lib/site-initializer/index.ts @@ -2,7 +2,6 @@ import { computed, watch } from 'vue'; import { QueryHelper } from '@cloudforet/core-lib/query'; -import APIClientManager from '@/api-clients/api-client-manager'; import { SpaceRouter } from '@/router'; import { setI18nLocale } from '@/translations'; @@ -10,6 +9,7 @@ import { ERROR_ROUTE, ROOT_ROUTE } from '@/router/constant'; import { errorRoutes } from '@/router/error-routes'; import { integralRoutes } from '@/router/integral-routes'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useDisplayStore } from '@/store/display/display-store'; import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; import { pinia } from '@/store/pinia'; @@ -17,22 +17,27 @@ import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import { useUserStore } from '@/store/user/user-store'; import config from '@/lib/config'; +import APIClientManager from '@/lib/config/global-config/api-client-manager'; import featureSchemaManager from '@/lib/config/global-config/feature-schema-manager'; +import { mergeConfig } from '@/lib/config/global-config/helpers/merge-config'; +import type { GlobalServiceConfig } from '@/lib/config/global-config/types/type'; import { initRequestIdleCallback } from '@/lib/request-idle-callback-polyfill'; import { initAmcharts5 } from '@/lib/site-initializer/amcharts5'; import { initGtag, initGtm } from '@/lib/site-initializer/analysis'; -import { initApiClient } from '@/lib/site-initializer/api-client'; +import { initApiConnectorAndAuth } from '@/lib/site-initializer/api-connector'; import { initDayjs } from '@/lib/site-initializer/dayjs'; import { initDomain } from '@/lib/site-initializer/domain'; import { initDomainSettings } from '@/lib/site-initializer/domain-settings'; import { initEcharts } from '@/lib/site-initializer/echarts'; import { initErrorHandler } from '@/lib/site-initializer/error-handler'; -import { mergeConfig } from '@/lib/site-initializer/merge-config'; import { initModeSetting } from '@/lib/site-initializer/mode-setting'; import { checkSsoAccessToken } from '@/lib/site-initializer/sso'; -import { initUserAndAuth } from '@/lib/site-initializer/user-auth'; +import { initUserAndToken } from '@/lib/site-initializer/user-token'; import { initWorkspace } from '@/lib/site-initializer/workspace'; +import { useTaskManagementTemplateStore } from '@/services/ops-flow/task-management-templates/stores/use-task-management-template-store'; + + const initQueryHelper = () => { const userStore = useUserStore(pinia); QueryHelper.init(computed(() => userStore.state.timezone)); @@ -40,9 +45,9 @@ const initQueryHelper = () => { let isRouterInitialized = false; const initRouter = (domainId?: string) => { - const userStore = useUserStore(pinia); const globalConfigSchemaStore = useGlobalConfigSchemaStore(pinia); const allReferenceStore = useAllReferenceStore(pinia); + const authorizationStore = useAuthorizationStore(pinia); const afterGrantedCallback = () => allReferenceStore.flush(); const adminChildren = integralRoutes[0].children?.find( @@ -63,9 +68,9 @@ const initRouter = (domainId?: string) => { } if (!domainId) { - SpaceRouter.init(errorRoutes, afterGrantedCallback, userStore); + SpaceRouter.init(errorRoutes, afterGrantedCallback, authorizationStore); } else { - SpaceRouter.init(integralRoutes, afterGrantedCallback, userStore); + SpaceRouter.init(integralRoutes, afterGrantedCallback, authorizationStore); } isRouterInitialized = true; }; @@ -75,6 +80,15 @@ const initI18n = () => { setI18nLocale(userStore.state.language || ''); }; +const initOpsFlowTaskManagementTemplate = async (mergedConfig: GlobalServiceConfig) => { + if (!mergedConfig.OPS_FLOW.ENABLED) return; + const taskManagementTemplateStore = useTaskManagementTemplateStore(pinia); + await Promise.allSettled([ + taskManagementTemplateStore.setInitialTemplateId(), + taskManagementTemplateStore.setInitialLandingData(), + ]); +}; + const removeInitializer = () => { const el = document.getElementById('site-loader-wrapper'); if (el?.parentElement) el.parentElement.removeChild(el); @@ -84,15 +98,17 @@ const init = async () => { /* Init SpaceONE Console */ try { await config.init(); - await initApiClient(config); + await initApiConnectorAndAuth(config); const domainId = await initDomain(config); - const userId = await initUserAndAuth(config); + const userId = await initUserAndToken(config); const mergedConfig = await mergeConfig(config, domainId); + await APIClientManager.initialize(mergedConfig); initDomainSettings(); await initModeSetting(); await initWorkspace(userId); + await initOpsFlowTaskManagementTemplate(mergedConfig); await featureSchemaManager.initialize(mergedConfig); - await APIClientManager.initialize(mergedConfig); + initErrorHandler(); initRouter(domainId); // prefetchResources(); initI18n(); @@ -102,7 +118,6 @@ const init = async () => { initGtm(config); initAmcharts5(config); initEcharts(); - initErrorHandler(); initRequestIdleCallback(); const results = await Promise.allSettled([ checkSsoAccessToken(), diff --git a/apps/web/src/lib/site-initializer/initTaskManagementTemplate.ts b/apps/web/src/lib/site-initializer/initTaskManagementTemplate.ts deleted file mode 100644 index 8c69456436..0000000000 --- a/apps/web/src/lib/site-initializer/initTaskManagementTemplate.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { pinia } from '@/store/pinia'; - -import { - useTaskManagementTemplateStore, -} from '@/services/ops-flow/task-management-templates/stores/use-task-management-template-store'; - - -export const initTaskManagementTemplate = async () => { - const taskManagementTemplateStore = useTaskManagementTemplateStore(pinia); - await Promise.allSettled([ - taskManagementTemplateStore.setInitialTemplateId(), - taskManagementTemplateStore.setInitialLandingData(), - ]); -}; diff --git a/apps/web/src/lib/site-initializer/user-auth.ts b/apps/web/src/lib/site-initializer/user-token.ts similarity index 95% rename from apps/web/src/lib/site-initializer/user-auth.ts rename to apps/web/src/lib/site-initializer/user-token.ts index 27f78671a1..9f51728cf5 100644 --- a/apps/web/src/lib/site-initializer/user-auth.ts +++ b/apps/web/src/lib/site-initializer/user-token.ts @@ -7,7 +7,7 @@ import { pinia } from '@/store/pinia'; import { useUserStore } from '@/store/user/user-store'; -export const initUserAndAuth = async (config): Promise => { +export const initUserAndToken = async (config): Promise => { const domainStore = useDomainStore(pinia); const userStore = useUserStore(pinia); let userId = userStore.state.userId; diff --git a/apps/web/src/lib/site-initializer/workspace.ts b/apps/web/src/lib/site-initializer/workspace.ts index f6ea3974bc..3e1d596c06 100644 --- a/apps/web/src/lib/site-initializer/workspace.ts +++ b/apps/web/src/lib/site-initializer/workspace.ts @@ -17,15 +17,6 @@ export const initWorkspace = async (userId?: string): Promise => { /* Set Default Workspace */ const { pathname } = window.location; - // let workspaceId: string | undefined; - // const workspacePath = pathname?.split('/')[1]; - // if (workspacePath === 'admin') { - // workspaceId = undefined; - // } else if (workspacePath) { - // workspaceId = workspacePath; - // } else workspaceId = lastAccessedWorkspaceId; - // userWorkspaceStore.setCurrentWorkspace(workspaceId); - // if (!USER_PAGE_FIRST_PATH_LIST.includes(pathname?.split('/')[1])) { userWorkspaceStore.setCurrentWorkspace(lastAccessedWorkspaceId); diff --git a/apps/web/src/query/composables/use-scoped-query.ts b/apps/web/src/query/composables/use-scoped-query.ts index df7398f27e..2ee342c174 100644 --- a/apps/web/src/query/composables/use-scoped-query.ts +++ b/apps/web/src/query/composables/use-scoped-query.ts @@ -42,7 +42,7 @@ import type { GrantScope } from '@/api-clients/identity/token/schema/type'; import type { QueryKeyArray } from '@/query/query-key/_types/query-key-type'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; type ScopedEnabled = MaybeRef; @@ -65,10 +65,10 @@ export const useScopedQuery = ( - () => userStore.state.currentGrantInfo?.scope, + () => authorizationStore.state.currentGrantInfo?.scope, ); const isAppReady = computed(() => !appContextStore.getters.globalGrantLoading); diff --git a/apps/web/src/router/helpers/route-helper.ts b/apps/web/src/router/helpers/route-helper.ts index 056679765a..fb27627324 100644 --- a/apps/web/src/router/helpers/route-helper.ts +++ b/apps/web/src/router/helpers/route-helper.ts @@ -2,6 +2,7 @@ import type { Route, NavigationGuardNext } from 'vue-router'; import type { JwtPayload } from 'jwt-decode'; import { jwtDecode } from 'jwt-decode'; +import { clone } from 'lodash'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; @@ -12,7 +13,6 @@ import { } from '@/router/constant'; import type { RouteScopeType } from '@/router/types'; -import { calculateIsAccessibleRoute } from '@/lib/access-control'; import type { MenuId } from '@/lib/menu/config'; import { getLastAccessedWorkspaceId, setCurrentAccessedWorkspaceId } from '@/lib/site-initializer/last-accessed-workspace'; @@ -21,6 +21,16 @@ import { LANDING_ROUTE } from '@/services/landing/routes/route-constant'; import { ADMIN_WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/admin/route-constant'; import { WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/route-constant'; + +const _getValidWorkspaceId = (workspaceId: string|undefined, workspaceList: WorkspaceModel[]): string|undefined => workspaceList.find((w) => w.workspace_id === workspaceId)?.workspace_id; + +const _calculateIsAccessibleRoute = (route: Route, pagePermissions: MenuId[]): boolean => { + const closetMenuRoute = clone(route?.matched)?.reverse().find((match) => !!match.meta.menuId); + const menuId = closetMenuRoute?.meta.menuId; + return pagePermissions.some((id) => id === menuId); +}; + + export const makeAdminRouteName = (routeName: string): string => { if (routeName.startsWith('admin.')) return routeName; return `admin.${routeName}`; @@ -50,9 +60,6 @@ export const getDecodedDataFromAccessToken = (): {rol: string, wid: string} => { } }; -export const getValidWorkspaceId = (workspaceId: string|undefined, workspaceList: WorkspaceModel[]): string|undefined => workspaceList.find((w) => w.workspace_id === workspaceId)?.workspace_id; - - // Router BeforeEach Guard - Route-Validation-and-Verification Process export const processTokenVerification = (to: Route, next: NavigationGuardNext, routeScope: RouteScopeType): boolean => { @@ -122,7 +129,7 @@ export const processWorkspaceAccessValidation = async (to: Route, next: Navigati const targetWorkspaceId = to.params.workspaceId; if (!targetWorkspaceId) { let lastAccessedWorkspaceId = await getLastAccessedWorkspaceId(); - if (!getValidWorkspaceId(lastAccessedWorkspaceId, workspaceList)) { + if (!_getValidWorkspaceId(lastAccessedWorkspaceId, workspaceList)) { await setCurrentAccessedWorkspaceId(undefined); lastAccessedWorkspaceId = undefined; } @@ -138,7 +145,7 @@ export const processWorkspaceAccessValidation = async (to: Route, next: Navigati return false; } - if (!getValidWorkspaceId(targetWorkspaceId, workspaceList)) { + if (!_getValidWorkspaceId(targetWorkspaceId, workspaceList)) { next({ name: ERROR_ROUTE._NAME, params: { statusCode: '404' }, }); @@ -155,7 +162,7 @@ export const shouldUpdateScope = (prevRole: string, routeScope: RouteScopeType, return isScopeChanged || isWorkspaceChanged; }; export const verifyPageAccessAndRedirect = (to: Route, next: NavigationGuardNext, workspaceId: string, pageAccessPermissionList: MenuId[]): void => { - const isAccessibleRoute = calculateIsAccessibleRoute(to, pageAccessPermissionList); + const isAccessibleRoute = _calculateIsAccessibleRoute(to, pageAccessPermissionList); if (isAccessibleRoute) { next({ ...to, diff --git a/apps/web/src/router/index.ts b/apps/web/src/router/index.ts index 04b8710ab0..a63525d659 100755 --- a/apps/web/src/router/index.ts +++ b/apps/web/src/router/index.ts @@ -22,9 +22,8 @@ import { import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useErrorStore } from '@/store/error/error-store'; +import type { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { pinia } from '@/store/pinia'; -import type { useUserStore } from '@/store/user/user-store'; import { getRecentConfig } from '@/lib/helper/router-recent-helper'; import type { MenuId } from '@/lib/menu/config'; @@ -36,7 +35,7 @@ const CHUNK_LOAD_REFRESH_STORAGE_KEY = 'SpaceRouter/ChunkLoadFailRefreshed'; const grantAndLoadByCurrentScope = async ( scope: GrantScope, afterGrantedCallback: () => void, - userStore: ReturnType, + authorizationStore: ReturnType, workspaceId?: string, ): Promise<{ failStatus: boolean }> => { const refreshToken = SpaceConnector.getRefreshToken(); @@ -46,20 +45,22 @@ const grantAndLoadByCurrentScope = async ( workspace_id: workspaceId, }; - const errorStore = useErrorStore(pinia); - const isGranted: boolean = await userStore.grantRole(grantRequest); + const isGranted: boolean = await authorizationStore.grantRole(grantRequest); if (isGranted) { afterGrantedCallback(); } - const grantAccessFailStatus = errorStore.state.grantAccessFailStatus; return { - failStatus: !!grantAccessFailStatus, + failStatus: !!authorizationStore.state.grantAccessFailStatus, }; }; export class SpaceRouter { static router: VueRouter; - static init(routes: RouteConfig[], afterGrantedCallback: () => void, userStore: ReturnType) { + static init( + routes: RouteConfig[], + afterGrantedCallback: () => void, + authorizationStore: ReturnType, + ) { if (SpaceRouter.router) throw new Error('Router init failed: Already initiated.'); Vue.use(VueRouter); @@ -116,7 +117,7 @@ export class SpaceRouter { /* Grant Scope Process */ if (routeScope !== ROUTE_SCOPE.EXCLUDE_AUTH && shouldUpdateScope(prevRole, routeScope, prevWorkspaceId, to.params.workspaceId)) { - const { failStatus } = await grantAndLoadByCurrentScope(routeScope, afterGrantedCallback, userStore, to.params.workspaceId); + const { failStatus } = await grantAndLoadByCurrentScope(routeScope, afterGrantedCallback, authorizationStore, to.params.workspaceId); if (failStatus) { // Grant fail await userWorkspaceStore.load(); @@ -125,7 +126,7 @@ export class SpaceRouter { params: { statusCode: '404' }, }); } else if (routeScope === ROUTE_SCOPE.WORKSPACE) { // Grant success - Workspace - verifyPageAccessAndRedirect(to, next, to.params.workspaceId, userStore.getters.pageAccessPermissionList); + verifyPageAccessAndRedirect(to, next, to.params.workspaceId, authorizationStore.getters.pageAccessPermissionList); } else next(); // Grant success - Others (Admin, User) } else { // Grant Process Not Needed appContextStore.setGlobalGrantLoading(false); @@ -140,7 +141,7 @@ export class SpaceRouter { // set target page as GTag page view if (GTag.gtag) GTag.setPageView(to); const isAdminMode = appContextStore.getters.isAdminMode; - const pageAccessPermissionMap = userStore.getters.pageAccessPermissionMap; + const pageAccessPermissionMap = authorizationStore.getters.pageAccessPermissionMap; const routeScope = getRouteScope(to); if (!isAdminMode && routeScope === 'WORKSPACE') { diff --git a/apps/web/src/services/_shared/dashboard/core/composables/_internal/use-dashboard-manageable.ts b/apps/web/src/services/_shared/dashboard/core/composables/_internal/use-dashboard-manageable.ts index 01c058e077..2179f37da9 100644 --- a/apps/web/src/services/_shared/dashboard/core/composables/_internal/use-dashboard-manageable.ts +++ b/apps/web/src/services/_shared/dashboard/core/composables/_internal/use-dashboard-manageable.ts @@ -8,21 +8,20 @@ import type { PublicFolderModel } from '@/api-clients/dashboard/public-folder/sc import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useDashboardSharedContext } from '@/services/_shared/dashboard/core/composables/_internal/use-dashboard-shared-context'; import type { DashboardSharedEntryPoint } from '@/services/_shared/dashboard/core/types/dashboard-shared-type'; - export const useDashboardManageable = () => { - const userStore = useUserStore(); + const authorizationStore = useAuthorizationStore(); const appContextStore = useAppContextStore(); const { entryPoint } = useDashboardSharedContext(); const isAdminMode = computed(() => appContextStore.getters.isAdminMode); const storeState = reactive({ - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), }); const _isManageable = ( diff --git a/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateScopeForm.vue b/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateScopeForm.vue index 3c5e0874f0..ae2785cc07 100644 --- a/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateScopeForm.vue +++ b/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateScopeForm.vue @@ -14,7 +14,7 @@ import type { WorkspaceModel } from '@/api-clients/identity/workspace/schema/mod import { i18n } from '@/translations'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import WorkspaceLogoIcon from '@/common/modules/navigations/top-bar/modules/top-bar-header/WorkspaceLogoIcon.vue'; @@ -34,9 +34,9 @@ const dashboardCreatePageStore = useDashboardCreatePageStore(); const dashboardCreatePageState = dashboardCreatePageStore.state; const userWorkspaceStore = useUserWorkspaceStore(); const userWorkspaceState = userWorkspaceStore.$state; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const storeState = reactive({ - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), selectedWorkspace: computed(() => userWorkspaceState.getters.currentWorkspace), }); diff --git a/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateStep2BundleCase.vue b/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateStep2BundleCase.vue index 562684ae10..ece80b7ef4 100644 --- a/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateStep2BundleCase.vue +++ b/apps/web/src/services/_shared/dashboard/dashboard-create/contextual-components/DashboardCreateStep2BundleCase.vue @@ -21,6 +21,7 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { useServiceQueryKey } from '@/query/query-key/use-service-query-key'; import { i18n } from '@/translations'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useUserStore } from '@/store/user/user-store'; import { showErrorMessage, showSuccessMessage } from '@/lib/helper/notice-alert-helper'; @@ -54,6 +55,7 @@ const dashboardCreatePageStore = useDashboardCreatePageStore(); const dashboardCreatePageState = dashboardCreatePageStore.state; const dashboardTreeControlStore = useDashboardTreeControlStore(); const dashboardTreeControlState = dashboardTreeControlStore.state; +const authorizationStore = useAuthorizationStore(); const userStore = useUserStore(); const router = useRouter(); const { @@ -62,7 +64,7 @@ const { const dashboardTemplateQuery = useDashboardTemplateQuery(); const storeState = reactive({ - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), }); const state = reactive({ loading: false, diff --git a/apps/web/src/services/alert-manager/v1/components/AlertMainDataTable.vue b/apps/web/src/services/alert-manager/v1/components/AlertMainDataTable.vue index efbf69a62a..61e8eb16b7 100644 --- a/apps/web/src/services/alert-manager/v1/components/AlertMainDataTable.vue +++ b/apps/web/src/services/alert-manager/v1/components/AlertMainDataTable.vue @@ -25,13 +25,13 @@ import { ALERT_STATE, ALERT_URGENCY } from '@/schema/monitoring/alert/constants' import { useReferenceRouter } from '@/router/composables/use-reference-router'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { ProjectReferenceMap } from '@/store/reference/project-reference-store'; import type { UserReferenceMap } from '@/store/reference/user-reference-store'; import type { WebhookReferenceMap } from '@/store/reference/webhook-reference-store'; import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { FILE_NAME_PREFIX } from '@/lib/excel-export/constant'; import { downloadExcel } from '@/lib/helper/file-download-helper'; import type { MenuId } from '@/lib/menu/config'; @@ -94,12 +94,12 @@ const emit = defineEmits<{(event: 'update', filters: Partial(() => userStore.state.timezone || ''), projects: computed(() => allReferenceStore.getters.project), users: computed(() => allReferenceStore.getters.user), webhooks: computed(() => allReferenceStore.getters.webhook), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); /* Search Tags */ @@ -213,7 +213,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), }); /* formatters & autocomplete handlers */ diff --git a/apps/web/src/services/alert-manager/v1/components/EscalationPolicyForm.vue b/apps/web/src/services/alert-manager/v1/components/EscalationPolicyForm.vue index 7d0af44909..2ccf19a949 100644 --- a/apps/web/src/services/alert-manager/v1/components/EscalationPolicyForm.vue +++ b/apps/web/src/services/alert-manager/v1/components/EscalationPolicyForm.vue @@ -18,8 +18,8 @@ import { i18n } from '@/translations'; import { useReferenceRouter } from '@/router/composables/use-reference-router'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; -import { useUserStore } from '@/store/user/user-store'; import { useFormValidator } from '@/common/composables/form-validator'; import type { ProjectTreeNodeData } from '@/common/modules/project/project-tree-type'; @@ -45,8 +45,7 @@ const allReferenceStore = useAllReferenceStore(); const userWorkspaceStore = useUserWorkspaceStore(); const escalationPolicyFormStore = useEscalationPolicyFormStore(); const escalationPolicyFormState = escalationPolicyFormStore.$state; -const userStore = useUserStore(); - +const authorizationStore = useAuthorizationStore(); const { getReferenceLocation } = useReferenceRouter(); const state = reactive({ @@ -57,7 +56,7 @@ const state = reactive({ PROJECT: i18n.t('MONITORING.ALERT.ESCALATION_POLICY.FORM.PROJECT'), })), resourceGroups: computed<{label: TranslateResult; value: EscalationPolicyModel['resource_group']}[]>(() => { - const currentRoleType = userStore.state.currentRoleInfo?.roleType; + const currentRoleType = authorizationStore.state.currentRoleInfo?.roleType; const resGroup: {label: TranslateResult; value: EscalationPolicyModel['resource_group']}[] = [ { label: i18n.t('MONITORING.ALERT.ESCALATION_POLICY.FORM.PROJECT'), value: 'PROJECT' }, ]; diff --git a/apps/web/src/services/alert-manager/v1/routes/routes.ts b/apps/web/src/services/alert-manager/v1/routes/routes.ts index c08be0f49b..d9341c4475 100644 --- a/apps/web/src/services/alert-manager/v1/routes/routes.ts +++ b/apps/web/src/services/alert-manager/v1/routes/routes.ts @@ -1,8 +1,5 @@ import type { RouteConfig } from 'vue-router'; -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect-route-helper'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; @@ -24,10 +21,7 @@ const alertManagerRoute: RouteConfig = { menuId: MENU_ID.ALERT_MANAGER, translationId: MENU_INFO_MAP[MENU_ID.ALERT_MANAGER].translationId, }, - redirect: (to) => { - const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); - }, + redirect: (to) => getRedirectRouteByPagePermission(to), component: AlertManagerContainer, children: [ { diff --git a/apps/web/src/services/alert-manager/v2/routes/routes.ts b/apps/web/src/services/alert-manager/v2/routes/routes.ts index 2c960f005b..c9aa074f1f 100644 --- a/apps/web/src/services/alert-manager/v2/routes/routes.ts +++ b/apps/web/src/services/alert-manager/v2/routes/routes.ts @@ -1,8 +1,5 @@ import type { RouteConfig } from 'vue-router'; -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect-route-helper'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; @@ -19,7 +16,6 @@ const AlertContainer = () => import('@/services/alert-manager/v2/AlertContainer. const AlertsMainPage = () => import('@/services/alert-manager/v2/pages/AlertsMainPage.vue'); const AlertsDetailPage = () => import('@/services/alert-manager/v2/pages/AlertsDetailPage.vue'); -const userStore = useUserStore(pinia); const alertManagerRoute: RouteConfig = { path: 'alert-manager', name: ALERT_MANAGER_ROUTE._NAME, @@ -27,7 +23,7 @@ const alertManagerRoute: RouteConfig = { menuId: MENU_ID.ALERT_MANAGER, translationId: MENU_INFO_MAP[MENU_ID.ALERT_MANAGER].translationId, }, - redirect: (to) => getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap), + redirect: (to) => getRedirectRouteByPagePermission(to), component: AlertManagerContainer, children: [ { diff --git a/apps/web/src/services/alert-manager/v2/stores/alert-page-store.ts b/apps/web/src/services/alert-manager/v2/stores/alert-page-store.ts index e42c17826f..52e0c42569 100644 --- a/apps/web/src/services/alert-manager/v2/stores/alert-page-store.ts +++ b/apps/web/src/services/alert-manager/v2/stores/alert-page-store.ts @@ -1,5 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck import { computed, reactive } from 'vue'; import { defineStore } from 'pinia'; diff --git a/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue b/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue index 3e4e9b3066..a048c9fe5a 100644 --- a/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue +++ b/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue @@ -16,9 +16,9 @@ import { i18n } from '@/translations'; import { useServiceRouter } from '@/router/composables/use-service-router'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; +import { useGlobalConfigUiAffectsSchema } from '@/lib/config/global-config/composables/use-global-config-ui-affects-schema'; import { MENU_ID } from '@/lib/menu/config'; import type { Reference } from '@/lib/reference/type'; @@ -62,7 +62,8 @@ const props = defineProps(); const allReferenceStore = useAllReferenceStore(); const allReferenceGetters = allReferenceStore.getters; const taskManagementTemplateStore = useTaskManagementTemplateStore(); -const globalConfigSchemaStore = useGlobalConfigSchemaStore(); +const alertManagerUiAffectsSchema = useGlobalConfigUiAffectsSchema('ALERT_MANAGER'); + const router = useRouter(); const serviceRouter = useServiceRouter(router); @@ -71,7 +72,7 @@ const { visibleContents } = useContentsAccessibility(MENU_ID.OPS_FLOW); /* Tabs */ const state = reactive({ - visibleAlertTab: computed(() => globalConfigSchemaStore.state.uiAffectsSchema.ALERT_MANAGER?.visibleAssetAlertTab), + visibleAlertTab: computed(() => alertManagerUiAffectsSchema.value?.visibleAssetAlertTab), }); const singleItemTabState = reactive({ tabs: computed(() => { diff --git a/apps/web/src/services/asset-inventory/components/CloudServiceHistoryDetailNoteTab.vue b/apps/web/src/services/asset-inventory/components/CloudServiceHistoryDetailNoteTab.vue index 2a8343b746..cee4506c79 100644 --- a/apps/web/src/services/asset-inventory/components/CloudServiceHistoryDetailNoteTab.vue +++ b/apps/web/src/services/asset-inventory/components/CloudServiceHistoryDetailNoteTab.vue @@ -20,9 +20,9 @@ import type { NoteListParameters } from '@/schema/inventory/note/api-verbs/list' import type { NoteModel } from '@/schema/inventory/note/model'; import { i18n } from '@/translations'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import type { MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; @@ -31,7 +31,6 @@ import ErrorHandler from '@/common/composables/error/errorHandler'; import { COST_EXPLORER_ROUTE } from '@/services/cost-explorer/routes/route-constant'; - interface Props { recordId: string; manageDisabled: boolean; @@ -47,9 +46,7 @@ const emit = defineEmits<{(e: 'refresh-note-count'): void}>(); const route = useRoute(); const userStore = useUserStore(); -const storeState = reactive({ - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), -}); +const authorizationStore = useAuthorizationStore(); const state = reactive({ id: '', noteInput: '', @@ -72,7 +69,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), }); const handleChangeNoteInput = (e) => { diff --git a/apps/web/src/services/asset-inventory/components/CloudServiceLSB.vue b/apps/web/src/services/asset-inventory/components/CloudServiceLSB.vue index 1f6f6d0171..38a3393a3c 100644 --- a/apps/web/src/services/asset-inventory/components/CloudServiceLSB.vue +++ b/apps/web/src/services/asset-inventory/components/CloudServiceLSB.vue @@ -13,9 +13,9 @@ import { import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { ProviderReferenceMap } from '@/store/reference/provider-reference-store'; -import { useUserStore } from '@/store/user/user-store'; import LSB from '@/common/modules/navigations/lsb/LSB.vue'; import type { @@ -47,14 +47,14 @@ const cloudServicePageState = cloudServicePageStore.$state; const cloudServiceDetailPageStore = useCloudServiceDetailPageStore(); const cloudServiceDetailPageState = cloudServiceDetailPageStore.$state; const allReferenceStore = useAllReferenceStore(); -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const route = useRoute(); const router = useRouter(); const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - currentGrantInfo: computed(() => userStore.state.currentGrantInfo), + currentGrantInfo: computed(() => authorizationStore.state.currentGrantInfo), providers: computed(() => allReferenceStore.getters.provider), }); const state = reactive({ diff --git a/apps/web/src/services/asset-inventory/components/CollectorMainContents.vue b/apps/web/src/services/asset-inventory/components/CollectorMainContents.vue index 00b801433a..aae4c0ddd6 100644 --- a/apps/web/src/services/asset-inventory/components/CollectorMainContents.vue +++ b/apps/web/src/services/asset-inventory/components/CollectorMainContents.vue @@ -21,11 +21,11 @@ import type { ToolboxOptions } from '@cloudforet/mirinae/types/controls/toolbox/ import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { PluginReferenceMap } from '@/store/reference/plugin-reference-store'; import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { FILE_NAME_PREFIX } from '@/lib/excel-export/constant'; import { downloadExcel } from '@/lib/helper/file-download-helper'; import type { ExcelDataField } from '@/lib/helper/file-download-helper/type'; @@ -46,7 +46,6 @@ import { useCollectorPageStore } from '@/services/asset-inventory/stores/collect import type { CollectorItemInfo } from '@/services/asset-inventory/types/collector-main-page-type'; import { COST_EXPLORER_ROUTE } from '@/services/cost-explorer/routes/route-constant'; - /** * @function * @name makePluginReferenceValueHandler * @param distinct @@ -82,6 +81,7 @@ const collectorPageStore = useCollectorPageStore(); const collectorPageState = collectorPageStore.state; const allReferenceStore = useAllReferenceStore(); const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const appContextStore = useAppContextStore(); const router = useRouter(); const route = useRoute(); @@ -90,7 +90,6 @@ const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), plugins: computed(() => allReferenceStore.getters.plugin), timezone: computed(() => userStore.state.timezone ?? 'UTC'), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const keyItemSets: KeyItemSet[] = [{ @@ -137,7 +136,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), searchTags: computed(() => { const tags = searchQueryHelper.setFilters(collectorPageState.searchFilters).queryTags; return tags.reduce((r: QueryItem[], d: any): QueryItem[] => { diff --git a/apps/web/src/services/asset-inventory/components/MetricExplorerHeader.vue b/apps/web/src/services/asset-inventory/components/MetricExplorerHeader.vue index 18dca0dd3f..b6381c4878 100644 --- a/apps/web/src/services/asset-inventory/components/MetricExplorerHeader.vue +++ b/apps/web/src/services/asset-inventory/components/MetricExplorerHeader.vue @@ -23,10 +23,9 @@ import type { MetricModel } from '@/schema/inventory/metric/model'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; -import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; import type { MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; @@ -53,7 +52,7 @@ const metricExplorerPageState = metricExplorerPageStore.state; const metricExplorerPageGetters = metricExplorerPageStore.getters; const allReferenceStore = useAllReferenceStore(); const appContextStore = useAppContextStore(); -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const router = useRouter(); const route = useRoute(); @@ -62,7 +61,6 @@ const storeState = reactive({ namespaces: computed(() => allReferenceStore.getters.namespace), currentMetric: computed(() => metricExplorerPageState.metric), isAdminMode: computed(() => appContextStore.getters.isAdminMode), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const state = reactive({ selectedMenuId: computed(() => { @@ -74,7 +72,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), currentMetricId: computed(() => route.params.metricId), isDuplicateEnabled: computed(() => Object.values(storeState.namespaces).find((d) => d.key === storeState.currentMetric?.namespace_id)?.data.group !== 'common'), currentMetricExampleId: computed(() => route.params.metricExampleId), diff --git a/apps/web/src/services/asset-inventory/components/MetricExplorerLSBMetric.vue b/apps/web/src/services/asset-inventory/components/MetricExplorerLSBMetric.vue index d94f478bf2..95c10a143b 100644 --- a/apps/web/src/services/asset-inventory/components/MetricExplorerLSBMetric.vue +++ b/apps/web/src/services/asset-inventory/components/MetricExplorerLSBMetric.vue @@ -12,15 +12,14 @@ import { import type { TreeDisplayMap, TreeNode } from '@cloudforet/mirinae/types/data-display/tree/tree-view/type'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CloudServiceTypeItem, CloudServiceTypeReferenceMap, } from '@/store/reference/cloud-service-type-reference-store'; import type { MetricReferenceItem } from '@/store/reference/metric-reference-store'; -import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import type { MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; @@ -46,7 +45,7 @@ const allReferenceStore = useAllReferenceStore(); const appContextStore = useAppContextStore(); const metricExplorerPageStore = useMetricExplorerPageStore(); const metricExplorerPageState = metricExplorerPageStore.state; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const route = useRoute(); const storeState = reactive({ @@ -60,7 +59,6 @@ const storeState = reactive({ return res; }), selectedNamespace: computed(() => metricExplorerPageState.selectedNamespace), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const state = reactive({ selectedMenuId: computed(() => { @@ -72,7 +70,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), selectedId: computed(() => { const routeName = { name: storeState.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.METRIC_EXPLORER.DETAIL._NAME : ASSET_INVENTORY_ROUTE.METRIC_EXPLORER.DETAIL._NAME }.name; if (!props.isDetailPage) return undefined; diff --git a/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue b/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue index 45ff1fdc53..18b0e32d58 100644 --- a/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue +++ b/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue @@ -23,14 +23,13 @@ import { SpaceRouter } from '@/router'; import type { CloudServiceAnalyzeParameters } from '@/schema/inventory/cloud-service/api-verbs/analyze'; import { i18n } from '@/translations'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CollectorReferenceMap } from '@/store/reference/collector-reference-store'; import type { ProjectGroupReferenceMap } from '@/store/reference/project-group-reference-store'; import type { ProviderReferenceMap } from '@/store/reference/provider-reference-store'; import type { ServiceAccountReferenceMap } from '@/store/reference/service-account-reference-store'; -import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { MENU_ID } from '@/lib/menu/config'; import { arrayToQueryString, @@ -69,7 +68,7 @@ const allReferenceStore = useAllReferenceStore(); const cloudServicePageStore = useCloudServicePageStore(); const cloudServicePageState = cloudServicePageStore.$state; const cloudServiceLSBStore = useCloudServiceLSBStore(); -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const storeState = reactive({ projects: computed(() => allReferenceStore.getters.project), @@ -77,7 +76,6 @@ const storeState = reactive({ serviceAccounts: computed(() => allReferenceStore.getters.serviceAccount), providers: computed(() => allReferenceStore.getters.provider), collectors: computed(() => allReferenceStore.getters.collector), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const handlerState = reactive({ keyItemSets: computed(() => [{ @@ -150,8 +148,8 @@ const state = reactive({ } return result; }), - writableServiceAccount: computed(() => storeState.pageAccessPermissionMap[MENU_ID.SERVICE_ACCOUNT].write), - writableCollector: computed(() => storeState.pageAccessPermissionMap[MENU_ID.COLLECTOR].write), + writableServiceAccount: computed(() => authorizationStore.getters.pageAccessPermissionMap[MENU_ID.SERVICE_ACCOUNT]?.write), + writableCollector: computed(() => authorizationStore.getters.pageAccessPermissionMap[MENU_ID.COLLECTOR]?.write), }); /* api */ diff --git a/apps/web/src/services/asset-inventory/pages/CollectorDetailPage.vue b/apps/web/src/services/asset-inventory/pages/CollectorDetailPage.vue index fa73b5e487..c4db18f4ee 100644 --- a/apps/web/src/services/asset-inventory/pages/CollectorDetailPage.vue +++ b/apps/web/src/services/asset-inventory/pages/CollectorDetailPage.vue @@ -41,9 +41,9 @@ import type { CollectorGetParameters } from '@/schema/inventory/collector/api-ve import type { CollectorModel } from '@/schema/inventory/collector/model'; import { i18n } from '@/translations'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; import type { MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; @@ -87,6 +87,7 @@ const collectorJobState = collectorJobStore.$state; const collectorDataModalStore = useCollectorDataModalStore(); const collectorDetailPageStore = useCollectorDetailPageStore(); const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const route = useRoute(); @@ -100,9 +101,6 @@ watch(() => collectorFormState.originCollector, async (collector) => { const queryHelper = new QueryHelper(); -const storeState = reactive({ - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), -}); const state = reactive({ selectedMenuId: computed(() => { const reversedMatched = clone(route.matched).reverse(); @@ -113,7 +111,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), isNotiVisible: computed(() => !collectorDetailPageStore.getters.isEditableCollector), isDomainAdmin: computed(() => userStore.getters.isDomainAdmin), loading: true, diff --git a/apps/web/src/services/asset-inventory/pages/SecurityPage.vue b/apps/web/src/services/asset-inventory/pages/SecurityPage.vue index 4157969357..e44048c72e 100644 --- a/apps/web/src/services/asset-inventory/pages/SecurityPage.vue +++ b/apps/web/src/services/asset-inventory/pages/SecurityPage.vue @@ -10,12 +10,11 @@ import { import { i18n } from '@/translations'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CollectorReferenceMap } from '@/store/reference/collector-reference-store'; import type { ServiceAccountReferenceMap } from '@/store/reference/service-account-reference-store'; -import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { MENU_ID } from '@/lib/menu/config'; import { useGrantScopeGuard } from '@/common/composables/grant-scope-guard'; @@ -31,7 +30,7 @@ import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-c const allReferenceStore = useAllReferenceStore(); const securityPageStore = useSecurityPageStore(); const securityPageGetters = securityPageStore.getters; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const route = useRoute(); @@ -41,7 +40,6 @@ const storeState = reactive({ selectedCloudServiceType: computed(() => securityPageGetters.selectedCloudServiceType), serviceAccounts: computed(() => allReferenceStore.getters.serviceAccount), collectors: computed(() => allReferenceStore.getters.collector), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const state = reactive({ pageParams: computed(() => route.params as unknown as CloudServiceDetailPageParams), @@ -70,8 +68,8 @@ const state = reactive({ } return result; }), - writableServiceAccount: computed(() => storeState.pageAccessPermissionMap[MENU_ID.SERVICE_ACCOUNT].write), - writableCollector: computed(() => storeState.pageAccessPermissionMap[MENU_ID.COLLECTOR].write), + writableServiceAccount: computed(() => authorizationStore.getters.pageAccessPermissionMap[MENU_ID.SERVICE_ACCOUNT]?.write), + writableCollector: computed(() => authorizationStore.getters.pageAccessPermissionMap[MENU_ID.COLLECTOR]?.write), }); const initData = async () => { diff --git a/apps/web/src/services/asset-inventory/pages/admin/AdminCollectorDetailPage.vue b/apps/web/src/services/asset-inventory/pages/admin/AdminCollectorDetailPage.vue index a0a6ab872a..cb51702a9e 100644 --- a/apps/web/src/services/asset-inventory/pages/admin/AdminCollectorDetailPage.vue +++ b/apps/web/src/services/asset-inventory/pages/admin/AdminCollectorDetailPage.vue @@ -121,9 +121,9 @@ import type { CollectorGetParameters } from '@/schema/inventory/collector/api-ve import type { CollectorModel } from '@/schema/inventory/collector/model'; import { i18n } from '@/translations'; -import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; + import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; import type { MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; @@ -168,7 +168,7 @@ const collectorJobState = collectorJobStore.$state; const collectorDataModalStore = useCollectorDataModalStore(); const collectorDetailPageStore = useCollectorDetailPageStore(); -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const route = useRoute(); @@ -182,9 +182,6 @@ watch(() => collectorFormState.originCollector, async (collector) => { const queryHelper = new QueryHelper(); -const storeState = reactive({ - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), -}); const state = reactive({ selectedMenuId: computed(() => { const reversedMatched = clone(route.matched).reverse(); @@ -195,7 +192,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), isNotiVisible: computed(() => !collectorDetailPageStore.getters.isEditableCollector), loading: true, collector: computed(() => collectorFormState.originCollector), diff --git a/apps/web/src/services/asset-inventory/routes/routes.ts b/apps/web/src/services/asset-inventory/routes/routes.ts index 1c973617fb..d963f1c9ce 100644 --- a/apps/web/src/services/asset-inventory/routes/routes.ts +++ b/apps/web/src/services/asset-inventory/routes/routes.ts @@ -2,9 +2,6 @@ import type { RouteConfig } from 'vue-router'; import { upperCase } from 'lodash'; -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect-route-helper'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; @@ -34,7 +31,6 @@ const CollectJobPage = () => import('@/services/asset-inventory/pages/CollectHis const CollectorDetailPage = () => import('@/services/asset-inventory/pages/CollectorDetailPage.vue'); -const userStore = useUserStore(pinia); const assetInventoryRoute: RouteConfig = { path: 'asset-inventory', name: ASSET_INVENTORY_ROUTE._NAME, @@ -42,7 +38,7 @@ const assetInventoryRoute: RouteConfig = { menuId: MENU_ID.ASSET_INVENTORY, translationId: MENU_INFO_MAP[MENU_ID.ASSET_INVENTORY].translationId, }, - redirect: (to) => getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap), + redirect: (to) => getRedirectRouteByPagePermission(to), component: AssetInventoryContainer, children: [ { diff --git a/apps/web/src/services/auth/authenticator/index.ts b/apps/web/src/services/auth/authenticator/index.ts index 321277a92f..4917181454 100644 --- a/apps/web/src/services/auth/authenticator/index.ts +++ b/apps/web/src/services/auth/authenticator/index.ts @@ -4,6 +4,7 @@ import type { AuthType } from '@/api-clients/identity/user/schema/type'; import { SpaceRouter } from '@/router'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useDisplayStore } from '@/store/display/display-store'; import { useDomainStore } from '@/store/domain/domain-store'; import { useErrorStore } from '@/store/error/error-store'; @@ -17,13 +18,15 @@ abstract class Authenticator { const errorStore = useErrorStore(); const domainStore = useDomainStore(); const userStore = useUserStore(); + const authorizationStore = useAuthorizationStore(); const displayStore = useDisplayStore(pinia); - await userStore.signIn({ + await authorizationStore.signIn({ domainId: domainStore.state.domainId, credentials, authType, verify_code: verifyCode, }); + await userStore.getUserInfo(); await userWorkspaceStore.load(); displayStore.setIsSignInFailed(false); errorStore.reset(); @@ -31,11 +34,11 @@ abstract class Authenticator { static async signOut(): Promise { const errorStore = useErrorStore(); - const userStore = useUserStore(); + const authorizationStore = useAuthorizationStore(); const displayStore = useDisplayStore(pinia); try { if (SpaceRouter.router) { - userStore.signOut(); + authorizationStore.signOut(); const userWorkspaceStore = useUserWorkspaceStore(); userWorkspaceStore.reset(); displayStore.setIsSignInFailed(false); diff --git a/apps/web/src/services/cost-explorer/components/BudgetDetailHeading.vue b/apps/web/src/services/cost-explorer/components/BudgetDetailHeading.vue index 0b7226e2ac..b86e7e3583 100644 --- a/apps/web/src/services/cost-explorer/components/BudgetDetailHeading.vue +++ b/apps/web/src/services/cost-explorer/components/BudgetDetailHeading.vue @@ -11,9 +11,9 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CostDataSourceReferenceMap } from '@/store/reference/cost-data-source-reference-store'; -import { useUserStore } from '@/store/user/user-store'; import { usePageEditableStatus } from '@/common/composables/page-editable-status'; @@ -34,15 +34,14 @@ const appContextStore = useAppContextStore(); const budgetPageStore = useBudgetDetailPageStore(); const budgetPageState = budgetPageStore.$state; const allReferenceStore = useAllReferenceStore(); -const userStore = useUserStore(); - +const authorizationStore = useAuthorizationStore(); const { hasReadWriteAccess } = usePageEditableStatus(); const router = useRouter(); const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), dataSourceMap: computed(() => allReferenceStore.getters.costDataSource), }); const state = reactive({ diff --git a/apps/web/src/services/cost-explorer/pages/BudgetDetailPage.vue b/apps/web/src/services/cost-explorer/pages/BudgetDetailPage.vue index f6bf045071..0fa7482ad0 100644 --- a/apps/web/src/services/cost-explorer/pages/BudgetDetailPage.vue +++ b/apps/web/src/services/cost-explorer/pages/BudgetDetailPage.vue @@ -7,9 +7,10 @@ import { PLink, PScopedNotification } from '@cloudforet/mirinae'; import type { BudgetModel } from '@/api-clients/cost-analysis/budget/schema/model'; import { i18n } from '@/translations'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; import { useUserStore } from '@/store/user/user-store'; +import { useGlobalConfigUiAffectsSchema } from '@/lib/config/global-config/composables/use-global-config-ui-affects-schema'; + import ErrorHandler from '@/common/composables/error/errorHandler'; import BudgetDetailBaseInformation from '@/services/cost-explorer/components/BudgetDetailBaseInformation.vue'; @@ -27,13 +28,14 @@ const props = withDefaults(defineProps(), { }); const userStore = useUserStore(); -const globalConfigSchemaStore = useGlobalConfigSchemaStore(); +const alertManagerUiAffectsSchema = useGlobalConfigUiAffectsSchema('ALERT_MANAGER'); + const budgetPageStore = useBudgetDetailPageStore(); const budgetPageState = budgetPageStore.$state; const state = reactive({ loading: true, budgetData: computed(() => budgetPageState.budgetData), - visibleBudgetNotification: computed(() => globalConfigSchemaStore.state.uiAffectsSchema.ALERT_MANAGER?.visibleBudgetNotification ?? false), + visibleBudgetNotification: computed(() => alertManagerUiAffectsSchema.value?.visibleBudgetNotification ?? false), isWorkspaceTarget: computed(() => (state.budgetData?.resource_group === 'WORKSPACE')), adminModeLink: computed(() => ({ name: ADMIN_COST_EXPLORER_ROUTE.BUDGET.DETAIL._NAME, diff --git a/apps/web/src/services/cost-explorer/pages/BudgetMainPage.vue b/apps/web/src/services/cost-explorer/pages/BudgetMainPage.vue index d88d7a97b8..eec8a1d4d6 100644 --- a/apps/web/src/services/cost-explorer/pages/BudgetMainPage.vue +++ b/apps/web/src/services/cost-explorer/pages/BudgetMainPage.vue @@ -8,7 +8,7 @@ import { import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { SpaceRouter } from '@/router'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { usePageEditableStatus } from '@/common/composables/page-editable-status'; @@ -16,12 +16,12 @@ import BudgetListPeriodCustomModal from '@/services/cost-explorer/components/Bud import BudgetMainList from '@/services/cost-explorer/components/BudgetMainList.vue'; import { COST_EXPLORER_ROUTE } from '@/services/cost-explorer/routes/route-constant'; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const { hasReadWriteAccess } = usePageEditableStatus(); const storeState = reactive({ - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), }); const state = reactive({ diff --git a/apps/web/src/services/cost-explorer/routes/routes.ts b/apps/web/src/services/cost-explorer/routes/routes.ts index 89d6a1545a..01b1bb5a5e 100644 --- a/apps/web/src/services/cost-explorer/routes/routes.ts +++ b/apps/web/src/services/cost-explorer/routes/routes.ts @@ -2,9 +2,6 @@ import type { RouteConfig } from 'vue-router'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect-route-helper'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; @@ -31,10 +28,7 @@ const costExplorerRoutes: RouteConfig = { menuId: MENU_ID.COST_EXPLORER, translationId: MENU_INFO_MAP[MENU_ID.COST_EXPLORER].translationId, }, - redirect: (to) => { - const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); - }, + redirect: (to) => getRedirectRouteByPagePermission(to), component: CostExplorerContainer, children: [ { diff --git a/apps/web/src/services/dashboards/DashboardsLSB.vue b/apps/web/src/services/dashboards/DashboardsLSB.vue index 5fa2365968..7f2ac62643 100644 --- a/apps/web/src/services/dashboards/DashboardsLSB.vue +++ b/apps/web/src/services/dashboards/DashboardsLSB.vue @@ -14,7 +14,7 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { MENU_ID } from '@/lib/menu/config'; @@ -40,7 +40,7 @@ import { DASHBOARDS_ROUTE } from '@/services/dashboards/routes/route-constant'; const appContextStore = useAppContextStore(); const favoriteStore = useFavoriteStore(); const favoriteGetters = favoriteStore.getters; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const { hasReadWriteAccess } = usePageEditableStatus(); @@ -58,7 +58,7 @@ const { } = useDashboardFolderQuery(); const storeState = reactive({ - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), favoriteItems: computed(() => favoriteGetters.dashboardItems), isAdminMode: computed(() => appContextStore.getters.isAdminMode), }); diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardCloneModal.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardCloneModal.vue index 481d787e72..c22b70bcef 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardCloneModal.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardCloneModal.vue @@ -16,7 +16,7 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { showErrorMessage } from '@/lib/helper/notice-alert-helper'; @@ -29,7 +29,6 @@ import { ADMIN_DASHBOARDS_ROUTE } from '@/services/dashboards/routes/admin/route import { DASHBOARDS_ROUTE } from '@/services/dashboards/routes/route-constant'; - interface Props { visible: boolean; dashboardId: string; @@ -51,7 +50,8 @@ const queryClient = useQueryClient(); const router = useRouter(); const appContextStore = useAppContextStore(); -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); + const { forms: { name, @@ -74,8 +74,8 @@ const { }); const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), }); const state = reactive({ proxyVisible: useProxyValue('visible', props, emit), diff --git a/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderFormModal.vue b/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderFormModal.vue index 18b939028b..fb690b8048 100644 --- a/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderFormModal.vue +++ b/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderFormModal.vue @@ -19,6 +19,7 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useUserStore } from '@/store/user/user-store'; import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; @@ -31,7 +32,6 @@ import { useDashboardFolderQuery } from '@/services/dashboards/composables/use-d import { useDashboardPageControlStore } from '@/services/dashboards/stores/dashboard-page-control-store'; import { useDashboardTreeControlStore } from '@/services/dashboards/stores/dashboard-tree-control-store'; - interface Props { visible: boolean; folderId?: string; @@ -44,7 +44,9 @@ const emit = defineEmits<{(e: 'update:visible', visible: boolean): void; }>(); const appContextStore = useAppContextStore(); +const authorizationStore = useAuthorizationStore(); const userStore = useUserStore(); + const dashboardPageControlStore = useDashboardPageControlStore(); const dashboardPageControlState = dashboardPageControlStore.state; const dashboardTreeControlStore = useDashboardTreeControlStore(); @@ -62,7 +64,7 @@ const { const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), }); const state = reactive({ proxyVisible: useProxyValue('visible', props, emit), diff --git a/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderTreeItem.vue b/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderTreeItem.vue index 7b8bf7ff5d..48de417d25 100644 --- a/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderTreeItem.vue +++ b/apps/web/src/services/dashboards/components/dashboard-folder/DashboardFolderTreeItem.vue @@ -16,7 +16,7 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import NewMark from '@/common/components/marks/NewMark.vue'; import FavoriteButton from '@/common/modules/favorites/favorite-button/FavoriteButton.vue'; @@ -51,7 +51,7 @@ const LABELS_LIMIT = 2; const appContextStore = useAppContextStore(); const dashboardTreeControlStore = useDashboardTreeControlStore(); const dashboardTreeControlState = dashboardTreeControlStore.state; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const { getDashboardManageable, getFolderManageable } = useDashboardManageable(); const { getControlDashboardMenuItems, getControlFolderMenuItems } = useDashboardControlMenuHelper(); @@ -59,7 +59,7 @@ const { getControlDashboardMenuItems, getControlFolderMenuItems } = useDashboard const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), }); const state = reactive({ slicedLabels: computed(() => props.treeData.data?.labels?.slice(0, LABELS_LIMIT) || []), diff --git a/apps/web/src/services/dashboards/components/dashboard-main/DashboardBundleCloneModal.vue b/apps/web/src/services/dashboards/components/dashboard-main/DashboardBundleCloneModal.vue index 057d8f4a81..722f13a81c 100644 --- a/apps/web/src/services/dashboards/components/dashboard-main/DashboardBundleCloneModal.vue +++ b/apps/web/src/services/dashboards/components/dashboard-main/DashboardBundleCloneModal.vue @@ -30,6 +30,7 @@ import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { CostDataSourceReferenceMap } from '@/store/reference/cost-data-source-reference-store'; import { useUserStore } from '@/store/user/user-store'; @@ -89,6 +90,7 @@ const dashboardPageControlState = dashboardPageControlStore.state; const dashboardTreeControlStore = useDashboardTreeControlStore(); const dashboardTreeControlState = dashboardTreeControlStore.state; const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const allReferenceStore = useAllReferenceStore(); const { privateWidgetAPI } = usePrivateWidgetApi(); const { publicWidgetAPI } = usePublicWidgetApi(); @@ -109,7 +111,7 @@ const queryClient = useQueryClient(); const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), costDataSource: computed(() => allReferenceStore.getters.costDataSource), userId: computed(() => userStore.state.userId), }); diff --git a/apps/web/src/services/dashboards/components/dashboard-main/DashboardLSBTree.vue b/apps/web/src/services/dashboards/components/dashboard-main/DashboardLSBTree.vue index 705a089852..72a751db81 100644 --- a/apps/web/src/services/dashboards/components/dashboard-main/DashboardLSBTree.vue +++ b/apps/web/src/services/dashboards/components/dashboard-main/DashboardLSBTree.vue @@ -15,7 +15,7 @@ import type { PublicFolderModel } from '@/api-clients/dashboard/public-folder/sc import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import FavoriteButton from '@/common/modules/favorites/favorite-button/FavoriteButton.vue'; import { FAVORITE_TYPE } from '@/common/modules/favorites/favorite-button/type'; @@ -43,11 +43,11 @@ const route = useRoute(); const router = useRouter(); const dashboardPageControlStore = useDashboardPageControlStore(); const appContextStore = useAppContextStore(); -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), }); const { getControlDashboardMenuItems, getControlFolderMenuItems } = useDashboardControlMenuHelper(); diff --git a/apps/web/src/services/dashboards/composables/use-dashboard-search-query.ts b/apps/web/src/services/dashboards/composables/use-dashboard-search-query.ts index 237b0b8741..20ed7414cd 100644 --- a/apps/web/src/services/dashboards/composables/use-dashboard-search-query.ts +++ b/apps/web/src/services/dashboards/composables/use-dashboard-search-query.ts @@ -19,7 +19,7 @@ import { useScopedQuery } from '@/query/composables/use-scoped-query'; import { useServiceQueryKey } from '@/query/query-key/use-service-query-key'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; const DEFAULT_LIST_DATA = { results: [] }; @@ -35,12 +35,12 @@ export const useDashboardSearchQuery = ({ searchFilters }: UseDashboardSearchQue const { privateDashboardAPI } = usePrivateDashboardApi(); const appContextStore = useAppContextStore(); - const userStore = useUserStore(); + const authorizationStore = useAuthorizationStore(); const searchApiQueryHelper = new ApiQueryHelper(); const _state = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), }); const searchQuery = ref({}); diff --git a/apps/web/src/services/dashboards/helpers/dashboard-tree-data-helper.ts b/apps/web/src/services/dashboards/helpers/dashboard-tree-data-helper.ts index 3251665228..12a4a267a8 100644 --- a/apps/web/src/services/dashboards/helpers/dashboard-tree-data-helper.ts +++ b/apps/web/src/services/dashboards/helpers/dashboard-tree-data-helper.ts @@ -1,9 +1,9 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck import type { TreeNode } from '@cloudforet/mirinae/types/data-display/tree/tree-view/type'; import type { DashboardModel } from '@/api-clients/dashboard/_types/dashboard-type'; import type { FolderModel } from '@/api-clients/dashboard/_types/folder-type'; +import type { PublicDashboardModel } from '@/api-clients/dashboard/public-dashboard/schema/model'; +import type { PublicFolderModel } from '@/api-clients/dashboard/public-folder/schema/model'; import type { DashboardTreeDataType, DashboardDataTableItem } from '@/services/dashboards/types/dashboard-folder-type'; @@ -22,7 +22,6 @@ export const getDashboardTreeData = ( depth: 0, data: { id: folder.folder_id, - name: folder.name, type: 'FOLDER', createdBy: folder.tags?.created_by, isNew: newIdList?.includes(folder.folder_id), @@ -40,7 +39,6 @@ export const getDashboardTreeData = ( depth: 0, data: { id: dashboard.dashboard_id, - name: dashboard.name, type: 'DASHBOARD', createdBy: dashboard.tags?.created_by, isNew: newIdList?.includes(dashboard.dashboard_id), @@ -52,7 +50,11 @@ export const getDashboardTreeData = ( if (folderNode) { dashboardNode.depth = 1; - folderNode.children.push(dashboardNode); + if (Array.isArray(folderNode.children)) { + folderNode.children.push(dashboardNode); + } else { + folderNode.children = [dashboardNode]; + } } else { rootNodes.push(dashboardNode); } @@ -116,13 +118,13 @@ export const isPublicControlButtonDisabled = (dashboardItems: DashboardModel[], if (result) return; const _isFolder = id.includes('folder'); if (_isFolder) { - const _folder = folderItems.find((f) => f.folder_id === id); + const _folder = folderItems.find((f) => f.folder_id === id) as PublicFolderModel; if (isProject) result = !!_folder?.shared; else if (_folder?.shared && _folder?.scope === 'WORKSPACE') { result = true; } } else { - const _dashboard = dashboardItems.find((d) => d.dashboard_id === id); + const _dashboard = dashboardItems.find((d) => d.dashboard_id === id) as PublicDashboardModel; if (isProject) result = !!_dashboard?.shared; else if (_dashboard?.shared && _dashboard?.scope === 'WORKSPACE') { result = true; diff --git a/apps/web/src/services/dashboards/pages/DashboardsMainPage.vue b/apps/web/src/services/dashboards/pages/DashboardsMainPage.vue index c68fe179c7..aa6cd16b74 100644 --- a/apps/web/src/services/dashboards/pages/DashboardsMainPage.vue +++ b/apps/web/src/services/dashboards/pages/DashboardsMainPage.vue @@ -23,7 +23,7 @@ import { SpaceRouter } from '@/router'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { replaceUrlQuery } from '@/lib/router-query-string'; @@ -53,7 +53,7 @@ const appContextStore = useAppContextStore(); const dashboardPageControlStore = useDashboardPageControlStore(); const dashboardTreeControlStore = useDashboardTreeControlStore(); const dashboardTreeControlState = dashboardTreeControlStore.state; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const { hasReadWriteAccess } = usePageEditableStatus(); @@ -80,8 +80,8 @@ const { } = useDashboardFolderQuery(); const storeState = reactive({ - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), isAdminMode: computed(() => appContextStore.getters.isAdminMode), }); diff --git a/apps/web/src/services/iam/components/RoleManagementTabDetail.vue b/apps/web/src/services/iam/components/RoleManagementTabDetail.vue index bdd99536f2..5fbcf76082 100644 --- a/apps/web/src/services/iam/components/RoleManagementTabDetail.vue +++ b/apps/web/src/services/iam/components/RoleManagementTabDetail.vue @@ -16,7 +16,7 @@ import type { RoleGetParameters } from '@/api-clients/identity/role/schema/api-v import type { RoleModel } from '@/api-clients/identity/role/schema/model'; import { i18n } from '@/translations'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; +import { useMenuStore } from '@/store/menu/menu-store'; import { PAGE_ACCESS } from '@/lib/access-control/config'; import { @@ -41,7 +41,7 @@ interface DetailMenuItems { const rolePageStore = useRolePageStore(); const rolePageState = rolePageStore.$state; -const globalConfigSchemaStore = useGlobalConfigSchemaStore(); +const menuStore = useMenuStore(); const detailMenuItems = computed(() => [ { name: 'page_access', label: i18n.t('IAM.ROLE.DETAIL.PAGE_ACCESS') as string }, @@ -145,7 +145,7 @@ watch(() => state.selectedRole.role_id, async (roleId) => { state.pageAccessDataList = getPageAccessMenuListByRoleType(state.data.role_type); const pageAccessPermissionMap = getPageAccessMapFromRawData({ - pageAccessPermissions: state.pageAccess, isRolePage: true, menuList: globalConfigSchemaStore.getters.menuList, + pageAccessPermissions: state.pageAccess, isRolePage: true, menuList: menuStore.getters.menuList, }); Object.entries(pageAccessPermissionMap).forEach(([itemId, accessible]) => { diff --git a/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue b/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue index 6e04ef2805..9ccb16c144 100644 --- a/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue +++ b/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue @@ -10,7 +10,7 @@ import { PPaneLayout } from '@cloudforet/mirinae'; import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import type { RoleType } from '@/api-clients/identity/role/type'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; +import { useMenuStore } from '@/store/menu/menu-store'; import { PAGE_ACCESS } from '@/lib/access-control/config'; import { getPageAccessMapFromRawData } from '@/lib/access-control/page-access-helper'; @@ -40,7 +40,7 @@ const props = withDefaults(defineProps(), { formType: FORM_TYPE.CREATE, }); -const globalConfigSchemaStore = useGlobalConfigSchemaStore(); +const menuStore = useMenuStore(); const emit = defineEmits<{(e: 'update-form', formData: RoleFormData): void, (e: 'update:is-page-access-valid', value: boolean): void, @@ -96,7 +96,7 @@ const handleUpdateEditor = (value: string) => { const setPageAccessPermissionsData = () => { if (!props.initialPageAccess) return; const pageAccessPermissionMap = getPageAccessMapFromRawData({ - pageAccessPermissions: props.initialPageAccess, isRolePage: true, menuList: globalConfigSchemaStore.getters.menuList, + pageAccessPermissions: props.initialPageAccess, isRolePage: true, menuList: menuStore.getters.menuList, }); // eslint-disable-next-line no-restricted-syntax for (const [itemId, accessible] of Object.entries(pageAccessPermissionMap)) { diff --git a/apps/web/src/services/iam/constants/role-constant.ts b/apps/web/src/services/iam/constants/role-constant.ts index fe7f75ccd0..ab279da733 100644 --- a/apps/web/src/services/iam/constants/role-constant.ts +++ b/apps/web/src/services/iam/constants/role-constant.ts @@ -3,7 +3,7 @@ import type { KeyItemSet } from '@cloudforet/mirinae/types/controls/search/query import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; -import { FEATURES } from '@/lib/config/global-config/constants/constants'; +import { SERVICE_FEATURES } from '@/lib/config/global-config/constants/constants'; import type { ExcelDataField } from '@/lib/helper/file-download-helper/type'; import { MENU_ID } from '@/lib/menu/config'; @@ -92,12 +92,12 @@ export const MANAGED_PAGE_ACCESS = [ ] as const; export const DEFAULT_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] = [ - { id: MENU_ID.DASHBOARDS, key: FEATURES.DASHBOARDS }, - { id: MENU_ID.SERVICE_ACCOUNT, key: FEATURES.SERVICE_ACCOUNT }, - { id: MENU_ID.PROJECT, key: FEATURES.PROJECT }, + { id: MENU_ID.DASHBOARDS, key: SERVICE_FEATURES.DASHBOARDS }, + { id: MENU_ID.SERVICE_ACCOUNT, key: SERVICE_FEATURES.SERVICE_ACCOUNT }, + { id: MENU_ID.PROJECT, key: SERVICE_FEATURES.PROJECT }, { id: MENU_ID.ASSET_INVENTORY, - key: FEATURES.ASSET_INVENTORY, + key: SERVICE_FEATURES.ASSET_INVENTORY, subMenuList: [ { id: MENU_ID.CLOUD_SERVICE }, { id: MENU_ID.SERVER }, @@ -108,7 +108,7 @@ export const DEFAULT_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] = }, { id: MENU_ID.COST_EXPLORER, - key: FEATURES.COST_EXPLORER, + key: SERVICE_FEATURES.COST_EXPLORER, subMenuList: [ { id: MENU_ID.COST_ANALYSIS }, { id: MENU_ID.BUDGET }, @@ -117,7 +117,7 @@ export const DEFAULT_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] = }, { id: MENU_ID.OPS_FLOW, - key: FEATURES.OPS_FLOW, + key: SERVICE_FEATURES.OPS_FLOW, subMenuList: [ { id: MENU_ID.OPS_FLOW_LANDING }, { id: MENU_ID.TASK_BOARD }, @@ -127,7 +127,7 @@ export const DEFAULT_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] = export const ALERT_V2_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] = [ { id: MENU_ID.ALERT_MANAGER, - key: FEATURES.ALERT_MANAGER, + key: SERVICE_FEATURES.ALERT_MANAGER, subMenuList: [ { id: MENU_ID.SERVICE }, { id: MENU_ID.ALERTS }, @@ -135,7 +135,7 @@ export const ALERT_V2_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] }, { id: MENU_ID.IAM, - key: FEATURES.IAM, + key: SERVICE_FEATURES.IAM, subMenuList: [ { id: MENU_ID.USER }, { id: MENU_ID.USER_GROUP }, @@ -147,7 +147,7 @@ export const ALERT_V2_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] export const ALERT_V1_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] = [ { id: MENU_ID.ALERT_MANAGER, - key: FEATURES.ALERT_MANAGER, + key: SERVICE_FEATURES.ALERT_MANAGER, subMenuList: [ { id: MENU_ID.ALERT_MANAGER_DASHBOARD }, { id: MENU_ID.ALERTS }, @@ -156,7 +156,7 @@ export const ALERT_V1_WORKSPACE_PAGE_ACCESS_MENU_LIST: PageAccessMenuByConfig[] }, { id: MENU_ID.IAM, - key: FEATURES.IAM, + key: SERVICE_FEATURES.IAM, subMenuList: [ { id: MENU_ID.USER }, { id: MENU_ID.APP }, diff --git a/apps/web/src/services/iam/pages/UserMainPage.vue b/apps/web/src/services/iam/pages/UserMainPage.vue index a1dcd64288..4d0b978897 100644 --- a/apps/web/src/services/iam/pages/UserMainPage.vue +++ b/apps/web/src/services/iam/pages/UserMainPage.vue @@ -7,7 +7,7 @@ import { ApiQueryHelper } from '@cloudforet/core-lib/space-connector/helper'; import { PHorizontalLayout } from '@cloudforet/mirinae'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useGrantScopeGuard } from '@/common/composables/grant-scope-guard'; import { usePageEditableStatus } from '@/common/composables/page-editable-status'; @@ -28,14 +28,14 @@ import { useUserPageStore } from '@/services/iam/store/user-page-store'; const appContextStore = useAppContextStore(); const userPageStore = useUserPageStore(); const userPageState = userPageStore.state; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const { hasReadWriteAccess } = usePageEditableStatus(); const storeState = reactive({ isAdminMode: computed(() => appContextStore.getters.isAdminMode), globalGrantLoading: computed(() => appContextStore.getters.globalGrantLoading), - grantInfo: computed(() => userStore.state.currentGrantInfo), + grantInfo: computed(() => authorizationStore.state.currentGrantInfo), }); const userListApiQueryHelper = new ApiQueryHelper() diff --git a/apps/web/src/services/iam/routes/routes.ts b/apps/web/src/services/iam/routes/routes.ts index 3217d92cb9..dafc64fb34 100644 --- a/apps/web/src/services/iam/routes/routes.ts +++ b/apps/web/src/services/iam/routes/routes.ts @@ -1,8 +1,5 @@ import type { RouteConfig } from 'vue-router'; -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect-route-helper'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; @@ -62,10 +59,7 @@ const iamRoutes: RouteConfig = { menuId: MENU_ID.IAM, translationId: MENU_INFO_MAP[MENU_ID.IAM].translationId, }, - redirect: (to) => { - const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); - }, + redirect: (to) => getRedirectRouteByPagePermission(to), component: IamContainer, children: iamRoutesChildren, }; diff --git a/apps/web/src/services/iam/store/user-page-store.ts b/apps/web/src/services/iam/store/user-page-store.ts index eaf2add9a6..75eed15da5 100644 --- a/apps/web/src/services/iam/store/user-page-store.ts +++ b/apps/web/src/services/iam/store/user-page-store.ts @@ -22,14 +22,14 @@ import type { WorkspaceUserGetParameters } from '@/api-clients/identity/workspac import type { WorkspaceUserListParameters } from '@/api-clients/identity/workspace-user/schema/api-verbs/list'; import type { WorkspaceUserModel, SummaryWorkspaceUserModel } from '@/api-clients/identity/workspace-user/schema/model'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import ErrorHandler from '@/common/composables/error/errorHandler'; import type { UserListItemType, ModalSettingState, ModalState } from '@/services/iam/types/user-type'; export const useUserPageStore = defineStore('page-user', () => { - const userStore = useUserStore(); + const authorizationStore = useAuthorizationStore(); const state = reactive({ isAdminMode: false, @@ -53,7 +53,7 @@ export const useUserPageStore = defineStore('page-user', () => { } as ModalState, }); const getters = reactive({ - isWorkspaceOwner: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), + isWorkspaceOwner: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_OWNER), selectedUsers: computed(():UserListItemType[] => { if (state.selectedIndices.length === 1 && !isEmpty(state.selectedUser)) return [state.selectedUser]; const users: UserListItemType[] = []; diff --git a/apps/web/src/services/info/components/NoticeDetail.vue b/apps/web/src/services/info/components/NoticeDetail.vue index 1b478cc026..a5e9f3fb9d 100644 --- a/apps/web/src/services/info/components/NoticeDetail.vue +++ b/apps/web/src/services/info/components/NoticeDetail.vue @@ -20,7 +20,7 @@ import type { PostModel } from '@/schema/board/post/model'; import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useNoticeStore } from '@/store/notice'; +import { useNoticeStore } from '@/store/notice/notice-store'; import { useUserStore } from '@/store/user/user-store'; import TextEditorViewer from '@/common/components/editor/TextEditorViewer.vue'; diff --git a/apps/web/src/services/info/components/NoticeList.vue b/apps/web/src/services/info/components/NoticeList.vue index c6c783c6a4..e0b96e7eb5 100644 --- a/apps/web/src/services/info/components/NoticeList.vue +++ b/apps/web/src/services/info/components/NoticeList.vue @@ -21,7 +21,7 @@ import type { PostModel } from '@/schema/board/post/model'; import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useNoticeStore } from '@/store/notice'; +import { useNoticeStore } from '@/store/notice/notice-store'; import ErrorHandler from '@/common/composables/error/errorHandler'; diff --git a/apps/web/src/services/info/routes/routes.ts b/apps/web/src/services/info/routes/routes.ts index a7f67b9c21..8028016b9c 100644 --- a/apps/web/src/services/info/routes/routes.ts +++ b/apps/web/src/services/info/routes/routes.ts @@ -1,8 +1,5 @@ import type { RouteConfig } from 'vue-router'; -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect-route-helper'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; @@ -22,10 +19,7 @@ const infoRoutes: RouteConfig = { menuId: MENU_ID.INFO, translationId: MENU_INFO_MAP[MENU_ID.INFO].translationId, }, - redirect: (to) => { - const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); - }, + redirect: (to) => getRedirectRouteByPagePermission(to), component: InfoContainer, children: [ { diff --git a/apps/web/src/services/landing/components/DomainLandingStartBanner.vue b/apps/web/src/services/landing/components/DomainLandingStartBanner.vue index fad60f0b05..435b4f806b 100644 --- a/apps/web/src/services/landing/components/DomainLandingStartBanner.vue +++ b/apps/web/src/services/landing/components/DomainLandingStartBanner.vue @@ -8,22 +8,16 @@ import { screens, PTextButton } from '@cloudforet/mirinae'; import type { WorkspaceModel } from '@/api-clients/identity/workspace/schema/model'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useUserStore } from '@/store/user/user-store'; - -import type { PageAccessMap } from '@/lib/access-control/config'; import { LANDING_ROUTE } from '@/services/landing/routes/route-constant'; const userWorkspaceStore = useUserWorkspaceStore(); const userWorkspaceGetters = userWorkspaceStore.getters; -const userStore = useUserStore(); - const router = useRouter(); const { width } = useWindowSize(); const storeState = reactive({ - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), workspaceList: computed(() => userWorkspaceGetters.workspaceList), }); const state = reactive({ diff --git a/apps/web/src/services/my-page/components/NotificationAddForm.vue b/apps/web/src/services/my-page/components/NotificationAddForm.vue index a55012ccf6..d1aa6f4ec5 100644 --- a/apps/web/src/services/my-page/components/NotificationAddForm.vue +++ b/apps/web/src/services/my-page/components/NotificationAddForm.vue @@ -15,8 +15,7 @@ import type { ChannelSchedule } from '@/schema/notification/type'; import type { UserChannelCreateParameters as UserChannelCreateParametersV1 } from '@/schema/notification/user-channel/api-verbs/create'; import { i18n } from '@/translations'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; - +import { useGlobalConfigUiAffectsSchema } from '@/lib/config/global-config/composables/use-global-config-ui-affects-schema'; import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; import type { ScheduleSettingFormType } from '@/common/components/schedule-setting-form/schedule-setting-form'; @@ -38,10 +37,10 @@ const props = withDefaults(defineProps<{ }); const router = useRouter(); -const globalConfigSchemaStore = useGlobalConfigSchemaStore(); +const alertManagerUiAffectsSchema = useGlobalConfigUiAffectsSchema('ALERT_MANAGER'); const state = reactive({ - visibleUserNotification: computed(() => globalConfigSchemaStore.state.uiAffectsSchema.ALERT_MANAGER?.visibleUserNotification ?? false), + visibleUserNotification: computed(() => alertManagerUiAffectsSchema.value?.visibleUserNotification ?? false), isDataValid: false, notificationLevel: 'LV1' as NotificationLevel, // diff --git a/apps/web/src/services/my-page/components/NotificationChannelItemSchedule.vue b/apps/web/src/services/my-page/components/NotificationChannelItemSchedule.vue index 21034ab726..4343665a7d 100644 --- a/apps/web/src/services/my-page/components/NotificationChannelItemSchedule.vue +++ b/apps/web/src/services/my-page/components/NotificationChannelItemSchedule.vue @@ -1,4 +1,6 @@ diff --git a/apps/web/src/services/project/v1/pages/ProjectSummaryPage.vue b/apps/web/src/services/project/v1/pages/ProjectSummaryPage.vue index 87446ccd1d..fdb83e4bee 100644 --- a/apps/web/src/services/project/v1/pages/ProjectSummaryPage.vue +++ b/apps/web/src/services/project/v1/pages/ProjectSummaryPage.vue @@ -11,8 +11,7 @@ import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { ProjectAlertConfigListParameters } from '@/schema/monitoring/project-alert-config/api-verbs/list'; import type { ProjectAlertConfigModel } from '@/schema/monitoring/project-alert-config/model'; -import { useGlobalConfigSchemaStore } from '@/store/global-config-schema/global-config-schema-store'; - +import { useGlobalConfigUiAffectsSchema } from '@/lib/config/global-config/composables/use-global-config-ui-affects-schema'; import { MENU_ID } from '@/lib/menu/config'; import { useContentsAccessibility } from '@/common/composables/contents-accessibility'; @@ -34,13 +33,13 @@ interface Props { } const props = defineProps(); -const globalConfigSchemaStore = useGlobalConfigSchemaStore(); +const alertManagerUiAffectsSchema = useGlobalConfigUiAffectsSchema('ALERT_MANAGER'); const { visibleContents: visibleAssetContents } = useContentsAccessibility(MENU_ID.ASSET_INVENTORY); const { visibleContents: visibleAlertContents } = useContentsAccessibility(MENU_ID.ALERT_MANAGER); const state = reactive({ - visibleAlertTab: computed(() => visibleAlertContents.value && (globalConfigSchemaStore.state.uiAffectsSchema.ALERT_MANAGER?.visibleProjectAlertTab ?? false)), + visibleAlertTab: computed(() => visibleAlertContents.value && (alertManagerUiAffectsSchema.value?.visibleProjectAlertTab ?? false)), hasAlertConfig: false, deprecatedNotiVisible: true, }); diff --git a/apps/web/src/services/project/v1/stores/project-page-store.ts b/apps/web/src/services/project/v1/stores/project-page-store.ts index e9315e43f7..0774c56f7f 100644 --- a/apps/web/src/services/project/v1/stores/project-page-store.ts +++ b/apps/web/src/services/project/v1/stores/project-page-store.ts @@ -14,7 +14,7 @@ import type { ProjectUpdateParameters } from '@/api-clients/identity/project/sch import type { ProjectUpdateProjectTypeParameters } from '@/api-clients/identity/project/schema/api-verbs/update-project-type'; import type { ProjectModel } from '@/api-clients/identity/project/schema/model'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import getRandomId from '@/lib/random-id-generator'; @@ -24,13 +24,12 @@ import type { } from '@/common/modules/project/project-tree-type'; import { useProjectTree } from '@/common/modules/project/use-project-tree'; - const projectTreeHelper = useProjectTree(); export const useProjectPageStore = defineStore('page-project', () => { - const userStore = useUserStore(); + const authorizationStore = useAuthorizationStore(); const _state = reactive({ - currentRoleType: computed(() => userStore.state.currentRoleInfo?.roleType), + currentRoleType: computed(() => authorizationStore.state.currentRoleInfo?.roleType), }); const state = reactive({ projectTreeKey: getRandomId(), diff --git a/apps/web/src/services/project/v2/components/ProjectGroupMemberManagementModal.vue b/apps/web/src/services/project/v2/components/ProjectGroupMemberManagementModal.vue index 0aa0d15051..d86555394b 100644 --- a/apps/web/src/services/project/v2/components/ProjectGroupMemberManagementModal.vue +++ b/apps/web/src/services/project/v2/components/ProjectGroupMemberManagementModal.vue @@ -13,10 +13,11 @@ import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/types/controls/ import { useProjectGroupApi } from '@/api-clients/identity/project-group/composables/use-project-group-api'; import type { ProjectGroupRemoveUsersParameters } from '@/api-clients/identity/project-group/schema/api-verbs/remove-users'; +import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useUserReferenceStore } from '@/store/reference/user-reference-store'; -import { useUserStore } from '@/store/user/user-store'; import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; @@ -31,8 +32,8 @@ const visible = computed(() => projectPageModalStore.state.projectGroupMemberMod const targetId = computed(() => projectPageModalStore.state.targetId); /* mode */ -const userStore = useUserStore(); -const readonlyMode = computed(() => userStore.state.currentRoleInfo?.roleType !== 'WORKSPACE_OWNER'); +const authorizationStore = useAuthorizationStore(); +const readonlyMode = computed(() => authorizationStore.state.currentRoleInfo?.roleType !== ROLE_TYPE.WORKSPACE_OWNER); /* project group users */ const { projectGroupAPI } = useProjectGroupApi(); diff --git a/apps/web/src/services/service-account/pages/ServiceAccountDetailPage.vue b/apps/web/src/services/service-account/pages/ServiceAccountDetailPage.vue index be0610068c..19317e2daa 100644 --- a/apps/web/src/services/service-account/pages/ServiceAccountDetailPage.vue +++ b/apps/web/src/services/service-account/pages/ServiceAccountDetailPage.vue @@ -20,12 +20,11 @@ import type { TrustedAccountGetParameters } from '@/api-clients/identity/trusted import type { TrustedAccountModel } from '@/api-clients/identity/trusted-account/schema/model'; import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { ProjectReferenceMap } from '@/store/reference/project-reference-store'; import type { ProviderReferenceMap } from '@/store/reference/provider-reference-store'; -import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import type { MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; @@ -58,7 +57,7 @@ const serviceAccountSchemaStore = useServiceAccountSchemaStore(); const serviceAccountPageStore = useServiceAccountPageStore(); const allReferenceStore = useAllReferenceStore(); const appContextStore = useAppContextStore(); -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const route = useRoute(); @@ -69,8 +68,7 @@ const storeState = reactive({ ? serviceAccountSchemaStore.getters.trustedAccountSchema?.options?.external_link : serviceAccountSchemaStore.getters.generalAccountSchema?.options?.external_link)), isAdminMode: computed(() => appContextStore.getters.isAdminMode), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), }); const state = reactive({ loading: true, @@ -83,7 +81,7 @@ const state = reactive({ } return targetMenuId; }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), + hasReadWriteAccess: computed(() => authorizationStore.getters.pageAccessPermissionMap[state.selectedMenuId]?.write), originServiceAccountItem: computed(() => serviceAccountPageStore.state.originServiceAccountItem), serviceAccountType: computed(() => serviceAccountPageStore.state.serviceAccountType), isTrustedAccount: computed(() => state.serviceAccountType === ACCOUNT_TYPE.TRUSTED), diff --git a/apps/web/src/services/service-account/pages/ServiceAccountPage.vue b/apps/web/src/services/service-account/pages/ServiceAccountPage.vue index 263aff2a68..b7fb65daf7 100644 --- a/apps/web/src/services/service-account/pages/ServiceAccountPage.vue +++ b/apps/web/src/services/service-account/pages/ServiceAccountPage.vue @@ -33,13 +33,13 @@ import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { CURRENCY_SYMBOL } from '@/store/display/constant'; import type { Currency } from '@/store/display/type'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import type { ProviderReferenceMap, ProviderItem } from '@/store/reference/provider-reference-store'; import { useUserStore } from '@/store/user/user-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { dynamicFieldsToExcelDataFields } from '@/lib/excel-export'; import { FILE_NAME_PREFIX } from '@/lib/excel-export/constant'; import { downloadExcel } from '@/lib/helper/file-download-helper'; @@ -83,6 +83,7 @@ const userWorkspaceStore = useUserWorkspaceStore(); const appContextStore = useAppContextStore(); const allReferenceStore = useAllReferenceStore(); const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const { hasReadWriteAccess } = usePageEditableStatus(); @@ -90,7 +91,6 @@ const { referenceFieldFormatter } = useReferenceFieldFormatter(); const storeState = reactive({ - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), currency: computed(() => serviceAccountPageGetters.currency), }); const state = reactive({ @@ -107,7 +107,7 @@ const state = reactive({ selectedProviderName: computed(() => state.providers[state.selectedProvider]?.label), timezone: computed(() => userStore.state.timezone || 'UTC'), grantLoading: computed(() => appContextStore.getters.globalGrantLoading), - currentGrantInfo: computed(() => userStore.state.currentGrantInfo), + currentGrantInfo: computed(() => authorizationStore.state.currentGrantInfo), isAgentModeAccount: computed(() => state.selectedProvider === 'kubernetes'), }); @@ -130,7 +130,7 @@ const typeOptionState = reactive({ }); const tableState = reactive({ - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), items: [] as ServiceAccountModel[] | TrustedAccountModel[], schema: computed(() => (tableState.isTrustedAccount ? serviceAccountSchemaState.trustedAccountTableSchema : serviceAccountSchemaState.generalAccountTableSchema)), diff --git a/apps/web/src/services/service-account/routes/routes.ts b/apps/web/src/services/service-account/routes/routes.ts index 23dffa3474..f4b4827da1 100644 --- a/apps/web/src/services/service-account/routes/routes.ts +++ b/apps/web/src/services/service-account/routes/routes.ts @@ -1,8 +1,5 @@ import type { RouteConfig } from 'vue-router'; -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect-route-helper'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; @@ -18,11 +15,10 @@ const ServiceAccountDetailPage = () => import('@/services/service-account/pages/ const ServiceAccountAddPage = () => import('@/services/service-account/pages/ServiceAccountAddPage.vue'); -const userStore = useUserStore(pinia); const serviceAccountRoute: RouteConfig = { path: 'service-account', meta: { menuId: MENU_ID.SERVICE_ACCOUNT, translationId: MENU_INFO_MAP[MENU_ID.SERVICE_ACCOUNT].translationId }, - redirect: (to) => getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap), + redirect: (to) => getRedirectRouteByPagePermission(to), component: ServiceAccountContainer, children: [ { diff --git a/apps/web/src/services/workspace-home/components/BookmarkBoard.vue b/apps/web/src/services/workspace-home/components/BookmarkBoard.vue index 780465e3ee..df56488e71 100644 --- a/apps/web/src/services/workspace-home/components/BookmarkBoard.vue +++ b/apps/web/src/services/workspace-home/components/BookmarkBoard.vue @@ -13,7 +13,7 @@ import type { UserConfigModel } from '@/api-clients/config/user-config/schema/mo import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import { i18n } from '@/translations'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { assetUrlConverter } from '@/lib/helper/asset-helper'; @@ -46,10 +46,10 @@ const bookmarkState = bookmarkStore.state; const workspaceHomePageStore = useWorkspaceHomePageStore(); const workspaceHomePageState = workspaceHomePageStore.state; const workspaceHomePageGetters = workspaceHomePageStore.getters; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const storeState = reactive({ - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), selectedBookmarks: computed(() => bookmarkState.selectedBookmarks), bookmarkType: computed(() => bookmarkState.bookmarkType), diff --git a/apps/web/src/services/workspace-home/components/BookmarkFullMode.vue b/apps/web/src/services/workspace-home/components/BookmarkFullMode.vue index 0270eb6583..d4b03ec7c6 100644 --- a/apps/web/src/services/workspace-home/components/BookmarkFullMode.vue +++ b/apps/web/src/services/workspace-home/components/BookmarkFullMode.vue @@ -3,7 +3,7 @@ import { computed, reactive } from 'vue'; import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; import { useBookmarkStore } from '@/common/components/bookmark/store/bookmark-store'; import type { BookmarkItem } from '@/common/components/bookmark/type/type'; @@ -26,13 +26,13 @@ const bookmarkStore = useBookmarkStore(); const bookmarkState = bookmarkStore.state; const workspaceHomePageStore = useWorkspaceHomePageStore(); const workspaceHomePageState = workspaceHomePageStore.state; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const storeState = reactive({ bookmarkType: computed(() => bookmarkState.bookmarkType), isFileFullMode: computed(() => workspaceHomePageState.isFileFullMode), - isWorkspaceMember: computed(() => userStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), + isWorkspaceMember: computed(() => authorizationStore.state.currentRoleInfo?.roleType === ROLE_TYPE.WORKSPACE_MEMBER), }); diff --git a/apps/web/src/services/workspace-home/components/UserConfigRecent.vue b/apps/web/src/services/workspace-home/components/UserConfigRecent.vue index e4d1910c8e..a9eadc905e 100644 --- a/apps/web/src/services/workspace-home/components/UserConfigRecent.vue +++ b/apps/web/src/services/workspace-home/components/UserConfigRecent.vue @@ -1,6 +1,6 @@ diff --git a/apps/web/src/services/workspace-home/components/WorkspaceInfo.vue b/apps/web/src/services/workspace-home/components/WorkspaceInfo.vue index b2c8a4ff1c..8d8e95d990 100644 --- a/apps/web/src/services/workspace-home/components/WorkspaceInfo.vue +++ b/apps/web/src/services/workspace-home/components/WorkspaceInfo.vue @@ -15,9 +15,8 @@ import { i18n } from '@/translations'; import { useAppContextStore } from '@/store/app-context/app-context-store'; import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; -import { useUserStore } from '@/store/user/user-store'; +import { useAuthorizationStore } from '@/store/authorization/authorization-store'; -import type { PageAccessMap } from '@/lib/access-control/config'; import { MENU_ID } from '@/lib/menu/config'; import FavoriteButton from '@/common/modules/favorites/favorite-button/FavoriteButton.vue'; @@ -51,7 +50,7 @@ const appPageStore = useAppPageStore(); const appContextStore = useAppContextStore(); const workspaceHomePageStore = useWorkspaceHomePageStore(); const workspaceHomePageState = workspaceHomePageStore.state; -const userStore = useUserStore(); +const authorizationStore = useAuthorizationStore(); const router = useRouter(); @@ -61,7 +60,6 @@ const storeState = reactive({ workspaceList: computed(() => userWorkspaceGetters.workspaceList), workspaceUserTotalCount: computed(() => workspaceHomePageState.workspaceUserTotalCount), appsTotalCount: computed(() => workspaceHomePageState.appsTotalCount), - pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), }); const state = reactive({ selectedWorkspace: computed(() => storeState.workspaceList.find((workspace) => workspace.workspace_id === storeState.currentWorkspace?.workspace_id) || {} as WorkspaceModel), @@ -183,7 +181,7 @@ const routerToWorkspaceUser = (isOpenModal: boolean) => { -