From ac4314dcda8f8f416d5f586a2365cd75bbd00610 Mon Sep 17 00:00:00 2001 From: "NaYeong,Kim" Date: Mon, 24 Mar 2025 11:08:09 +0900 Subject: [PATCH 1/6] feat: apply new global config (route, menu, API) (#5709) * feat: create each feature configurator Signed-off-by: NaYeong,Kim * feat(route): changed to central management method for config Signed-off-by: NaYeong,Kim * feat(menu): changed to central management method for config Signed-off-by: NaYeong,Kim * feat: replace existing config usage with values from the menu store Signed-off-by: NaYeong,Kim * chore: add type Signed-off-by: NaYeong,Kim * feat(route, menu): apply version dependency between services Signed-off-by: NaYeong,Kim * feat(project): apply version Signed-off-by: NaYeong,Kim * feat(api): create APIClientLoader and add interceptor at SpaceConnector Signed-off-by: NaYeong,Kim * refactor: change the api endpoint to a schema management approach Signed-off-by: NaYeong,Kim * feat: service account top-level menuization Signed-off-by: NaYeong,Kim --------- Signed-off-by: NaYeong,Kim --- .../src/api-clients/api-clients-schema.json | 12 + apps/web/src/api-clients/loader.ts | 83 +++++++ .../CustomFieldModalForDynamicLayout.vue | 6 +- .../navigations/gnb/GNBNavigationRail.vue | 2 +- .../top-bar/modules/top-bar-search/helper.ts | 3 +- .../lib/access-control/page-access-helper.ts | 10 +- .../access-control/redirect-route-helper.ts | 44 +--- .../src/lib/helper/router-recent-helper.ts | 3 +- apps/web/src/lib/menu/config.ts | 2 +- apps/web/src/lib/menu/menu-architecture.ts | 228 +----------------- apps/web/src/lib/menu/menu-info.ts | 5 +- apps/web/src/lib/reference/referenceRouter.ts | 6 +- .../src/lib/site-initializer/api-client.ts | 9 +- apps/web/src/lib/site-initializer/index.ts | 34 ++- apps/web/src/router/admin-routes.ts | 22 -- .../alert-manager-v1-integral-routes.ts | 67 ----- .../alert-manager-v1-workspace-routes.ts | 4 +- apps/web/src/router/integral-routes.ts | 11 +- .../components/WorkspaceGroupTabWorkspace.vue | 4 +- .../WorkspaceGroupWokrspaceDeleteModal.vue | 4 +- .../components/WorkspaceManagementTable.vue | 6 +- .../components/WorkspacesDeleteModal.vue | 4 +- .../services/alert-manager/configurator.ts | 37 +++ .../alert-manager/v1/routes/routes.ts | 6 +- .../alert-manager/v2/routes/routes.ts | 2 +- .../components/CloudServiceDetailTabs.vue | 17 +- .../services/asset-inventory/configurator.ts | 43 ++++ .../pages/CloudServicePage.vue | 3 +- .../asset-inventory/pages/SecurityPage.vue | 3 +- .../routes/admin/route-constant.ts | 6 - .../asset-inventory/routes/admin/routes.ts | 43 ---- .../asset-inventory/routes/route-constant.ts | 6 - .../services/asset-inventory/routes/routes.ts | 45 +--- apps/web/src/services/configurator.ts | 137 +++++++++++ .../components/CostAnalysisDataTable.vue | 5 +- .../services/cost-explorer/configurator.ts | 42 ++++ .../services/cost-explorer/routes/routes.ts | 2 +- .../src/services/dashboards/configurator.ts | 30 +++ .../components/RoleManagementTabDetail.vue | 7 +- .../RoleUpdateFormPermissionForm.vue | 8 +- apps/web/src/services/iam/configurator.ts | 58 +++++ .../iam/helpers/role-page-access-menu-list.ts | 10 +- .../iam/routes/admin/route-constant.ts | 4 + .../src/services/iam/routes/admin/routes.ts | 111 +++++---- apps/web/src/services/iam/routes/routes.ts | 62 ++--- .../src/services/info/routes/admin/routes.ts | 4 +- apps/web/src/services/info/routes/routes.ts | 6 +- .../LandingWorkspaceGroupRemoveUserModal.vue | 4 +- .../web/src/services/my-page/routes/routes.ts | 2 +- .../web/src/services/ops-flow/configurator.ts | 37 +++ .../src/services/ops-flow/routes/routes.ts | 2 +- apps/web/src/services/project/configurator.ts | 26 ++ .../v1/components/ProjectDetailTabHeader.vue | 3 +- .../v1/components/ProjectMainProjectCard.vue | 14 +- .../ProjectSummaryServiceAccountsWidget.vue | 6 +- .../v2/components/ProjectMainProjectCard.vue | 14 +- .../ServiceAccountContainer.vue | 9 + .../ServiceAccountAddClusterModal.vue | 6 +- .../ServiceAccountAddClusterScriptField.vue | 0 .../ServiceAccountAttachedGeneralAccounts.vue | 10 +- .../components/ServiceAccountAutoSync.vue | 8 +- .../ServiceAccountAutoSyncDetail.vue | 4 +- .../components/ServiceAccountAutoSyncForm.vue | 4 +- .../ServiceAccountAutoSyncMappingMethod.vue | 4 +- .../components/ServiceAccountBadge.vue | 2 +- .../ServiceAccountBaseInformation.vue | 10 +- .../ServiceAccountBaseInformationDetail.vue | 8 +- .../ServiceAccountBaseInformationForm.vue | 6 +- .../components/ServiceAccountCluster.vue | 8 +- .../ServiceAccountClusterDetail.vue | 2 +- .../components/ServiceAccountCredentials.vue | 8 +- .../ServiceAccountCredentialsDetail.vue | 2 +- .../ServiceAccountCredentialsForm.vue | 6 +- .../components/ServiceAccountDeleteModal.vue | 12 +- .../components/ServiceAccountEditModal.vue | 2 +- .../ServiceAccountProjectDetail.vue | 0 .../components/ServiceAccountProjectForm.vue | 2 +- .../components/WorkspaceDropdown.vue | 0 .../services/service-account/configurator.ts | 24 ++ .../constants/service-account-constant.ts | 0 .../helpers/agent-mode-helper.ts | 0 .../dynamic-layout-schema-template.ts | 2 +- .../dynamic-ui-schema-generator/index.ts | 6 +- .../dynamic-ui-schema-generator/type.ts | 0 .../pages/ServiceAccountAddPage.vue | 27 +-- .../pages/ServiceAccountDetailPage.vue | 28 +-- .../pages/ServiceAccountPage.vue | 41 ++-- .../routes/admin/route-constant.ts | 8 + .../service-account/routes/admin/routes.ts | 56 +++++ .../service-account/routes/route-constant.ts | 8 + .../services/service-account/routes/routes.ts | 61 +++++ .../stores/service-account-agent-store.ts | 0 .../stores/service-account-page-store.ts | 2 +- .../stores/service-account-schema-store.ts | 6 +- .../types/service-account-page-type.ts | 0 .../components/AccountSummary.vue | 6 +- .../components/AssetSummary.vue | 3 +- .../config/global-config-setting-store.ts | 36 +++ apps/web/src/store/display/display-store.ts | 22 +- apps/web/src/store/display/type.ts | 1 - apps/web/src/store/menu/menu-store.ts | 53 ++++ .../escalation-policy-reference-store.ts | 27 +-- .../reference/service-reference-store.ts | 11 +- .../reference/webhook-reference-store.ts | 15 +- apps/web/src/store/user/user-store.ts | 4 +- .../core-lib/src/space-connector/index.ts | 19 +- .../src/space-connector/service-api.ts | 18 +- .../console-translation-2.8.babel | 42 ++-- packages/language-pack/en.json | 2 +- packages/language-pack/ja.json | 2 +- packages/language-pack/ko.json | 2 +- 111 files changed, 1169 insertions(+), 850 deletions(-) create mode 100644 apps/web/src/api-clients/api-clients-schema.json create mode 100644 apps/web/src/api-clients/loader.ts delete mode 100644 apps/web/src/router/admin-routes.ts delete mode 100644 apps/web/src/router/alert-manager-v1-integral-routes.ts create mode 100644 apps/web/src/services/alert-manager/configurator.ts create mode 100644 apps/web/src/services/asset-inventory/configurator.ts create mode 100644 apps/web/src/services/configurator.ts create mode 100644 apps/web/src/services/cost-explorer/configurator.ts create mode 100644 apps/web/src/services/dashboards/configurator.ts create mode 100644 apps/web/src/services/iam/configurator.ts create mode 100644 apps/web/src/services/ops-flow/configurator.ts create mode 100644 apps/web/src/services/project/configurator.ts create mode 100644 apps/web/src/services/service-account/ServiceAccountContainer.vue rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountAddClusterModal.vue (98%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountAddClusterScriptField.vue (100%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountAttachedGeneralAccounts.vue (97%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountAutoSync.vue (94%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountAutoSyncDetail.vue (95%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountAutoSyncForm.vue (97%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountAutoSyncMappingMethod.vue (98%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountBadge.vue (93%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountBaseInformation.vue (94%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountBaseInformationDetail.vue (90%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountBaseInformationForm.vue (96%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountCluster.vue (96%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountClusterDetail.vue (97%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountCredentials.vue (97%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountCredentialsDetail.vue (98%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountCredentialsForm.vue (98%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountDeleteModal.vue (92%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountEditModal.vue (98%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountProjectDetail.vue (100%) rename apps/web/src/services/{asset-inventory => service-account}/components/ServiceAccountProjectForm.vue (97%) rename apps/web/src/services/{asset-inventory => service-account}/components/WorkspaceDropdown.vue (100%) create mode 100644 apps/web/src/services/service-account/configurator.ts rename apps/web/src/services/{asset-inventory => service-account}/constants/service-account-constant.ts (100%) rename apps/web/src/services/{asset-inventory => service-account}/helpers/agent-mode-helper.ts (100%) rename apps/web/src/services/{asset-inventory => service-account}/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template.ts (99%) rename apps/web/src/services/{asset-inventory => service-account}/helpers/dynamic-ui-schema-generator/index.ts (96%) rename apps/web/src/services/{asset-inventory => service-account}/helpers/dynamic-ui-schema-generator/type.ts (100%) rename apps/web/src/services/{asset-inventory => service-account}/pages/ServiceAccountAddPage.vue (92%) rename apps/web/src/services/{asset-inventory => service-account}/pages/ServiceAccountDetailPage.vue (92%) rename apps/web/src/services/{asset-inventory => service-account}/pages/ServiceAccountPage.vue (92%) create mode 100644 apps/web/src/services/service-account/routes/admin/route-constant.ts create mode 100644 apps/web/src/services/service-account/routes/admin/routes.ts create mode 100644 apps/web/src/services/service-account/routes/route-constant.ts create mode 100644 apps/web/src/services/service-account/routes/routes.ts rename apps/web/src/services/{asset-inventory => service-account}/stores/service-account-agent-store.ts (100%) rename apps/web/src/services/{asset-inventory => service-account}/stores/service-account-page-store.ts (99%) rename apps/web/src/services/{asset-inventory => service-account}/stores/service-account-schema-store.ts (97%) rename apps/web/src/services/{asset-inventory => service-account}/types/service-account-page-type.ts (100%) create mode 100644 apps/web/src/store/config/global-config-setting-store.ts create mode 100644 apps/web/src/store/menu/menu-store.ts diff --git a/apps/web/src/api-clients/api-clients-schema.json b/apps/web/src/api-clients/api-clients-schema.json new file mode 100644 index 0000000000..a00c420343 --- /dev/null +++ b/apps/web/src/api-clients/api-clients-schema.json @@ -0,0 +1,12 @@ +{ + "DASHBOARD": { + "V1": "v1/dashboard" + }, + "ALERT_MANAGER": { + "V1": "v1/monitoring", + "V2": "v2/alertManager" + }, + "PROJECT": { + "V1": "v1/project" + } +} diff --git a/apps/web/src/api-clients/loader.ts b/apps/web/src/api-clients/loader.ts new file mode 100644 index 0000000000..a601637677 --- /dev/null +++ b/apps/web/src/api-clients/loader.ts @@ -0,0 +1,83 @@ +import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; + +import apiClientsSchema from '@/api-clients/api-clients-schema.json'; + +import config from '@/lib/config'; + +interface ServiceConfig { + ENABLED: boolean; + VERSION: string; +} + +interface GlobalConfig { + SERVICES: { + [key: string]: ServiceConfig; + }; +} + +class APIClientLoader { + // eslint-disable-next-line no-undef + [key: string]: any; + + private config: GlobalConfig['SERVICES'] | null = null; + + private apiClientsSchema: Record> = {}; + + async initialize() { + await config.init(); + this.config = config.get('SERVICES') || {}; + this.apiClientsSchema = apiClientsSchema; + + this.defineDynamicServices(); + } + + private defineDynamicServices() { + if (!this.apiClientsSchema) { + throw new Error('[APIClientLoader] APIClientLoader 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) { + console.warn(`[APIClientLoader] ${serviceName} is disabled or not configured.`); + return null; + } + + const apiClientSchemaByService = this.apiClientsSchema[serviceName]; + if (!apiClientSchemaByService) { + console.warn('[APIClientLoader] apiClientSchemaByService is not configured.'); + return null; + } + + const version = serviceConfig.VERSION; + const endpointDefinition = apiClientSchemaByService[version]; + if (!endpointDefinition) { + console.error(`[APIClientLoader] No endpoint mapping found for ${serviceName} with version ${version}.`); + return null; + } + + const [clientVersion, clientEndpoint] = endpointDefinition.split('/'); + + const client = clientVersion === 'v1' ? SpaceConnector.client : SpaceConnector.clientV2; + const endpoint = client[clientEndpoint]; + if (!endpoint) { + console.error(`[APIClientLoader] No client found for endpoint "${clientEndpoint}" using "${clientVersion}".`); + return null; + } + + return { endpoint, version }; + } +} + +export default new APIClientLoader(); diff --git a/apps/web/src/common/modules/custom-table/custom-field-modal/CustomFieldModalForDynamicLayout.vue b/apps/web/src/common/modules/custom-table/custom-field-modal/CustomFieldModalForDynamicLayout.vue index f4266fe0c0..31adf2a591 100644 --- a/apps/web/src/common/modules/custom-table/custom-field-modal/CustomFieldModalForDynamicLayout.vue +++ b/apps/web/src/common/modules/custom-table/custom-field-modal/CustomFieldModalForDynamicLayout.vue @@ -21,12 +21,12 @@ import { useProxyValue } from '@/common/composables/proxy-state'; import { TAGS_OPTIONS, TAGS_PREFIX } from '@/common/modules/custom-table/custom-field-modal/config'; import ColumnItemForDynamicLayout from '@/common/modules/custom-table/custom-field-modal/modules/ColumnItemForDynamicLayout.vue'; -import { convertAgentModeOptions } from '@/services/asset-inventory/helpers/agent-mode-helper'; -import { getServiceAccountTableSchema, updateCustomTableSchema } from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator'; +import { convertAgentModeOptions } from '@/services/service-account/helpers/agent-mode-helper'; +import { getServiceAccountTableSchema, updateCustomTableSchema } from '@/services/service-account/helpers/dynamic-ui-schema-generator'; import type { GetSchemaParams, ResourceType, -} from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator/type'; +} from '@/services/service-account/helpers/dynamic-ui-schema-generator/type'; const SelectCloudServiceTagColumns = () => import('@/common/modules/custom-table/custom-field-modal/modules/SelectCloudServiceTagColumns.vue'); const SelectTagColumns = () => import('@/common/modules/custom-table/custom-field-modal/modules/SelectTagColumns.vue'); diff --git a/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue b/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue index ddf03e1609..f4593f0749 100644 --- a/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue +++ b/apps/web/src/common/modules/navigations/gnb/GNBNavigationRail.vue @@ -60,7 +60,7 @@ const storeState = reactive({ costDataSource: computed(() => allReferenceGetters.costDataSource), }); -const noParentsMenuList:MenuId[] = [MENU_ID.DASHBOARDS, MENU_ID.WORKSPACE_HOME, MENU_ID.PROJECT]; +const noParentsMenuList:MenuId[] = [MENU_ID.WORKSPACE_HOME, MENU_ID.DASHBOARDS, MENU_ID.PROJECT, MENU_ID.SERVICE_ACCOUNT]; const state = reactive({ isInit: false as boolean|undefined, diff --git a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/helper.ts b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/helper.ts index 1a9fe88780..6dd2444f28 100644 --- a/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/helper.ts +++ b/apps/web/src/common/modules/navigations/top-bar/modules/top-bar-search/helper.ts @@ -8,6 +8,7 @@ import type { SearchTab } from '@/common/modules/navigations/top-bar/modules/top import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; import { DASHBOARDS_ROUTE } from '@/services/dashboards/routes/route-constant'; import { PROJECT_ROUTE_V1 } from '@/services/project/v1/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; const queryHelper = new QueryHelper(); @@ -15,7 +16,7 @@ export const topBarSearchReferenceRouter = (type: Exclude, switch (type) { case SEARCH_TAB.SERVICE_ACCOUNT: return { - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, + name: SERVICE_ACCOUNT_ROUTE.DETAIL._NAME, params: { serviceAccountId: resourceId, workspaceId }, }; case SEARCH_TAB.PROJECT: diff --git a/apps/web/src/lib/access-control/page-access-helper.ts b/apps/web/src/lib/access-control/page-access-helper.ts index 56f8db059a..063ed6b5c6 100644 --- a/apps/web/src/lib/access-control/page-access-helper.ts +++ b/apps/web/src/lib/access-control/page-access-helper.ts @@ -1,5 +1,7 @@ import type { RoleType } from '@/api-clients/identity/role/type'; +import { useMenuStore } from '@/store/menu/menu-store'; + import type { PageAccessMap, } from '@/lib/access-control/config'; @@ -11,9 +13,7 @@ import { WORKSPACE_OWNER_DEFAULT_PERMISSIONS, WORKSPACE_USER_MINIMAL_PERMISSIONS, } from '@/lib/access-control/config'; -import config from '@/lib/config'; import type { Menu, MenuId } from '@/lib/menu/config'; -import { MENU_LIST, MENU_LIST_FOR_ALERT_MANAGER_V2 } from '@/lib/menu/menu-architecture'; import type { LSBItem, LSBMenu } from '@/common/modules/navigations/lsb/type'; @@ -38,10 +38,10 @@ export const flattenMenu = (menuList: Menu[]): Menu[] => menuList.flatMap((menu) ...(menu.subMenuList ? flattenMenu(menu.subMenuList) : []), ]); -export const getPageAccessMapFromRawData = (pageAccessPermissions?: string[], domainId?: string): PageAccessMap => { +export const getPageAccessMapFromRawData = (pageAccessPermissions?: string[]): PageAccessMap => { + const menuStore = useMenuStore(); const result: PageAccessMap = {}; - const isAlertManagerVersionV2 = (config.get('ADVANCED_SERVICE')?.alert_manager_v2 ?? []).includes(domainId); - const menuListByVersion = (isAlertManagerVersionV2 ? MENU_LIST_FOR_ALERT_MANAGER_V2 : MENU_LIST); + const menuListByVersion = menuStore.state.menuList; const flattenedMenuList = flattenMenu(menuListByVersion); const setPermissions = (id: string, read = true, write = true, access = true) => { result[id] = { read, write, access }; 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 835d0e7423..7836ae454b 100644 --- a/apps/web/src/lib/access-control/redirect-route-helper.ts +++ b/apps/web/src/lib/access-control/redirect-route-helper.ts @@ -3,47 +3,25 @@ import type { Location } from 'vue-router/types/router'; import { ERROR_ROUTE } from '@/router/constant'; +import type { FlattenedMenuMap } from '@/store/menu/menu-store'; +import { useMenuStore } from '@/store/menu/menu-store'; + import type { PageAccessMap } from '@/lib/access-control/config'; -import config from '@/lib/config'; -import type { Menu, MenuId } from '@/lib/menu/config'; -import { MENU_LIST, MENU_LIST_FOR_ALERT_MANAGER_V2 } from '@/lib/menu/menu-architecture'; +import type { MenuId } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; -type FlattenedMenuMap = Partial>; -const FLATTENED_MENU_MAP = {}; -const getSubMenuIdsToMap = (menu: Menu, flattenedMenuMap: FlattenedMenuMap = {}): FlattenedMenuMap => { - let results: MenuId[] = []; - const subMenuList = menu.subMenuList; - if (subMenuList) { - subMenuList.forEach((subMenu) => { - results = subMenuList.map((d) => d.id); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getSubMenuIdsToMap(subMenu, flattenedMenuMap); - }); - } - flattenedMenuMap[menu.id] = results; - return flattenedMenuMap; -}; - -const makeFlattenedMenuMap = (domainId:string) => { - const isAlertManagerVersionV2 = (config.get('ADVANCED_SERVICE')?.alert_manager_v2 ?? []).includes(domainId); - const menuListByVersion = (isAlertManagerVersionV2 ? MENU_LIST_FOR_ALERT_MANAGER_V2 : MENU_LIST); - menuListByVersion.forEach((menu) => { - getSubMenuIdsToMap(menu, FLATTENED_MENU_MAP); - }); -}; - -const getSubMenuListByMenuId = (menuId: MenuId): MenuId[] => { - if (FLATTENED_MENU_MAP[menuId]) return FLATTENED_MENU_MAP[menuId]; +const getSubMenuListByMenuId = (menuId: MenuId, flattenedMenu: FlattenedMenuMap): MenuId[] => { + if (flattenedMenu[menuId]) return flattenedMenu[menuId] || []; return []; }; -export const getRedirectRouteByPagePermission = (route: Route, pagePermissionsMap: PageAccessMap, domainId:string): Location => { - const isFlattenedMenuMapEmpty = Object.keys(FLATTENED_MENU_MAP).length === 0; - if (isFlattenedMenuMapEmpty) makeFlattenedMenuMap(domainId); +export const getRedirectRouteByPagePermission = (route: Route, pagePermissionsMap: PageAccessMap): Location => { const menuId = route.meta?.menuId; if (!menuId) return { name: ERROR_ROUTE._NAME, params: { statusCode: '404' } }; - const subMenuIdList = getSubMenuListByMenuId(menuId); + + const menuStore = useMenuStore(); + const generateFlattenedMenuMap = menuStore.getters.generateFlattenedMenuMap; + const subMenuIdList = getSubMenuListByMenuId(menuId, generateFlattenedMenuMap); let redirectMenuId: MenuId|undefined; subMenuIdList.some((subMenuId) => { if (pagePermissionsMap[subMenuId]) { diff --git a/apps/web/src/lib/helper/router-recent-helper.ts b/apps/web/src/lib/helper/router-recent-helper.ts index 4db9fa45a0..e2cf62139d 100644 --- a/apps/web/src/lib/helper/router-recent-helper.ts +++ b/apps/web/src/lib/helper/router-recent-helper.ts @@ -12,6 +12,7 @@ import { MANAGED_COST_QUERY_SET_ID_LIST } from '@/services/cost-explorer/constan import { COST_EXPLORER_ROUTE } from '@/services/cost-explorer/routes/route-constant'; import { DASHBOARDS_ROUTE } from '@/services/dashboards/routes/route-constant'; import { PROJECT_ROUTE_V1 } from '@/services/project/v1/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; interface RecentConfig { itemType: RecentType; @@ -63,7 +64,7 @@ export const getRecentConfig = (to: Route): RecentConfig | undefined => { return { itemType: RECENT_TYPE.PROJECT, workspaceId, itemId: projectId }; } - if (to.name === ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME) { + if (to.name === SERVICE_ACCOUNT_ROUTE.DETAIL._NAME) { const serviceAccountId = to?.params?.serviceAccountId; const isTrustedAccount = serviceAccountId.startsWith('ta'); if (!serviceAccountId) return undefined; diff --git a/apps/web/src/lib/menu/config.ts b/apps/web/src/lib/menu/config.ts index 8038c7442b..ba6711164e 100644 --- a/apps/web/src/lib/menu/config.ts +++ b/apps/web/src/lib/menu/config.ts @@ -5,12 +5,12 @@ export const MENU_ID = Object.freeze({ WORKSPACE_HOME: 'workspace_home', DASHBOARDS: 'dashboards', PROJECT: 'project', + SERVICE_ACCOUNT: 'service_account', ASSET_INVENTORY: 'asset_inventory', CLOUD_SERVICE: 'cloud_service', SERVER: 'server', SECURITY: 'security', COLLECTOR: 'collector', - SERVICE_ACCOUNT: 'service_account', COST_EXPLORER: 'cost_explorer', COST_ANALYSIS: 'cost_analysis', COST_ADVANCED_SETTINGS: 'cost_advanced_settings', diff --git a/apps/web/src/lib/menu/menu-architecture.ts b/apps/web/src/lib/menu/menu-architecture.ts index e22148adaf..d2919df90e 100644 --- a/apps/web/src/lib/menu/menu-architecture.ts +++ b/apps/web/src/lib/menu/menu-architecture.ts @@ -1,71 +1,11 @@ import type { Menu } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; -export const MENU_LIST: Menu[] = [ +export const DEFAULT_MENU_LIST: Menu[] = [ { id: MENU_ID.WORKSPACE_HOME, needPermissionByRole: true, }, - { - id: MENU_ID.DASHBOARDS, - needPermissionByRole: true, - }, - { id: MENU_ID.PROJECT, needPermissionByRole: true }, - { - id: MENU_ID.ASSET_INVENTORY, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.CLOUD_SERVICE, needPermissionByRole: true }, - { id: MENU_ID.SERVER, needPermissionByRole: true }, - { id: MENU_ID.SECURITY, needPermissionByRole: true }, - { id: MENU_ID.METRIC_EXPLORER, needPermissionByRole: true }, - { id: MENU_ID.COLLECTOR, needPermissionByRole: true }, - { id: MENU_ID.SERVICE_ACCOUNT, needPermissionByRole: true }, - ], - }, - { - id: MENU_ID.COST_EXPLORER, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.COST_ANALYSIS, needPermissionByRole: true }, - { id: MENU_ID.BUDGET, needPermissionByRole: true }, - { id: MENU_ID.COST_REPORT, needPermissionByRole: true }, - ], - }, - { - id: MENU_ID.ALERT_MANAGER, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.ALERT_MANAGER_DASHBOARD, needPermissionByRole: true }, - { id: MENU_ID.ALERTS, needPermissionByRole: true }, - { id: MENU_ID.ESCALATION_POLICY, needPermissionByRole: true }, - ], - }, - { - id: MENU_ID.OPS_FLOW, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.OPS_FLOW_LANDING }, - { id: MENU_ID.TASK_BOARD }, - ], - }, - { - - id: MENU_ID.IAM, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.USER, needPermissionByRole: true }, - { id: MENU_ID.APP, needPermissionByRole: true }, - ], - }, - { - id: MENU_ID.MY_PAGE, - hideOnSiteMap: true, - subMenuList: [ - { id: MENU_ID.ACCOUNT_PROFILE }, - { id: MENU_ID.NOTIFICATIONS }, - ], - }, { id: MENU_ID.INFO, hideOnGNB: true, @@ -74,65 +14,6 @@ export const MENU_LIST: Menu[] = [ { id: MENU_ID.NOTICE }, ], }, -]; - - -export const MENU_LIST_FOR_ALERT_MANAGER_V2: Menu[] = [ - { - id: MENU_ID.WORKSPACE_HOME, - needPermissionByRole: true, - }, - { - id: MENU_ID.DASHBOARDS, - needPermissionByRole: true, - }, - { id: MENU_ID.PROJECT, needPermissionByRole: true }, - { - id: MENU_ID.ASSET_INVENTORY, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.CLOUD_SERVICE, needPermissionByRole: true }, - { id: MENU_ID.SERVER, needPermissionByRole: true }, - { id: MENU_ID.SECURITY, needPermissionByRole: true }, - { id: MENU_ID.METRIC_EXPLORER, needPermissionByRole: true }, - { id: MENU_ID.COLLECTOR, needPermissionByRole: true }, - { id: MENU_ID.SERVICE_ACCOUNT, needPermissionByRole: true }, - ], - }, - { - id: MENU_ID.COST_EXPLORER, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.COST_ANALYSIS, needPermissionByRole: true }, - { id: MENU_ID.BUDGET, needPermissionByRole: true }, - { id: MENU_ID.COST_REPORT, needPermissionByRole: true }, - ], - }, - { - id: MENU_ID.ALERT_MANAGER, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.SERVICE, needPermissionByRole: true }, - { id: MENU_ID.ALERTS, needPermissionByRole: true }, - ], - }, - { - id: MENU_ID.OPS_FLOW, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.OPS_FLOW_LANDING }, - { id: MENU_ID.TASK_BOARD }, - ], - }, - { - id: MENU_ID.IAM, - needPermissionByRole: true, - subMenuList: [ - { id: MENU_ID.USER, needPermissionByRole: true }, - { id: MENU_ID.USER_GROUP, needPermissionByRole: true }, - { id: MENU_ID.APP, needPermissionByRole: true }, - ], - }, { id: MENU_ID.MY_PAGE, hideOnSiteMap: true, @@ -141,113 +22,9 @@ export const MENU_LIST_FOR_ALERT_MANAGER_V2: Menu[] = [ { id: MENU_ID.NOTIFICATIONS }, ], }, - { - id: MENU_ID.INFO, - hideOnGNB: true, - hideOnSiteMap: true, - subMenuList: [ - { id: MENU_ID.NOTICE }, - ], - }, ]; -export const ADMIN_MENU_LIST: Menu[] = [ - { - id: MENU_ID.DASHBOARDS, - }, - { - id: MENU_ID.ASSET_INVENTORY, - subMenuList: [ - { id: MENU_ID.CLOUD_SERVICE }, - { id: MENU_ID.SERVER }, - { id: MENU_ID.SECURITY }, - { id: MENU_ID.METRIC_EXPLORER }, - { id: MENU_ID.COLLECTOR }, - { id: MENU_ID.SERVICE_ACCOUNT }, - ], - }, - { - id: MENU_ID.COST_EXPLORER, - subMenuList: [ - { id: MENU_ID.COST_ANALYSIS }, - { id: MENU_ID.BUDGET }, - { id: MENU_ID.COST_REPORT }, - { id: MENU_ID.DATA_SOURCES }, - { id: MENU_ID.COST_ADVANCED_SETTINGS }, - ], - }, - { - id: MENU_ID.OPS_FLOW, - subMenuList: [ - { id: MENU_ID.TASK_MANAGEMENT }, - ], - }, - { - id: MENU_ID.IAM, - subMenuList: [ - { id: MENU_ID.USER }, - { id: MENU_ID.USER_GROUP }, - { id: MENU_ID.APP }, - { id: MENU_ID.ROLE }, - ], - }, - { - id: MENU_ID.ADVANCED, - subMenuList: [ - { id: MENU_ID.WORKSPACES }, - { id: MENU_ID.WORKSPACE_GROUP }, - { id: MENU_ID.BOOKMARK }, - { id: MENU_ID.AUTO_DORMANCY_CONFIGURATION }, - { id: MENU_ID.PREFERENCES }, - ], - }, - { - id: MENU_ID.INFO, - subMenuList: [ - { id: MENU_ID.NOTICE }, - ], - }, -]; - -export const ADMIN_MENU_LIST_FOR_ALERT_MANAGER_V2: Menu[] = [ - { - id: MENU_ID.DASHBOARDS, - }, - { - id: MENU_ID.ASSET_INVENTORY, - subMenuList: [ - { id: MENU_ID.CLOUD_SERVICE }, - { id: MENU_ID.SERVER }, - { id: MENU_ID.SECURITY }, - { id: MENU_ID.METRIC_EXPLORER }, - { id: MENU_ID.COLLECTOR }, - { id: MENU_ID.SERVICE_ACCOUNT }, - ], - }, - { - id: MENU_ID.COST_EXPLORER, - subMenuList: [ - { id: MENU_ID.COST_ANALYSIS }, - { id: MENU_ID.BUDGET }, - { id: MENU_ID.COST_REPORT }, - { id: MENU_ID.DATA_SOURCES }, - { id: MENU_ID.COST_ADVANCED_SETTINGS }, - ], - }, - { - id: MENU_ID.OPS_FLOW, - subMenuList: [ - { id: MENU_ID.TASK_MANAGEMENT }, - ], - }, - { - id: MENU_ID.IAM, - subMenuList: [ - { id: MENU_ID.USER }, - { id: MENU_ID.APP }, - { id: MENU_ID.ROLE }, - ], - }, +export const DEFAULT_ADMIN_MENU_LIST: Menu[] = [ { id: MENU_ID.ADVANCED, subMenuList: [ @@ -260,6 +37,7 @@ export const ADMIN_MENU_LIST_FOR_ALERT_MANAGER_V2: Menu[] = [ }, { id: MENU_ID.INFO, + hideOnSiteMap: true, subMenuList: [ { id: MENU_ID.NOTICE }, ], diff --git a/apps/web/src/lib/menu/menu-info.ts b/apps/web/src/lib/menu/menu-info.ts index 56bbe79ace..0739c4dc0e 100644 --- a/apps/web/src/lib/menu/menu-info.ts +++ b/apps/web/src/lib/menu/menu-info.ts @@ -15,6 +15,7 @@ import { MY_PAGE_ROUTE } from '@/services/my-page/routes/route-constant'; import { ADMIN_OPS_FLOW_ROUTE } from '@/services/ops-flow/routes/admin/route-constant'; import { OPS_FLOW_ROUTE } from '@/services/ops-flow/routes/route-constant'; import { PROJECT_ROUTE_V1 } from '@/services/project/v1/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; import { WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/route-constant'; export const MENU_INFO_MAP: Record = Object.freeze({ @@ -75,8 +76,8 @@ export const MENU_INFO_MAP: Record = Object.freeze({ }, [MENU_ID.SERVICE_ACCOUNT]: { menuId: MENU_ID.SERVICE_ACCOUNT, - routeName: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, - translationId: 'MENU.ASSET_INVENTORY_SERVICE_ACCOUNT', + routeName: SERVICE_ACCOUNT_ROUTE._NAME, + translationId: 'MENU.SERVICE_ACCOUNT', icon: 'ic_service_service-account', }, [MENU_ID.COST_EXPLORER]: { diff --git a/apps/web/src/lib/reference/referenceRouter.ts b/apps/web/src/lib/reference/referenceRouter.ts index 1595a66867..fa034c2110 100644 --- a/apps/web/src/lib/reference/referenceRouter.ts +++ b/apps/web/src/lib/reference/referenceRouter.ts @@ -10,6 +10,8 @@ import type { Reference, ResourceType } from '@/lib/reference/type'; import { ADMIN_ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/admin/route-constant'; import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; import { PROJECT_ROUTE_V1 } from '@/services/project/v1/routes/route-constant'; +import { ADMIN_SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/admin/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; interface LinkFormatter { (baseUrl: string, data: string, reference: Reference, query: Location['query']): Location; @@ -123,12 +125,12 @@ const routerMap = (isAdminMode?: boolean): RouterMap => ({ }, 'identity.ServiceAccount': { - name: isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, + name: isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE.DETAIL._NAME : SERVICE_ACCOUNT_ROUTE.DETAIL._NAME, formatter: serviceAccountLinkFormatter, }, 'identity.TrustedAccount': { - name: isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, + name: isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE.DETAIL._NAME : SERVICE_ACCOUNT_ROUTE.DETAIL._NAME, formatter: serviceAccountLinkFormatter, }, 'inventory.CloudService': diff --git a/apps/web/src/lib/site-initializer/api-client.ts b/apps/web/src/lib/site-initializer/api-client.ts index 676ba4b857..3e92d1888d 100644 --- a/apps/web/src/lib/site-initializer/api-client.ts +++ b/apps/web/src/lib/site-initializer/api-client.ts @@ -2,14 +2,16 @@ import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; import TokenAPI from '@cloudforet/core-lib/space-connector/token-api'; import type { DevConfig, MockConfig, AuthConfig } from '@cloudforet/core-lib/space-connector/type'; -import type { TokenGrantParameters } from '@/api-clients/identity/token/schema/api-verbs/grant'; -import type { TokenGrantModel } from '@/api-clients/identity/token/schema/model'; +import APIClientLoader from '@/api-clients/loader'; import { useErrorStore } from '@/store/error/error-store'; import { pinia } from '@/store/pinia'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import { useUserStore } from '@/store/user/user-store'; +import type { TokenGrantParameters } from '@/schema/identity/token/api-verbs/grant'; +import type { TokenGrantModel } from '@/schema/identity/token/model'; + const getAfterCallApiMap = () => ({ '/inventory/cloud-service-type/create': (data) => { @@ -425,13 +427,16 @@ 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, ); + await APIClientLoader.initialize(); const existingRefreshToken = SpaceConnector.getRefreshToken(); if (!existingRefreshToken) return; diff --git a/apps/web/src/lib/site-initializer/index.ts b/apps/web/src/lib/site-initializer/index.ts index 7509043719..ee0c021c8b 100644 --- a/apps/web/src/lib/site-initializer/index.ts +++ b/apps/web/src/lib/site-initializer/index.ts @@ -5,8 +5,7 @@ import { QueryHelper } from '@cloudforet/core-lib/query'; import { SpaceRouter } from '@/router'; import { setI18nLocale } from '@/translations'; -import { alertManagerV1IntegralRoutes } from '@/router/alert-manager-v1-integral-routes'; -import { ERROR_ROUTE } from '@/router/constant'; +import { ERROR_ROUTE, ROOT_ROUTE } from '@/router/constant'; import { errorRoutes } from '@/router/error-routes'; import { integralRoutes } from '@/router/integral-routes'; @@ -31,10 +30,7 @@ import { checkSsoAccessToken } from '@/lib/site-initializer/sso'; import { initUserAndAuth } from '@/lib/site-initializer/user-auth'; import { initWorkspace } from '@/lib/site-initializer/workspace'; - -const initConfig = async () => { - await config.init(); -}; +import ServiceConfigurator from '@/services/configurator'; const initQueryHelper = () => { const userStore = useUserStore(pinia); @@ -46,12 +42,29 @@ const initRouter = (domainId?: string) => { const userStore = useUserStore(pinia); const allReferenceStore = useAllReferenceStore(pinia); const afterGrantedCallback = () => allReferenceStore.flush(); + + const adminChildren = integralRoutes[0].children?.find( + (route) => route.name === ROOT_ROUTE.ADMIN._NAME, + )?.children; + + const workspaceChildren = integralRoutes[0].children?.find( + (route) => route.name === ROOT_ROUTE.WORKSPACE._NAME, + )?.children; + + if (adminChildren) { + const dynamicAdminRoutes = ServiceConfigurator.getRoutes('admin'); + adminChildren.push(...dynamicAdminRoutes); + } + + if (workspaceChildren) { + const dynamicWorkspaceRoutes = ServiceConfigurator.getRoutes('workspace'); + workspaceChildren.push(...dynamicWorkspaceRoutes); + } + if (!domainId) { SpaceRouter.init(errorRoutes, afterGrantedCallback, userStore); } else { - const isAlertManagerVersionV2 = (config.get('ADVANCED_SERVICE')?.alert_manager_v2 ?? []).includes(domainId); - const routes = isAlertManagerVersionV2 ? integralRoutes : alertManagerV1IntegralRoutes; - SpaceRouter.init(routes, afterGrantedCallback, userStore); + SpaceRouter.init(integralRoutes, afterGrantedCallback, userStore); } isRouterInitialized = true; }; @@ -69,7 +82,8 @@ const removeInitializer = () => { const init = async () => { /* Init SpaceONE Console */ try { - await initConfig(); + await config.init(); + await ServiceConfigurator.initialize(); await initApiClient(config); const domainId = await initDomain(config); const userId = await initUserAndAuth(config); diff --git a/apps/web/src/router/admin-routes.ts b/apps/web/src/router/admin-routes.ts deleted file mode 100644 index 9c93483dd0..0000000000 --- a/apps/web/src/router/admin-routes.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { RouteConfig } from 'vue-router'; - -import adminAdvancedRoutes from '@/services/advanced/routes/admin/routes'; -import adminAssetInventoryRoutes from '@/services/asset-inventory/routes/admin/routes'; -import adminCostExplorerRoutes from '@/services/cost-explorer/routes/admin/routes'; -import adminDashboardsRoutes from '@/services/dashboards/routes/admin/routes'; -import adminIamRoutes from '@/services/iam/routes/admin/routes'; -import adminInfoRoute from '@/services/info/routes/admin/routes'; -import adminOpsFlowRoutes from '@/services/ops-flow/routes/admin/routes'; -import adminWorkspaceHomeRoutes from '@/services/workspace-home/routes/admin/routes'; - - -export const adminRoutes: RouteConfig[] = [ - adminWorkspaceHomeRoutes, - adminDashboardsRoutes, - adminCostExplorerRoutes, - adminAssetInventoryRoutes, - adminIamRoutes, - adminAdvancedRoutes, - adminInfoRoute, - adminOpsFlowRoutes, -]; diff --git a/apps/web/src/router/alert-manager-v1-integral-routes.ts b/apps/web/src/router/alert-manager-v1-integral-routes.ts deleted file mode 100644 index 13641db1e0..0000000000 --- a/apps/web/src/router/alert-manager-v1-integral-routes.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { RouteConfig } from 'vue-router'; - -import { alertManagerV1AdminRoutes } from '@/router/alert-manager-v1-admin-routes'; -import { alertManagerV1WorkspaceRoutes } from '@/router/alert-manager-v1-workspace-routes'; -import { ROOT_ROUTE, ROUTE_SCOPE } from '@/router/constant'; -import { errorRoutes } from '@/router/error-routes'; -import { externalRoutes } from '@/router/external-routes'; - -import { pinia } from '@/store/pinia'; -import { useUserStore } from '@/store/user/user-store'; - -import authRoutes from '@/services/auth/routes/routes'; -import landingPageRoutes from '@/services/landing/routes/routes'; -import myPageRoutes from '@/services/my-page/routes/routes'; -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 userStore = useUserStore(pinia); - -export const alertManagerV1IntegralRoutes: RouteConfig[] = [ - { - path: '/', - component: { template: '' }, - children: [ - { - path: '', - name: ROOT_ROUTE._NAME, - redirect: () => ({ - name: ROOT_ROUTE.WORKSPACE._NAME, - }), - }, - ...authRoutes, - landingPageRoutes, - ...externalRoutes, - { - path: 'admin', - name: ROOT_ROUTE.ADMIN._NAME, - meta: { scope: ROUTE_SCOPE.DOMAIN }, - redirect: () => { - if (!userStore.getters.isDomainAdmin) return { name: ROOT_ROUTE.WORKSPACE._NAME }; - return ({ name: ADMIN_WORKSPACE_HOME_ROUTE._NAME }); - }, - component: { template: '' }, - children: [ - ...alertManagerV1AdminRoutes, - ], - }, - { - path: 'workspace/:workspaceId?', - name: ROOT_ROUTE.WORKSPACE._NAME, - meta: { scope: ROUTE_SCOPE.WORKSPACE }, - redirect: (to) => ({ - name: WORKSPACE_HOME_ROUTE._NAME, - params: { - ...to.params, - }, - }), - component: { template: '' }, - children: [ - ...alertManagerV1WorkspaceRoutes, - ], - }, - myPageRoutes, - ...errorRoutes, - ], - }, -]; diff --git a/apps/web/src/router/alert-manager-v1-workspace-routes.ts b/apps/web/src/router/alert-manager-v1-workspace-routes.ts index 43221836b9..0ae2601167 100644 --- a/apps/web/src/router/alert-manager-v1-workspace-routes.ts +++ b/apps/web/src/router/alert-manager-v1-workspace-routes.ts @@ -1,6 +1,6 @@ import type { RouteConfig } from 'vue-router'; -import alertManagerRouteV1 from '@/services/alert-manager/v1/routes/routes'; +import alertManagerRoute from '@/services/alert-manager/v1/routes/routes'; import assetInventoryRoute from '@/services/asset-inventory/routes/routes'; import costExplorerRoute from '@/services/cost-explorer/routes/routes'; import dashboardsRoute from '@/services/dashboards/routes/routes'; @@ -17,7 +17,7 @@ export const alertManagerV1WorkspaceRoutes: RouteConfig[] = [ iamRoutes, assetInventoryRoute, projectRoute, - alertManagerRouteV1, + alertManagerRoute, costExplorerRoute, infoRoute, opsFlowRoutes, diff --git a/apps/web/src/router/integral-routes.ts b/apps/web/src/router/integral-routes.ts index 106e74ef15..fbebe4a5e3 100644 --- a/apps/web/src/router/integral-routes.ts +++ b/apps/web/src/router/integral-routes.ts @@ -1,10 +1,8 @@ import type { RouteConfig } from 'vue-router'; -import { adminRoutes } from '@/router/admin-routes'; import { ROOT_ROUTE, ROUTE_SCOPE } from '@/router/constant'; import { errorRoutes } from '@/router/error-routes'; import { externalRoutes } from '@/router/external-routes'; -import { workspaceRoutes } from '@/router/workspace-routes'; import { pinia } from '@/store/pinia'; import { useUserStore } from '@/store/user/user-store'; @@ -15,7 +13,6 @@ import myPageRoutes from '@/services/my-page/routes/routes'; import { ADMIN_WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/admin/route-constant'; import { WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/route-constant'; - export const integralRoutes: RouteConfig[] = [ { path: '/', @@ -41,9 +38,7 @@ export const integralRoutes: RouteConfig[] = [ return ({ name: ADMIN_WORKSPACE_HOME_ROUTE._NAME }); }, component: { template: '' }, - children: [ - ...adminRoutes, - ], + children: [], }, { path: 'workspace/:workspaceId?', @@ -56,9 +51,7 @@ export const integralRoutes: RouteConfig[] = [ }, }), component: { template: '' }, - children: [ - ...workspaceRoutes, - ], + children: [], }, myPageRoutes, ...errorRoutes, diff --git a/apps/web/src/services/advanced/components/WorkspaceGroupTabWorkspace.vue b/apps/web/src/services/advanced/components/WorkspaceGroupTabWorkspace.vue index 89bde3879c..b43f2d3141 100644 --- a/apps/web/src/services/advanced/components/WorkspaceGroupTabWorkspace.vue +++ b/apps/web/src/services/advanced/components/WorkspaceGroupTabWorkspace.vue @@ -28,8 +28,8 @@ import { gray } from '@/styles/colors'; import { workspaceStateFormatter } from '@/services/advanced/composables/refined-table-data'; import { WORKSPACE_GROUP_MODAL_TYPE } from '@/services/advanced/constants/workspace-group-constant'; import { useWorkspaceGroupPageStore } from '@/services/advanced/store/workspace-group-page-store'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; import { IAM_ROUTE } from '@/services/iam/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; import { WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/route-constant'; const workspaceGroupPageStore = useWorkspaceGroupPageStore(); @@ -86,7 +86,7 @@ const getUserRouteLocationByWorkspaceId = (item) => ({ }); const getServiceAccountRouteLocationByWorkspaceId = (item) => ({ - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, + name: SERVICE_ACCOUNT_ROUTE._NAME, params: { workspaceId: item?.workspace_id, }, diff --git a/apps/web/src/services/advanced/components/WorkspaceGroupWokrspaceDeleteModal.vue b/apps/web/src/services/advanced/components/WorkspaceGroupWokrspaceDeleteModal.vue index a640aa5ee2..733598639d 100644 --- a/apps/web/src/services/advanced/components/WorkspaceGroupWokrspaceDeleteModal.vue +++ b/apps/web/src/services/advanced/components/WorkspaceGroupWokrspaceDeleteModal.vue @@ -22,8 +22,8 @@ import { sortTableItems } from '@/common/utils/table-sort'; import { workspaceStateFormatter } from '@/services/advanced/composables/refined-table-data'; import { WORKSPACE_GROUP_MODAL_TYPE } from '@/services/advanced/constants/workspace-group-constant'; import { useWorkspaceGroupPageStore } from '@/services/advanced/store/workspace-group-page-store'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; import { IAM_ROUTE } from '@/services/iam/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; import { WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/route-constant'; @@ -73,7 +73,7 @@ const getUserRouteLocationByWorkspaceId = (item) => ({ }); const getServiceAccountRouteLocationByWorkspaceId = (item) => ({ - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, + name: SERVICE_ACCOUNT_ROUTE._NAME, params: { workspaceId: item?.workspace_id, }, diff --git a/apps/web/src/services/advanced/components/WorkspaceManagementTable.vue b/apps/web/src/services/advanced/components/WorkspaceManagementTable.vue index 23f9e1a005..88f47c35d8 100644 --- a/apps/web/src/services/advanced/components/WorkspaceManagementTable.vue +++ b/apps/web/src/services/advanced/components/WorkspaceManagementTable.vue @@ -43,12 +43,10 @@ import { WORKSPACE_TABLE_FIELDS, } from '@/services/advanced/constants/workspace-constant'; import { useWorkspacePageStore } from '@/services/advanced/store/workspace-page-store'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; import { IAM_ROUTE } from '@/services/iam/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; import { WORKSPACE_HOME_ROUTE } from '@/services/workspace-home/routes/route-constant'; - - interface Props { tableHeight?: number; hasReadWriteAccess?: boolean; @@ -211,7 +209,7 @@ const getUserRouteLocationByWorkspaceName = (item: WorkspaceModel) => ({ }, }); const getServiceAccountRouteLocationByWorkspaceName = (item: WorkspaceModel) => ({ - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, + name: SERVICE_ACCOUNT_ROUTE._NAME, params: { workspaceId: item?.workspace_id, }, diff --git a/apps/web/src/services/advanced/components/WorkspacesDeleteModal.vue b/apps/web/src/services/advanced/components/WorkspacesDeleteModal.vue index 597b14d460..9de96b6489 100644 --- a/apps/web/src/services/advanced/components/WorkspacesDeleteModal.vue +++ b/apps/web/src/services/advanced/components/WorkspacesDeleteModal.vue @@ -19,7 +19,7 @@ import WorkspaceLogoIcon from '@/common/modules/navigations/top-bar/modules/top- import { workspaceStateFormatter } from '@/services/advanced/composables/refined-table-data'; import { WORKSPACE_STATE } from '@/services/advanced/constants/workspace-constant'; import { useWorkspacePageStore } from '@/services/advanced/store/workspace-page-store'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; interface Props { visible: boolean; @@ -136,7 +136,7 @@ const handleConfirm = async () => { {{ state.relatedTrustedAccount.name }} diff --git a/apps/web/src/services/alert-manager/configurator.ts b/apps/web/src/services/alert-manager/configurator.ts new file mode 100644 index 0000000000..2c6b784a0b --- /dev/null +++ b/apps/web/src/services/alert-manager/configurator.ts @@ -0,0 +1,37 @@ +import type { Menu } from '@/lib/menu/config'; +import { MENU_ID } from '@/lib/menu/config'; + +import alertManagerRouteV1 from '@/services/alert-manager/v1/routes/routes'; +import alertManagerRoute from '@/services/alert-manager/v2/routes/routes'; +import type { FeatureVersions } from '@/services/configurator'; + +class AlertManagerConfigurator { + static getAdminRoutes() { + return null; + } + + static getWorkspaceRoutes(featureVersions: FeatureVersions) { + return featureVersions.ALERT_MANAGER === 'V1' ? alertManagerRouteV1 : alertManagerRoute; + } + + static getAdminMenu(): Menu|null { + return null; + } + + static getWorkspaceMenu(featureVersions: FeatureVersions): Menu { + return { + id: MENU_ID.ALERT_MANAGER, + needPermissionByRole: true, + subMenuList: featureVersions.ALERT_MANAGER === 'V1' ? [ + { id: MENU_ID.ALERT_MANAGER_DASHBOARD, needPermissionByRole: true }, + { id: MENU_ID.ALERTS, needPermissionByRole: true }, + { id: MENU_ID.ESCALATION_POLICY, needPermissionByRole: true }, + ] : [ + { id: MENU_ID.SERVICE, needPermissionByRole: true }, + { id: MENU_ID.ALERTS, needPermissionByRole: true }, + ], + }; + } +} + +export default AlertManagerConfigurator; 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 fee28a1651..c08be0f49b 100644 --- a/apps/web/src/services/alert-manager/v1/routes/routes.ts +++ b/apps/web/src/services/alert-manager/v1/routes/routes.ts @@ -17,7 +17,7 @@ const EscalationPolicyPage = () => import('@/services/alert-manager/v1/pages/Esc const AlertDetailPage = () => import('@/services/alert-manager/v1/pages/AlertDetailPage.vue'); -const alertManagerRouteV1: RouteConfig = { +const alertManagerRoute: RouteConfig = { path: 'alert-manager-v1', name: ALERT_MANAGER_ROUTE_V1._NAME, meta: { @@ -26,7 +26,7 @@ const alertManagerRouteV1: RouteConfig = { }, redirect: (to) => { const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap, userStore.getters.domainId); + return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); }, component: AlertManagerContainer, children: [ @@ -74,4 +74,4 @@ const alertManagerRouteV1: RouteConfig = { ], }; -export default alertManagerRouteV1; +export default alertManagerRoute; 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 1d61b36fc6..1741e510c4 100644 --- a/apps/web/src/services/alert-manager/v2/routes/routes.ts +++ b/apps/web/src/services/alert-manager/v2/routes/routes.ts @@ -27,7 +27,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, userStore.getters.domainId), + redirect: (to) => getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap), component: AlertManagerContainer, children: [ { diff --git a/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue b/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue index 3d58bcbd90..a8c7290e6b 100644 --- a/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue +++ b/apps/web/src/services/asset-inventory/components/CloudServiceDetailTabs.vue @@ -15,12 +15,10 @@ import type { CloudServiceGetParameters } from '@/schema/inventory/cloud-service import type { CloudServiceModel } from '@/schema/inventory/cloud-service/model'; import { i18n } from '@/translations'; -import { useDisplayStore } from '@/store/display/display-store'; import { useDomainStore } from '@/store/domain/domain-store'; import { useAllReferenceStore } from '@/store/reference/all-reference-store'; import config from '@/lib/config'; -import { MENU_ID } from '@/lib/menu/config'; import type { Reference } from '@/lib/reference/type'; @@ -65,7 +63,6 @@ const isAlertManagerVersionV2 = (config.get('ADVANCED_SERVICE')?.alert_manager_v const allReferenceStore = useAllReferenceStore(); const allReferenceGetters = allReferenceStore.getters; -const displayStore = useDisplayStore(); const taskManagementTemplateStore = useTaskManagementTemplateStore(); const router = useRouter(); @@ -88,9 +85,10 @@ const singleItemTabState = reactive({ if (isAlertManagerVersionV2) { defaultTabs.push({ name: 'alerts', label: i18n.t('INVENTORY.CLOUD_SERVICE.PAGE.TAB_ALERTS') }); } - if (displayStore.getters.availableAdvancedServices[MENU_ID.OPS_FLOW]) { - defaultTabs.push({ name: 'task', label: taskManagementTemplateStore.templates.Task }); - } + // TODO: will be changed to store + // if (displayStore.getters.availableAdvancedServices[MENU_ID.OPS_FLOW]) { + // defaultTabs.push({ name: 'task', label: taskManagementTemplateStore.templates.Task }); + // } return defaultTabs; }), activeTab: 'detail', @@ -102,9 +100,10 @@ const multiItemTabState = reactive({ { name: 'data', label: i18n.t('INVENTORY.CLOUD_SERVICE.PAGE.TAB_SELECTED_DATA') }, { name: 'monitoring', label: i18n.t('INVENTORY.CLOUD_SERVICE.PAGE.TAB_MONITORING') }, ]; - if (displayStore.getters.availableAdvancedServices[MENU_ID.OPS_FLOW]) { - defaultTabs.push({ name: 'task', label: taskManagementTemplateStore.templates.Task }); - } + // TODO: will be changed to store + // if (displayStore.getters.availableAdvancedServices[MENU_ID.OPS_FLOW]) { + // defaultTabs.push({ name: 'task', label: taskManagementTemplateStore.templates.Task }); + // } return defaultTabs; }), activeTab: 'data', diff --git a/apps/web/src/services/asset-inventory/configurator.ts b/apps/web/src/services/asset-inventory/configurator.ts new file mode 100644 index 0000000000..f35d693557 --- /dev/null +++ b/apps/web/src/services/asset-inventory/configurator.ts @@ -0,0 +1,43 @@ +import { MENU_ID } from '@/lib/menu/config'; + +import adminAssetInventoryRoutes from '@/services/asset-inventory/routes/admin/routes'; +import assetInventoryRoute from '@/services/asset-inventory/routes/routes'; + +class AssetInventoryConfigurator { + static getAdminRoutes() { + return adminAssetInventoryRoutes; + } + + static getWorkspaceRoutes() { + return assetInventoryRoute; + } + + static getAdminMenu() { + return { + id: MENU_ID.ASSET_INVENTORY, + subMenuList: [ + { id: MENU_ID.CLOUD_SERVICE }, + { id: MENU_ID.SERVER }, + { id: MENU_ID.SECURITY }, + { id: MENU_ID.METRIC_EXPLORER }, + { id: MENU_ID.COLLECTOR }, + ], + }; + } + + static getWorkspaceMenu() { + return { + id: MENU_ID.ASSET_INVENTORY, + needPermissionByRole: true, + subMenuList: [ + { id: MENU_ID.CLOUD_SERVICE, needPermissionByRole: true }, + { id: MENU_ID.SERVER, needPermissionByRole: true }, + { id: MENU_ID.SECURITY, needPermissionByRole: true }, + { id: MENU_ID.METRIC_EXPLORER, needPermissionByRole: true }, + { id: MENU_ID.COLLECTOR, needPermissionByRole: true }, + ], + }; + } +} + +export default AssetInventoryConfigurator; diff --git a/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue b/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue index 2d6ffcf8d4..45ff1fdc53 100644 --- a/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue +++ b/apps/web/src/services/asset-inventory/pages/CloudServicePage.vue @@ -58,6 +58,7 @@ import type { CloudServiceMainPageUrlQueryValue, } from '@/services/asset-inventory/types/cloud-service-page-type'; import type { EmptyData, Period } from '@/services/asset-inventory/types/type'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; interface Response { results: CloudServiceAnalyzeResult[]; @@ -129,7 +130,7 @@ const state = reactive({ let result = {} as EmptyData; if (state.isNoServiceAccounts) { result = { - to: state.writableServiceAccount ? { name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME } : {}, + to: state.writableServiceAccount ? { name: SERVICE_ACCOUNT_ROUTE._NAME } : {}, buttonText: state.writableServiceAccount ? i18n.t('INVENTORY.ADD_SERVICE_ACCOUNT') : undefined, desc: i18n.t('INVENTORY.EMPTY_CLOUD_SERVICE'), }; diff --git a/apps/web/src/services/asset-inventory/pages/SecurityPage.vue b/apps/web/src/services/asset-inventory/pages/SecurityPage.vue index 7ab6bd3b4d..4157969357 100644 --- a/apps/web/src/services/asset-inventory/pages/SecurityPage.vue +++ b/apps/web/src/services/asset-inventory/pages/SecurityPage.vue @@ -26,6 +26,7 @@ import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-c import { useSecurityPageStore } from '@/services/asset-inventory/stores/security-page-store'; import type { CloudServiceDetailPageParams } from '@/services/asset-inventory/types/cloud-service-detail-page-type'; import type { EmptyData } from '@/services/asset-inventory/types/type'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; const allReferenceStore = useAllReferenceStore(); const securityPageStore = useSecurityPageStore(); @@ -49,7 +50,7 @@ const state = reactive({ let result = {} as EmptyData; if (!Object.keys(storeState.serviceAccounts).length) { result = { - to: state.writableServiceAccount ? { name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME } : {}, + to: state.writableServiceAccount ? { name: SERVICE_ACCOUNT_ROUTE._NAME } : {}, buttonText: state.writableServiceAccount ? i18n.t('INVENTORY.ADD_SERVICE_ACCOUNT') : undefined, desc: i18n.t('INVENTORY.EMPTY_CLOUD_SERVICE'), }; diff --git a/apps/web/src/services/asset-inventory/routes/admin/route-constant.ts b/apps/web/src/services/asset-inventory/routes/admin/route-constant.ts index 9b3c148aa9..5937ca45e5 100644 --- a/apps/web/src/services/asset-inventory/routes/admin/route-constant.ts +++ b/apps/web/src/services/asset-inventory/routes/admin/route-constant.ts @@ -29,12 +29,6 @@ export const ADMIN_ASSET_INVENTORY_ROUTE = Object.freeze({ JOB: { _NAME: `${MENU_ID.ASSET_INVENTORY}.${MENU_ID.COLLECTOR}.history.job` }, }, }, - SERVICE_ACCOUNT: { - _NAME: `admin.${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}`, - DETAIL: { _NAME: `admin.${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}.detail` }, - ADD: { _NAME: `admin.${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}.add` }, - NO_RESOURCE: { _NAME: `admin.${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}.no_resource` }, - }, METRIC_EXPLORER: { _NAME: `admin.${MENU_ID.ASSET_INVENTORY}.${MENU_ID.METRIC_EXPLORER}`, DETAIL: { diff --git a/apps/web/src/services/asset-inventory/routes/admin/routes.ts b/apps/web/src/services/asset-inventory/routes/admin/routes.ts index 8c4146e528..20bad53fca 100644 --- a/apps/web/src/services/asset-inventory/routes/admin/routes.ts +++ b/apps/web/src/services/asset-inventory/routes/admin/routes.ts @@ -5,7 +5,6 @@ import { upperCase } from 'lodash'; import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; -import { ACCOUNT_TYPE_BADGE_OPTION } from '@/services/asset-inventory/constants/service-account-constant'; import { ADMIN_ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/admin/route-constant'; const AssetInventoryContainer = () => import('@/services/asset-inventory/AssetInventoryContainer.vue'); @@ -28,10 +27,6 @@ const AdminCollectorHistoryPage = () => import('@/services/asset-inventory/pages const AdminCollectHistoryJobPage = () => import('@/services/asset-inventory/pages/admin/AdminCollectHistoryJobPage.vue'); const AdminCollectorDetailPage = () => import('@/services/asset-inventory/pages/admin/AdminCollectorDetailPage.vue'); -const ServiceAccountPage = () => import('@/services/asset-inventory/pages/ServiceAccountPage.vue'); -const ServiceAccountDetailPage = () => import('@/services/asset-inventory/pages/ServiceAccountDetailPage.vue'); -const ServiceAccountAddPage = () => import('@/services/asset-inventory/pages/ServiceAccountAddPage.vue'); - const adminAssetInventoryRoute: RouteConfig = { path: 'asset-inventory', @@ -161,44 +156,6 @@ const adminAssetInventoryRoute: RouteConfig = { }, ], }, - { - path: 'service-account', - meta: { menuId: MENU_ID.SERVICE_ACCOUNT, translationId: MENU_INFO_MAP[MENU_ID.SERVICE_ACCOUNT].translationId }, - component: { template: '' }, - children: [ - { - path: '/', - name: ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, - meta: { menuId: MENU_ID.SERVICE_ACCOUNT }, - props: true, - component: ServiceAccountPage as any, - }, - { - path: 'no-resource', - name: ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.NO_RESOURCE._NAME, - meta: { translationId: 'COMMON.ERROR.NO_RESOURCE_TITLE' }, - component: NoResourcePage as any, - }, - { - path: ':serviceAccountId', - name: ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, - meta: { label: ({ params }) => params.serviceAccountId, copiable: true }, - props: true, - component: ServiceAccountDetailPage, - }, - { - path: 'add/:provider/:serviceAccountType', - name: ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.ADD._NAME, - meta: { - translationId: ({ params }) => (['IDENTITY.SERVICE_ACCOUNT.ADD.TITLE', { - type: ACCOUNT_TYPE_BADGE_OPTION[params.serviceAccountType].label, - }]), - }, - props: true, - component: ServiceAccountAddPage as any, - }, - ], - }, { path: 'metric-explorer', meta: { menuId: MENU_ID.METRIC_EXPLORER, translationId: MENU_INFO_MAP[MENU_ID.METRIC_EXPLORER].translationId }, diff --git a/apps/web/src/services/asset-inventory/routes/route-constant.ts b/apps/web/src/services/asset-inventory/routes/route-constant.ts index 0a77066f4f..d4281aac69 100644 --- a/apps/web/src/services/asset-inventory/routes/route-constant.ts +++ b/apps/web/src/services/asset-inventory/routes/route-constant.ts @@ -29,12 +29,6 @@ export const ASSET_INVENTORY_ROUTE = Object.freeze({ JOB: { _NAME: `${MENU_ID.ASSET_INVENTORY}.${MENU_ID.COLLECTOR}.history.job` }, }, }, - SERVICE_ACCOUNT: { - _NAME: `${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}`, - DETAIL: { _NAME: `${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}.detail` }, - ADD: { _NAME: `${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}.add` }, - NO_RESOURCE: { _NAME: `${MENU_ID.ASSET_INVENTORY}.${MENU_ID.SERVICE_ACCOUNT}.no_resource` }, - }, METRIC_EXPLORER: { _NAME: `${MENU_ID.ASSET_INVENTORY}.${MENU_ID.METRIC_EXPLORER}`, DETAIL: { diff --git a/apps/web/src/services/asset-inventory/routes/routes.ts b/apps/web/src/services/asset-inventory/routes/routes.ts index 299df9d357..ebcc9d7cd9 100644 --- a/apps/web/src/services/asset-inventory/routes/routes.ts +++ b/apps/web/src/services/asset-inventory/routes/routes.ts @@ -9,7 +9,6 @@ import { getRedirectRouteByPagePermission } from '@/lib/access-control/redirect- import { MENU_ID } from '@/lib/menu/config'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; -import { ACCOUNT_TYPE_BADGE_OPTION } from '@/services/asset-inventory/constants/service-account-constant'; import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; const AssetInventoryContainer = () => import('@/services/asset-inventory/AssetInventoryContainer.vue'); @@ -30,10 +29,6 @@ const MetricExplorerDetailPage = () => import('@/services/asset-inventory/pages/ const CollectorMainPage = () => import('@/services/asset-inventory/pages/CollectorMainPage.vue'); const CreateCollectorPage = () => import('@/services/asset-inventory/pages/CollectorCreatePage.vue'); -const ServiceAccountPage = () => import('@/services/asset-inventory/pages/ServiceAccountPage.vue'); -const ServiceAccountDetailPage = () => import('@/services/asset-inventory/pages/ServiceAccountDetailPage.vue'); -const ServiceAccountAddPage = () => import('@/services/asset-inventory/pages/ServiceAccountAddPage.vue'); - const CollectorHistoryPage = () => import('@/services/asset-inventory/pages/CollectorHistoryPage.vue'); const CollectJobPage = () => import('@/services/asset-inventory/pages/CollectHistoryJobPage.vue'); const CollectorDetailPage = () => import('@/services/asset-inventory/pages/CollectorDetailPage.vue'); @@ -47,7 +42,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, userStore.getters.domainId), + redirect: (to) => getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap), component: AssetInventoryContainer, children: [ { @@ -169,44 +164,6 @@ const assetInventoryRoute: RouteConfig = { }, ], }, - { - path: 'service-account', - meta: { menuId: MENU_ID.SERVICE_ACCOUNT, translationId: MENU_INFO_MAP[MENU_ID.SERVICE_ACCOUNT].translationId }, - component: { template: '' }, - children: [ - { - path: '/', - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, - meta: { menuId: MENU_ID.SERVICE_ACCOUNT }, - props: true, - component: ServiceAccountPage as any, - }, - { - path: 'no-resource', - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.NO_RESOURCE._NAME, - meta: { translationId: 'COMMON.ERROR.NO_RESOURCE_TITLE' }, - component: NoResourcePage as any, - }, - { - path: ':serviceAccountId', - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, - meta: { label: ({ params }) => params.serviceAccountId, copiable: true }, - props: true, - component: ServiceAccountDetailPage, - }, - { - path: 'add/:provider/:serviceAccountType', - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.ADD._NAME, - meta: { - translationId: ({ params }) => (['IDENTITY.SERVICE_ACCOUNT.ADD.TITLE', { - type: ACCOUNT_TYPE_BADGE_OPTION[params.serviceAccountType].label, - }]), - }, - props: true, - component: ServiceAccountAddPage as any, - }, - ], - }, { path: 'metric-explorer', meta: { menuId: MENU_ID.METRIC_EXPLORER, translationId: MENU_INFO_MAP[MENU_ID.METRIC_EXPLORER].translationId }, diff --git a/apps/web/src/services/configurator.ts b/apps/web/src/services/configurator.ts new file mode 100644 index 0000000000..2f76c39e56 --- /dev/null +++ b/apps/web/src/services/configurator.ts @@ -0,0 +1,137 @@ +import type { RouteConfig } from 'vue-router'; + +import { useGlobalConfigSettingStore } from '@/store/config/global-config-setting-store'; +import { useMenuStore } from '@/store/menu/menu-store'; + +import config from '@/lib/config'; +import type { Menu } from '@/lib/menu/config'; +import { DEFAULT_ADMIN_MENU_LIST, DEFAULT_MENU_LIST } from '@/lib/menu/menu-architecture'; + +import adminAdvancedRoutes from '@/services/advanced/routes/admin/routes'; +import AlertManagerConfigurator from '@/services/alert-manager/configurator'; +import AssetInventoryConfigurator from '@/services/asset-inventory/configurator'; +import CostExplorerConfigurator from '@/services/cost-explorer/configurator'; +import DashboardConfigurator from '@/services/dashboards/configurator'; +import IamConfigurator from '@/services/iam/configurator'; +import adminInfoRoutes from '@/services/info/routes/admin/routes'; +import infoRoutes from '@/services/info/routes/routes'; +import OpsFlowConfigurator from '@/services/ops-flow/configurator'; +import ProjectConfigurator from '@/services/project/configurator'; +import ServiceAccountConfigurator from '@/services/service-account/configurator'; +import adminWorkspaceHomeRoutes from '@/services/workspace-home/routes/admin/routes'; +import workspaceHomeRoute from '@/services/workspace-home/routes/routes'; + +interface ServiceConfig { + ENABLED: boolean; + VERSION: string; +} + +interface GlobalConfig { + SERVICES: { + [key: string]: ServiceConfig; + }; +} + +export interface FeatureVersions { + DASHBOARD: string; + PROJECT: string; + SERVICE_ACCOUNT: string; + ASSET_INVENTORY: string; + COST_EXPLORER: string; + ALERT_MANAGER: string; + OPS_FLOW: string; + IAM: string; +} + +class ServiceConfigurator { + private config: GlobalConfig | null = null; + + private featureVersions: FeatureVersions = {} as FeatureVersions; + + private featureConfigurators: Record = { + DASHBOARD: DashboardConfigurator, + PROJECT: ProjectConfigurator, + SERVICE_ACCOUNT: ServiceAccountConfigurator, + ASSET_INVENTORY: AssetInventoryConfigurator, + COST_EXPLORER: CostExplorerConfigurator, + ALERT_MANAGER: AlertManagerConfigurator, + OPS_FLOW: OpsFlowConfigurator, + IAM: IamConfigurator, + }; + + async initialize() { + const globalConfigSettingStore = useGlobalConfigSettingStore(); + + await config.init(); + this.config = config.get('SERVICES') || {}; + + if (!this.config) return; + const featureVersions = { + IAM: 'V1', + ...Object.fromEntries( + Object.entries(this.config).map(([key, value]) => [key, value.VERSION]), + ), + }; + globalConfigSettingStore.setFeatureVersion(featureVersions); + this.featureVersions = globalConfigSettingStore.state.featureVersions; + } + + private get allServices() { + if (!this.config) { + throw new Error('ServiceConfigurator is not initialized.'); + } + return { ...this.config, IAM: { ENABLED: true, VERSION: 'V1' } }; + } + + getRoutes(mode: 'admin' | 'workspace'): RouteConfig[] { + const baseRoutes = mode === 'admin' + ? [adminWorkspaceHomeRoutes, adminAdvancedRoutes, adminInfoRoutes] + : [workspaceHomeRoute, infoRoutes]; + + Object.entries(this.allServices).forEach(([serviceName, serviceConfig]) => { + if (serviceConfig.ENABLED) { + const configurator = this.featureConfigurators[serviceName]; + if (configurator) { + const route = mode === 'admin' + ? configurator.getAdminRoutes(this.featureVersions) + : configurator.getWorkspaceRoutes(this.featureVersions); + if (route && !baseRoutes.some((existingRoute) => existingRoute.path === route.path)) { + baseRoutes.push(route); + } + } + } + }); + + return baseRoutes; + } + + getMenuList(mode: 'admin' | 'workspace'): Menu[] { + const menuStore = useMenuStore(); + + const menuList: Menu[] = mode === 'admin' ? [] : DEFAULT_MENU_LIST; + + Object.entries(this.allServices).forEach(([serviceName, serviceConfig]) => { + if (serviceConfig.ENABLED) { + const configurator = this.featureConfigurators[serviceName]; + if (configurator) { + const serviceMenu = mode === 'admin' + ? configurator.getAdminMenu(this.featureVersions) + : configurator.getWorkspaceMenu(this.featureVersions); + if (serviceMenu && !menuList.some((existingRoute) => existingRoute.id === serviceMenu.id)) { + menuList.push(serviceMenu); + } + } + } + }); + + if (mode === 'admin') { + menuList.push(...DEFAULT_ADMIN_MENU_LIST); + } + + menuStore.setMenuList(menuList); + + return menuList; + } +} + +export default new ServiceConfigurator(); diff --git a/apps/web/src/services/cost-explorer/components/CostAnalysisDataTable.vue b/apps/web/src/services/cost-explorer/components/CostAnalysisDataTable.vue index cf1c3f4d72..122aaee469 100644 --- a/apps/web/src/services/cost-explorer/components/CostAnalysisDataTable.vue +++ b/apps/web/src/services/cost-explorer/components/CostAnalysisDataTable.vue @@ -46,8 +46,6 @@ import { usageUnitFormatter } from '@/lib/helper/usage-formatter'; import ErrorHandler from '@/common/composables/error/errorHandler'; - -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; import { GRANULARITY, GROUP_BY, @@ -66,6 +64,7 @@ import type { DisplayDataType, } from '@/services/cost-explorer/types/cost-explorer-query-type'; import { PROJECT_ROUTE_V1 } from '@/services/project/v1/routes/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; type CostAnalyzeRawData = { @@ -413,7 +412,7 @@ const handleClickRowData = (fieldName: string, value: string) => { _params = { id: value, workspaceId: storeState.currentWorkspaceId }; } if (fieldName === GROUP_BY.SERVICE_ACCOUNT) { - _routeName = ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME; + _routeName = SERVICE_ACCOUNT_ROUTE.DETAIL._NAME; _params = { serviceAccountId: value, workspaceId: storeState.currentWorkspaceId }; } diff --git a/apps/web/src/services/cost-explorer/configurator.ts b/apps/web/src/services/cost-explorer/configurator.ts new file mode 100644 index 0000000000..49bfd3d40f --- /dev/null +++ b/apps/web/src/services/cost-explorer/configurator.ts @@ -0,0 +1,42 @@ +import type { Menu } from '@/lib/menu/config'; +import { MENU_ID } from '@/lib/menu/config'; + +import adminCostExplorerRoutes from '@/services/cost-explorer/routes/admin/routes'; +import costExplorerRoutes from '@/services/cost-explorer/routes/routes'; + +class CostExplorerConfigurator { + static getAdminRoutes() { + return adminCostExplorerRoutes; + } + + static getWorkspaceRoutes() { + return costExplorerRoutes; + } + + static getAdminMenu(): Menu { + return { + id: MENU_ID.COST_EXPLORER, + subMenuList: [ + { id: MENU_ID.COST_ANALYSIS }, + { id: MENU_ID.BUDGET }, + { id: MENU_ID.COST_REPORT }, + { id: MENU_ID.DATA_SOURCES }, + { id: MENU_ID.COST_ADVANCED_SETTINGS }, + ], + }; + } + + static getWorkspaceMenu(): Menu { + return { + id: MENU_ID.COST_EXPLORER, + needPermissionByRole: true, + subMenuList: [ + { id: MENU_ID.COST_ANALYSIS, needPermissionByRole: true }, + { id: MENU_ID.BUDGET, needPermissionByRole: true }, + { id: MENU_ID.COST_REPORT, needPermissionByRole: true }, + ], + }; + } +} + +export default CostExplorerConfigurator; diff --git a/apps/web/src/services/cost-explorer/routes/routes.ts b/apps/web/src/services/cost-explorer/routes/routes.ts index 0d68b6bb23..fb47ba2f8b 100644 --- a/apps/web/src/services/cost-explorer/routes/routes.ts +++ b/apps/web/src/services/cost-explorer/routes/routes.ts @@ -33,7 +33,7 @@ const costExplorerRoutes: RouteConfig = { }, redirect: (to) => { const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap, userStore.getters.domainId); + return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); }, component: CostExplorerContainer, children: [ diff --git a/apps/web/src/services/dashboards/configurator.ts b/apps/web/src/services/dashboards/configurator.ts new file mode 100644 index 0000000000..914b548404 --- /dev/null +++ b/apps/web/src/services/dashboards/configurator.ts @@ -0,0 +1,30 @@ +import type { Menu } from '@/lib/menu/config'; +import { MENU_ID } from '@/lib/menu/config'; + +import adminDashboardsRoute from '@/services/dashboards/routes/admin/routes'; +import dashboardsRoute from '@/services/dashboards/routes/routes'; + +class DashboardConfigurator { + static getAdminRoutes() { + return adminDashboardsRoute; + } + + static getWorkspaceRoutes() { + return dashboardsRoute; + } + + static getAdminMenu(): Menu { + return { + id: MENU_ID.DASHBOARDS, + }; + } + + static getWorkspaceMenu(): Menu { + return { + id: MENU_ID.DASHBOARDS, + needPermissionByRole: true, + }; + } +} + +export default DashboardConfigurator; diff --git a/apps/web/src/services/iam/components/RoleManagementTabDetail.vue b/apps/web/src/services/iam/components/RoleManagementTabDetail.vue index 0d92280374..ab9e71a44b 100644 --- a/apps/web/src/services/iam/components/RoleManagementTabDetail.vue +++ b/apps/web/src/services/iam/components/RoleManagementTabDetail.vue @@ -16,8 +16,6 @@ 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 { useDomainStore } from '@/store/domain/domain-store'; - import { PAGE_ACCESS } from '@/lib/access-control/config'; import { getPageAccessMapFromRawData, @@ -41,7 +39,6 @@ interface DetailMenuItems { const rolePageStore = useRolePageStore(); const rolePageState = rolePageStore.$state; -const domainStore = useDomainStore(); const detailMenuItems = computed(() => [ { name: 'page_access', label: i18n.t('IAM.ROLE.DETAIL.PAGE_ACCESS') as string }, @@ -142,9 +139,9 @@ watch(() => state.selectedRole.role_id, async (roleId) => { : roleId; await getRoleDetailData(selectedRoleId); - state.pageAccessDataList = getPageAccessMenuListByRoleType(state.data.role_type, domainStore.state.domainId); + state.pageAccessDataList = getPageAccessMenuListByRoleType(state.data.role_type); - const pageAccessPermissionMap = getPageAccessMapFromRawData(state.pageAccess, domainStore.state.domainId); + const pageAccessPermissionMap = getPageAccessMapFromRawData(state.pageAccess); Object.entries(pageAccessPermissionMap).forEach(([itemId, accessible]) => { if (!itemId) return; diff --git a/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue b/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue index a7e86988c3..3f6d4d07f2 100644 --- a/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue +++ b/apps/web/src/services/iam/components/RoleUpdateFormPermissionForm.vue @@ -10,8 +10,6 @@ import { PPaneLayout } from '@cloudforet/mirinae'; import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import type { RoleType } from '@/api-clients/identity/role/type'; -import { useDomainStore } from '@/store/domain/domain-store'; - import { PAGE_ACCESS } from '@/lib/access-control/config'; import { getPageAccessMapFromRawData } from '@/lib/access-control/page-access-helper'; @@ -23,8 +21,6 @@ import { FORM_TYPE } from '@/services/iam/constants/role-constant'; import { getPageAccessList, getPageAccessMenuListByRoleType } from '@/services/iam/helpers/role-page-access-menu-list'; import type { PageAccessMenuItem, RoleFormData } from '@/services/iam/types/role-type'; -const domainStore = useDomainStore(); - interface Props { initialPageAccess?: string[]; initialPermissions?: string[]; @@ -95,7 +91,7 @@ const handleUpdateEditor = (value: string) => { }; const setPageAccessPermissionsData = () => { if (!props.initialPageAccess) return; - const pageAccessPermissionMap = getPageAccessMapFromRawData(props.initialPageAccess, domainStore.state.domainId); + const pageAccessPermissionMap = getPageAccessMapFromRawData(props.initialPageAccess); // eslint-disable-next-line no-restricted-syntax for (const [itemId, accessible] of Object.entries(pageAccessPermissionMap)) { if (!itemId) return; @@ -130,7 +126,7 @@ watch(() => state.pageAccessPermissions, (pageAccessPermissions, prevPageAccessP emit('update-form', { page_access: pageAccessPermissions }); }); watch([() => props.roleType, () => props.initialPageAccess], ([roleType]) => { - menuItems.value = getPageAccessMenuListByRoleType(roleType, domainStore.state.domainId); + menuItems.value = getPageAccessMenuListByRoleType(roleType); setPageAccessPermissionsData(); }, { immediate: true }); diff --git a/apps/web/src/services/iam/configurator.ts b/apps/web/src/services/iam/configurator.ts new file mode 100644 index 0000000000..b3ed943ba0 --- /dev/null +++ b/apps/web/src/services/iam/configurator.ts @@ -0,0 +1,58 @@ + +import type { Menu } from '@/lib/menu/config'; +import { MENU_ID } from '@/lib/menu/config'; + +import type { FeatureVersions } from '@/services/configurator'; +import adminIamRoutes, { ADMIN_USER_GROUP_ROUTE } from '@/services/iam/routes/admin/routes'; +import iamRoutes, { USER_GROUP_ROUTE } from '@/services/iam/routes/routes'; + +class IamConfigurator { + static getAdminRoutes(featureVersions: FeatureVersions) { + const adminRoutes = adminIamRoutes; + if (featureVersions.ALERT_MANAGER === 'V2') { + adminRoutes.children?.push(ADMIN_USER_GROUP_ROUTE); + } + return adminRoutes; + } + + static getWorkspaceRoutes(featureVersions: FeatureVersions) { + const routes = iamRoutes; + if (featureVersions.ALERT_MANAGER === 'V2') { + routes.children?.push(USER_GROUP_ROUTE); + } + return routes; + } + + static getAdminMenu(featureVersions: FeatureVersions): Menu { + return { + id: MENU_ID.IAM, + subMenuList: featureVersions.ALERT_MANAGER === 'V1' ? [ + { id: MENU_ID.USER }, + { id: MENU_ID.APP }, + { id: MENU_ID.ROLE }, + ] : [ + { id: MENU_ID.USER }, + { id: MENU_ID.USER_GROUP }, + { id: MENU_ID.APP }, + { id: MENU_ID.ROLE }, + ], + }; + } + + static getWorkspaceMenu(featureVersions: FeatureVersions): Menu { + return { + id: MENU_ID.IAM, + needPermissionByRole: true, + subMenuList: featureVersions.ALERT_MANAGER === 'V1' ? [ + { id: MENU_ID.USER, needPermissionByRole: true }, + { id: MENU_ID.APP, needPermissionByRole: true }, + ] : [ + { id: MENU_ID.USER, needPermissionByRole: true }, + { id: MENU_ID.USER_GROUP, needPermissionByRole: true }, + { id: MENU_ID.APP, needPermissionByRole: true }, + ], + }; + } +} + +export default IamConfigurator; diff --git a/apps/web/src/services/iam/helpers/role-page-access-menu-list.ts b/apps/web/src/services/iam/helpers/role-page-access-menu-list.ts index a8fe46ec9f..ddb687000a 100644 --- a/apps/web/src/services/iam/helpers/role-page-access-menu-list.ts +++ b/apps/web/src/services/iam/helpers/role-page-access-menu-list.ts @@ -1,11 +1,11 @@ import type { RoleType } from '@/api-clients/identity/role/type'; +import { useMenuStore } from '@/store/menu/menu-store'; + import { PAGE_ACCESS } from '@/lib/access-control/config'; import { getDefaultPageAccessPermissionList } from '@/lib/access-control/page-access-helper'; -import config from '@/lib/config'; import type { Menu, MenuId } from '@/lib/menu/config'; import { MENU_ID } from '@/lib/menu/config'; -import { MENU_LIST, MENU_LIST_FOR_ALERT_MANAGER_V2 } from '@/lib/menu/menu-architecture'; import { MENU_INFO_MAP } from '@/lib/menu/menu-info'; import type { PageAccessMenuItem } from '@/services/iam/types/role-type'; @@ -30,11 +30,11 @@ const flattenSubMenuList = (subMenuList: Menu[], defaultMenuIds: MenuId[], trans return results; }; -export const getPageAccessMenuListByRoleType = (roleType: RoleType, domainId: string): PageAccessMenuItem[] => { +export const getPageAccessMenuListByRoleType = (roleType: RoleType): PageAccessMenuItem[] => { + const menuStore = useMenuStore(); const results: PageAccessMenuItem[] = []; const defaultMenuIdsByRoleType = getDefaultPageAccessPermissionList(roleType); - const isAlertManagerVersionV2 = (config.get('ADVANCED_SERVICE')?.alert_manager_v2 ?? []).includes(domainId); - const menuListByVersion = (isAlertManagerVersionV2 ? MENU_LIST_FOR_ALERT_MANAGER_V2 : MENU_LIST); + const menuListByVersion = menuStore.state.menuList; menuListByVersion.forEach((menu) => { if (menu.needPermissionByRole && defaultMenuIdsByRoleType.includes(menu.id)) { if (menu.id === MENU_ID.WORKSPACE_HOME) return; diff --git a/apps/web/src/services/iam/routes/admin/route-constant.ts b/apps/web/src/services/iam/routes/admin/route-constant.ts index e4678ad3d1..628a714a73 100644 --- a/apps/web/src/services/iam/routes/admin/route-constant.ts +++ b/apps/web/src/services/iam/routes/admin/route-constant.ts @@ -5,6 +5,9 @@ export const ADMIN_IAM_ROUTE = { USER: { _NAME: `admin.${MENU_ID.IAM}.${MENU_ID.USER}`, }, + USER_GROUP: { + _NAME: `admin.${MENU_ID.IAM}.${MENU_ID.USER_GROUP}`, + }, APP: { _NAME: `admin.${MENU_ID.IAM}.${MENU_ID.APP}`, }, @@ -18,3 +21,4 @@ export const ADMIN_IAM_ROUTE = { }, }, } as const; + diff --git a/apps/web/src/services/iam/routes/admin/routes.ts b/apps/web/src/services/iam/routes/admin/routes.ts index e8dd6b21ac..0a8bda3924 100644 --- a/apps/web/src/services/iam/routes/admin/routes.ts +++ b/apps/web/src/services/iam/routes/admin/routes.ts @@ -8,11 +8,72 @@ import { ADMIN_IAM_ROUTE } from '@/services/iam/routes/admin/route-constant'; const IamContainer = () => import('@/services/iam/IamContainer.vue'); const UserMainPage = () => import('@/services/iam/pages/UserMainPage.vue'); +const UserGroupMainPage = () => import('@/services/iam/pages/UserGroupMainPage.vue'); const AppMainPage = () => import('@/services/iam/pages/AppMainPage.vue'); const RolePage = () => import('@/services/iam/pages/admin/AdminRolePage.vue'); const RoleCreatePage = () => import('@/services/iam/pages/admin/AdminRoleCreatePage.vue'); const RoleUpdatePage = () => import('@/services/iam/pages/admin/AdminRoleUpdatePage.vue'); +export const ADMIN_USER_GROUP_ROUTE = { + path: 'user-group', + name: ADMIN_IAM_ROUTE.USER_GROUP._NAME, + meta: { + menuId: MENU_ID.USER_GROUP, + translationId: MENU_INFO_MAP[MENU_ID.USER_GROUP].translationId, + }, + component: UserGroupMainPage as any, +} as const; + +export const adminIamRoutesChildren = [ + { + path: 'user', + name: ADMIN_IAM_ROUTE.USER._NAME, + meta: { + menuId: MENU_ID.USER, + translationId: MENU_INFO_MAP[MENU_ID.USER].translationId, + }, + component: UserMainPage as any, + }, + { + path: 'app', + name: ADMIN_IAM_ROUTE.APP._NAME, + meta: { + menuId: MENU_ID.APP, + translationId: MENU_INFO_MAP[MENU_ID.APP].translationId, + }, + component: AppMainPage as any, + }, + { + path: 'role', + meta: { + menuId: MENU_ID.ROLE, + translationId: MENU_INFO_MAP[MENU_ID.ROLE].translationId, + }, + component: { template: '' }, + children: [ + { + path: '/', + name: ADMIN_IAM_ROUTE.ROLE._NAME, + props: true, + component: RolePage, + }, + { + path: 'create', + name: ADMIN_IAM_ROUTE.ROLE.CREATE._NAME, + meta: { translationId: 'IAM.ROLE.FORM.CREATE_TITLE' }, + component: RoleCreatePage, + }, + { + path: 'edit/:id', + name: ADMIN_IAM_ROUTE.ROLE.EDIT._NAME, + meta: { translationId: 'IAM.ROLE.FORM.EDIT_TITLE' }, + props: true, + component: RoleUpdatePage, + }, + ], + }, +]; + const adminIamRoutes: RouteConfig = { path: 'iam', name: ADMIN_IAM_ROUTE._NAME, @@ -24,54 +85,6 @@ const adminIamRoutes: RouteConfig = { name: ADMIN_IAM_ROUTE.USER._NAME, }), component: IamContainer, - children: [ - { - path: 'user', - name: ADMIN_IAM_ROUTE.USER._NAME, - meta: { - menuId: MENU_ID.USER, - translationId: MENU_INFO_MAP[MENU_ID.USER].translationId, - }, - component: UserMainPage as any, - }, - { - path: 'app', - name: ADMIN_IAM_ROUTE.APP._NAME, - meta: { - menuId: MENU_ID.APP, - translationId: MENU_INFO_MAP[MENU_ID.APP].translationId, - }, - component: AppMainPage as any, - }, - { - path: 'role', - meta: { - menuId: MENU_ID.ROLE, - translationId: MENU_INFO_MAP[MENU_ID.ROLE].translationId, - }, - component: { template: '' }, - children: [ - { - path: '/', - name: ADMIN_IAM_ROUTE.ROLE._NAME, - props: true, - component: RolePage, - }, - { - path: 'create', - name: ADMIN_IAM_ROUTE.ROLE.CREATE._NAME, - meta: { translationId: 'IAM.ROLE.FORM.CREATE_TITLE' }, - component: RoleCreatePage, - }, - { - path: 'edit/:id', - name: ADMIN_IAM_ROUTE.ROLE.EDIT._NAME, - meta: { translationId: 'IAM.ROLE.FORM.EDIT_TITLE' }, - props: true, - component: RoleUpdatePage, - }, - ], - }, - ], + children: adminIamRoutesChildren, }; export default adminIamRoutes; diff --git a/apps/web/src/services/iam/routes/routes.ts b/apps/web/src/services/iam/routes/routes.ts index 80cb2aa958..2c798d33c5 100644 --- a/apps/web/src/services/iam/routes/routes.ts +++ b/apps/web/src/services/iam/routes/routes.ts @@ -15,6 +15,36 @@ const UserMainPage = () => import('@/services/iam/pages/UserMainPage.vue'); const UserGroupMainPage = () => import('@/services/iam/pages/UserGroupMainPage.vue'); const AppMainPage = () => import('@/services/iam/pages/AppMainPage.vue'); +export const USER_GROUP_ROUTE = { + path: 'user-group', + name: IAM_ROUTE.USER_GROUP._NAME, + meta: { + menuId: MENU_ID.USER_GROUP, + translationId: MENU_INFO_MAP[MENU_ID.USER_GROUP].translationId, + }, + component: UserGroupMainPage as any, +} as const; + +export const iamRoutesChildren = [ + { + path: 'user', + name: IAM_ROUTE.USER._NAME, + meta: { + menuId: MENU_ID.USER, + translationId: MENU_INFO_MAP[MENU_ID.USER].translationId, + }, + component: UserMainPage as any, + }, + { + path: 'app', + name: IAM_ROUTE.APP._NAME, + meta: { + menuId: MENU_ID.APP, + translationId: MENU_INFO_MAP[MENU_ID.APP].translationId, + }, + component: AppMainPage as any, + }, +]; const iamRoutes: RouteConfig = { path: 'iam', @@ -25,37 +55,9 @@ const iamRoutes: RouteConfig = { }, redirect: (to) => { const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap, userStore.getters.domainId); + return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); }, component: IamContainer, - children: [ - { - path: 'user', - name: IAM_ROUTE.USER._NAME, - meta: { - menuId: MENU_ID.USER, - translationId: MENU_INFO_MAP[MENU_ID.USER].translationId, - }, - component: UserMainPage as any, - }, - { - path: 'user-group', - name: IAM_ROUTE.USER_GROUP._NAME, - meta: { - menuId: MENU_ID.USER_GROUP, - translationId: MENU_INFO_MAP[MENU_ID.USER_GROUP].translationId, - }, - component: UserGroupMainPage as any, - }, - { - path: 'app', - name: IAM_ROUTE.APP._NAME, - meta: { - menuId: MENU_ID.APP, - translationId: MENU_INFO_MAP[MENU_ID.APP].translationId, - }, - component: AppMainPage as any, - }, - ], + children: iamRoutesChildren, }; export default iamRoutes; diff --git a/apps/web/src/services/info/routes/admin/routes.ts b/apps/web/src/services/info/routes/admin/routes.ts index 60329283f8..3b7fc38cb5 100644 --- a/apps/web/src/services/info/routes/admin/routes.ts +++ b/apps/web/src/services/info/routes/admin/routes.ts @@ -14,7 +14,7 @@ const AdminNoticeDetailPage = () => import('@/services/info/pages/admin/AdminNot const AdminNoticeCreatePage = () => import('@/services/info/pages/admin/AdminNoticeCreatePage.vue'); const AdminNoticeUpdatePage = () => import('@/services/info/pages/admin/AdminNoticeUpdatePage.vue'); -const infoRoute: RouteConfig = { +const adminInfoRoutes: RouteConfig = { path: 'info', name: ADMIN_INFO_ROUTE._NAME, meta: { @@ -65,4 +65,4 @@ const infoRoute: RouteConfig = { ], }; -export default infoRoute; +export default adminInfoRoutes; diff --git a/apps/web/src/services/info/routes/routes.ts b/apps/web/src/services/info/routes/routes.ts index 0e36b2e52e..a7f67b9c21 100644 --- a/apps/web/src/services/info/routes/routes.ts +++ b/apps/web/src/services/info/routes/routes.ts @@ -15,7 +15,7 @@ const NoticeMainPage = () => import('@/services/info/pages/NoticeMainPage.vue'); const NoticeDetailPage = () => import('@/services/info/pages/NoticeDetailPage.vue'); -const infoRoute: RouteConfig = { +const infoRoutes: RouteConfig = { path: 'info', name: INFO_ROUTE._NAME, meta: { @@ -24,7 +24,7 @@ const infoRoute: RouteConfig = { }, redirect: (to) => { const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap, userStore.getters.domainId); + return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); }, component: InfoContainer, children: [ @@ -55,4 +55,4 @@ const infoRoute: RouteConfig = { ], }; -export default infoRoute; +export default infoRoutes; diff --git a/apps/web/src/services/landing/components/workspace-landing/landing-group-workspaces/LandingWorkspaceGroupRemoveUserModal.vue b/apps/web/src/services/landing/components/workspace-landing/landing-group-workspaces/LandingWorkspaceGroupRemoveUserModal.vue index 5cbebed210..998cce901c 100644 --- a/apps/web/src/services/landing/components/workspace-landing/landing-group-workspaces/LandingWorkspaceGroupRemoveUserModal.vue +++ b/apps/web/src/services/landing/components/workspace-landing/landing-group-workspaces/LandingWorkspaceGroupRemoveUserModal.vue @@ -20,9 +20,9 @@ import ErrorHandler from '@/common/composables/error/errorHandler'; import { useProxyValue } from '@/common/composables/proxy-state'; import { workspaceStateFormatter, groupUserStateFormatter } from '@/services/advanced/composables/refined-table-data'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; import { IAM_ROUTE } from '@/services/iam/routes/route-constant'; import { useLandingPageStore } from '@/services/landing/store/landing-page-store'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; const emit = defineEmits<{(e: 'confirm'): void; (e: 'update:visible'): void; @@ -61,7 +61,7 @@ const getUserRouteLocationByWorkspaceId = (item) => ({ }); const getServiceAccountRouteLocationByWorkspaceId = (item) => ({ - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, + name: SERVICE_ACCOUNT_ROUTE._NAME, params: { workspaceId: item?.workspace_id, }, diff --git a/apps/web/src/services/my-page/routes/routes.ts b/apps/web/src/services/my-page/routes/routes.ts index 7557a2c951..4d4ccce9e8 100644 --- a/apps/web/src/services/my-page/routes/routes.ts +++ b/apps/web/src/services/my-page/routes/routes.ts @@ -28,7 +28,7 @@ const myPageRoutes: RouteConfig = { }, redirect: (to) => { const userStore = useUserStore(pinia); - return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap, userStore.getters.domainId); + return getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap); }, component: MyPageContainer, children: [ diff --git a/apps/web/src/services/ops-flow/configurator.ts b/apps/web/src/services/ops-flow/configurator.ts new file mode 100644 index 0000000000..e673fdb6c0 --- /dev/null +++ b/apps/web/src/services/ops-flow/configurator.ts @@ -0,0 +1,37 @@ +import type { Menu } from '@/lib/menu/config'; +import { MENU_ID } from '@/lib/menu/config'; + +import adminOpsFlowRoutes from '@/services/ops-flow/routes/admin/routes'; +import opsFlowRoutes from '@/services/ops-flow/routes/routes'; + +class OpsFlowConfigurator { + static getAdminRoutes() { + return adminOpsFlowRoutes; + } + + static getWorkspaceRoutes() { + return opsFlowRoutes; + } + + static getAdminMenu(): Menu { + return { + id: MENU_ID.OPS_FLOW, + subMenuList: [ + { id: MENU_ID.TASK_MANAGEMENT }, + ], + }; + } + + static getWorkspaceMenu(): Menu { + return { + id: MENU_ID.OPS_FLOW, + needPermissionByRole: true, + subMenuList: [ + { id: MENU_ID.OPS_FLOW_LANDING }, + { id: MENU_ID.TASK_BOARD }, + ], + }; + } +} + +export default OpsFlowConfigurator; diff --git a/apps/web/src/services/ops-flow/routes/routes.ts b/apps/web/src/services/ops-flow/routes/routes.ts index 4072e67164..a7a8455df9 100644 --- a/apps/web/src/services/ops-flow/routes/routes.ts +++ b/apps/web/src/services/ops-flow/routes/routes.ts @@ -28,7 +28,7 @@ const opsFlowRoutes: RouteConfig = { menuId: MENU_ID.OPS_FLOW, translationId: MENU_INFO_MAP[MENU_ID.OPS_FLOW].translationId, }, - redirect: (to) => getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap, userStore.getters.domainId), + redirect: (to) => getRedirectRouteByPagePermission(to, userStore.getters.pageAccessPermissionMap), component: OpsFlowContainer, children: [ { diff --git a/apps/web/src/services/project/configurator.ts b/apps/web/src/services/project/configurator.ts new file mode 100644 index 0000000000..b5b566c843 --- /dev/null +++ b/apps/web/src/services/project/configurator.ts @@ -0,0 +1,26 @@ +import type { Menu } from '@/lib/menu/config'; +import { MENU_ID } from '@/lib/menu/config'; + +import type { FeatureVersions } from '@/services/configurator'; +import projectRoutesV1 from '@/services/project/v1/routes/routes'; +import projectRoutes from '@/services/project/v2/routes/routes'; + +class ProjectConfigurator { + static getAdminRoutes() { + return null; + } + + static getWorkspaceRoutes(featureVersions: FeatureVersions) { + return featureVersions.PROJECT === 'V1' ? projectRoutesV1 : projectRoutes; + } + + static getAdminMenu(): Menu|null { + return null; + } + + static getWorkspaceMenu(): Menu { + return { id: MENU_ID.PROJECT, needPermissionByRole: true }; + } +} + +export default ProjectConfigurator; diff --git a/apps/web/src/services/project/v1/components/ProjectDetailTabHeader.vue b/apps/web/src/services/project/v1/components/ProjectDetailTabHeader.vue index 14f4256fa5..bf79e8a4f2 100644 --- a/apps/web/src/services/project/v1/components/ProjectDetailTabHeader.vue +++ b/apps/web/src/services/project/v1/components/ProjectDetailTabHeader.vue @@ -58,6 +58,7 @@ import { useProjectTreeStore } from '@/services/project/v-shared/stores/project- import ProjectMainDeleteModal from '@/services/project/v1/components/ProjectMainDeleteModal.vue'; import { PROJECT_ROUTE_V1 } from '@/services/project/v1/routes/route-constant'; import { useProjectDetailPageStore } from '@/services/project/v1/stores/project-detail-page-store'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; const ROLE_INFO_MAP = { @@ -134,7 +135,7 @@ const state = reactive({ { label: i18n.t('PROJECT.DETAIL.SERVICE_ACCOUNT'), to: { - name: ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, + name: SERVICE_ACCOUNT_ROUTE._NAME, params: { workspaceId: userWorkspaceStore.getters.currentWorkspaceId, }, diff --git a/apps/web/src/services/project/v1/components/ProjectMainProjectCard.vue b/apps/web/src/services/project/v1/components/ProjectMainProjectCard.vue index 790971552b..a4aebb2bd5 100644 --- a/apps/web/src/services/project/v1/components/ProjectMainProjectCard.vue +++ b/apps/web/src/services/project/v1/components/ProjectMainProjectCard.vue @@ -1,5 +1,4 @@ + + diff --git a/apps/web/src/services/asset-inventory/components/ServiceAccountAddClusterModal.vue b/apps/web/src/services/service-account/components/ServiceAccountAddClusterModal.vue similarity index 98% rename from apps/web/src/services/asset-inventory/components/ServiceAccountAddClusterModal.vue rename to apps/web/src/services/service-account/components/ServiceAccountAddClusterModal.vue index ee872dd8dd..ef6561dc4f 100644 --- a/apps/web/src/services/asset-inventory/components/ServiceAccountAddClusterModal.vue +++ b/apps/web/src/services/service-account/components/ServiceAccountAddClusterModal.vue @@ -22,9 +22,9 @@ import { useProxyValue } from '@/common/composables/proxy-state'; import { red, violet } from '@/styles/colors'; -import ServiceAccountAddClusterScriptField from '@/services/asset-inventory/components/ServiceAccountAddClusterScriptField.vue'; -import { OPEN_COST_OPTIONS } from '@/services/asset-inventory/constants/service-account-constant'; -import { useServiceAccountAgentStore } from '@/services/asset-inventory/stores/service-account-agent-store'; +import ServiceAccountAddClusterScriptField from '@/services/service-account/components/ServiceAccountAddClusterScriptField.vue'; +import { OPEN_COST_OPTIONS } from '@/services/service-account/constants/service-account-constant'; +import { useServiceAccountAgentStore } from '@/services/service-account/stores/service-account-agent-store'; diff --git a/apps/web/src/services/asset-inventory/components/ServiceAccountAddClusterScriptField.vue b/apps/web/src/services/service-account/components/ServiceAccountAddClusterScriptField.vue similarity index 100% rename from apps/web/src/services/asset-inventory/components/ServiceAccountAddClusterScriptField.vue rename to apps/web/src/services/service-account/components/ServiceAccountAddClusterScriptField.vue diff --git a/apps/web/src/services/asset-inventory/components/ServiceAccountAttachedGeneralAccounts.vue b/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue similarity index 97% rename from apps/web/src/services/asset-inventory/components/ServiceAccountAttachedGeneralAccounts.vue rename to apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue index b8c70ce20e..0499e370bb 100644 --- a/apps/web/src/services/asset-inventory/components/ServiceAccountAttachedGeneralAccounts.vue +++ b/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue @@ -46,11 +46,11 @@ import WorkspaceLogoIcon from '@/common/modules/navigations/top-bar/modules/top- import { green, red } from '@/styles/colors'; -import { getAccountFields, stateFormatter } from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; -import { useServiceAccountPageStore } from '@/services/asset-inventory/stores/service-account-page-store'; -import { useServiceAccountSchemaStore } from '@/services/asset-inventory/stores/service-account-schema-store'; import { PROJECT_ROUTE_V1 } from '@/services/project/v1/routes/route-constant'; +import { getAccountFields, stateFormatter } from '@/services/service-account/helpers/dynamic-ui-schema-generator'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; +import { useServiceAccountPageStore } from '@/services/service-account/stores/service-account-page-store'; +import { useServiceAccountSchemaStore } from '@/services/service-account/stores/service-account-schema-store'; const props = withDefaults(defineProps<{ serviceAccountId: string; @@ -332,7 +332,7 @@ watch(() => state.trustedAccountId, async (ta) => { {{ state.relatedTrustedAccount.name }} diff --git a/apps/web/src/services/asset-inventory/components/ServiceAccountEditModal.vue b/apps/web/src/services/service-account/components/ServiceAccountEditModal.vue similarity index 98% rename from apps/web/src/services/asset-inventory/components/ServiceAccountEditModal.vue rename to apps/web/src/services/service-account/components/ServiceAccountEditModal.vue index 4b46568027..58ae180f56 100644 --- a/apps/web/src/services/asset-inventory/components/ServiceAccountEditModal.vue +++ b/apps/web/src/services/service-account/components/ServiceAccountEditModal.vue @@ -22,7 +22,7 @@ import ErrorHandler from '@/common/composables/error/errorHandler'; import { useFormValidator } from '@/common/composables/form-validator'; import { useProxyValue } from '@/common/composables/proxy-state'; -import { useServiceAccountPageStore } from '@/services/asset-inventory/stores/service-account-page-store'; +import { useServiceAccountPageStore } from '@/services/service-account/stores/service-account-page-store'; const props = defineProps<{ visible: boolean; diff --git a/apps/web/src/services/asset-inventory/components/ServiceAccountProjectDetail.vue b/apps/web/src/services/service-account/components/ServiceAccountProjectDetail.vue similarity index 100% rename from apps/web/src/services/asset-inventory/components/ServiceAccountProjectDetail.vue rename to apps/web/src/services/service-account/components/ServiceAccountProjectDetail.vue diff --git a/apps/web/src/services/asset-inventory/components/ServiceAccountProjectForm.vue b/apps/web/src/services/service-account/components/ServiceAccountProjectForm.vue similarity index 97% rename from apps/web/src/services/asset-inventory/components/ServiceAccountProjectForm.vue rename to apps/web/src/services/service-account/components/ServiceAccountProjectForm.vue index 36c7496588..9464f78bb2 100644 --- a/apps/web/src/services/asset-inventory/components/ServiceAccountProjectForm.vue +++ b/apps/web/src/services/service-account/components/ServiceAccountProjectForm.vue @@ -20,7 +20,7 @@ import { import { useProxyValue } from '@/common/composables/proxy-state'; import ProjectSelectDropdown from '@/common/modules/project/ProjectSelectDropdown.vue'; -import type { ProjectForm } from '@/services/asset-inventory/types/service-account-page-type'; +import type { ProjectForm } from '@/services/service-account/types/service-account-page-type'; export default { diff --git a/apps/web/src/services/asset-inventory/components/WorkspaceDropdown.vue b/apps/web/src/services/service-account/components/WorkspaceDropdown.vue similarity index 100% rename from apps/web/src/services/asset-inventory/components/WorkspaceDropdown.vue rename to apps/web/src/services/service-account/components/WorkspaceDropdown.vue diff --git a/apps/web/src/services/service-account/configurator.ts b/apps/web/src/services/service-account/configurator.ts new file mode 100644 index 0000000000..03cc640185 --- /dev/null +++ b/apps/web/src/services/service-account/configurator.ts @@ -0,0 +1,24 @@ +import { MENU_ID } from '@/lib/menu/config'; + +import adminServiceAccountRoute from '@/services/service-account/routes/admin/routes'; +import serviceAccountRoute from '@/services/service-account/routes/routes'; + +class ServiceAccountConfigurator { + static getAdminRoutes() { + return adminServiceAccountRoute; + } + + static getWorkspaceRoutes() { + return serviceAccountRoute; + } + + static getAdminMenu() { + return { id: MENU_ID.SERVICE_ACCOUNT }; + } + + static getWorkspaceMenu() { + return { id: MENU_ID.SERVICE_ACCOUNT, needPermissionByRole: true }; + } +} + +export default ServiceAccountConfigurator; diff --git a/apps/web/src/services/asset-inventory/constants/service-account-constant.ts b/apps/web/src/services/service-account/constants/service-account-constant.ts similarity index 100% rename from apps/web/src/services/asset-inventory/constants/service-account-constant.ts rename to apps/web/src/services/service-account/constants/service-account-constant.ts diff --git a/apps/web/src/services/asset-inventory/helpers/agent-mode-helper.ts b/apps/web/src/services/service-account/helpers/agent-mode-helper.ts similarity index 100% rename from apps/web/src/services/asset-inventory/helpers/agent-mode-helper.ts rename to apps/web/src/services/service-account/helpers/agent-mode-helper.ts diff --git a/apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template.ts b/apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template.ts similarity index 99% rename from apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template.ts rename to apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template.ts index 34a65d475a..0ac811d4c6 100644 --- a/apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template.ts +++ b/apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template.ts @@ -3,7 +3,7 @@ import type { DynamicField } from '@cloudforet/mirinae/types/data-display/dynamic/dynamic-field/type/field-schema'; import type { SearchSchema } from '@cloudforet/mirinae/types/data-display/dynamic/dynamic-layout/type/layout-schema'; -import type { ItemLayout, QuerySearchTableLayout } from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator/type'; +import type { ItemLayout, QuerySearchTableLayout } from '@/services/service-account/helpers/dynamic-ui-schema-generator/type'; export const getDefaultDetailSchema = (fields: DynamicField[], options: { isTrustedAccount: boolean, diff --git a/apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/index.ts b/apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/index.ts similarity index 96% rename from apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/index.ts rename to apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/index.ts index fc4ded6e97..c406b6c579 100644 --- a/apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/index.ts +++ b/apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/index.ts @@ -13,9 +13,9 @@ import type { SchemaModel } from '@/api-clients/identity/schema/schema/model'; import ErrorHandler from '@/common/composables/error/errorHandler'; -import { ACCOUNT_STATE_COLOR } from '@/services/asset-inventory/constants/service-account-constant'; -import { getDefaultSearchSchema, getDefaultTableSchema } from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template'; -import type { GetSchemaParams, ResourceType, QuerySearchTableLayout } from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator/type'; +import { ACCOUNT_STATE_COLOR } from '@/services/service-account/constants/service-account-constant'; +import { getDefaultSearchSchema, getDefaultTableSchema } from '@/services/service-account/helpers/dynamic-ui-schema-generator/dynamic-layout-schema-template'; +import type { GetSchemaParams, ResourceType, QuerySearchTableLayout } from '@/services/service-account/helpers/dynamic-ui-schema-generator/type'; const getCustomTableSchemaKey = (userData:{userType:string, userId: string}, resourceType:ResourceType, provider:string) => { const { userType, userId } = userData; diff --git a/apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/type.ts b/apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/type.ts similarity index 100% rename from apps/web/src/services/asset-inventory/helpers/dynamic-ui-schema-generator/type.ts rename to apps/web/src/services/service-account/helpers/dynamic-ui-schema-generator/type.ts diff --git a/apps/web/src/services/asset-inventory/pages/ServiceAccountAddPage.vue b/apps/web/src/services/service-account/pages/ServiceAccountAddPage.vue similarity index 92% rename from apps/web/src/services/asset-inventory/pages/ServiceAccountAddPage.vue rename to apps/web/src/services/service-account/pages/ServiceAccountAddPage.vue index 24caee2b4f..280b72cf22 100644 --- a/apps/web/src/services/asset-inventory/pages/ServiceAccountAddPage.vue +++ b/apps/web/src/services/service-account/pages/ServiceAccountAddPage.vue @@ -31,21 +31,20 @@ import { showSuccessMessage } from '@/lib/helper/notice-alert-helper'; import ErrorHandler from '@/common/composables/error/errorHandler'; import InfoButton from '@/common/modules/portals/InfoButton.vue'; -import ServiceAccountAutoSyncForm from '@/services/asset-inventory/components/ServiceAccountAutoSyncForm.vue'; +import ServiceAccountAutoSyncForm from '@/services/service-account/components/ServiceAccountAutoSyncForm.vue'; import ServiceAccountBaseInformationForm - from '@/services/asset-inventory/components/ServiceAccountBaseInformationForm.vue'; + from '@/services/service-account/components/ServiceAccountBaseInformationForm.vue'; import ServiceAccountCredentialsForm - from '@/services/asset-inventory/components/ServiceAccountCredentialsForm.vue'; + from '@/services/service-account/components/ServiceAccountCredentialsForm.vue'; import { ACCOUNT_TYPE_BADGE_OPTION, PROVIDER_ACCOUNT_NAME, -} from '@/services/asset-inventory/constants/service-account-constant'; -import { ADMIN_ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/admin/route-constant'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; -import { useServiceAccountPageStore } from '@/services/asset-inventory/stores/service-account-page-store'; -import { useServiceAccountSchemaStore } from '@/services/asset-inventory/stores/service-account-schema-store'; -import type { BaseInformationForm, CredentialForm } from '@/services/asset-inventory/types/service-account-page-type'; - +} from '@/services/service-account/constants/service-account-constant'; +import { ADMIN_SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/admin/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; +import { useServiceAccountPageStore } from '@/services/service-account/stores/service-account-page-store'; +import { useServiceAccountSchemaStore } from '@/services/service-account/stores/service-account-schema-store'; +import type { BaseInformationForm, CredentialForm } from '@/services/service-account/types/service-account-page-type'; const serviceAccountSchemaStore = useServiceAccountSchemaStore(); const serviceAccountPageStore = useServiceAccountPageStore(); @@ -186,12 +185,12 @@ const handleSave = async () => { if (state.isTrustedAccount && serviceAccountPageFormState.isAutoSyncEnabled) state.createModal = true; else if (props.provider === 'kubernetes') { router.push({ - name: state.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, + name: state.isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE.DETAIL._NAME : SERVICE_ACCOUNT_ROUTE.DETAIL._NAME, params: { serviceAccountId: accountId as string }, }).catch(() => {}); } else { router.push({ - name: state.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, + name: state.isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE._NAME : SERVICE_ACCOUNT_ROUTE._NAME, query: { provider: props.provider }, }).catch(() => {}); } @@ -219,7 +218,7 @@ const handleSync = async () => { state.createModal = false; serviceAccountPageStore.initState(); router.push({ - name: state.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, + name: state.isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE.DETAIL._NAME : SERVICE_ACCOUNT_ROUTE.DETAIL._NAME, params: { serviceAccountId: state.createdAccountId }, }).catch(() => {}); } catch (e) { @@ -229,7 +228,7 @@ const handleSync = async () => { const handleRouteToServiceAccountDetailPage = () => { router.push({ - name: state.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, + name: state.isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE.DETAIL._NAME : SERVICE_ACCOUNT_ROUTE.DETAIL._NAME, params: { serviceAccountId: state.createdAccountId }, }).catch(() => {}); }; diff --git a/apps/web/src/services/asset-inventory/pages/ServiceAccountDetailPage.vue b/apps/web/src/services/service-account/pages/ServiceAccountDetailPage.vue similarity index 92% rename from apps/web/src/services/asset-inventory/pages/ServiceAccountDetailPage.vue rename to apps/web/src/services/service-account/pages/ServiceAccountDetailPage.vue index cdfaa8a995..be0610068c 100644 --- a/apps/web/src/services/asset-inventory/pages/ServiceAccountDetailPage.vue +++ b/apps/web/src/services/service-account/pages/ServiceAccountDetailPage.vue @@ -12,8 +12,6 @@ import { PLink, PButton, PIconButton, PHeading, PLazyImg, PHeadingLayout, } from '@cloudforet/mirinae'; - - import { ROLE_TYPE } from '@/api-clients/identity/role/constant'; import type { ServiceAccountGetParameters } from '@/api-clients/identity/service-account/schema/api-verbs/get'; import { ACCOUNT_TYPE } from '@/api-clients/identity/service-account/schema/constant'; @@ -33,22 +31,22 @@ import { MENU_ID } from '@/lib/menu/config'; import ErrorHandler from '@/common/composables/error/errorHandler'; +import { COST_EXPLORER_ROUTE } from '@/services/cost-explorer/routes/route-constant'; import ServiceAccountAttachedGeneralAccounts - from '@/services/asset-inventory/components/ServiceAccountAttachedGeneralAccounts.vue'; -import ServiceAccountAutoSync from '@/services/asset-inventory/components/ServiceAccountAutoSync.vue'; + from '@/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue'; +import ServiceAccountAutoSync from '@/services/service-account/components/ServiceAccountAutoSync.vue'; import ServiceAccountBaseInformation - from '@/services/asset-inventory/components/ServiceAccountBaseInformation.vue'; -import ServiceAccountCluster from '@/services/asset-inventory/components/ServiceAccountCluster.vue'; + from '@/services/service-account/components/ServiceAccountBaseInformation.vue'; +import ServiceAccountCluster from '@/services/service-account/components/ServiceAccountCluster.vue'; import ServiceAccountCredentials - from '@/services/asset-inventory/components/ServiceAccountCredentials.vue'; + from '@/services/service-account/components/ServiceAccountCredentials.vue'; import ServiceAccountDeleteModal - from '@/services/asset-inventory/components/ServiceAccountDeleteModal.vue'; -import ServiceAccountEditModal from '@/services/asset-inventory/components/ServiceAccountEditModal.vue'; -import { ADMIN_ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/admin/route-constant'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; -import { useServiceAccountPageStore } from '@/services/asset-inventory/stores/service-account-page-store'; -import { useServiceAccountSchemaStore } from '@/services/asset-inventory/stores/service-account-schema-store'; -import { COST_EXPLORER_ROUTE } from '@/services/cost-explorer/routes/route-constant'; + from '@/services/service-account/components/ServiceAccountDeleteModal.vue'; +import ServiceAccountEditModal from '@/services/service-account/components/ServiceAccountEditModal.vue'; +import { ADMIN_SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/admin/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; +import { useServiceAccountPageStore } from '@/services/service-account/stores/service-account-page-store'; +import { useServiceAccountSchemaStore } from '@/services/service-account/stores/service-account-schema-store'; const router = useRouter(); @@ -155,7 +153,7 @@ const handleRefresh = () => { }; const handleClickBackbutton = () => { router.push({ - name: storeState.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT._NAME, query: { provider: state.providerKey }, + name: storeState.isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE._NAME : SERVICE_ACCOUNT_ROUTE._NAME, query: { provider: state.providerKey }, }).catch(() => {}); }; diff --git a/apps/web/src/services/asset-inventory/pages/ServiceAccountPage.vue b/apps/web/src/services/service-account/pages/ServiceAccountPage.vue similarity index 92% rename from apps/web/src/services/asset-inventory/pages/ServiceAccountPage.vue rename to apps/web/src/services/service-account/pages/ServiceAccountPage.vue index 4e5c362fbc..8f20562118 100644 --- a/apps/web/src/services/asset-inventory/pages/ServiceAccountPage.vue +++ b/apps/web/src/services/service-account/pages/ServiceAccountPage.vue @@ -5,8 +5,6 @@ import { } from 'vue'; import { useRoute, useRouter } from 'vue-router/composables'; -import { clone } from 'lodash'; - import { QueryHelper } from '@cloudforet/core-lib/query'; import type { ConsoleFilter } from '@cloudforet/core-lib/query/type'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; @@ -45,8 +43,6 @@ 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'; -import type { MenuId } from '@/lib/menu/config'; -import { MENU_ID } from '@/lib/menu/config'; import { referenceFieldFormatter } from '@/lib/reference/referenceFieldFormatter'; import type { Reference } from '@/lib/reference/type'; import { replaceUrlQuery } from '@/lib/router-query-string'; @@ -54,6 +50,7 @@ import { replaceUrlQuery } from '@/lib/router-query-string'; import AutoSyncState from '@/common/components/badge/auto-sync-state/AutoSyncState.vue'; import { useQuerySearchPropsWithSearchSchema } from '@/common/composables/dynamic-layout'; import ErrorHandler from '@/common/composables/error/errorHandler'; +import { usePageEditableStatus } from '@/common/composables/page-editable-status'; import CustomFieldModalForDynamicLayout from '@/common/modules/custom-table/custom-field-modal/CustomFieldModalForDynamicLayout.vue'; import { gray } from '@/styles/colors'; @@ -62,15 +59,14 @@ import ProviderList from '@/services/asset-inventory/components/ProviderList.vue import { ACCOUNT_TYPE_BADGE_OPTION, PROVIDER_ACCOUNT_NAME, -} from '@/services/asset-inventory/constants/service-account-constant'; -import { convertAgentModeOptions } from '@/services/asset-inventory/helpers/agent-mode-helper'; -import { stateFormatter } from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator'; -import type { QuerySearchTableLayout } from '@/services/asset-inventory/helpers/dynamic-ui-schema-generator/type'; -import { ADMIN_ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/admin/route-constant'; -import { ASSET_INVENTORY_ROUTE } from '@/services/asset-inventory/routes/route-constant'; -import { useServiceAccountPageStore } from '@/services/asset-inventory/stores/service-account-page-store'; -import { useServiceAccountSchemaStore } from '@/services/asset-inventory/stores/service-account-schema-store'; -import { COST_EXPLORER_ROUTE } from '@/services/cost-explorer/routes/route-constant'; +} from '@/services/service-account/constants/service-account-constant'; +import { convertAgentModeOptions } from '@/services/service-account/helpers/agent-mode-helper'; +import { stateFormatter } from '@/services/service-account/helpers/dynamic-ui-schema-generator'; +import type { QuerySearchTableLayout } from '@/services/service-account/helpers/dynamic-ui-schema-generator/type'; +import { ADMIN_SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/admin/route-constant'; +import { SERVICE_ACCOUNT_ROUTE } from '@/services/service-account/routes/route-constant'; +import { useServiceAccountPageStore } from '@/services/service-account/stores/service-account-page-store'; +import { useServiceAccountSchemaStore } from '@/services/service-account/stores/service-account-schema-store'; const { width } = useWindowSize(); @@ -89,21 +85,14 @@ const allReferenceStore = useAllReferenceStore(); const userStore = useUserStore(); +const { hasReadWriteAccess } = usePageEditableStatus(); + + const storeState = reactive({ pageAccessPermissionMap: computed(() => userStore.getters.pageAccessPermissionMap), currency: computed(() => serviceAccountPageGetters.currency), }); const state = reactive({ - selectedMenuId: computed(() => { - const reversedMatched = clone(route.matched).reverse(); - const closestRoute = reversedMatched.find((d) => d.meta?.menuId !== undefined); - const targetMenuId: MenuId = closestRoute?.meta?.menuId || MENU_ID.WORKSPACE_HOME; - if (route.name === COST_EXPLORER_ROUTE.LANDING._NAME) { - return ''; - } - return targetMenuId; - }), - hasReadWriteAccess: computed(() => storeState.pageAccessPermissionMap[state.selectedMenuId]?.write), isAdminMode: computed(() => appContextStore.getters.isAdminMode), trustedAccounts: computed(() => allReferenceStore.getters.trustedAccount), providers: computed(() => allReferenceStore.getters.provider), @@ -278,7 +267,7 @@ const fieldHandler: DynamicLayoutFieldHandler> = /** Add & Delete Service Accounts Action (Dropdown) * */ const clickAddServiceAccount = () => { router.push({ - name: state.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.ADD._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.ADD._NAME, + name: state.isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE.ADD._NAME : SERVICE_ACCOUNT_ROUTE.ADD._NAME, params: { provider: state.selectedProvider, serviceAccountType: state.isAdminMode ? ACCOUNT_TYPE.TRUSTED : serviceAccountSchemaState.selectedAccountType }, query: { nextPath: route.fullPath }, }).catch(() => {}); @@ -292,7 +281,7 @@ const handleSelectServiceAccountType = (accountType: AccountType) => { serviceAc const handleClickRow = (index) => { const item = tableState.items[index]; router.push({ - name: state.isAdminMode ? ADMIN_ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME : ASSET_INVENTORY_ROUTE.SERVICE_ACCOUNT.DETAIL._NAME, + name: state.isAdminMode ? ADMIN_SERVICE_ACCOUNT_ROUTE.DETAIL._NAME : SERVICE_ACCOUNT_ROUTE.DETAIL._NAME, params: { serviceAccountId: tableState.isTrustedAccount ? item.trusted_account_id : item.service_account_id }, }).catch(() => {}); }; @@ -401,7 +390,7 @@ onMounted(async () => {