diff --git a/.gitignore b/.gitignore index 17f0f9a2..cd4389a1 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,11 @@ asset/mcmpapi/mcmpapi-*.yaml dockercontainer-volume container-volume old -dockerfiles/nginx/nginx.conf \ No newline at end of file +dockerfiles/nginx/nginx.conf + +# Documentation (local only) +doc/ +# Spec reference (local only) +# Developers copy SPEC.md.template to SPEC.md for local reference +# SPEC.md is not committed to avoid conflicts +SPEC.md diff --git a/Dockerfile.mciammanager b/Dockerfile.mciammanager index 778d42d5..bc12ad38 100644 --- a/Dockerfile.mciammanager +++ b/Dockerfile.mciammanager @@ -1,6 +1,6 @@ # --- Build Stage --- -FROM golang:1.23.1-alpine AS builder -# Updated Go version to match go.mod (1.23.1) +FROM golang:1.25.0-alpine AS builder +# Updated Go version to match go.mod (1.25.0) # Install build dependencies if any (e.g., git for private modules) RUN apk add --no-cache git diff --git a/asset/mcmpapi/frameworks.yaml b/asset/mcmpapi/frameworks.yaml new file mode 100644 index 00000000..32d2c645 --- /dev/null +++ b/asset/mcmpapi/frameworks.yaml @@ -0,0 +1,84 @@ +# Swagger-to-Actions Framework Configuration +# This file defines multiple frameworks and their Swagger specifications +# to be aggregated into a single serviceActions YAML file. +# +# Version Management: +# - Each framework has a 'version' field to track the active API version +# - The output file includes '_meta' with version, repository, and generatedAt +# - mc-iam-manager can load this file at init and manage version tracking in DB + +# Output file path (relative to this config file) +output: ./service-actions.yaml + +# HTTP timeout for fetching remote Swagger specs (in seconds) +timeout: 30 + +# Enable verbose output +verbose: false + +# List of frameworks to process +frameworks: + # MC-IAM-Manager - Identity and Access Management + - name: mc-iam-manager + version: "0.3.0" # Active version (local development) + repository: https://github.com/m-cmp/mc-iam-manager + swagger: ../../docs/swagger.yaml # Local path relative to this file + + # MC-Observability - Monitoring and Observability + # Note: Swagger file path needs to be verified - currently not found in v0.5.0 + # - name: mc-observability + # version: "0.5.0" # Latest release: v0.5.0 (Nov 3, 2025) + # repository: https://github.com/m-cmp/mc-observability + # swagger: https://raw.githubusercontent.com/m-cmp/mc-observability/v0.5.0/swagger/swagger.yaml + + # MC-Application-Manager - Application Deployment Management + - name: mc-application-manager + version: "0.5.0" # Latest release: v0.5.0 + repository: https://github.com/m-cmp/mc-application-manager + swagger: https://raw.githubusercontent.com/m-cmp/mc-application-manager/v0.5.0/swagger.json + + # MC-Cost-Optimizer - Cost Optimization + - name: mc-cost-optimizer + version: "0.5.0" # Latest release: v0.5.0 + repository: https://github.com/m-cmp/mc-cost-optimizer + swagger: https://raw.githubusercontent.com/m-cmp/mc-cost-optimizer/v0.5.0/swagger.yaml + + # MC-Workflow-Manager - Workflow Orchestration + - name: mc-workflow-manager + version: "0.5.0" # Latest release: v0.5.0 + repository: https://github.com/m-cmp/mc-workflow-manager + swagger: https://raw.githubusercontent.com/m-cmp/mc-workflow-manager/v0.5.0/swagger.json + + # MC-Infra-Manager - Multi-Cloud Infrastructure Management + # Note: No releases found - using main branch + # - name: mc-infra-manager + # version: "main" # No releases, using main branch + # repository: https://github.com/m-cmp/mc-infra-manager + # swagger: https://raw.githubusercontent.com/m-cmp/mc-infra-manager/main/swagger.yaml + + # MC-Infra-Connector - Cloud Infrastructure Connection + # Note: No releases found - using main branch + # - name: mc-infra-connector + # version: "main" # No releases, using main branch + # repository: https://github.com/m-cmp/mc-infra-connector + # swagger: https://raw.githubusercontent.com/m-cmp/mc-infra-connector/main/swagger.yaml + + # MC-Data-Manager - Data Management + # Note: No releases found - using main branch + # - name: mc-data-manager + # version: "main" # No releases, using main branch + # repository: https://github.com/m-cmp/mc-data-manager + # swagger: https://raw.githubusercontent.com/m-cmp/mc-data-manager/main/swagger.yaml + + # MC-Across-Service-Manager - Cross-Service Management + # Note: Latest release is v0.1.0, not v0.5.0 - Swagger file path needs verification + # - name: mc-across-service-manager + # version: "0.1.0" # Latest release: v0.1.0 (not v0.5.0) + # repository: https://github.com/m-cmp/mc-across-service-manager + # swagger: https://raw.githubusercontent.com/m-cmp/mc-across-service-manager/v0.1.0/swagger.yaml + + # MC-Web-Console - Web Console Interface + # - name: mc-web-console + # version: "0.1.0" + # repository: https://github.com/m-cmp/mc-web-console + # swagger: /path/to/swagger.yaml diff --git a/asset/mcmpapi/service-actions.yaml b/asset/mcmpapi/service-actions.yaml new file mode 100644 index 00000000..ee2c0966 --- /dev/null +++ b/asset/mcmpapi/service-actions.yaml @@ -0,0 +1,1121 @@ +serviceActions: + mc-application-manager: + _meta: + version: 0.5.0 + repository: https://github.com/m-cmp/mc-application-manager + generatedAt: "2026-01-06T07:17:34Z" + checkConnectionUsingPOST: + method: post + resourcePath: /oss/connection-check + description: checkConnection + createCatalogRefUsingPOST: + method: post + resourcePath: /catalog/software/ref/{catalogIdx} + description: software catalog 관련정보 등록(webpage, workflow 등) + createCatalogUsingPOST: + method: post + resourcePath: /catalog/software/ + description: software catalog 등록 + createComponentByTextUsingPOST: + method: post + resourcePath: /oss/v1/components/{module}/create/{name}/text + description: createComponentByText + createComponentUsingPOST: + method: post + resourcePath: /oss/v1/components/{module}/create/{name} + description: createComponent + createManifestUsingPOST: + method: post + resourcePath: /manifest/ + description: createManifest + createRepositoryUsingPOST: + method: post + resourcePath: /oss/v1/repositories/{module}/create + description: createRepository + createRepositoryUsingPOST_1: + method: post + resourcePath: /repository/ + description: createRepository + deleteCatalogRefWorkflowUsingDELETE: + method: delete + resourcePath: /catalog/software/ref/{catalogIdx}/{catalogRefIdx} + description: deleteCatalogRefWorkflow + deleteCatalogUsingDELETE: + method: delete + resourcePath: /catalog/software/{catalogIdx} + description: software catalog 삭제 + deleteComponentUsingDELETE: + method: delete + resourcePath: /oss/v1/components/{module}/delete/{id} + description: deleteComponent + deleteOssTypeUsingDELETE: + method: delete + resourcePath: /ossType/{ossTypeIdx} + description: deleteOssType + deleteOssUsingDELETE: + method: delete + resourcePath: /oss/{ossIdx} + description: deleteOss + deleteRepositoryFileUsingDELETE: + method: delete + resourcePath: /repository/file/{filename} + description: deleteRepositoryFile + deleteRepositoryUsingDELETE: + method: delete + resourcePath: /oss/v1/repositories/{module}/delete/{name} + description: deleteRepository + deleteRepositoryUsingDELETE_1: + method: delete + resourcePath: /repository/ + description: deleteRepository + detailOssTypeUsingGET: + method: get + resourcePath: /ossType/{ossTypeIdx} + description: detailOssType + detailOssUsingGET: + method: get + resourcePath: /oss/{ossIdx} + description: detailOss + errorHtmlUsingDELETE: + method: delete + resourcePath: /error + description: errorHtml + errorHtmlUsingGET: + method: get + resourcePath: /error + description: errorHtml + errorHtmlUsingHEAD: + method: head + resourcePath: /error + description: errorHtml + errorHtmlUsingOPTIONS: + method: options + resourcePath: /error + description: errorHtml + errorHtmlUsingPATCH: + method: patch + resourcePath: /error + description: errorHtml + errorHtmlUsingPOST: + method: post + resourcePath: /error + description: errorHtml + errorHtmlUsingPUT: + method: put + resourcePath: /error + description: errorHtml + execWorkflowUsingPOST: + method: post + resourcePath: /catalog/software/ref/workflow + description: execWorkflow + generateConfigmapYamlUsingPOST: + method: post + resourcePath: /yaml/configmap + description: generateConfigmapYaml + generateDeploymentYamlUsingPOST: + method: post + resourcePath: /yaml/deployment + description: generateDeploymentYaml + generateHPAYamlUsingPOST: + method: post + resourcePath: /yaml/hpa + description: generateHPAYaml + generatePodYamlUsingPOST: + method: post + resourcePath: /yaml/pod + description: generatePodYaml + generateServiceYamlUsingPOST: + method: post + resourcePath: /yaml/service + description: generateServiceYaml + getArtifactHubListUsingGET: + method: get + resourcePath: /search/artifacthub/{keyword} + description: getArtifactHubList + getCatalogDetailUsingGET: + method: get + resourcePath: /catalog/software/{catalogIdx} + description: software catalog 내용 확인(연결된 정보들까지) + getCatalogListUsingGET: + method: get + resourcePath: /catalog/software/ + description: software catalog 리스트 불러오기 + getCatalogReferenceUsingGET: + method: get + resourcePath: /catalog/software/ref/{catalogIdx} + description: getCatalogReference + getComponentDetailByNameUsingGET: + method: get + resourcePath: /oss/v1/components/{module}/detail/{id} + description: getComponentDetailByName + getComponentListUsingGET: + method: get + resourcePath: /oss/v1/components/{module}/list/{name} + description: getComponentList + getDockerHubListUsingGET: + method: get + resourcePath: /search/dockerhub/{keyword} + description: getDockerHubList + getManifestDetailTxtUsingGET: + method: get + resourcePath: /manifest/{manifestIdx}/txt + description: getManifestDetailTxt + getManifestDetailUsingGET: + method: get + resourcePath: /manifest/{manifestIdx} + description: getManifestDetail + getManifestUsingGET: + method: get + resourcePath: /manifest/ + description: getManifest + getOssListUsingGET: + method: get + resourcePath: /oss/list/{ossTypeName} + description: getOssList + getOssListUsingGET_1: + method: get + resourcePath: /oss/list + description: getOssList + getOssTypeListUsingGET: + method: get + resourcePath: /ossType/list + description: getOssTypeList + getRepositoryDetailByNameUsingGET: + method: get + resourcePath: /oss/v1/repositories/{module}/detail/{name} + description: getRepositoryDetailByName + getRepositoryFileUsingGET: + method: get + resourcePath: /repository/file/{filename} + description: getRepositoryFile + getRepositoryListUsingGET: + method: get + resourcePath: /oss/v1/repositories/{module}/list + description: getRepositoryList + getRepositoryListUsingGET_1: + method: get + resourcePath: /repository/ + description: getRepositoryList + getRepositoryUsingGET: + method: get + resourcePath: /repository/{repositoryName} + description: getRepository + insertRepositoryUsingPOST: + method: post + resourcePath: /repository/{repositoryName} + description: insertRepository + isOssInfoDuplicatedUsingGET: + method: get + resourcePath: /oss/duplicate + description: isOssInfoDuplicated + openapiJsonUsingGET: + method: get + resourcePath: /v3/api-docs + description: openapiJson + openapiJsonUsingGET_1: + method: get + resourcePath: /v3/api-docs/swagger-config + description: openapiJson + openapiYamlUsingGET: + method: get + resourcePath: /v3/api-docs.yaml + description: openapiYaml + redirectToUiUsingGET: + method: get + resourcePath: /swagger-ui.html + description: redirectToUi + registOssTypeUsingPOST: + method: post + resourcePath: /ossType + description: registOssType + registOssUsingPOST: + method: post + resourcePath: /oss + description: registOss + saveManifestUsingGET: + method: get + resourcePath: /manifest/download/{manifestIdx} + description: saveManifest + updateCatalogUsingPUT: + method: put + resourcePath: /catalog/software/ + description: software catalog 수정 + updateManifestUsingDELETE: + method: delete + resourcePath: /manifest/{manifestIdx} + description: updateManifest + updateManifestUsingPUT: + method: put + resourcePath: /manifest/ + description: updateManifest + updateOssTypeUsingPATCH: + method: patch + resourcePath: /ossType/{ossTypeIdx} + description: updateOssType + updateOssUsingPATCH: + method: patch + resourcePath: /oss/{ossIdx} + description: updateOss + updateRepositoryUsingPUT: + method: put + resourcePath: /oss/v1/repositories/{module}/update + description: updateRepository + updateRepositoryUsingPUT_1: + method: put + resourcePath: /repository/ + description: updateRepository + uploadFilesUsingPOST: + method: post + resourcePath: /repository/file/ + description: file upload + mc-cost-optimizer: + _meta: + version: 0.5.0 + repository: https://github.com/m-cmp/mc-cost-optimizer + generatedAt: "2026-01-06T07:17:34Z" + getAbrnormalRcmd: + method: post + resourcePath: /api/costopti/be/opti/abnormalRcmd + description: 최근 24시간동안 과금이 발생한 서비스들의 이상 비용 여부를 확인한다. + getAlarmHistory: + method: post + resourcePath: /api/costopti/be/alarm/history + description: 최근 7일간 발생한 최적화 알람을 조회한다. + getBillAsset: + method: post + resourcePath: /api/costopti/be/getBillAsset + description: 이번달 사용한 서비스(VM, DB 등) 단위의 비용을 확인합니다. + getBillingBaseInfo: + method: post + resourcePath: /api/costopti/be/invoice/getBillingBaseInfo + description: 이번달 CSP별 요약된 빌링 인보이스를 확인한다. + getCurMonthBill: + method: post + resourcePath: /api/costopti/be/getCurMonthBill + description: 지난달 대비 이번달 비용을 확인합니다. + getInstOptiSizeRcmd: + method: post + resourcePath: /api/costopti/be/opti/instOptiSizeRcmd + description: 사용중인 인스턴스의 추천 사이즈를 확인한다. + getInvoice: + method: post + resourcePath: /api/costopti/be/invoice/getInvoice + description: 이번달 빌링 인보이스 내역을 확인한다. + getProjects: + method: get + resourcePath: /api/costopti/be/getProjects + description: 워크스페이스에 속한 프로젝트 목록을 조회합니다. + getReadyz: + method: get + resourcePath: /api/costopti/be/readyz + description: 어플리케이션의 상태를 조회합니다. + getSummary: + method: post + resourcePath: /api/costopti/be/invoice/getSummary + description: CSP별 빌링 인보이스 비용을 월별로 확인한다. + getTop5Bill: + method: post + resourcePath: /api/costopti/be/getTop5Bill + description: 이번달에 사용한 비용 상위 5개의 리소스와 비용을 확인합니다. + getUnusedRcmd: + method: post + resourcePath: /api/costopti/be/opti/unusedRcmd + description: 최근 24시간동안 과금이 발생한 리소스에 대하여 미사용 자원을 추천한다. + getWorkspaces: + method: get + resourcePath: /api/costopti/be/getWorkspaces + description: 워크스페이스 목록을 조회합니다. + updateTBBRscMeta: + method: get + resourcePath: /api/costopti/be/updateRscMeta + description: "" + mc-iam-manager: + _meta: + version: 0.3.0 + repository: https://github.com/m-cmp/mc-iam-manager + generatedAt: "2026-01-06T07:17:34Z" + UpdateFrameworkService: + method: put + resourcePath: /api/mcmp-apis/name/{serviceName} + description: Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API service definition identified by its name. Cannot update name or version. + addCspRoleMappings: + method: post + resourcePath: /api/roles/csp-roles + description: Create a new mapping between role and CSP role + addProjectToWorkspace: + method: post + resourcePath: /api/workspaces/assign/projects + description: Add a project to a workspace + addUserToWorkspace: + method: post + resourcePath: /api/workspaces/{id}/users + description: Add a user to a workspace + addWorkspaceToProject: + method: post + resourcePath: /api/projects/{id}/workspaces/{workspaceId} + description: 프로젝트에 워크스페이스를 연결합니다. + assignMciamPermissionToRole: + method: post + resourcePath: /api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId} + description: 역할에 MC-IAM 권한을 할당합니다. + assignPlatformRole: + method: post + resourcePath: /api/roles/assign/platform-role + description: Assign a platform role to a user + assignRole: + method: post + resourcePath: /api/roles/id/{roleId}/assign + description: Assign a role to a user + assignWorkspaceRole: + method: post + resourcePath: /api/roles/assign/workspace-role + description: Assign a workspace role to a user + checkUserRoles: + method: get + resourcePath: /api/setup/check-user-roles + description: Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다. + createCspRole: + method: post + resourcePath: /api/roles/csp + description: Create a new csp role + createCspRoles: + method: post + resourcePath: /api/roles/csp-roles/batch + description: Create multiple new csp roles + createMciamPermission: + method: post + resourcePath: /api/permissions/mciam + description: Create a new permission with the specified information. + createMcmpApiPermissionActionMapping: + method: post + resourcePath: /api/mcmp-api-permission-action-mappings + description: Creates a new mapping between a permission and an API action + createMenu: + method: post + resourcePath: /api/menus + description: Create a new menu + createMenusRolesMapping: + method: post + resourcePath: /api/menus/platform-roles + description: Create a new menu mapping + createPlatformRole: + method: post + resourcePath: /api/roles/platform-roles + description: Create a new menu role + createProject: + method: post + resourcePath: /api/projects + description: Create a new project with the specified information. + createResourceType: + method: post + resourcePath: /api/resource-types/cloud-resources + description: 새로운 리소스 타입을 생성합니다 + createRole: + method: post + resourcePath: /api/roles + description: Create a new role + createUser: + method: post + resourcePath: /api/users + description: Create a new user with the specified information. + createWorkspace: + method: post + resourcePath: /api/workspaces + description: Create a new workspace with the specified information. + createWorkspaceRole: + method: post + resourcePath: /api/roles/workspace-roles + description: Create a new workspace role + deleteCspRole: + method: delete + resourcePath: /api/roles/csp-roles/id/{roleId} + description: Delete a role + deleteMapping: + method: delete + resourcePath: /api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId} + description: Deletes a mapping between a permission and an API action + deleteMciamPermission: + method: delete + resourcePath: /api/permissions/mciam/{id} + description: Delete a permission by its ID. + deleteMenu: + method: delete + resourcePath: /api/menus/id/{menuId} + description: Delete a menu + deleteMenusRolesMapping: + method: delete + resourcePath: /api/menus/platform-roles + description: Delete the mapping between a platform role and a menu. + deletePlatformRole: + method: delete + resourcePath: /api/roles/platform-roles/id/{roleId} + description: Delete a platform role + deleteProject: + method: delete + resourcePath: /api/projects/{id} + description: Delete a project by its ID. + deleteResourceType: + method: delete + resourcePath: /api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId + description: 리소스 타입을 삭제합니다 + deleteRole: + method: delete + resourcePath: /api/roles/id/{roleId} + description: Delete a role by its name. + deleteUser: + method: delete + resourcePath: /api/users/{id} + description: Delete a user by their ID. + deleteWorkspace: + method: delete + resourcePath: /api/workspaces/id/{workspaceId} + description: Delete a workspace by its ID. + deleteWorkspaceRole: + method: delete + resourcePath: /api/roles/workspace-roles/id/{roleId} + description: Delete a workspace role + getCloudResourceTypeByID: + method: get + resourcePath: /api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId + description: 특정 리소스 타입을 ID로 조회합니다 + getCspRoleByID: + method: get + resourcePath: /api/roles/csp/id/{roleId} + description: Get csp role details by ID + getCspRoleByName: + method: get + resourcePath: /api/roles/csp/name/{roleName} + description: Get csp role details by Name + getCspRoleMappingByRoleId: + method: get + resourcePath: /api/roles/csp-roles/id/:roleId + description: Get a mapping between role and CSP role + getMciamPermissionByID: + method: get + resourcePath: /api/permissions/mciam/id/{id} + description: Retrieve permission details by permission ID. + getMenuByID: + method: post + resourcePath: /api/menus/id/{menuId} + description: Get menu details by ID + getPlatformActionsByPermissionID: + method: get + resourcePath: /api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions + description: Returns all platform actions mapped to a specific permission + getPlatformRoleByID: + method: get + resourcePath: /api/roles/platform-roles/id/{roleId} + description: Get platform role details by ID + getPlatformRoleByName: + method: get + resourcePath: /api/roles/platform-roles/name/{roleName} + description: Get menu role details by Name + getProjectByID: + method: get + resourcePath: /api/projects/{id} + description: Retrieve project details by project ID. + getProjectByName: + method: get + resourcePath: /api/projects/name/{projectName} + description: Get project details by name + getRoleByRoleID: + method: get + resourcePath: /api/roles/id/{roleId} + description: Get role details by ID + getRoleByRoleName: + method: get + resourcePath: /api/roles/name/{roleName} + description: Retrieve role details by role name. + getRoleMasterMappings: + method: get + resourcePath: /api/roles/mappings/role/id/:roleId + description: Get role master mappings + getRoleMciamPermissions: + method: get + resourcePath: /api/roles/{roleType}/{roleId}/mciam-permissions + description: 특정 역할의 MC-IAM 권한 ID 목록을 조회합니다. + getUserByID: + method: get + resourcePath: /api/users/id/{userId} + description: Retrieve user details by user ID. + getUserByKcID: + method: get + resourcePath: /api/users/kc/{kcUserId} + description: Get user details by KcID + getUserByUsername: + method: get + resourcePath: /api/users/name/{username} + description: Get user details by username + getUserMenuTree: + method: get + resourcePath: /api/menus/user-menu-tree + description: Get menu tree based on user's platform roles + getUserWorkspaceAndWorkspaceRolesByUserID: + method: get + resourcePath: /api/users/id/{userId}/workspaces/roles/list + description: Get workspaces and roles for a specific user + getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID: + method: get + resourcePath: /api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list + description: Get workspaces and roles for a specific user and workspace + getUserWorkspaceRoles: + method: get + resourcePath: /api/workspaces/id/{workspaceId}/users/id/{userId} + description: Get roles assigned to a user in a workspace + getUserWorkspacesByUserID: + method: get + resourcePath: /api/users/id/{userId}/workspaces/list + description: Get workspaces for a specific user + getWorkspaceByID: + method: get + resourcePath: /api/workspaces/id/{workspaceId} + description: Retrieve workspace details by workspace ID. + getWorkspaceByName: + method: get + resourcePath: /api/workspaces/name/{workspaceName} + description: Retrieve specific workspace by name + getWorkspaceProjectsByWorkspaceId: + method: get + resourcePath: /api/workspaces/id/{workspaceId}/projects/list + description: Retrieve project list belonging to specific workspace + getWorkspaceRoleByID: + method: get + resourcePath: /api/roles/workspace-roles/id/{roleId} + description: Get workspace role details by ID + getWorkspaceRoleByName: + method: get + resourcePath: /api/roles/workspace-roles/name/{roleName} + description: Get workspace role details by Name + initializeMenuPermissions: + method: get + resourcePath: /api/setup/initial-role-menu-permission + description: CSV 파일을 읽어서 메뉴 권한을 초기화합니다 + listAllWorkspaceUsersAndRoles: + method: post + resourcePath: /api/workspaces/users-roles/list + description: Retrieve the list of users and roles assigned to the workspace. + listCSPRoles: + method: post + resourcePath: /api/roles/csp/list + description: Get a list of all csp roles + listCloudResourceTypes: + method: post + resourcePath: /api/resource-types/cloud-resources/list + description: 모든 리소스 타입 목록을 조회합니다 + listCspRoleMappings: + method: post + resourcePath: /api/roles/csp-roles/list + description: Get a mapping between role and CSP role + listMappedMenusByRole: + method: post + resourcePath: /api/menus/platform-roles/list + description: List menus mapped to a specific platform role. + listMciamPermissions: + method: post + resourcePath: /api/permissions/mciam/list + description: Retrieve a list of all permissions. + listMenus: + method: post + resourcePath: /api/menus/list + description: List all menus as a tree structure. Admin permission required. + listMenusTree: + method: post + resourcePath: /api/menus/tree/list + description: List all menus as a tree structure. Admin permission required. + listPermissionsByActionID: + method: get + resourcePath: /api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions + description: Returns all permissions mapped to a specific API action + listPlatformActions: + method: post + resourcePath: /api/mcmp-api-permission-action-mappings/list + description: Returns all platform actions mapped to a specific permission + listPlatformRoles: + method: post + resourcePath: /api/roles/menu-roles/list + description: Get a list of all menu roles + listProjects: + method: post + resourcePath: /api/projects/list + description: Retrieve a list of all projects. + listRoleMasterMappings: + method: post + resourcePath: /api/roles/mappings/list + description: List role master mappings + listRoles: + method: post + resourcePath: /api/roles/list + description: Retrieve a list of all roles. + listServicesAndActions: + method: post + resourcePath: /api/mcmp-apis/list + description: Retrieves all MCMP API service and action definitions currently stored in the database. + listUserMenu: + method: post + resourcePath: /api/users/menus/list + description: Get the menu list accessible to the current user's platform role. + listUserMenuTree: + method: post + resourcePath: /api/users/menus-tree/list + description: Get the menu tree accessible to the current user's platform role. + listUserProjectsByWorkspace: + method: get + resourcePath: /api/users/workspaces/id/{workspaceId}/projects/list + description: List projects for the current user + listUserWorkspaceAndWorkspaceRoles: + method: post + resourcePath: /api/users/workspaces/roles/list + description: List workspaces and roles for the current user + listUserWorkspaces: + method: post + resourcePath: /api/users/workspaces/list + description: List workspaces for the current user + listUsers: + method: post + resourcePath: /api/users/list + description: Retrieve a list of all users. + listUsersAndRolesByWorkspace: + method: post + resourcePath: /api/workspaces/id/{workspaceId}/users/list + description: Retrieve users and roles list belonging to workspace + listUsersByCspRole: + method: post + resourcePath: /api/roles/mappings/csp-roles/list + description: List users by csp role + listUsersByPlatformRole: + method: post + resourcePath: /api/roles/mappings/platform-roles/users/list + description: List users by platform role + listUsersByWorkspaceRole: + method: post + resourcePath: /api/roles/mappings/workspace-roles/users/list + description: List users by workspace role + listWorkspaceActionsByPermissionID: + method: post + resourcePath: /api/mcmp-api-permission-action-mappings/actions/list + description: Returns all workspace actions mapped to a specific permission + listWorkspaceProjects: + method: post + resourcePath: /api/workspaces/projects/list + description: Retrieve project list belonging to specific workspace + listWorkspaceRoles: + method: post + resourcePath: /api/roles/workspace-roles/list + description: Get a list of all workspace roles + listWorkspaceUsers: + method: post + resourcePath: /api/workspaces/users/list + description: List users by workspace criteria + listWorkspaces: + method: post + resourcePath: /api/workspaces/list + description: Retrieve a list of all workspaces. + mciamAuthCerts: + method: get + resourcePath: /api/auth/certs + description: Retrieve authentication certificates for MC-IAM-Manager to be used in target frameworks for token validation. + mciamCheckHealth: + method: get + resourcePath: /readyz + description: Check the health status of the service. + mciamCreateCredential: + method: post + resourcePath: /api/csp-credentials + description: 새로운 CSP 인증 정보를 생성합니다 + mciamDeleteCredential: + method: delete + resourcePath: /api/csp-credentials/{id} + description: CSP 인증 정보를 삭제합니다 + mciamGetCredentialByID: + method: get + resourcePath: /api/csp-credentials/{id} + description: 특정 CSP 인증 정보를 ID로 조회합니다 + mciamGetTempCredentialProviders: + method: get + resourcePath: /api/auth/temp-credential-csps + description: Get temporary credential provider information for AWS and GCP + mciamGetTemporaryCredentials: + method: post + resourcePath: /api/workspaces/temporary-credentials + description: Get temporary credentials for CSP + mciamListCredentials: + method: get + resourcePath: /api/csp-credentials + description: 모든 CSP 인증 정보 목록을 조회합니다 + mciamLogin: + method: post + resourcePath: /api/auth/login + description: Authenticate user and issue JWT token. + mciamLogout: + method: post + resourcePath: /api/auth/logout + description: Invalidate the user's refresh token and log out. + mciamRefreshToken: + method: post + resourcePath: /api/auth/refresh + description: Refresh JWT access token using a valid refresh token. + mciamUpdateCredential: + method: put + resourcePath: /api/csp-credentials/{id} + description: CSP 인증 정보를 업데이트합니다 + mciamValidateToken: + method: post + resourcePath: /api/auth/validate + description: Validate the current access token and refresh if expired + mciamWorkspaceTicket: + method: post + resourcePath: /api/workspaces/workspace-ticket + description: Set workspace ticket + mcmpApiCall: + method: post + resourcePath: /api/mcmp-apis/mcmpApiCall + description: Executes a defined MCMP API action with parameters structured in McmpApiCallRequest. + registerMenusFromBody: + method: post + resourcePath: /api/menus/setup/initial-menus2 + description: 'Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.' + registerMenusFromYAML: + method: post + resourcePath: /api/menus/setup/initial-menus + description: Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml. + removeCspRoleMappings: + method: delete + resourcePath: /api/roles/unassign/csp-roles + description: Delete a mapping between workspace role and CSP role + removeMciamPermissionFromRole: + method: delete + resourcePath: /api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId} + description: 역할에서 MC-IAM 권한을 제거합니다. + removePlatformRole: + method: delete + resourcePath: /api/roles/unassign/platform-role + description: Remove a platform role from a user + removeProjectFromWorkspace: + method: delete + resourcePath: /api/workspaces/unassign/projects + description: Remove a project from a workspace + removeRole: + method: delete + resourcePath: /api/roles/id/{roleId}/unassign + description: Remove a role from a user + removeUserFromWorkspace: + method: delete + resourcePath: /api/workspaces/{id}/users/{userId} + description: Remove a user from a workspace + removeWorkspaceRole: + method: delete + resourcePath: /api/roles/unassign/workspace-role + description: Remove a workspace role from a user + setActiveVersion: + method: put + resourcePath: /api/mcmp-apis/name/{serviceName}/versions/{version}/activate + description: Sets the specified version of an MCMP API service as the active one. + setupInitialAdmin: + method: post + resourcePath: /api/initial-admin + description: Creates the initial platform admin user with necessary permissions. platform admin 생성인데 + syncMcmpAPIs: + method: post + resourcePath: /api/mcmp-apis/syncMcmpAPIs + description: Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database. + syncProjects: + method: post + resourcePath: /api/setup/sync-projects + description: mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다. + testCallGetAllNs: + method: get + resourcePath: /api/mcmp-apis/test/mc-infra-manager/getallns + description: Calls the GetAllNs action of the mc-infra-manager service via the CallApi service. + updateCspRole: + method: put + resourcePath: /api/roles/csp-roles/id/{roleId} + description: Update role information + updateMapping: + method: put + resourcePath: /api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId} + description: Updates an existing mapping between a permission and an API action + updateMciamPermission: + method: put + resourcePath: /api/permissions/mciam/{id} + description: Update the details of an existing permission. + updateMenu: + method: put + resourcePath: /api/menus/id/{menuId} + description: Update menu information + updateProject: + method: put + resourcePath: /api/projects/{id} + description: Update the details of an existing project. + updateResourceType: + method: put + resourcePath: /api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId + description: 리소스 타입 정보를 업데이트합니다 + updateRole: + method: put + resourcePath: /api/roles/id/{roleId} + description: Update the details of an existing role. + updateUser: + method: put + resourcePath: /api/users/{id} + description: Update the details of an existing user. + updateUserStatus: + method: post + resourcePath: /api/users/id/{userId}/status + description: Update user status (active/inactive) + updateWorkspace: + method: put + resourcePath: /api/workspaces/id/{workspaceId} + description: Update the details of an existing workspace. + mc-workflow-manager: + _meta: + version: 0.5.0 + repository: https://github.com/m-cmp/mc-workflow-manager + generatedAt: "2026-01-06T07:17:34Z" + checkConnectionUsingGET: + method: get + resourcePath: /readyz + description: checkConnection + checkConnectionUsingPOST: + method: post + resourcePath: /oss/connection-check + description: checkConnection + deleteEventListnerUsingDELETE: + method: delete + resourcePath: /eventlistener/{eventListenerIdx} + description: deleteEventListner + deleteOssTypeUsingDELETE: + method: delete + resourcePath: /ossType/{ossTypeIdx} + description: deleteOssType + deleteOssUsingDELETE: + method: delete + resourcePath: /oss/{ossIdx} + description: deleteOss + deleteWorkflowStageTypeUsingDELETE: + method: delete + resourcePath: /workflowStageType/{workflowStageTypeIdx} + description: deleteWorkflowStageType + deleteWorkflowStageUsingDELETE: + method: delete + resourcePath: /workflowStage/{workflowStageIdx} + description: deleteWorkflowStage + deleteWorkflowUsingDELETE: + method: delete + resourcePath: /workflow/{workflowIdx} + description: deleteWorkflow + detailEventListenerUsingGET: + method: get + resourcePath: /eventlistener/{eventListenerIdx} + description: detailEventListener + detailOssTypeUsingGET: + method: get + resourcePath: /ossType/{ossTypeIdx} + description: detailOssType + detailOssUsingGET: + method: get + resourcePath: /oss/{ossIdx} + description: detailOss + detailWorkflowStageTypeUsingGET: + method: get + resourcePath: /workflowStageType/{workflowStageTypeIdx} + description: detailWorkflowStageType + detailWorkflowStageUsingGET: + method: get + resourcePath: /workflowStage/{workflowStageIdx} + description: detailWorkflowStage + errorUsingDELETE: + method: delete + resourcePath: /error + description: error + errorUsingGET: + method: get + resourcePath: /error + description: error + errorUsingHEAD: + method: head + resourcePath: /error + description: error + errorUsingOPTIONS: + method: options + resourcePath: /error + description: error + errorUsingPATCH: + method: patch + resourcePath: /error + description: error + errorUsingPOST: + method: post + resourcePath: /error + description: error + errorUsingPUT: + method: put + resourcePath: /error + description: error + getDefaultWorkflowStageUsingGET: + method: get + resourcePath: /workflowStage/default/script/{workflowStageTypeName} + description: getDefaultWorkflowStage + getEventListenerListUsingGET: + method: get + resourcePath: /eventlistener/list + description: getEventListenerList + getOssListUsingGET: + method: get + resourcePath: /oss/list/{ossTypeName} + description: getOssList + getOssListUsingGET_1: + method: get + resourcePath: /oss/list + description: getOssList + getOssTypeFilteredListUsingGET: + method: get + resourcePath: /ossType/filter/list + description: getOssTypeFilteredList + getOssTypeListUsingGET: + method: get + resourcePath: /ossType/list + description: getOssTypeList + getWorkflowDetailUsingGET: + method: get + resourcePath: /eventlistener/workflowDetail/{workflowIdx}/{evnetListenerYn} + description: getWorkflowDetail + getWorkflowHistoryListUsingGET: + method: get + resourcePath: /workflow/history/{workflowIdx} + description: getWorkflowHistoryList + getWorkflowListUsingGET: + method: get + resourcePath: /eventlistener/workflowList/{eventListenerYn} + description: getWorkflowList + getWorkflowListUsingGET_1: + method: get + resourcePath: /workflow/list + description: getWorkflowList + getWorkflowLogUsingGET: + method: get + resourcePath: /workflow/log/{workflowIdx} + description: getWorkflowLog + getWorkflowParamListUsingGET: + method: get + resourcePath: /workflow/param/list + description: getWorkflowParamList + getWorkflowRunHistoryListUsingGET: + method: get + resourcePath: /workflow/runHistory/{workflowIdx} + description: getWorkflowRunHistoryList + getWorkflowStageHistoryListUsingGET: + method: get + resourcePath: /workflow/stageHistory/{workflowIdx} + description: getWorkflowStageHistoryList + getWorkflowStageListUsingGET: + method: get + resourcePath: /workflow/workflowStageList + description: getWorkflowStageList + getWorkflowStageListUsingGET_1: + method: get + resourcePath: /workflowStage/list + description: getWorkflowStageList + getWorkflowStageListUsingGET_2: + method: get + resourcePath: /workflowStageType/list + description: getWorkflowStageList + getWorkflowTemplateUsingGET: + method: get + resourcePath: /workflow/template/{workflowName} + description: getWorkflowTemplate + getWorkflowUsingGET: + method: get + resourcePath: /workflow/{workflowIdx} + description: getWorkflow + isEventListenerDuplicatedUsingGET: + method: get + resourcePath: /eventlistener/duplicate + description: isEventListenerDuplicated + isOssInfoDuplicatedUsingGET: + method: get + resourcePath: /oss/duplicate + description: isOssInfoDuplicated + isWorkflowNameDuplicatedUsingGET: + method: get + resourcePath: /workflow/name/duplicate + description: isWorkflowNameDuplicated + isWorkflowStageNameDuplicatedUsingGET: + method: get + resourcePath: /workflowStage/duplicate + description: isWorkflowStageNameDuplicated + openapiJsonUsingGET: + method: get + resourcePath: /v3/api-docs + description: openapiJson + openapiJsonUsingGET_1: + method: get + resourcePath: /v3/api-docs/swagger-config + description: openapiJson + openapiYamlUsingGET: + method: get + resourcePath: /v3/api-docs.yaml + description: openapiYaml + redirectToUiUsingGET: + method: get + resourcePath: /swagger-ui.html + description: redirectToUi + registEventListnerUsingPOST: + method: post + resourcePath: /eventlistener + description: registEventListner + registOssTypeUsingPOST: + method: post + resourcePath: /ossType + description: registOssType + registOssUsingPOST: + method: post + resourcePath: /oss + description: registOss + registWorkflowStageUsingPOST: + method: post + resourcePath: /workflowStage + description: registWorkflowStage + registWorkflowStageUsingPOST_1: + method: post + resourcePath: /workflowStageType + description: registWorkflowStage + registWorkflowUsingPOST: + method: post + resourcePath: /workflow + description: registWorkflow + runEventListenerUsingGET: + method: get + resourcePath: /eventlistener/run/{eventListenerIdx} + description: runEventListener + runWorkflowGetUsingGET: + method: get + resourcePath: /workflow/run/{workflowIdx} + description: runWorkflowGet + runWorkflowPostUsingPOST: + method: post + resourcePath: /workflow/run + description: runWorkflowPost + updateEventListnerUsingPATCH: + method: patch + resourcePath: /eventlistener/{eventListenerIdx} + description: updateEventListner + updateOssTypeUsingPATCH: + method: patch + resourcePath: /ossType/{ossTypeIdx} + description: updateOssType + updateOssUsingPATCH: + method: patch + resourcePath: /oss/{ossIdx} + description: updateOss + updateWorkflowStageTypeUsingPATCH: + method: patch + resourcePath: /workflowStageType/{workflowStageTypeIdx} + description: updateWorkflowStageType + updateWorkflowStageUsingPATCH: + method: patch + resourcePath: /workflowStage/{workflowStageIdx} + description: updateWorkflowStage + updateWorkflowUsingPATCH: + method: patch + resourcePath: /workflow/{workflowIdx} + description: updateWorkflow diff --git a/conf/mc-iam-manager/frameworks.yaml b/conf/mc-iam-manager/frameworks.yaml new file mode 100644 index 00000000..32d2c645 --- /dev/null +++ b/conf/mc-iam-manager/frameworks.yaml @@ -0,0 +1,84 @@ +# Swagger-to-Actions Framework Configuration +# This file defines multiple frameworks and their Swagger specifications +# to be aggregated into a single serviceActions YAML file. +# +# Version Management: +# - Each framework has a 'version' field to track the active API version +# - The output file includes '_meta' with version, repository, and generatedAt +# - mc-iam-manager can load this file at init and manage version tracking in DB + +# Output file path (relative to this config file) +output: ./service-actions.yaml + +# HTTP timeout for fetching remote Swagger specs (in seconds) +timeout: 30 + +# Enable verbose output +verbose: false + +# List of frameworks to process +frameworks: + # MC-IAM-Manager - Identity and Access Management + - name: mc-iam-manager + version: "0.3.0" # Active version (local development) + repository: https://github.com/m-cmp/mc-iam-manager + swagger: ../../docs/swagger.yaml # Local path relative to this file + + # MC-Observability - Monitoring and Observability + # Note: Swagger file path needs to be verified - currently not found in v0.5.0 + # - name: mc-observability + # version: "0.5.0" # Latest release: v0.5.0 (Nov 3, 2025) + # repository: https://github.com/m-cmp/mc-observability + # swagger: https://raw.githubusercontent.com/m-cmp/mc-observability/v0.5.0/swagger/swagger.yaml + + # MC-Application-Manager - Application Deployment Management + - name: mc-application-manager + version: "0.5.0" # Latest release: v0.5.0 + repository: https://github.com/m-cmp/mc-application-manager + swagger: https://raw.githubusercontent.com/m-cmp/mc-application-manager/v0.5.0/swagger.json + + # MC-Cost-Optimizer - Cost Optimization + - name: mc-cost-optimizer + version: "0.5.0" # Latest release: v0.5.0 + repository: https://github.com/m-cmp/mc-cost-optimizer + swagger: https://raw.githubusercontent.com/m-cmp/mc-cost-optimizer/v0.5.0/swagger.yaml + + # MC-Workflow-Manager - Workflow Orchestration + - name: mc-workflow-manager + version: "0.5.0" # Latest release: v0.5.0 + repository: https://github.com/m-cmp/mc-workflow-manager + swagger: https://raw.githubusercontent.com/m-cmp/mc-workflow-manager/v0.5.0/swagger.json + + # MC-Infra-Manager - Multi-Cloud Infrastructure Management + # Note: No releases found - using main branch + # - name: mc-infra-manager + # version: "main" # No releases, using main branch + # repository: https://github.com/m-cmp/mc-infra-manager + # swagger: https://raw.githubusercontent.com/m-cmp/mc-infra-manager/main/swagger.yaml + + # MC-Infra-Connector - Cloud Infrastructure Connection + # Note: No releases found - using main branch + # - name: mc-infra-connector + # version: "main" # No releases, using main branch + # repository: https://github.com/m-cmp/mc-infra-connector + # swagger: https://raw.githubusercontent.com/m-cmp/mc-infra-connector/main/swagger.yaml + + # MC-Data-Manager - Data Management + # Note: No releases found - using main branch + # - name: mc-data-manager + # version: "main" # No releases, using main branch + # repository: https://github.com/m-cmp/mc-data-manager + # swagger: https://raw.githubusercontent.com/m-cmp/mc-data-manager/main/swagger.yaml + + # MC-Across-Service-Manager - Cross-Service Management + # Note: Latest release is v0.1.0, not v0.5.0 - Swagger file path needs verification + # - name: mc-across-service-manager + # version: "0.1.0" # Latest release: v0.1.0 (not v0.5.0) + # repository: https://github.com/m-cmp/mc-across-service-manager + # swagger: https://raw.githubusercontent.com/m-cmp/mc-across-service-manager/v0.1.0/swagger.yaml + + # MC-Web-Console - Web Console Interface + # - name: mc-web-console + # version: "0.1.0" + # repository: https://github.com/m-cmp/mc-web-console + # swagger: /path/to/swagger.yaml diff --git a/conf/mc-iam-manager/menu.yaml b/conf/mc-iam-manager/menu.yaml index 0d37b5d6..ab161459 100644 --- a/conf/mc-iam-manager/menu.yaml +++ b/conf/mc-iam-manager/menu.yaml @@ -263,6 +263,14 @@ menus: isaction: true priority: 2 menunumber: 1740 + + - id: csproles + parentid: workspaces + displayname: CSP Roles + restype: menu + isaction: true + priority: 2 + menunumber: 1741 - id: projectboard parentid: workspaces diff --git a/conf/mc-iam-manager/service-actions.yaml b/conf/mc-iam-manager/service-actions.yaml new file mode 100644 index 00000000..ee2c0966 --- /dev/null +++ b/conf/mc-iam-manager/service-actions.yaml @@ -0,0 +1,1121 @@ +serviceActions: + mc-application-manager: + _meta: + version: 0.5.0 + repository: https://github.com/m-cmp/mc-application-manager + generatedAt: "2026-01-06T07:17:34Z" + checkConnectionUsingPOST: + method: post + resourcePath: /oss/connection-check + description: checkConnection + createCatalogRefUsingPOST: + method: post + resourcePath: /catalog/software/ref/{catalogIdx} + description: software catalog 관련정보 등록(webpage, workflow 등) + createCatalogUsingPOST: + method: post + resourcePath: /catalog/software/ + description: software catalog 등록 + createComponentByTextUsingPOST: + method: post + resourcePath: /oss/v1/components/{module}/create/{name}/text + description: createComponentByText + createComponentUsingPOST: + method: post + resourcePath: /oss/v1/components/{module}/create/{name} + description: createComponent + createManifestUsingPOST: + method: post + resourcePath: /manifest/ + description: createManifest + createRepositoryUsingPOST: + method: post + resourcePath: /oss/v1/repositories/{module}/create + description: createRepository + createRepositoryUsingPOST_1: + method: post + resourcePath: /repository/ + description: createRepository + deleteCatalogRefWorkflowUsingDELETE: + method: delete + resourcePath: /catalog/software/ref/{catalogIdx}/{catalogRefIdx} + description: deleteCatalogRefWorkflow + deleteCatalogUsingDELETE: + method: delete + resourcePath: /catalog/software/{catalogIdx} + description: software catalog 삭제 + deleteComponentUsingDELETE: + method: delete + resourcePath: /oss/v1/components/{module}/delete/{id} + description: deleteComponent + deleteOssTypeUsingDELETE: + method: delete + resourcePath: /ossType/{ossTypeIdx} + description: deleteOssType + deleteOssUsingDELETE: + method: delete + resourcePath: /oss/{ossIdx} + description: deleteOss + deleteRepositoryFileUsingDELETE: + method: delete + resourcePath: /repository/file/{filename} + description: deleteRepositoryFile + deleteRepositoryUsingDELETE: + method: delete + resourcePath: /oss/v1/repositories/{module}/delete/{name} + description: deleteRepository + deleteRepositoryUsingDELETE_1: + method: delete + resourcePath: /repository/ + description: deleteRepository + detailOssTypeUsingGET: + method: get + resourcePath: /ossType/{ossTypeIdx} + description: detailOssType + detailOssUsingGET: + method: get + resourcePath: /oss/{ossIdx} + description: detailOss + errorHtmlUsingDELETE: + method: delete + resourcePath: /error + description: errorHtml + errorHtmlUsingGET: + method: get + resourcePath: /error + description: errorHtml + errorHtmlUsingHEAD: + method: head + resourcePath: /error + description: errorHtml + errorHtmlUsingOPTIONS: + method: options + resourcePath: /error + description: errorHtml + errorHtmlUsingPATCH: + method: patch + resourcePath: /error + description: errorHtml + errorHtmlUsingPOST: + method: post + resourcePath: /error + description: errorHtml + errorHtmlUsingPUT: + method: put + resourcePath: /error + description: errorHtml + execWorkflowUsingPOST: + method: post + resourcePath: /catalog/software/ref/workflow + description: execWorkflow + generateConfigmapYamlUsingPOST: + method: post + resourcePath: /yaml/configmap + description: generateConfigmapYaml + generateDeploymentYamlUsingPOST: + method: post + resourcePath: /yaml/deployment + description: generateDeploymentYaml + generateHPAYamlUsingPOST: + method: post + resourcePath: /yaml/hpa + description: generateHPAYaml + generatePodYamlUsingPOST: + method: post + resourcePath: /yaml/pod + description: generatePodYaml + generateServiceYamlUsingPOST: + method: post + resourcePath: /yaml/service + description: generateServiceYaml + getArtifactHubListUsingGET: + method: get + resourcePath: /search/artifacthub/{keyword} + description: getArtifactHubList + getCatalogDetailUsingGET: + method: get + resourcePath: /catalog/software/{catalogIdx} + description: software catalog 내용 확인(연결된 정보들까지) + getCatalogListUsingGET: + method: get + resourcePath: /catalog/software/ + description: software catalog 리스트 불러오기 + getCatalogReferenceUsingGET: + method: get + resourcePath: /catalog/software/ref/{catalogIdx} + description: getCatalogReference + getComponentDetailByNameUsingGET: + method: get + resourcePath: /oss/v1/components/{module}/detail/{id} + description: getComponentDetailByName + getComponentListUsingGET: + method: get + resourcePath: /oss/v1/components/{module}/list/{name} + description: getComponentList + getDockerHubListUsingGET: + method: get + resourcePath: /search/dockerhub/{keyword} + description: getDockerHubList + getManifestDetailTxtUsingGET: + method: get + resourcePath: /manifest/{manifestIdx}/txt + description: getManifestDetailTxt + getManifestDetailUsingGET: + method: get + resourcePath: /manifest/{manifestIdx} + description: getManifestDetail + getManifestUsingGET: + method: get + resourcePath: /manifest/ + description: getManifest + getOssListUsingGET: + method: get + resourcePath: /oss/list/{ossTypeName} + description: getOssList + getOssListUsingGET_1: + method: get + resourcePath: /oss/list + description: getOssList + getOssTypeListUsingGET: + method: get + resourcePath: /ossType/list + description: getOssTypeList + getRepositoryDetailByNameUsingGET: + method: get + resourcePath: /oss/v1/repositories/{module}/detail/{name} + description: getRepositoryDetailByName + getRepositoryFileUsingGET: + method: get + resourcePath: /repository/file/{filename} + description: getRepositoryFile + getRepositoryListUsingGET: + method: get + resourcePath: /oss/v1/repositories/{module}/list + description: getRepositoryList + getRepositoryListUsingGET_1: + method: get + resourcePath: /repository/ + description: getRepositoryList + getRepositoryUsingGET: + method: get + resourcePath: /repository/{repositoryName} + description: getRepository + insertRepositoryUsingPOST: + method: post + resourcePath: /repository/{repositoryName} + description: insertRepository + isOssInfoDuplicatedUsingGET: + method: get + resourcePath: /oss/duplicate + description: isOssInfoDuplicated + openapiJsonUsingGET: + method: get + resourcePath: /v3/api-docs + description: openapiJson + openapiJsonUsingGET_1: + method: get + resourcePath: /v3/api-docs/swagger-config + description: openapiJson + openapiYamlUsingGET: + method: get + resourcePath: /v3/api-docs.yaml + description: openapiYaml + redirectToUiUsingGET: + method: get + resourcePath: /swagger-ui.html + description: redirectToUi + registOssTypeUsingPOST: + method: post + resourcePath: /ossType + description: registOssType + registOssUsingPOST: + method: post + resourcePath: /oss + description: registOss + saveManifestUsingGET: + method: get + resourcePath: /manifest/download/{manifestIdx} + description: saveManifest + updateCatalogUsingPUT: + method: put + resourcePath: /catalog/software/ + description: software catalog 수정 + updateManifestUsingDELETE: + method: delete + resourcePath: /manifest/{manifestIdx} + description: updateManifest + updateManifestUsingPUT: + method: put + resourcePath: /manifest/ + description: updateManifest + updateOssTypeUsingPATCH: + method: patch + resourcePath: /ossType/{ossTypeIdx} + description: updateOssType + updateOssUsingPATCH: + method: patch + resourcePath: /oss/{ossIdx} + description: updateOss + updateRepositoryUsingPUT: + method: put + resourcePath: /oss/v1/repositories/{module}/update + description: updateRepository + updateRepositoryUsingPUT_1: + method: put + resourcePath: /repository/ + description: updateRepository + uploadFilesUsingPOST: + method: post + resourcePath: /repository/file/ + description: file upload + mc-cost-optimizer: + _meta: + version: 0.5.0 + repository: https://github.com/m-cmp/mc-cost-optimizer + generatedAt: "2026-01-06T07:17:34Z" + getAbrnormalRcmd: + method: post + resourcePath: /api/costopti/be/opti/abnormalRcmd + description: 최근 24시간동안 과금이 발생한 서비스들의 이상 비용 여부를 확인한다. + getAlarmHistory: + method: post + resourcePath: /api/costopti/be/alarm/history + description: 최근 7일간 발생한 최적화 알람을 조회한다. + getBillAsset: + method: post + resourcePath: /api/costopti/be/getBillAsset + description: 이번달 사용한 서비스(VM, DB 등) 단위의 비용을 확인합니다. + getBillingBaseInfo: + method: post + resourcePath: /api/costopti/be/invoice/getBillingBaseInfo + description: 이번달 CSP별 요약된 빌링 인보이스를 확인한다. + getCurMonthBill: + method: post + resourcePath: /api/costopti/be/getCurMonthBill + description: 지난달 대비 이번달 비용을 확인합니다. + getInstOptiSizeRcmd: + method: post + resourcePath: /api/costopti/be/opti/instOptiSizeRcmd + description: 사용중인 인스턴스의 추천 사이즈를 확인한다. + getInvoice: + method: post + resourcePath: /api/costopti/be/invoice/getInvoice + description: 이번달 빌링 인보이스 내역을 확인한다. + getProjects: + method: get + resourcePath: /api/costopti/be/getProjects + description: 워크스페이스에 속한 프로젝트 목록을 조회합니다. + getReadyz: + method: get + resourcePath: /api/costopti/be/readyz + description: 어플리케이션의 상태를 조회합니다. + getSummary: + method: post + resourcePath: /api/costopti/be/invoice/getSummary + description: CSP별 빌링 인보이스 비용을 월별로 확인한다. + getTop5Bill: + method: post + resourcePath: /api/costopti/be/getTop5Bill + description: 이번달에 사용한 비용 상위 5개의 리소스와 비용을 확인합니다. + getUnusedRcmd: + method: post + resourcePath: /api/costopti/be/opti/unusedRcmd + description: 최근 24시간동안 과금이 발생한 리소스에 대하여 미사용 자원을 추천한다. + getWorkspaces: + method: get + resourcePath: /api/costopti/be/getWorkspaces + description: 워크스페이스 목록을 조회합니다. + updateTBBRscMeta: + method: get + resourcePath: /api/costopti/be/updateRscMeta + description: "" + mc-iam-manager: + _meta: + version: 0.3.0 + repository: https://github.com/m-cmp/mc-iam-manager + generatedAt: "2026-01-06T07:17:34Z" + UpdateFrameworkService: + method: put + resourcePath: /api/mcmp-apis/name/{serviceName} + description: Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API service definition identified by its name. Cannot update name or version. + addCspRoleMappings: + method: post + resourcePath: /api/roles/csp-roles + description: Create a new mapping between role and CSP role + addProjectToWorkspace: + method: post + resourcePath: /api/workspaces/assign/projects + description: Add a project to a workspace + addUserToWorkspace: + method: post + resourcePath: /api/workspaces/{id}/users + description: Add a user to a workspace + addWorkspaceToProject: + method: post + resourcePath: /api/projects/{id}/workspaces/{workspaceId} + description: 프로젝트에 워크스페이스를 연결합니다. + assignMciamPermissionToRole: + method: post + resourcePath: /api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId} + description: 역할에 MC-IAM 권한을 할당합니다. + assignPlatformRole: + method: post + resourcePath: /api/roles/assign/platform-role + description: Assign a platform role to a user + assignRole: + method: post + resourcePath: /api/roles/id/{roleId}/assign + description: Assign a role to a user + assignWorkspaceRole: + method: post + resourcePath: /api/roles/assign/workspace-role + description: Assign a workspace role to a user + checkUserRoles: + method: get + resourcePath: /api/setup/check-user-roles + description: Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다. + createCspRole: + method: post + resourcePath: /api/roles/csp + description: Create a new csp role + createCspRoles: + method: post + resourcePath: /api/roles/csp-roles/batch + description: Create multiple new csp roles + createMciamPermission: + method: post + resourcePath: /api/permissions/mciam + description: Create a new permission with the specified information. + createMcmpApiPermissionActionMapping: + method: post + resourcePath: /api/mcmp-api-permission-action-mappings + description: Creates a new mapping between a permission and an API action + createMenu: + method: post + resourcePath: /api/menus + description: Create a new menu + createMenusRolesMapping: + method: post + resourcePath: /api/menus/platform-roles + description: Create a new menu mapping + createPlatformRole: + method: post + resourcePath: /api/roles/platform-roles + description: Create a new menu role + createProject: + method: post + resourcePath: /api/projects + description: Create a new project with the specified information. + createResourceType: + method: post + resourcePath: /api/resource-types/cloud-resources + description: 새로운 리소스 타입을 생성합니다 + createRole: + method: post + resourcePath: /api/roles + description: Create a new role + createUser: + method: post + resourcePath: /api/users + description: Create a new user with the specified information. + createWorkspace: + method: post + resourcePath: /api/workspaces + description: Create a new workspace with the specified information. + createWorkspaceRole: + method: post + resourcePath: /api/roles/workspace-roles + description: Create a new workspace role + deleteCspRole: + method: delete + resourcePath: /api/roles/csp-roles/id/{roleId} + description: Delete a role + deleteMapping: + method: delete + resourcePath: /api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId} + description: Deletes a mapping between a permission and an API action + deleteMciamPermission: + method: delete + resourcePath: /api/permissions/mciam/{id} + description: Delete a permission by its ID. + deleteMenu: + method: delete + resourcePath: /api/menus/id/{menuId} + description: Delete a menu + deleteMenusRolesMapping: + method: delete + resourcePath: /api/menus/platform-roles + description: Delete the mapping between a platform role and a menu. + deletePlatformRole: + method: delete + resourcePath: /api/roles/platform-roles/id/{roleId} + description: Delete a platform role + deleteProject: + method: delete + resourcePath: /api/projects/{id} + description: Delete a project by its ID. + deleteResourceType: + method: delete + resourcePath: /api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId + description: 리소스 타입을 삭제합니다 + deleteRole: + method: delete + resourcePath: /api/roles/id/{roleId} + description: Delete a role by its name. + deleteUser: + method: delete + resourcePath: /api/users/{id} + description: Delete a user by their ID. + deleteWorkspace: + method: delete + resourcePath: /api/workspaces/id/{workspaceId} + description: Delete a workspace by its ID. + deleteWorkspaceRole: + method: delete + resourcePath: /api/roles/workspace-roles/id/{roleId} + description: Delete a workspace role + getCloudResourceTypeByID: + method: get + resourcePath: /api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId + description: 특정 리소스 타입을 ID로 조회합니다 + getCspRoleByID: + method: get + resourcePath: /api/roles/csp/id/{roleId} + description: Get csp role details by ID + getCspRoleByName: + method: get + resourcePath: /api/roles/csp/name/{roleName} + description: Get csp role details by Name + getCspRoleMappingByRoleId: + method: get + resourcePath: /api/roles/csp-roles/id/:roleId + description: Get a mapping between role and CSP role + getMciamPermissionByID: + method: get + resourcePath: /api/permissions/mciam/id/{id} + description: Retrieve permission details by permission ID. + getMenuByID: + method: post + resourcePath: /api/menus/id/{menuId} + description: Get menu details by ID + getPlatformActionsByPermissionID: + method: get + resourcePath: /api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions + description: Returns all platform actions mapped to a specific permission + getPlatformRoleByID: + method: get + resourcePath: /api/roles/platform-roles/id/{roleId} + description: Get platform role details by ID + getPlatformRoleByName: + method: get + resourcePath: /api/roles/platform-roles/name/{roleName} + description: Get menu role details by Name + getProjectByID: + method: get + resourcePath: /api/projects/{id} + description: Retrieve project details by project ID. + getProjectByName: + method: get + resourcePath: /api/projects/name/{projectName} + description: Get project details by name + getRoleByRoleID: + method: get + resourcePath: /api/roles/id/{roleId} + description: Get role details by ID + getRoleByRoleName: + method: get + resourcePath: /api/roles/name/{roleName} + description: Retrieve role details by role name. + getRoleMasterMappings: + method: get + resourcePath: /api/roles/mappings/role/id/:roleId + description: Get role master mappings + getRoleMciamPermissions: + method: get + resourcePath: /api/roles/{roleType}/{roleId}/mciam-permissions + description: 특정 역할의 MC-IAM 권한 ID 목록을 조회합니다. + getUserByID: + method: get + resourcePath: /api/users/id/{userId} + description: Retrieve user details by user ID. + getUserByKcID: + method: get + resourcePath: /api/users/kc/{kcUserId} + description: Get user details by KcID + getUserByUsername: + method: get + resourcePath: /api/users/name/{username} + description: Get user details by username + getUserMenuTree: + method: get + resourcePath: /api/menus/user-menu-tree + description: Get menu tree based on user's platform roles + getUserWorkspaceAndWorkspaceRolesByUserID: + method: get + resourcePath: /api/users/id/{userId}/workspaces/roles/list + description: Get workspaces and roles for a specific user + getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID: + method: get + resourcePath: /api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list + description: Get workspaces and roles for a specific user and workspace + getUserWorkspaceRoles: + method: get + resourcePath: /api/workspaces/id/{workspaceId}/users/id/{userId} + description: Get roles assigned to a user in a workspace + getUserWorkspacesByUserID: + method: get + resourcePath: /api/users/id/{userId}/workspaces/list + description: Get workspaces for a specific user + getWorkspaceByID: + method: get + resourcePath: /api/workspaces/id/{workspaceId} + description: Retrieve workspace details by workspace ID. + getWorkspaceByName: + method: get + resourcePath: /api/workspaces/name/{workspaceName} + description: Retrieve specific workspace by name + getWorkspaceProjectsByWorkspaceId: + method: get + resourcePath: /api/workspaces/id/{workspaceId}/projects/list + description: Retrieve project list belonging to specific workspace + getWorkspaceRoleByID: + method: get + resourcePath: /api/roles/workspace-roles/id/{roleId} + description: Get workspace role details by ID + getWorkspaceRoleByName: + method: get + resourcePath: /api/roles/workspace-roles/name/{roleName} + description: Get workspace role details by Name + initializeMenuPermissions: + method: get + resourcePath: /api/setup/initial-role-menu-permission + description: CSV 파일을 읽어서 메뉴 권한을 초기화합니다 + listAllWorkspaceUsersAndRoles: + method: post + resourcePath: /api/workspaces/users-roles/list + description: Retrieve the list of users and roles assigned to the workspace. + listCSPRoles: + method: post + resourcePath: /api/roles/csp/list + description: Get a list of all csp roles + listCloudResourceTypes: + method: post + resourcePath: /api/resource-types/cloud-resources/list + description: 모든 리소스 타입 목록을 조회합니다 + listCspRoleMappings: + method: post + resourcePath: /api/roles/csp-roles/list + description: Get a mapping between role and CSP role + listMappedMenusByRole: + method: post + resourcePath: /api/menus/platform-roles/list + description: List menus mapped to a specific platform role. + listMciamPermissions: + method: post + resourcePath: /api/permissions/mciam/list + description: Retrieve a list of all permissions. + listMenus: + method: post + resourcePath: /api/menus/list + description: List all menus as a tree structure. Admin permission required. + listMenusTree: + method: post + resourcePath: /api/menus/tree/list + description: List all menus as a tree structure. Admin permission required. + listPermissionsByActionID: + method: get + resourcePath: /api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions + description: Returns all permissions mapped to a specific API action + listPlatformActions: + method: post + resourcePath: /api/mcmp-api-permission-action-mappings/list + description: Returns all platform actions mapped to a specific permission + listPlatformRoles: + method: post + resourcePath: /api/roles/menu-roles/list + description: Get a list of all menu roles + listProjects: + method: post + resourcePath: /api/projects/list + description: Retrieve a list of all projects. + listRoleMasterMappings: + method: post + resourcePath: /api/roles/mappings/list + description: List role master mappings + listRoles: + method: post + resourcePath: /api/roles/list + description: Retrieve a list of all roles. + listServicesAndActions: + method: post + resourcePath: /api/mcmp-apis/list + description: Retrieves all MCMP API service and action definitions currently stored in the database. + listUserMenu: + method: post + resourcePath: /api/users/menus/list + description: Get the menu list accessible to the current user's platform role. + listUserMenuTree: + method: post + resourcePath: /api/users/menus-tree/list + description: Get the menu tree accessible to the current user's platform role. + listUserProjectsByWorkspace: + method: get + resourcePath: /api/users/workspaces/id/{workspaceId}/projects/list + description: List projects for the current user + listUserWorkspaceAndWorkspaceRoles: + method: post + resourcePath: /api/users/workspaces/roles/list + description: List workspaces and roles for the current user + listUserWorkspaces: + method: post + resourcePath: /api/users/workspaces/list + description: List workspaces for the current user + listUsers: + method: post + resourcePath: /api/users/list + description: Retrieve a list of all users. + listUsersAndRolesByWorkspace: + method: post + resourcePath: /api/workspaces/id/{workspaceId}/users/list + description: Retrieve users and roles list belonging to workspace + listUsersByCspRole: + method: post + resourcePath: /api/roles/mappings/csp-roles/list + description: List users by csp role + listUsersByPlatformRole: + method: post + resourcePath: /api/roles/mappings/platform-roles/users/list + description: List users by platform role + listUsersByWorkspaceRole: + method: post + resourcePath: /api/roles/mappings/workspace-roles/users/list + description: List users by workspace role + listWorkspaceActionsByPermissionID: + method: post + resourcePath: /api/mcmp-api-permission-action-mappings/actions/list + description: Returns all workspace actions mapped to a specific permission + listWorkspaceProjects: + method: post + resourcePath: /api/workspaces/projects/list + description: Retrieve project list belonging to specific workspace + listWorkspaceRoles: + method: post + resourcePath: /api/roles/workspace-roles/list + description: Get a list of all workspace roles + listWorkspaceUsers: + method: post + resourcePath: /api/workspaces/users/list + description: List users by workspace criteria + listWorkspaces: + method: post + resourcePath: /api/workspaces/list + description: Retrieve a list of all workspaces. + mciamAuthCerts: + method: get + resourcePath: /api/auth/certs + description: Retrieve authentication certificates for MC-IAM-Manager to be used in target frameworks for token validation. + mciamCheckHealth: + method: get + resourcePath: /readyz + description: Check the health status of the service. + mciamCreateCredential: + method: post + resourcePath: /api/csp-credentials + description: 새로운 CSP 인증 정보를 생성합니다 + mciamDeleteCredential: + method: delete + resourcePath: /api/csp-credentials/{id} + description: CSP 인증 정보를 삭제합니다 + mciamGetCredentialByID: + method: get + resourcePath: /api/csp-credentials/{id} + description: 특정 CSP 인증 정보를 ID로 조회합니다 + mciamGetTempCredentialProviders: + method: get + resourcePath: /api/auth/temp-credential-csps + description: Get temporary credential provider information for AWS and GCP + mciamGetTemporaryCredentials: + method: post + resourcePath: /api/workspaces/temporary-credentials + description: Get temporary credentials for CSP + mciamListCredentials: + method: get + resourcePath: /api/csp-credentials + description: 모든 CSP 인증 정보 목록을 조회합니다 + mciamLogin: + method: post + resourcePath: /api/auth/login + description: Authenticate user and issue JWT token. + mciamLogout: + method: post + resourcePath: /api/auth/logout + description: Invalidate the user's refresh token and log out. + mciamRefreshToken: + method: post + resourcePath: /api/auth/refresh + description: Refresh JWT access token using a valid refresh token. + mciamUpdateCredential: + method: put + resourcePath: /api/csp-credentials/{id} + description: CSP 인증 정보를 업데이트합니다 + mciamValidateToken: + method: post + resourcePath: /api/auth/validate + description: Validate the current access token and refresh if expired + mciamWorkspaceTicket: + method: post + resourcePath: /api/workspaces/workspace-ticket + description: Set workspace ticket + mcmpApiCall: + method: post + resourcePath: /api/mcmp-apis/mcmpApiCall + description: Executes a defined MCMP API action with parameters structured in McmpApiCallRequest. + registerMenusFromBody: + method: post + resourcePath: /api/menus/setup/initial-menus2 + description: 'Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.' + registerMenusFromYAML: + method: post + resourcePath: /api/menus/setup/initial-menus + description: Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml. + removeCspRoleMappings: + method: delete + resourcePath: /api/roles/unassign/csp-roles + description: Delete a mapping between workspace role and CSP role + removeMciamPermissionFromRole: + method: delete + resourcePath: /api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId} + description: 역할에서 MC-IAM 권한을 제거합니다. + removePlatformRole: + method: delete + resourcePath: /api/roles/unassign/platform-role + description: Remove a platform role from a user + removeProjectFromWorkspace: + method: delete + resourcePath: /api/workspaces/unassign/projects + description: Remove a project from a workspace + removeRole: + method: delete + resourcePath: /api/roles/id/{roleId}/unassign + description: Remove a role from a user + removeUserFromWorkspace: + method: delete + resourcePath: /api/workspaces/{id}/users/{userId} + description: Remove a user from a workspace + removeWorkspaceRole: + method: delete + resourcePath: /api/roles/unassign/workspace-role + description: Remove a workspace role from a user + setActiveVersion: + method: put + resourcePath: /api/mcmp-apis/name/{serviceName}/versions/{version}/activate + description: Sets the specified version of an MCMP API service as the active one. + setupInitialAdmin: + method: post + resourcePath: /api/initial-admin + description: Creates the initial platform admin user with necessary permissions. platform admin 생성인데 + syncMcmpAPIs: + method: post + resourcePath: /api/mcmp-apis/syncMcmpAPIs + description: Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database. + syncProjects: + method: post + resourcePath: /api/setup/sync-projects + description: mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다. + testCallGetAllNs: + method: get + resourcePath: /api/mcmp-apis/test/mc-infra-manager/getallns + description: Calls the GetAllNs action of the mc-infra-manager service via the CallApi service. + updateCspRole: + method: put + resourcePath: /api/roles/csp-roles/id/{roleId} + description: Update role information + updateMapping: + method: put + resourcePath: /api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId} + description: Updates an existing mapping between a permission and an API action + updateMciamPermission: + method: put + resourcePath: /api/permissions/mciam/{id} + description: Update the details of an existing permission. + updateMenu: + method: put + resourcePath: /api/menus/id/{menuId} + description: Update menu information + updateProject: + method: put + resourcePath: /api/projects/{id} + description: Update the details of an existing project. + updateResourceType: + method: put + resourcePath: /api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId + description: 리소스 타입 정보를 업데이트합니다 + updateRole: + method: put + resourcePath: /api/roles/id/{roleId} + description: Update the details of an existing role. + updateUser: + method: put + resourcePath: /api/users/{id} + description: Update the details of an existing user. + updateUserStatus: + method: post + resourcePath: /api/users/id/{userId}/status + description: Update user status (active/inactive) + updateWorkspace: + method: put + resourcePath: /api/workspaces/id/{workspaceId} + description: Update the details of an existing workspace. + mc-workflow-manager: + _meta: + version: 0.5.0 + repository: https://github.com/m-cmp/mc-workflow-manager + generatedAt: "2026-01-06T07:17:34Z" + checkConnectionUsingGET: + method: get + resourcePath: /readyz + description: checkConnection + checkConnectionUsingPOST: + method: post + resourcePath: /oss/connection-check + description: checkConnection + deleteEventListnerUsingDELETE: + method: delete + resourcePath: /eventlistener/{eventListenerIdx} + description: deleteEventListner + deleteOssTypeUsingDELETE: + method: delete + resourcePath: /ossType/{ossTypeIdx} + description: deleteOssType + deleteOssUsingDELETE: + method: delete + resourcePath: /oss/{ossIdx} + description: deleteOss + deleteWorkflowStageTypeUsingDELETE: + method: delete + resourcePath: /workflowStageType/{workflowStageTypeIdx} + description: deleteWorkflowStageType + deleteWorkflowStageUsingDELETE: + method: delete + resourcePath: /workflowStage/{workflowStageIdx} + description: deleteWorkflowStage + deleteWorkflowUsingDELETE: + method: delete + resourcePath: /workflow/{workflowIdx} + description: deleteWorkflow + detailEventListenerUsingGET: + method: get + resourcePath: /eventlistener/{eventListenerIdx} + description: detailEventListener + detailOssTypeUsingGET: + method: get + resourcePath: /ossType/{ossTypeIdx} + description: detailOssType + detailOssUsingGET: + method: get + resourcePath: /oss/{ossIdx} + description: detailOss + detailWorkflowStageTypeUsingGET: + method: get + resourcePath: /workflowStageType/{workflowStageTypeIdx} + description: detailWorkflowStageType + detailWorkflowStageUsingGET: + method: get + resourcePath: /workflowStage/{workflowStageIdx} + description: detailWorkflowStage + errorUsingDELETE: + method: delete + resourcePath: /error + description: error + errorUsingGET: + method: get + resourcePath: /error + description: error + errorUsingHEAD: + method: head + resourcePath: /error + description: error + errorUsingOPTIONS: + method: options + resourcePath: /error + description: error + errorUsingPATCH: + method: patch + resourcePath: /error + description: error + errorUsingPOST: + method: post + resourcePath: /error + description: error + errorUsingPUT: + method: put + resourcePath: /error + description: error + getDefaultWorkflowStageUsingGET: + method: get + resourcePath: /workflowStage/default/script/{workflowStageTypeName} + description: getDefaultWorkflowStage + getEventListenerListUsingGET: + method: get + resourcePath: /eventlistener/list + description: getEventListenerList + getOssListUsingGET: + method: get + resourcePath: /oss/list/{ossTypeName} + description: getOssList + getOssListUsingGET_1: + method: get + resourcePath: /oss/list + description: getOssList + getOssTypeFilteredListUsingGET: + method: get + resourcePath: /ossType/filter/list + description: getOssTypeFilteredList + getOssTypeListUsingGET: + method: get + resourcePath: /ossType/list + description: getOssTypeList + getWorkflowDetailUsingGET: + method: get + resourcePath: /eventlistener/workflowDetail/{workflowIdx}/{evnetListenerYn} + description: getWorkflowDetail + getWorkflowHistoryListUsingGET: + method: get + resourcePath: /workflow/history/{workflowIdx} + description: getWorkflowHistoryList + getWorkflowListUsingGET: + method: get + resourcePath: /eventlistener/workflowList/{eventListenerYn} + description: getWorkflowList + getWorkflowListUsingGET_1: + method: get + resourcePath: /workflow/list + description: getWorkflowList + getWorkflowLogUsingGET: + method: get + resourcePath: /workflow/log/{workflowIdx} + description: getWorkflowLog + getWorkflowParamListUsingGET: + method: get + resourcePath: /workflow/param/list + description: getWorkflowParamList + getWorkflowRunHistoryListUsingGET: + method: get + resourcePath: /workflow/runHistory/{workflowIdx} + description: getWorkflowRunHistoryList + getWorkflowStageHistoryListUsingGET: + method: get + resourcePath: /workflow/stageHistory/{workflowIdx} + description: getWorkflowStageHistoryList + getWorkflowStageListUsingGET: + method: get + resourcePath: /workflow/workflowStageList + description: getWorkflowStageList + getWorkflowStageListUsingGET_1: + method: get + resourcePath: /workflowStage/list + description: getWorkflowStageList + getWorkflowStageListUsingGET_2: + method: get + resourcePath: /workflowStageType/list + description: getWorkflowStageList + getWorkflowTemplateUsingGET: + method: get + resourcePath: /workflow/template/{workflowName} + description: getWorkflowTemplate + getWorkflowUsingGET: + method: get + resourcePath: /workflow/{workflowIdx} + description: getWorkflow + isEventListenerDuplicatedUsingGET: + method: get + resourcePath: /eventlistener/duplicate + description: isEventListenerDuplicated + isOssInfoDuplicatedUsingGET: + method: get + resourcePath: /oss/duplicate + description: isOssInfoDuplicated + isWorkflowNameDuplicatedUsingGET: + method: get + resourcePath: /workflow/name/duplicate + description: isWorkflowNameDuplicated + isWorkflowStageNameDuplicatedUsingGET: + method: get + resourcePath: /workflowStage/duplicate + description: isWorkflowStageNameDuplicated + openapiJsonUsingGET: + method: get + resourcePath: /v3/api-docs + description: openapiJson + openapiJsonUsingGET_1: + method: get + resourcePath: /v3/api-docs/swagger-config + description: openapiJson + openapiYamlUsingGET: + method: get + resourcePath: /v3/api-docs.yaml + description: openapiYaml + redirectToUiUsingGET: + method: get + resourcePath: /swagger-ui.html + description: redirectToUi + registEventListnerUsingPOST: + method: post + resourcePath: /eventlistener + description: registEventListner + registOssTypeUsingPOST: + method: post + resourcePath: /ossType + description: registOssType + registOssUsingPOST: + method: post + resourcePath: /oss + description: registOss + registWorkflowStageUsingPOST: + method: post + resourcePath: /workflowStage + description: registWorkflowStage + registWorkflowStageUsingPOST_1: + method: post + resourcePath: /workflowStageType + description: registWorkflowStage + registWorkflowUsingPOST: + method: post + resourcePath: /workflow + description: registWorkflow + runEventListenerUsingGET: + method: get + resourcePath: /eventlistener/run/{eventListenerIdx} + description: runEventListener + runWorkflowGetUsingGET: + method: get + resourcePath: /workflow/run/{workflowIdx} + description: runWorkflowGet + runWorkflowPostUsingPOST: + method: post + resourcePath: /workflow/run + description: runWorkflowPost + updateEventListnerUsingPATCH: + method: patch + resourcePath: /eventlistener/{eventListenerIdx} + description: updateEventListner + updateOssTypeUsingPATCH: + method: patch + resourcePath: /ossType/{ossTypeIdx} + description: updateOssType + updateOssUsingPATCH: + method: patch + resourcePath: /oss/{ossIdx} + description: updateOss + updateWorkflowStageTypeUsingPATCH: + method: patch + resourcePath: /workflowStageType/{workflowStageTypeIdx} + description: updateWorkflowStageType + updateWorkflowStageUsingPATCH: + method: patch + resourcePath: /workflowStage/{workflowStageIdx} + description: updateWorkflowStage + updateWorkflowUsingPATCH: + method: patch + resourcePath: /workflow/{workflowIdx} + description: updateWorkflow diff --git a/docker-compose-dev.yaml b/docker-compose-dev.yaml new file mode 100644 index 00000000..6bdc965a --- /dev/null +++ b/docker-compose-dev.yaml @@ -0,0 +1,81 @@ +version: '3.8' + +# Release 브랜치에서 이미 생성된 네트워크를 외부 네트워크로 참조 +# 네트워크 이름이 다를 경우 'docker network ls | grep mc-iam-manager'로 확인 후 수정 +networks: + mc-iam-manager-network: + external: true + name: mc-iam-manager_mc-iam-manager-network + mc-infra-manager-network: + external: true + name: mc-iam-manager_mc-infra-manager-network + +services: + # Dev 환경용 mc-iam-manager 소스 컨테이너 + mc-iam-manager-dev: + container_name: mc-iam-manager-dev + build: + context: . + dockerfile: Dockerfile.mciammanager + image: mc-iam-manager:dev + platform: linux/amd64 + restart: unless-stopped + networks: + - mc-iam-manager-network + - mc-infra-manager-network + ports: + - '5006:5006' # Dev 환경 전용 포트 + environment: + # Release 브랜치의 로컬 Docker 컨테이너를 참조하도록 override + # .env 파일의 원격 서버 설정을 로컬 Docker 컨테이너로 변경 + MC_IAM_MANAGER_DATABASE_HOST: mc-iam-manager-db + MC_IAM_MANAGER_DATABASE_NAME: ${MC_IAM_MANAGER_DATABASE_NAME} + MC_IAM_MANAGER_DATABASE_USER: ${MC_IAM_MANAGER_DATABASE_USER} + MC_IAM_MANAGER_DATABASE_PASSWORD: ${MC_IAM_MANAGER_DATABASE_PASSWORD} + MC_IAM_MANAGER_DATABASE_PORT: 5432 + MC_IAM_MANAGER_DATABASE_SSLMODE: disable + MC_IAM_MANAGER_DATABASE_URL: postgres://${MC_IAM_MANAGER_DATABASE_USER}:${MC_IAM_MANAGER_DATABASE_PASSWORD}@mc-iam-manager-db:5432/${MC_IAM_MANAGER_DATABASE_NAME}?sslmode=disable + DATABASE_URL: postgres://${MC_IAM_MANAGER_DATABASE_USER}:${MC_IAM_MANAGER_DATABASE_PASSWORD}@mc-iam-manager-db:5432/${MC_IAM_MANAGER_DATABASE_NAME}?sslmode=disable + + # Keycloak 설정 - Release 브랜치의 로컬 Keycloak 컨테이너 사용 + MC_IAM_MANAGER_KEYCLOAK_HOST: http://mc-iam-manager-kc:8080 + MC_IAM_MANAGER_KEYCLOAK_DOMAIN: mc-iam-manager-kc + MC_IAM_MANAGER_KEYCLOAK_PORT: 8080 + MC_IAM_MANAGER_KEYCLOAK_REALM: ${MC_IAM_MANAGER_KEYCLOAK_REALM} + MC_IAM_MANAGER_KEYCLOAK_CLIENT_PATH: mc-iam-manager-kc/realms/${MC_IAM_MANAGER_KEYCLOAK_REALM} + MC_IAM_MANAGER_KEYCLOAK_ADMIN: ${MC_IAM_MANAGER_KEYCLOAK_ADMIN} + MC_IAM_MANAGER_KEYCLOAK_ADMIN_PASSWORD: ${MC_IAM_MANAGER_KEYCLOAK_ADMIN_PASSWORD} + MC_IAM_MANAGER_KEYCLOAK_DATABASE_NAME: ${MC_IAM_MANAGER_KEYCLOAK_DATABASE_NAME} + + # 애플리케이션 포트 설정 + PORT: 5006 + MC_IAM_MANAGER_PORT: 5006 + MC_IAM_MANAGER_DOMAIN: mciambase.onecloudcon.com + MC_IAM_MANAGER_HOST: http://mciambase.onecloudcon.com:5006 + + # 기타 필요한 환경 변수들 + DEFAULT_LANGUAGE: ${DEFAULT_LANGUAGE} + MODE: ${MODE} + USE_TICKET_VALID: ${USE_TICKET_VALID} + MC_IAM_MANAGER_PLATFORMADMIN_ID: ${MC_IAM_MANAGER_PLATFORMADMIN_ID} + MC_IAM_MANAGER_PLATFORMADMIN_PASSWORD: ${MC_IAM_MANAGER_PLATFORMADMIN_PASSWORD} + MC_IAM_MANAGER_PLATFORMADMIN_FIRSTNAME: ${MC_IAM_MANAGER_PLATFORMADMIN_FIRSTNAME} + MC_IAM_MANAGER_PLATFORMADMIN_LASTNAME: ${MC_IAM_MANAGER_PLATFORMADMIN_LASTNAME} + MC_IAM_MANAGER_PLATFORMADMIN_EMAIL: ${MC_IAM_MANAGER_PLATFORMADMIN_EMAIL} + + # MC-INFRA-MANAGER 설정 + MCINFRAMANAGER: ${MCINFRAMANAGER} + MCINFRAMANAGER_APIUSERNAME: ${MCINFRAMANAGER_APIUSERNAME} + MCINFRAMANAGER_APIPASSWORD: ${MCINFRAMANAGER_APIPASSWORD} + + env_file: + - ./.env + volumes: + - ./tool/mcc:/app/tool/mcc + healthcheck: + test: [ 'CMD', '/app/tool/mcc', 'rest', 'get', 'http://mciambase.onecloudcon.com:5006/readyz' ] + interval: 30s + timeout: 10s + retries: 5 + start_period: 30s + diff --git a/docker-compose.yaml b/docker-compose.yaml index 89870a01..f38bda0e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,7 +14,7 @@ services: ##### MC-INFRA-CONNECTOR ######################################################################################################################### mc-infra-connector: - image: cloudbaristaorg/cb-spider:0.11.1 + image: cloudbaristaorg/cb-spider:edge pull_policy: missing container_name: mc-infra-connector platform: linux/amd64 @@ -47,7 +47,7 @@ services: ##### MC-INFRA-MANAGER ######################################################################################################################### mc-infra-manager: - image: cloudbaristaorg/cb-tumblebug:0.11.1 + image: cloudbaristaorg/cb-tumblebug:edge container_name: mc-infra-manager pull_policy: missing platform: linux/amd64 diff --git a/docs/docs.go b/docs/docs.go index f8c60fce..f5ad29ec 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -15,14 +15,43 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/api/call": { - "post": { - "security": [ - { - "BearerAuth": [] - } + "/api/auth/certs": { + "get": { + "description": "Retrieve authentication certificates for MC-IAM-Manager to be used in target frameworks for token validation.", + "consumes": [ + "application/json" ], - "description": "Executes a defined MCMP API action with query parameters and a request body.", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Get authentication certificates", + "operationId": "mciamAuthCerts", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/auth/login": { + "post": { + "description": "Authenticate user and issue JWT token.", "consumes": [ "application/json" ], @@ -30,29 +59,41 @@ const docTemplate = `{ "application/json" ], "tags": [ - "McmpAPI" + "auth" ], - "summary": "Call an external MCMP API action (Generic Request)", + "summary": "User login", + "operationId": "mciamLogin", "parameters": [ { - "description": "Generic API Call Request", - "name": "callRequest", + "description": "Login Credentials", + "name": "credentials", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/mcmpapi.ServiceApiCallRequest" + "$ref": "#/definitions/idp.UserLogin" } } ], + "responses": {} + } + }, + "/api/auth/logout": { + "post": { + "description": "Invalidate the user's refresh token and log out.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Logout user", + "operationId": "mciamLogout", "responses": { "200": { - "description": "External API Response (structure depends on the called API)", - "schema": { - "type": "object" - } - }, - "400": { - "description": "error: Invalid request body or parameters", + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -60,17 +101,53 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Service or action not found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } + } + } + } + }, + "/api/auth/refresh": { + "post": { + "description": "Refresh JWT access token using a valid refresh token.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Refresh access token", + "operationId": "mciamRefreshToken", + "parameters": [ + { + "description": "Refresh token", + "name": "refresh_token", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "New token information", + "schema": { + "type": "object", + "additionalProperties": true + } }, - "500": { - "description": "error: Internal server error or failed to call external API", + "400": { + "description": "error: Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -78,8 +155,8 @@ const docTemplate = `{ } } }, - "503": { - "description": "error: External API unavailable", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -90,9 +167,9 @@ const docTemplate = `{ } } }, - "/api/permissions": { + "/api/auth/temp-credential-csps": { "get": { - "description": "모든 권한 목록을 조회합니다.", + "description": "Get temporary credential provider information for AWS and GCP", "consumes": [ "application/json" ], @@ -100,23 +177,29 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "auth" ], - "summary": "권한 목록 조회", + "summary": "Get temporary credential CSP information", + "operationId": "mciamGetTempCredentialProviders", "responses": { "200": { - "description": "OK", + "description": "CSP temporary credential information", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Permission" - } + "type": "object", + "additionalProperties": true } } } - }, + } + }, + "/api/auth/validate": { "post": { - "description": "새로운 권한을 생성합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Validate the current access token and refresh if expired", "consumes": [ "application/json" ], @@ -124,33 +207,58 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "auth" ], - "summary": "권한 생성", + "summary": "Validate access token", + "operationId": "mciamValidateToken", "parameters": [ { - "description": "권한 정보", - "name": "permission", + "description": "Refresh token", + "name": "refresh_token", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Permission" + "type": "string" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "Token validation result with new token if refreshed", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "error: Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", "schema": { - "$ref": "#/definitions/model.Permission" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/permissions/{id}": { + "/api/csp-credentials": { "get": { - "description": "ID로 특정 권한을 조회합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "모든 CSP 인증 정보 목록을 조회합니다", "consumes": [ "application/json" ], @@ -158,29 +266,80 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "csp-credentials" + ], + "summary": "CSP 인증 정보 목록 조회", + "operationId": "mciamListCredentials", + "responses": {} + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "새로운 CSP 인증 정보를 생성합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" ], - "summary": "ID로 권한 조회", + "tags": [ + "csp-credentials" + ], + "summary": "새 CSP 인증 정보 생성", + "operationId": "mciamCreateCredential", + "responses": {} + } + }, + "/api/csp-credentials/{id}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "특정 CSP 인증 정보를 ID로 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "CSP 인증 정보 ID로 조회", + "operationId": "mciamGetCredentialByID", "parameters": [ { "type": "string", - "description": "권한 ID", + "description": "Credential ID", "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { - "$ref": "#/definitions/model.Permission" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } }, "put": { - "description": "기존 권한을 수정합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -188,38 +347,38 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "csp-credentials" ], - "summary": "권한 수정", + "summary": "CSP 인증 정보 업데이트", + "operationId": "mciamUpdateCredential", "parameters": [ { "type": "string", - "description": "권한 ID", + "description": "Credential ID", "name": "id", "in": "path", "required": true - }, - { - "description": "권한 정보", - "name": "permission", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Permission" - } } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { - "$ref": "#/definitions/model.Permission" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } }, "delete": { - "description": "권한을 삭제합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 삭제합니다", "consumes": [ "application/json" ], @@ -227,13 +386,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "csp-credentials" ], - "summary": "권한 삭제", + "summary": "CSP 인증 정보 삭제", + "operationId": "mciamDeleteCredential", "parameters": [ { "type": "string", - "description": "권한 ID", + "description": "Credential ID", "name": "id", "in": "path", "required": true @@ -242,13 +402,40 @@ const docTemplate = `{ "responses": { "204": { "description": "No Content" + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Credential not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } } }, - "/api/platform-roles": { - "get": { - "description": "모든 플랫폼 역할을 조회합니다.", + "/api/initial-admin": { + "post": { + "description": "Creates the initial platform admin user with necessary permissions. platform admin 생성인데", "consumes": [ "application/json" ], @@ -256,23 +443,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "platform-roles" + "admin" + ], + "summary": "Setup initial platform admin", + "operationId": "setupInitialAdmin", + "parameters": [ + { + "description": "Setup Initial Admin Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.SetupInitialAdminRequest" + } + } ], - "summary": "플랫폼 역할 목록 조회", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.PlatformRole" - } + "$ref": "#/definitions/model.Response" } } } - }, + } + }, + "/api/mcmp-api-permission-action-mappings": { "post": { - "description": "새로운 플랫폼 역할을 생성합니다.", + "description": "Creates a new mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -280,33 +478,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "platform-roles" + "mcmp-api-permission-action-mappings" ], - "summary": "플랫폼 역할 생성", + "summary": "Create permission-action mapping", + "operationId": "createMcmpApiPermissionActionMapping", "parameters": [ { - "description": "Platform Role", - "name": "role", + "description": "Mapping to create", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.PlatformRole" + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" } } ], "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/model.PlatformRole" - } + "204": { + "description": "No Content" } } } }, - "/api/platform-roles/{id}": { - "get": { - "description": "ID로 플랫폼 역할을 조회합니다.", + "/api/mcmp-api-permission-action-mappings/actions/list": { + "post": { + "description": "Returns all workspace actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -314,14 +510,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "platform-roles" + "mcmp-api-permission-action-mappings" ], - "summary": "플랫폼 역할 조회", + "summary": "Get workspace actions by permission ID", + "operationId": "listWorkspaceActionsByPermissionID", "parameters": [ { - "type": "integer", - "description": "Platform Role ID", - "name": "id", + "type": "string", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -330,13 +527,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.PlatformRole" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" + } } } } - }, - "put": { - "description": "기존 플랫폼 역할을 수정합니다.", + } + }, + "/api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions": { + "get": { + "description": "Returns all permissions mapped to a specific API action", "consumes": [ "application/json" ], @@ -344,67 +546,35 @@ const docTemplate = `{ "application/json" ], "tags": [ - "platform-roles" + "mcmp-api-permission-action-mappings" ], - "summary": "플랫폼 역할 수정", + "summary": "Get permissions by action ID", + "operationId": "listPermissionsByActionID", "parameters": [ { "type": "integer", - "description": "Platform Role ID", - "name": "id", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true - }, - { - "description": "Platform Role", - "name": "role", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.PlatformRole" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.PlatformRole" + "type": "array", + "items": { + "type": "string" + } } } } - }, - "delete": { - "description": "플랫폼 역할을 삭제합니다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "platform-roles" - ], - "summary": "플랫폼 역할 삭제", - "parameters": [ - { - "type": "integer", - "description": "Platform Role ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - } - } } }, - "/api/roles/{roleType}/{roleId}/permissions": { - "get": { - "description": "특정 역할의 권한 목록을 조회합니다.", + "/api/mcmp-api-permission-action-mappings/list": { + "post": { + "description": "Returns all platform actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -412,21 +582,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "역할의 권한 목록 조회", + "summary": "List platform actions by permission ID", + "operationId": "listPlatformActions", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "역할 ID", - "name": "roleId", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -437,16 +601,16 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Permission" + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/api/roles/{roleType}/{roleId}/permissions/{permissionId}": { - "post": { - "description": "역할에 권한을 할당합니다.", + "/api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId}": { + "put": { + "description": "Updates an existing mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -454,40 +618,49 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "역할에 권한 할당", + "summary": "Update permission-action mapping", + "operationId": "updateMapping", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true }, { "type": "integer", - "description": "역할 ID", - "name": "roleId", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true }, { - "type": "string", - "description": "권한 ID", - "name": "permissionId", - "in": "path", - "required": true + "description": "Updated mapping", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } }, "delete": { - "description": "역할에서 권한을 제거합니다.", + "description": "Deletes a mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -495,28 +668,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "역할에서 권한 제거", + "summary": "Delete permission-action mapping", + "operationId": "deleteMapping", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true }, { "type": "integer", - "description": "역할 ID", - "name": "roleId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "권한 ID", - "name": "permissionId", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true } @@ -528,9 +695,9 @@ const docTemplate = `{ } } }, - "/auth/login": { - "post": { - "description": "사용자 ID와 비밀번호로 로그인하여 JWT 토큰을 발급받습니다.", + "/api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions": { + "get": { + "description": "Returns all platform actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -538,69 +705,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "auth" + "mcmp-api-permission-action-mappings" ], - "summary": "로그인", + "summary": "Get platform actions by permission ID", + "operationId": "getPlatformActionsByPermissionID", "parameters": [ { - "description": "로그인 정보 (Id, Password)", - "name": "login", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/idp.UserLogin" - } + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "로그인 성공 및 토큰 정보 (gocloak.JWT 구조체와 유사)", - "schema": { - "type": "object", - "additionalProperties": true - } - }, - "400": { - "description": "error: 잘못된 요청 형식", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "401": { - "description": "error: 인증 실패 (자격 증명 오류)", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: 계정이 비활성화되었거나 승인 대기 중입니다", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "error: 서버 내부 오류 (Keycloak 통신, DB 동기화 등)", + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/mcmp-apis": { - "get": { + "/api/mcmp-apis/list": { + "post": { "security": [ { "BearerAuth": [] @@ -617,6 +749,7 @@ const docTemplate = `{ "McmpAPI" ], "summary": "Get All Stored MCMP API Definitions", + "operationId": "listServicesAndActions", "parameters": [ { "type": "string", @@ -650,7 +783,7 @@ const docTemplate = `{ } } }, - "/mcmp-apis/call": { + "/api/mcmp-apis/mcmpApiCall": { "post": { "security": [ { @@ -668,6 +801,7 @@ const docTemplate = `{ "McmpAPI" ], "summary": "Call an external MCMP API action (Structured Request)", + "operationId": "mcmpApiCall", "parameters": [ { "description": "API Call Request", @@ -675,7 +809,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiCallRequest" + "$ref": "#/definitions/model.McmpApiCallRequest" } } ], @@ -725,109 +859,7 @@ const docTemplate = `{ } } }, - "/mcmp-apis/sync": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "McmpAPI // Updated tag" - ], - "summary": "Sync MCMP API Definitions", - "responses": { - "200": { - "description": "message: Successfully triggered MCMP API sync\" // Updated message", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "message: Failed to trigger MCMP API sync\" // Updated message", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/mcmp-apis/test/mc-infra-manager/getallns": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", - "produces": [ - "application/json" - ], - "tags": [ - "McmpAPI", - "Test" - ], - "summary": "Test Call to mc-infra-manager GetAllNs", - "responses": { - "200": { - "description": "Response from mc-infra-manager GetAllNs", - "schema": { - "type": "object" - } - }, - "400": { - "description": "error: Bad Request (e.g., invalid parameters)", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "error: Service or Action Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "error: Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "503": { - "description": "error: External API Service Unavailable", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/mcmp-apis/{serviceName}": { + "/api/mcmp-apis/name/{serviceName}": { "put": { "security": [ { @@ -845,6 +877,7 @@ const docTemplate = `{ "McmpAPI" ], "summary": "Update MCMP API Service Definition", + "operationId": "UpdateFrameworkService", "parameters": [ { "type": "string", @@ -903,7 +936,7 @@ const docTemplate = `{ } } }, - "/mcmp-apis/{serviceName}/versions/{version}/activate": { + "/api/mcmp-apis/name/{serviceName}/versions/{version}/activate": { "put": { "security": [ { @@ -921,6 +954,7 @@ const docTemplate = `{ "McmpAPI" ], "summary": "Set Active Version for a Service", + "operationId": "setActiveVersion", "parameters": [ { "type": "string", @@ -971,14 +1005,14 @@ const docTemplate = `{ } } }, - "/menus": { - "get": { + "/api/mcmp-apis/syncMcmpAPIs": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "현재 로그인한 사용자의 Platform Role에 따라 접근 가능한 메뉴 목록을 트리 구조로 조회합니다.", + "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", "consumes": [ "application/json" ], @@ -986,21 +1020,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "McmpAPI" ], - "summary": "현재 사용자의 메뉴 트리 조회", + "summary": "Sync MCMP API Definitions", + "operationId": "syncMcmpAPIs", "responses": { "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" - } - } - }, - "401": { - "description": "error: Unauthorized", + "description": "message: Successfully triggered MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -1009,7 +1035,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "message: Failed to trigger MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -1018,75 +1044,34 @@ const docTemplate = `{ } } } - }, - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "새로운 메뉴를 생성합니다", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "새 메뉴 생성", - "parameters": [ - { - "description": "Menu Info", - "name": "menu", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Menu" - } - } - ], - "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/model.Menu" - } - } - } } }, - "/menus/all": { + "/api/mcmp-apis/test/mc-infra-manager/getallns": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "모든 메뉴 목록을 트리 구조로 조회합니다. 관리자 권한이 필요합니다.", - "consumes": [ - "application/json" - ], + "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", "produces": [ "application/json" ], "tags": [ - "menus" + "McmpAPI", + "Test" ], - "summary": "모든 메뉴 트리 조회 (관리자용)", + "summary": "Test Call to mc-infra-manager GetAllNs", + "operationId": "testCallGetAllNs", "responses": { "200": { - "description": "OK", + "description": "Response from mc-infra-manager GetAllNs", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" - } + "type": "object" } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "error: Bad Request (e.g., invalid parameters)", "schema": { "type": "object", "additionalProperties": { @@ -1094,8 +1079,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "error: Service or Action Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1104,59 +1089,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/menus/register-from-body": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "요청 본문에 포함된 YAML 텍스트를 파싱하여 메뉴를 데이터베이스에 등록하거나 업데이트합니다. Content-Type은 text/plain, text/yaml, application/yaml 등을 권장합니다.", - "consumes": [ - "text/plain" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "요청 본문의 YAML 내용으로 메뉴 등록/업데이트", - "parameters": [ - { - "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", - "description": "Menu definitions in YAML format (must contain 'menus:' root key)", - "name": "yaml", - "in": "body", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "message: Successfully registered menus from request body", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", + "description": "error: Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1164,8 +1097,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "error: 서버 내부 오류", + "503": { + "description": "error: External API Service Unavailable", "schema": { "type": "object", "additionalProperties": { @@ -1176,14 +1109,14 @@ const docTemplate = `{ } } }, - "/menus/register-from-yaml": { + "/api/menus": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "filePath 쿼리 파라미터로 지정된 로컬 YAML 파일 또는 파라미터가 없을 경우 .env 파일의 MCWEBCONSOLE_MENUYAML URL에서 메뉴를 가져와 데이터베이스에 등록/업데이트합니다. URL에서 가져올 경우 asset/menu/menu.yaml에 저장됩니다.", + "description": "Create a new menu", "consumes": [ "application/json" ], @@ -1193,45 +1126,37 @@ const docTemplate = `{ "tags": [ "menus" ], - "summary": "YAML 파일 또는 URL에서 메뉴 등록/업데이트", + "summary": "Create new menu", + "operationId": "createMenu", "parameters": [ { - "type": "string", - "description": "YAML 파일 경로 (선택 사항, 없으면 .env의 URL 또는 기본 로컬 경로 사용)", - "name": "filePath", - "in": "query" + "description": "Menu Info", + "name": "menu", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Menu" + } } ], "responses": { - "200": { - "description": "message: Successfully registered menus from YAML", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "error: 실패 메시지", + "201": { + "description": "Created", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } } }, - "/menus/{id}": { - "get": { + "/api/menus/id/{menuId}": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "특정 메뉴를 ID로 조회합니다", + "description": "Update menu information", "consumes": [ "application/json" ], @@ -1241,7 +1166,8 @@ const docTemplate = `{ "tags": [ "menus" ], - "summary": "메뉴 ID로 조회", + "summary": "Update menu information", + "operationId": "updateMenu", "parameters": [ { "type": "string", @@ -1249,6 +1175,15 @@ const docTemplate = `{ "name": "id", "in": "path", "required": true + }, + { + "description": "Menu Info", + "name": "menu", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Menu" + } } ], "responses": { @@ -1260,13 +1195,13 @@ const docTemplate = `{ } } }, - "put": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "메뉴 정보를 업데이트합니다", + "description": "Get menu details by ID", "consumes": [ "application/json" ], @@ -1276,23 +1211,15 @@ const docTemplate = `{ "tags": [ "menus" ], - "summary": "메뉴 정보 업데이트", + "summary": "Get menu by ID", + "operationId": "getMenuByID", "parameters": [ { "type": "string", "description": "Menu ID", - "name": "id", + "name": "menuId", "in": "path", "required": true - }, - { - "description": "Menu Info", - "name": "menu", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Menu" - } } ], "responses": { @@ -1310,7 +1237,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "메뉴를 삭제합니다", + "description": "Delete a menu", "consumes": [ "application/json" ], @@ -1320,7 +1247,8 @@ const docTemplate = `{ "tags": [ "menus" ], - "summary": "메뉴 삭제", + "summary": "Delete menu", + "operationId": "deleteMenu", "parameters": [ { "type": "string", @@ -1337,14 +1265,14 @@ const docTemplate = `{ } } }, - "/projects": { - "get": { + "/api/menus/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "모든 프로젝트 목록을 조회합니다 (연결된 워크스페이스 정보 포함).", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -1352,16 +1280,35 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "모든 프로젝트 조회", + "summary": "List all menus", + "operationId": "listMenus", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.MenuTreeNode" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -1375,14 +1322,16 @@ const docTemplate = `{ } } } - }, + } + }, + "/api/menus/platform-roles": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "새로운 프로젝트를 생성합니다.", + "description": "Create a new menu mapping", "consumes": [ "application/json" ], @@ -1390,17 +1339,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "menu" ], - "summary": "프로젝트 생성", + "summary": "Create menu mapping", + "operationId": "createMenusRolesMapping", "parameters": [ { - "description": "프로젝트 정보 (ID, CreatedAt, UpdatedAt, Workspaces 제외)", - "name": "project", + "description": "Menu Mapping", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.CreateMenuMappingRequest" } } ], @@ -1408,11 +1358,14 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/model.Project" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "error: 잘못된 요청 형식", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1421,7 +1374,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1430,16 +1383,14 @@ const docTemplate = `{ } } } - } - }, - "/projects/name/{name}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "이름으로 특정 프로젝트를 조회합니다 (연결된 워크스페이스 정보 포함).", + "description": "Delete the mapping between a platform role and a menu.", "consumes": [ "application/json" ], @@ -1447,27 +1398,36 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "이름으로 프로젝트 조회", + "summary": "Delete platform role-menu mapping", + "operationId": "deleteMenusRolesMapping", "parameters": [ { "type": "string", - "description": "프로젝트 이름", - "name": "name", - "in": "path", - "required": true + "description": "Platform Role ID", + "name": "roleId", + "in": "query" + }, + { + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "message: Menu mapping deleted successfully", "schema": { - "$ref": "#/definitions/model.Project" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "400": { + "description": "error: platform role and menu ID are required", "schema": { "type": "object", "additionalProperties": { @@ -1487,14 +1447,14 @@ const docTemplate = `{ } } }, - "/projects/{id}": { - "get": { + "/api/menus/platform-roles/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "ID로 특정 프로젝트를 조회합니다 (연결된 워크스페이스 정보 포함).", + "description": "List menus mapped to a specific platform role.", "consumes": [ "application/json" ], @@ -1502,36 +1462,36 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "ID로 프로젝트 조회", + "summary": "List menus mapped to platform role", + "operationId": "listMappedMenusByRole", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Project" - } + "type": "string", + "description": "Platform Role ID", + "name": "roleId", + "in": "query" }, - "400": { - "description": "error: 잘못된 프로젝트 ID", + { + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" } } }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "400": { + "description": "error: platform role is required", "schema": { "type": "object", "additionalProperties": { @@ -1549,14 +1509,16 @@ const docTemplate = `{ } } } - }, - "put": { + } + }, + "/api/menus/setup/initial-menus": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "기존 프로젝트 정보를 부분적으로 수정합니다.", + "description": "Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml.", "consumes": [ "application/json" ], @@ -1564,45 +1526,21 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "프로젝트 수정", + "summary": "Register/Update menus from YAML file or URL", + "operationId": "registerMenusFromYAML", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "수정할 필드와 값 (예: {\\", - "name": "updates", - "in": "body", - "required": true, - "schema": { - "type": "object" - } + "type": "string", + "description": "YAML file path (optional, uses .env URL or default local path if not provided)", + "name": "filePath", + "in": "query" } ], "responses": { "200": { - "description": "업데이트된 프로젝트 정보", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "400": { - "description": "error: 잘못된 요청 형식 또는 ID", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "description": "message: Successfully registered menus from YAML", "schema": { "type": "object", "additionalProperties": { @@ -1611,7 +1549,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "error: 실패 메시지", "schema": { "type": "object", "additionalProperties": { @@ -1620,39 +1558,42 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/menus/setup/initial-menus2": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "프로젝트를 삭제합니다. 연결된 워크스페이스와의 관계도 해제됩니다.", + "description": "Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.", "consumes": [ - "application/json" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "프로젝트 삭제", + "summary": "Register/Update menus from YAML in request body", + "operationId": "registerMenusFromBody", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true + "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", + "description": "Menu definitions in YAML format (must contain 'menus:' root key)", + "name": "yaml", + "in": "body", + "required": true, + "schema": { + "type": "string" + } } ], "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 프로젝트 ID", + "200": { + "description": "message: Successfully registered menus from request body", "schema": { "type": "object", "additionalProperties": { @@ -1660,8 +1601,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "400": { + "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", "schema": { "type": "object", "additionalProperties": { @@ -1681,14 +1622,14 @@ const docTemplate = `{ } } }, - "/projects/{id}/workspaces/{workspaceId}": { + "/api/menus/tree/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 프로젝트에 워크스페이스를 연결합니다.", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -1696,31 +1637,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" - ], - "summary": "프로젝트에 워크스페이스 연결", - "parameters": [ - { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true - } + "menus" ], + "summary": "List all menus Tree", + "operationId": "listMenusTree", "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } + } }, - "400": { - "description": "error: 잘못된 ID 형식", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -1728,8 +1660,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -1747,14 +1679,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/menus/user-menu-tree": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "특정 프로젝트에서 워크스페이스 연결을 해제합니다.", + "description": "Get menu tree based on user's platform roles", "consumes": [ "application/json" ], @@ -1762,40 +1696,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" - ], - "summary": "프로젝트에서 워크스페이스 연결 해제", - "parameters": [ - { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true - } + "menus" ], + "summary": "Get user menu tree by platform roles", + "operationId": "getUserMenuTree", "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 ID 형식", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" } } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1806,70 +1722,101 @@ const docTemplate = `{ } } }, - "/readyz": { - "get": { - "description": "애플리케이션의 준비 상태를 확인합니다. status=detail 쿼리 파라미터로 상세 상태를 확인할 수 있습니다.", + "/api/permissions/mciam": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new permission with the specified information.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Health" + "permissions" ], - "summary": "애플리케이션 준비 상태 확인", + "summary": "Create new permission", + "operationId": "createMciamPermission", "parameters": [ { - "type": "string", - "description": "상세 상태 확인 여부 ('detail')", - "name": "status", - "in": "query" + "description": "Permission Info", + "name": "permission", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.MciamPermission" + } } ], "responses": { - "200": { - "description": "상세 상태 정보 (status=detail)", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/service.HealthStatus" + "$ref": "#/definitions/model.MciamPermission" } }, - "503": { - "description": "상세 상태 확인 중 오류 발생 시", + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/service.HealthStatus" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/user/workspaces": { + "/api/permissions/mciam/id/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "현재 로그인한 사용자가 접근 가능한 워크스페이스 및 각 워크스페이스에서의 역할 목록을 조회합니다.", + "description": "Retrieve permission details by permission ID.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "users", - "workspaces", - "roles", - "me" + "permissions" + ], + "summary": "Get permission by ID", + "operationId": "getMciamPermissionByID", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } ], - "summary": "내 워크스페이스 및 역할 목록 조회", "responses": { "200": { - "description": "성공 시 워크스페이스 및 역할 정보 목록 반환", + "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/service.WorkspaceRoleInfo" - } + "$ref": "#/definitions/model.MciamPermission" } }, - "401": { - "description": "error: Unauthorized", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1878,7 +1825,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1889,51 +1836,37 @@ const docTemplate = `{ } } }, - "/users": { - "get": { + "/api/permissions/mciam/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "모든 사용자 목록을 조회합니다. 'admin' 또는 'platformAdmin' 역할이 필요합니다.", + "description": "Retrieve a list of all permissions.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "users" + "permissions" ], - "summary": "사용자 목록 조회 (관리자용)", + "summary": "List all permissions", + "operationId": "listMciamPermissions", "responses": { "200": { - "description": "성공 시 사용자 목록 반환", + "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.User" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: Forbidden (권한 부족)", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/model.MciamPermission" } } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1942,43 +1875,16 @@ const docTemplate = `{ } } } - }, - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "responses": {} } }, - "/users/{id}": { + "/api/permissions/mciam/{id}": { "put": { "security": [ { "BearerAuth": [] } ], - "parameters": [ - { - "type": "integer", - "description": "User DB ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": {} - } - }, - "/users/{id}/approve": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "지정된 사용자를 활성화하고 시스템 사용을 승인합니다. 'admin' 또는 'platformadmin' 역할이 필요합니다.", + "description": "Update the details of an existing permission.", "consumes": [ "application/json" ], @@ -1986,33 +1892,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "permissions" ], - "summary": "사용자 승인 (관리자용)", + "summary": "Update permission", + "operationId": "updateMciamPermission", "parameters": [ { "type": "string", - "description": "사용자 Keycloak ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true + }, + { + "description": "Permission Info", + "name": "permission", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.MciamPermission" + } } ], "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 사용자 ID", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.MciamPermission" } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2020,8 +1930,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden (권한 부족)", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2030,7 +1940,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2039,16 +1949,14 @@ const docTemplate = `{ } } } - } - }, - "/workspaces": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "모든 워크스페이스 목록을 조회합니다 (연결된 프로젝트 정보 포함).", + "description": "Delete a permission by its ID.", "consumes": [ "application/json" ], @@ -2056,21 +1964,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "permissions" + ], + "summary": "Delete permission", + "operationId": "deleteMciamPermission", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } ], - "summary": "모든 워크스페이스 조회", "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" + "type": "object", + "additionalProperties": { + "type": "string" } } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2079,14 +2000,16 @@ const docTemplate = `{ } } } - }, + } + }, + "/api/projects": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "새로운 워크스페이스를 생성합니다.", + "description": "Create a new project with the specified information.", "consumes": [ "application/json" ], @@ -2094,17 +2017,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스 생성", + "summary": "Create new project", + "operationId": "createProject", "parameters": [ { - "description": "워크스페이스 정보 (ID, CreatedAt, UpdatedAt, Projects 제외)", - "name": "workspace", + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } } ], @@ -2112,11 +2036,11 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } }, "400": { - "description": "error: 잘못된 요청 형식", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2125,7 +2049,48 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/projects/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all projects.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "projects" + ], + "summary": "List all projects", + "operationId": "listProjects", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2136,14 +2101,14 @@ const docTemplate = `{ } } }, - "/workspaces/name/{name}": { + "/api/projects/name/{projectName}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "이름으로 특정 워크스페이스를 조회합니다 (연결된 프로젝트 정보 포함).", + "description": "Get project details by name", "consumes": [ "application/json" ], @@ -2151,13 +2116,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "이름으로 워크스페이스 조회", + "summary": "Get project by name", + "operationId": "getProjectByName", "parameters": [ { "type": "string", - "description": "워크스페이스 이름", + "description": "Project Name", "name": "name", "in": "path", "required": true @@ -2167,11 +2133,11 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2180,7 +2146,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2191,14 +2157,14 @@ const docTemplate = `{ } } }, - "/workspaces/{id}": { + "/api/projects/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "ID로 특정 워크스페이스를 조회합니다 (연결된 프로젝트 정보 포함).", + "description": "Retrieve project details by project ID.", "consumes": [ "application/json" ], @@ -2206,14 +2172,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "ID로 워크스페이스 조회", + "summary": "Get project by ID", + "operationId": "getProjectByID", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", + "type": "string", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } @@ -2222,20 +2189,11 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "400": { - "description": "error: 잘못된 워크스페이스 ID", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Project" } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2244,7 +2202,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2260,7 +2218,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "기존 워크스페이스 정보를 부분적으로 수정합니다.", + "description": "Update the details of an existing project.", "consumes": [ "application/json" ], @@ -2268,36 +2226,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스 수정", + "summary": "Update project", + "operationId": "updateProject", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", + "type": "string", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "수정할 필드와 값 (예: {\\", - "name": "updates", + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "type": "object" + "$ref": "#/definitions/model.Project" } } ], "responses": { "200": { - "description": "업데이트된 워크스페이스 정보", + "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } }, "400": { - "description": "error: 잘못된 요청 형식 또는 ID", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2306,7 +2265,7 @@ const docTemplate = `{ } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2315,7 +2274,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2331,7 +2290,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "워크스페이스를 삭제합니다. 연결된 프로젝트와의 관계도 해제됩니다.", + "description": "Delete a project by its ID.", "consumes": [ "application/json" ], @@ -2339,14 +2298,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스 삭제", + "summary": "Delete project", + "operationId": "deleteProject", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", + "type": "string", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } @@ -2355,17 +2315,8 @@ const docTemplate = `{ "204": { "description": "No Content" }, - "400": { - "description": "error: 잘못된 워크스페이스 ID", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2374,7 +2325,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2385,14 +2336,14 @@ const docTemplate = `{ } } }, - "/workspaces/{id}/projects": { - "get": { + "/api/projects/{id}/workspaces/{workspaceId}": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스 ID에 연결된 모든 프로젝트 목록을 조회합니다.", + "description": "프로젝트에 워크스페이스를 연결합니다.", "consumes": [ "application/json" ], @@ -2400,30 +2351,32 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스에 연결된 프로젝트 목록 조회", + "summary": "프로젝트에 워크스페이스 연결", + "operationId": "addWorkspaceToProject", "parameters": [ { "type": "integer", - "description": "워크스페이스 ID", + "description": "프로젝트 ID", "name": "id", "in": "path", "required": true + }, + { + "type": "integer", + "description": "워크스페이스 ID", + "name": "workspaceId", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "성공 시 프로젝트 목록 반환", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Project" - } - } + "204": { + "description": "No Content" }, "400": { - "description": "error: 잘못된 워크스페이스 ID", + "description": "error: 잘못된 ID 형식", "schema": { "type": "object", "additionalProperties": { @@ -2432,7 +2385,7 @@ const docTemplate = `{ } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", "schema": { "type": "object", "additionalProperties": { @@ -2452,14 +2405,14 @@ const docTemplate = `{ } } }, - "/workspaces/{id}/projects/{projectId}": { + "/api/resource-types/cloud-resources": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스에 프로젝트를 연결합니다.", + "description": "새로운 리소스 타입을 생성합니다", "consumes": [ "application/json" ], @@ -2467,31 +2420,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "resource-types" ], - "summary": "워크스페이스에 프로젝트 연결", + "summary": "Cloud에서 관리되는 Resource(vm, nlb, k8s 등의 그룹) 새 리소스 타입 생성", + "operationId": "createResourceType", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "프로젝트 ID", - "name": "projectId", - "in": "path", - "required": true + "description": "Resource Type Info", + "name": "resourceType", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.ResourceType" + } } ], "responses": { - "204": { - "description": "No Content" + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } }, "400": { - "description": "error: 잘못된 ID 형식", + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -2499,8 +2451,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: 워크스페이스 또는 프로젝트를 찾을 수 없습니다", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2508,8 +2460,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2518,14 +2470,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스에서 프로젝트 연결을 해제합니다.", + "description": "특정 리소스 타입을 ID로 조회합니다", "consumes": [ "application/json" ], @@ -2533,31 +2487,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "resource-types" ], - "summary": "워크스페이스에서 프로젝트 연결 해제", + "summary": "리소스 타입 ID로 조회", + "operationId": "getCloudResourceTypeByID", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", + "type": "string", + "description": "Resource Type ID", "name": "id", "in": "path", "required": true - }, - { - "type": "integer", - "description": "프로젝트 ID", - "name": "projectId", - "in": "path", - "required": true } ], "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 ID 형식", + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } + }, + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2565,8 +2516,17 @@ const docTemplate = `{ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -2575,16 +2535,14 @@ const docTemplate = `{ } } } - } - }, - "/workspaces/{id}/users": { - "get": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스에 속한 모든 사용자와 각 사용자의 역할을 조회합니다.", + "description": "리소스 타입 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -2592,32 +2550,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces", - "users", - "roles" + "resource-types" ], - "summary": "워크스페이스 사용자 및 역할 목록 조회", + "summary": "리소스 타입 업데이트", + "operationId": "updateResourceType", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", + "type": "string", + "description": "Resource Type ID", "name": "id", "in": "path", "required": true + }, + { + "description": "Resource Type Info", + "name": "resourceType", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.ResourceType" + } } ], "responses": { "200": { - "description": "성공 시 사용자 및 역할 목록 반환", + "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/service.UserWithRoles" - } + "$ref": "#/definitions/model.ResourceType" } }, "400": { - "description": "error: 잘못된 워크스페이스 ID", + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -2625,8 +2588,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2634,8 +2597,17 @@ const docTemplate = `{ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -2644,16 +2616,14 @@ const docTemplate = `{ } } } - } - }, - "/workspaces/{workspaceId}/users/{userId}/roles/{roleId}": { - "post": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스 내의 사용자에게 특정 워크스페이스 역할을 할당합니다.", + "description": "리소스 타입을 삭제합니다", "consumes": [ "application/json" ], @@ -2661,30 +2631,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces", - "roles", - "users" + "resource-types" ], - "summary": "워크스페이스 사용자에게 역할 할당", + "summary": "리소스 타입 삭제", + "operationId": "deleteResourceType", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "사용자 DB ID (db_id)", - "name": "userId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 역할 ID", - "name": "roleId", + "type": "string", + "description": "Resource Type ID", + "name": "id", "in": "path", "required": true } @@ -2693,8 +2648,17 @@ const docTemplate = `{ "204": { "description": "No Content" }, - "400": { - "description": "error: 잘못된 ID 형식", + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2703,16 +2667,48 @@ const docTemplate = `{ } }, "404": { - "description": "error: 사용자, 역할 또는 워크스페이스를 찾을 수 없습니다", + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { "type": "string" } } + } + } + } + }, + "/api/resource-types/cloud-resources/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "모든 리소스 타입 목록을 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "resource-types" + ], + "summary": "리소스 타입 목록 조회", + "operationId": "listCloudResourceTypes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ResourceType" + } + } }, - "409": { - "description": "error: 역할이 해당 워크스페이스에 속하지 않음", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2720,8 +2716,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2730,14 +2726,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/roles": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스 내의 사용자에게서 특정 워크스페이스 역할을 제거합니다.", + "description": "Create a new role", "consumes": [ "application/json" ], @@ -2745,40 +2743,91 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces", - "roles", - "users" + "roles" ], - "summary": "워크스페이스 사용자 역할 제거", + "summary": "Create role", + "operationId": "createRole", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } }, - { - "type": "integer", - "description": "사용자 DB ID (db_id)", - "name": "userId", - "in": "path", - "required": true + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/assign/platform-role": { + "post": { + "security": [ { - "type": "integer", - "description": "워크스페이스 역할 ID", - "name": "roleId", - "in": "path", - "required": true + "BearerAuth": [] + } + ], + "description": "Assign a platform role to a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Assign platform role", + "operationId": "assignPlatformRole", + "parameters": [ + { + "description": "Platform Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } }, "400": { - "description": "error: 잘못된 ID 형식", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2786,8 +2835,51 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: 역할 또는 워크스페이스를 찾을 수 없습니다\" // User existence check is optional here", + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/assign/workspace-role": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Assign a workspace role to a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Assign workspace role", + "operationId": "assignWorkspaceRole", + "parameters": [ + { + "description": "Workspace Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignWorkspaceRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -2795,8 +2887,8 @@ const docTemplate = `{ } } }, - "409": { - "description": "error: 역할이 해당 워크스페이스에 속하지 않음", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2805,7 +2897,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2815,176 +2907,4718 @@ const docTemplate = `{ } } } - } - }, - "definitions": { - "idp.UserLogin": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "password": { - "type": "string" + }, + "/api/roles/csp": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new csp role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create csp role", + "operationId": "createCspRole", + "parameters": [ + { + "description": "CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new mapping between role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create role-CSP role mapping", + "operationId": "addCspRoleMappings", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/batch": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create multiple new csp roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create multiple csp roles", + "operationId": "createCspRoles", + "parameters": [ + { + "description": "Multiple CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspRolesRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CspRole" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/id/:roleId": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a mapping between role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role-CSP role mapping", + "operationId": "getCspRoleMappingByRoleId", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/id/{roleId}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update role information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Update csp role", + "operationId": "updateCspRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete csp role", + "operationId": "deleteCspRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a mapping between role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role-CSP role mapping", + "operationId": "listCspRoleMappings", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get csp role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get csp role by ID", + "operationId": "getCspRoleByID", + "parameters": [ + { + "type": "string", + "description": "CSP Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a list of all csp roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List csp roles", + "operationId": "listCSPRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get csp role details by Name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get csp role by Name", + "operationId": "getCspRoleByName", + "parameters": [ + { + "type": "string", + "description": "CSP Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role by ID", + "operationId": "getRoleByRoleID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Update role", + "operationId": "updateRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a role by its name.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete role", + "operationId": "deleteRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/id/{roleId}/assign": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Assign a role to a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Assign role", + "operationId": "assignRole", + "parameters": [ + { + "description": "Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/id/{roleId}/unassign": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a role from a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Remove role", + "operationId": "removeRole", + "parameters": [ + { + "description": "Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all roles.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List all roles", + "operationId": "listRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/csp-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by csp role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List users by csp role", + "operationId": "listUsersByCspRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List role master mappings", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List role master mappings", + "operationId": "listRoleMasterMappings", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/platform-roles/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by platform role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List users by platform role", + "operationId": "listUsersByPlatformRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/role/id/:roleId": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get role master mappings", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role master mappings", + "operationId": "getRoleMasterMappings", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/workspace-roles/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by workspace role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List users by workspace role", + "operationId": "listUsersByWorkspaceRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/menu-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a list of all menu roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List menu roles", + "operationId": "listPlatformRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve role details by role name.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role by Name", + "operationId": "getRoleByRoleName", + "parameters": [ + { + "type": "string", + "description": "Role name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/platform-roles": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new menu role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create menu role", + "operationId": "createPlatformRole", + "parameters": [ + { + "description": "Menu Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/platform-roles/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get platform role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get platform role by ID", + "operationId": "getPlatformRoleByID", + "parameters": [ + { + "type": "string", + "description": "Platform Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a platform role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete platform role", + "operationId": "deletePlatformRole", + "parameters": [ + { + "type": "string", + "description": "Platform Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/platform-roles/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get menu role details by Name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get menu role by Name", + "operationId": "getPlatformRoleByName", + "parameters": [ + { + "type": "string", + "description": "Menu Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/unassign/csp-roles": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a mapping between workspace role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete workspace role-CSP role mapping", + "operationId": "removeCspRoleMappings", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/unassign/platform-role": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a platform role from a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Remove platform role", + "operationId": "removePlatformRole", + "parameters": [ + { + "description": "Platform Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/unassign/workspace-role": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a workspace role from a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Remove workspace role", + "operationId": "removeWorkspaceRole", + "parameters": [ + { + "description": "Workspace Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create workspace role", + "operationId": "createWorkspaceRole", + "parameters": [ + { + "description": "Workspace Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspace role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get workspace role by ID", + "operationId": "getWorkspaceRoleByID", + "parameters": [ + { + "type": "string", + "description": "Workspace Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a workspace role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete workspace role", + "operationId": "deleteWorkspaceRole", + "parameters": [ + { + "type": "string", + "description": "Workspace Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a list of all workspace roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List workspace roles", + "operationId": "listWorkspaceRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspace role details by Name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get workspace role by Name", + "operationId": "getWorkspaceRoleByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions": { + "get": { + "description": "특정 역할의 MC-IAM 권한 ID 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할의 MC-IAM 권한 목록 조회 - Renamed", + "operationId": "getRoleMciamPermissions", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "권한 ID 목록", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId}": { + "post": { + "description": "역할에 MC-IAM 권한을 할당합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에 MC-IAM 권한 할당 - Renamed", + "operationId": "assignMciamPermissionToRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + }, + "delete": { + "description": "역할에서 MC-IAM 권한을 제거합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에서 MC-IAM 권한 제거 - Renamed", + "operationId": "removeMciamPermissionFromRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/api/setup/check-user-roles": { + "get": { + "description": "Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Check user roles", + "operationId": "checkUserRoles", + "parameters": [ + { + "type": "string", + "description": "Username to check roles", + "name": "username", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/initial-role-menu-permission": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSV 파일을 읽어서 메뉴 권한을 초기화합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Initialize menu permissions from CSV", + "operationId": "initializeMenuPermissions", + "parameters": [ + { + "type": "string", + "description": "CSV file path (optional, uses default if not provided)", + "name": "filePath", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/sync-projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "projects" + ], + "summary": "mc-infra-manager와 프로젝트 동기화", + "operationId": "syncProjects", + "responses": { + "200": { + "description": "message: Project synchronization successful", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류 또는 동기화 실패", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new user with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Create new user", + "operationId": "createUser", + "parameters": [ + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve user details by user ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by ID", + "operationId": "getUserByID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/status": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update user status (active/inactive)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user status", + "operationId": "updateUserStatus", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Status", + "name": "status", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UserStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user and workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID and workspace ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspaces by user ID", + "operationId": "getUserWorkspacesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/kc/{kcUserId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by KcID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by KcID", + "operationId": "getUserByKcID", + "parameters": [ + { + "type": "string", + "description": "User KcID", + "name": "kcUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all users.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List all users", + "operationId": "listUsers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.User" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus-tree/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get the menu tree accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu tree", + "operationId": "listUserMenuTree", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus/list": { + "post": { + "description": "Get the menu list accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu list", + "operationId": "listUserMenu", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" + } + } + } + } + } + }, + "/api/users/name/{username}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by username", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by username", + "operationId": "getUserByUsername", + "parameters": [ + { + "type": "string", + "description": "Username", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List projects for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user projects by workspace", + "operationId": "listUserProjectsByWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspaces", + "operationId": "listUserWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces and roles for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspace and roles", + "operationId": "listUserWorkspaceAndWorkspaceRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing user.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user", + "operationId": "updateUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a user by their ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Delete user", + "operationId": "deleteUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Create new workspace", + "operationId": "createWorkspace", + "parameters": [ + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/assign/projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Add a project to a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Add project to workspace", + "operationId": "addProjectToWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "error: Invalid request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace or Project not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve workspace details by workspace ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by ID", + "operationId": "getWorkspaceByID", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing workspace.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Update workspace", + "operationId": "updateWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a workspace by its ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Delete workspace", + "operationId": "deleteWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "getWorkspaceProjectsByWorkspaceId", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get roles assigned to a user in a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get user workspace roles", + "operationId": "getUserWorkspaceRoles", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/list": { + "post": { + "description": "Retrieve users and roles list belonging to workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List users and roles by workspace", + "operationId": "listUsersAndRolesByWorkspace", + "parameters": [ + { + "type": "integer", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "400": { + "description": "error: Invalid workspace ID", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Internal server error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all workspaces.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List all workspaces", + "operationId": "listWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/name/{workspaceName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve specific workspace by name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by name", + "operationId": "getWorkspaceByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Name", + "name": "workspaceName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/projects/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "listWorkspaceProjects", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/temporary-credentials": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get temporary credentials for CSP", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "Get temporary credentials", + "operationId": "mciamGetTemporaryCredentials", + "responses": {} + } + }, + "/api/workspaces/unassign/projects": { + "delete": { + "description": "Remove a project from a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Remove project from workspace", + "operationId": "removeProjectFromWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/api/workspaces/users-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve the list of users and roles assigned to the workspace.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List users and roles in workspace", + "operationId": "listAllWorkspaceUsersAndRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.WorkspaceWithUsersAndRoles" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Internal server error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by workspace criteria", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace users", + "operationId": "listWorkspaceUsers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.WorkspaceWithUsersAndRoles" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/workspace-ticket": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Set workspace ticket", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Set workspace ticket", + "operationId": "mciamWorkspaceTicket", + "responses": { + "200": { + "description": "message: Workspace ticket set successfully", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/{id}/users": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Add a user to a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Add user to workspace", + "operationId": "addUserToWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/{id}/users/{userId}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a user from a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Remove user from workspace", + "operationId": "removeUserFromWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/readyz": { + "get": { + "description": "Check the health status of the service.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "health" + ], + "summary": "Health check", + "operationId": "mciamCheckHealth", + "parameters": [ + { + "type": "string", + "description": "Detail check components (nginx,db,keycloak,all)", + "name": "detail", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + } + }, + "definitions": { + "constants.AuthMethod": { + "type": "string", + "enum": [ + "OIDC", + "SAML" + ], + "x-enum-varnames": [ + "AuthMethodOIDC", + "AuthMethodSAML" + ] + }, + "constants.CSPType": { + "type": "string", + "enum": [ + "aws", + "gcp", + "azure" + ], + "x-enum-varnames": [ + "CSPTypeAWS", + "CSPTypeGCP", + "CSPTypeAzure" + ] + }, + "constants.IAMRoleType": { + "type": "string", + "enum": [ + "platform", + "workspace", + "csp" + ], + "x-enum-comments": { + "RoleTypeCSP": "CSP 역할", + "RoleTypePlatform": "플랫폼 역할", + "RoleTypeWorkspace": "워크스페이스 역할" + }, + "x-enum-descriptions": [ + "플랫폼 역할", + "워크스페이스 역할", + "CSP 역할" + ], + "x-enum-varnames": [ + "RoleTypePlatform", + "RoleTypeWorkspace", + "RoleTypeCSP" + ] + }, + "idp.UserLogin": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAction": { + "type": "object", + "properties": { + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "description": "Auto-incrementing primary key", + "type": "integer" + }, + "method": { + "type": "string" + }, + "resourcePath": { + "type": "string" + }, + "serviceName": { + "description": "Foreign key reference (indexed)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAuthInfo": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "type": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiDefinitions": { + "type": "object", + "properties": { + "serviceActions": { + "description": "Use renamed ServiceAction", + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" + } + } + }, + "services": { + "description": "Use renamed ServiceDefinition", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + } + } + } + }, + "mcmpapi.McmpApiPermissionActionMapping": { + "type": "object", + "properties": { + "actionID": { + "type": "integer" + }, + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "permissionID": { + "type": "string" + }, + "updatedAt": { + "type": "string" } } }, - "mcmpapi.ApiQueryParam": { + "mcmpapi.McmpApiServiceAction": { "type": "object", - "required": [ - "key", - "value" - ], "properties": { - "key": { + "description": { "type": "string" }, - "value": { + "method": { + "type": "string" + }, + "resourcePath": { "type": "string" } } }, - "mcmpapi.McmpApiAuthInfo": { + "mcmpapi.McmpApiServiceDefinition": { "type": "object", "properties": { - "password": { + "auth": { + "description": "Use renamed AuthInfo", + "allOf": [ + { + "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + } + ] + }, + "baseURL": { "type": "string" }, - "type": { + "version": { + "type": "string" + } + } + }, + "model.AssignRoleRequest": { + "type": "object", + "properties": { + "roleId": { + "description": "역할 ID (문자열로 받음)", + "type": "string" + }, + "roleName": { + "description": "역할명", + "type": "string" + }, + "roleType": { + "description": "역할 타입 (platform/workspace)", + "type": "string" + }, + "userId": { + "description": "사용자 ID (문자열로 받음)", "type": "string" }, "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", "type": "string" } } }, - "mcmpapi.McmpApiCallRequest": { + "model.AssignWorkspaceRoleRequest": { "type": "object", - "required": [ - "actionName", - "serviceName" - ], "properties": { - "actionName": { - "description": "Target action name (operationId)", + "roleId": { + "description": "역할 ID (문자열로 받음)", "type": "string" }, - "requestParams": { - "description": "Parameters for the external API call", - "allOf": [ - { - "$ref": "#/definitions/mcmpapi.McmpApiRequestParams" - } - ] + "roleName": { + "description": "역할명", + "type": "string" }, - "serviceName": { - "description": "Target service name", + "userId": { + "description": "사용자 ID (문자열로 받음)", + "type": "string" + }, + "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", "type": "string" } } }, - "mcmpapi.McmpApiDefinitions": { + "model.CreateCspRoleRequest": { "type": "object", "properties": { - "serviceActions": { - "description": "Use renamed ServiceAction", - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" - } - } + "cspRoleName": { + "description": "csp의 RoleName. 여러 role이 있기때문에 csp에 정의한 role로 구분하기 위해 사용", + "type": "string" }, - "services": { - "description": "Use renamed ServiceDefinition", - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + "cspType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "iamIdentifier": { + "type": "string" + }, + "iamRoleId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idpIdentifier": { + "type": "string" + }, + "path": { + "type": "string" + }, + "status": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Tag" + } + } + } + }, + "model.CreateCspRolesRequest": { + "type": "object", + "required": [ + "cspRoles" + ], + "properties": { + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" } } } }, - "mcmpapi.McmpApiRequestParams": { + "model.CreateMenuMappingRequest": { "type": "object", + "required": [ + "menuIds", + "roleId" + ], "properties": { - "body": { - "description": "Request body (accept any JSON structure) - Changed from json.RawMessage for swag compatibility" + "menuIds": { + "type": "array", + "items": { + "type": "string" + } }, - "pathParams": { - "description": "Parameters to replace in the resource path (e.g., {userId})", - "type": "object", - "additionalProperties": { + "roleId": { + "type": "string" + } + } + }, + "model.CreateRoleRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" + } + }, + "description": { + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { "type": "string" } }, - "queryParams": { - "description": "Parameters to append as query string (?key=value)", - "type": "object", - "additionalProperties": { + "name": { + "type": "string" + }, + "parentId": { + "type": "integer" + }, + "roleTypes": { + "description": "RoleTypes []constants.IAMRoleType ` + "`" + `json:\"roleTypes\" validate:\"required,dive,oneof=platform workspace csp\"` + "`" + `", + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" + } + } + } + }, + "model.CspRole": { + "type": "object", + "properties": { + "create_date": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "csp_type": { + "type": "string" + }, + "deleted_at": { + "type": "string" + }, + "description": { + "type": "string" + }, + "iam_identifier": { + "type": "string" + }, + "iam_role_id": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "idp_identifier": { + "type": "string" + }, + "max_session_duration": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + }, + "permissions": { + "type": "array", + "items": { "type": "string" } + }, + "permissions_boundary": { + "type": "string" + }, + "role_last_used": { + "$ref": "#/definitions/model.RoleLastUsed" + }, + "status": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Tag" + } + }, + "updated_at": { + "type": "string" + } + } + }, + "model.FilterRoleMasterMappingRequest": { + "type": "object", + "properties": { + "authMethod": { + "type": "string" + }, + "cspRoleId": { + "type": "string" + }, + "cspRoleName": { + "type": "string" + }, + "cspType": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectName": { + "type": "string" + }, + "roleId": { + "type": "string" + }, + "roleTypes": { + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" + } + }, + "userId": { + "type": "string" + }, + "username": { + "type": "string" + }, + "workspaceId": { + "type": "string" + }, + "workspaceName": { + "type": "string" } } }, - "mcmpapi.McmpApiServiceAction": { + "model.MciamPermission": { "type": "object", "properties": { + "action": { + "description": "e.g., create, read, update, delete", + "type": "string" + }, + "createdAt": { + "description": "Match DB schema", + "type": "string" + }, "description": { "type": "string" }, - "method": { + "frameworkId": { + "description": "FK to mcmp_resource_types.framework_id", "type": "string" }, - "resourcePath": { + "id": { + "description": "Format: \u003cframework_id\u003e:\u003cresource_type_id\u003e:\u003caction\u003e", + "type": "string" + }, + "name": { + "type": "string" + }, + "resourceTypeId": { + "description": "FK to mcmp_resource_types.id", + "type": "string" + }, + "updatedAt": { + "description": "Match DB schema", "type": "string" } } }, - "mcmpapi.McmpApiServiceDefinition": { + "model.McmpApiCallRequest": { "type": "object", + "required": [ + "actionName", + "serviceName" + ], "properties": { - "auth": { - "description": "Use renamed AuthInfo", + "actionName": { + "description": "Target action name (operationId)", + "type": "string" + }, + "requestParams": { + "description": "Parameters for the external API call", "allOf": [ { - "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + "$ref": "#/definitions/model.McmpApiRequestParams" } - ] - }, - "baseURL": { - "type": "string" + ] }, - "version": { + "serviceName": { + "description": "Target service name", "type": "string" } } }, - "mcmpapi.ServiceApiCallRequest": { - "type": "object" + "model.McmpApiRequestParams": { + "type": "object", + "properties": { + "body": { + "description": "Request body (accept any JSON structure) - Changed from json.RawMessage for swag compatibility" + }, + "pathParams": { + "description": "Parameters to replace in the resource path (e.g., {userId})", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "queryParams": { + "description": "Parameters to append as query string (?key=value)", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } }, "model.Menu": { "type": "object", "properties": { - "display_name": { + "displayName": { "type": "string" }, "id": { "type": "string" }, - "is_action": { + "isAction": { "type": "boolean" }, - "menu_number": { + "menuNumber": { "type": "integer" }, - "parent_id": { + "parentId": { "type": "string" }, "priority": { "type": "integer" }, - "res_type": { + "resType": { "type": "string" } } @@ -2999,78 +7633,126 @@ const docTemplate = `{ "$ref": "#/definitions/model.MenuTreeNode" } }, - "display_name": { + "displayName": { "type": "string" }, "id": { "type": "string" }, - "is_action": { + "isAction": { "type": "boolean" }, - "menu_number": { + "menuNumber": { "type": "integer" }, - "parent_id": { + "parentId": { "type": "string" }, "priority": { "type": "integer" }, - "res_type": { + "resType": { "type": "string" } } }, - "model.Permission": { + "model.Project": { "type": "object", "properties": { "created_at": { "type": "string" }, "description": { - "description": "Increased size to match roles", "type": "string" }, "id": { - "description": "Changed to string", - "type": "string" + "type": "integer" }, "name": { - "description": "Assuming Name column exists or needs to be added", + "type": "string" + }, + "nsid": { + "description": "Namespace ID", "type": "string" }, "updated_at": { "type": "string" + }, + "workspaces": { + "description": "M:N relationship", + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } } } }, - "model.PlatformRole": { + "model.ResourceType": { "type": "object", "properties": { - "created_at": { + "createdAt": { "type": "string" }, "description": { "type": "string" }, + "frameworkId": { + "description": "Identifier of the framework (e.g., \"mc-iam-manager\", \"mc-infra-manager\")", + "type": "string" + }, "id": { - "type": "integer" + "description": "Unique identifier within the framework (e.g., \"workspace\", \"vm\")", + "type": "string" }, "name": { + "description": "Display name (e.g., \"Workspace\", \"Virtual Machine\")", "type": "string" }, - "updated_at": { + "updatedAt": { "type": "string" } } }, - "model.Project": { + "model.Response": { + "type": "object", + "properties": { + "error": { + "type": "boolean" + }, + "message": { + "type": "string" + } + } + }, + "model.RoleLastUsed": { + "type": "object", + "properties": { + "last_used_date": { + "type": "string" + }, + "region": { + "type": "string" + } + } + }, + "model.RoleMaster": { "type": "object", "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + }, "created_at": { "type": "string" }, + "csp_role_mappings": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterCspRoleMapping" + } + }, "description": { "type": "string" }, @@ -3080,19 +7762,141 @@ const docTemplate = `{ "name": { "type": "string" }, - "nsid": { - "description": "Namespace ID", - "type": "string" + "parent": { + "$ref": "#/definitions/model.RoleMaster" + }, + "parent_id": { + "type": "integer" + }, + "predefined": { + "type": "boolean" + }, + "role_subs": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleSub" + } }, "updated_at": { "type": "string" + } + } + }, + "model.RoleMasterCspRoleMapping": { + "type": "object", + "properties": { + "auth_method": { + "$ref": "#/definitions/constants.AuthMethod" + }, + "createdAt": { + "type": "string" }, - "workspaces": { - "description": "M:N relationship", + "cspRoles": { + "description": "서비스 레이어에서 조합", "type": "array", "items": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.CspRole" + } + }, + "description": { + "type": "string" + }, + "roleId": { + "type": "integer" + } + } + }, + "model.RoleMasterCspRoleMappingRequest": { + "type": "object", + "properties": { + "authMethod": { + "$ref": "#/definitions/constants.AuthMethod" + }, + "cspRoleId": { + "type": "string" + }, + "cspType": { + "$ref": "#/definitions/constants.CSPType" + }, + "description": { + "type": "string" + }, + "roleId": { + "type": "string" + } + } + }, + "model.RoleMasterMapping": { + "type": "object", + "properties": { + "role_id": { + "type": "integer" + }, + "role_master_csp_role_mappings": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterCspRoleMapping" + } + }, + "role_name": { + "type": "string" + }, + "user_platform_roles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserPlatformRole" } + }, + "user_workspace_roles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + } + }, + "model.RoleSub": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "role_id": { + "type": "integer" + }, + "role_type": { + "$ref": "#/definitions/constants.IAMRoleType" + }, + "updated_at": { + "type": "string" + } + } + }, + "model.SetupInitialAdminRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "model.Tag": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" } } }, @@ -3130,10 +7934,10 @@ const docTemplate = `{ "type": "string" }, "platform_roles": { - "description": "관계 정의 (Foreign Key는 DB ID인 'ID' 필드를 참조해야 함)", + "description": "관계 정의", "type": "array", "items": { - "$ref": "#/definitions/model.PlatformRole" + "$ref": "#/definitions/model.RoleMaster" } }, "updated_at": { @@ -3144,116 +7948,132 @@ const docTemplate = `{ "type": "string" }, "workspace_roles": { - "description": "Changed foreignKey to ID", "type": "array", "items": { - "$ref": "#/definitions/model.WorkspaceRole" + "$ref": "#/definitions/model.RoleMaster" } } } }, - "model.Workspace": { + "model.UserPlatformRole": { "type": "object", "properties": { "created_at": { "type": "string" }, - "description": { - "type": "string" - }, - "id": { + "role_id": { "type": "integer" }, - "name": { - "type": "string" - }, - "projects": { - "description": "M:N relationship", - "type": "array", - "items": { - "$ref": "#/definitions/model.Project" - } + "user_id": { + "type": "integer" }, - "updated_at": { + "username": { + "description": "사용자 정보 (JOIN으로 가져올 필드들)", "type": "string" } } }, - "model.WorkspaceRole": { + "model.UserStatusRequest": { "type": "object", "properties": { - "created_at": { - "type": "string" - }, - "description": { - "type": "string" - }, "id": { - "type": "integer" + "description": "DB에 저장되는 정보 (mcmp_users 테이블)", + "type": "string" }, - "name": { - "description": "이름은 고유해야 함", + "kc_id": { + "description": "Keycloak User ID", "type": "string" }, - "updated_at": { + "status": { + "description": "사용자 상태", "type": "string" } } }, - "service.HealthStatus": { + "model.UserWorkspaceRole": { "type": "object", "properties": { - "db_connection": { + "created_at": { "type": "string" }, - "keycloak_admin_login": { - "type": "string" + "role": { + "$ref": "#/definitions/model.RoleMaster" }, - "keycloak_client_check": { - "type": "string" + "role_id": { + "type": "integer" }, - "keycloak_realm_check": { + "role_name": { "type": "string" }, - "mcmp_actions_count": { - "type": "integer" + "user": { + "$ref": "#/definitions/model.User" }, - "mcmp_services_count": { + "user_id": { "type": "integer" }, - "menus_count": { - "type": "integer" + "username": { + "type": "string" }, - "platform_roles_count": { - "type": "integer" + "workspace": { + "$ref": "#/definitions/model.Workspace" }, - "workspace_roles_count": { + "workspace_id": { "type": "integer" + }, + "workspace_name": { + "type": "string" } } }, - "service.UserWithRoles": { + "model.Workspace": { "type": "object", "properties": { - "roles": { + "created_at": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "projects": { "type": "array", "items": { - "$ref": "#/definitions/model.WorkspaceRole" + "$ref": "#/definitions/model.Project" } }, - "user": { - "$ref": "#/definitions/model.User" + "updated_at": { + "type": "string" } } }, - "service.WorkspaceRoleInfo": { + "model.WorkspaceWithUsersAndRoles": { "type": "object", "properties": { - "role": { - "$ref": "#/definitions/model.WorkspaceRole" + "created_at": { + "type": "string" }, - "workspace": { - "$ref": "#/definitions/model.Workspace" + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } } } } @@ -3271,7 +8091,7 @@ const docTemplate = `{ // SwaggerInfo holds exported Swagger Info so clients can modify it var SwaggerInfo = &swag.Spec{ Version: "1.0", - Host: "localhost:3000", + Host: "localhost", BasePath: "/api/v1", Schemes: []string{}, Title: "MC IAM Manager API", diff --git a/docs/swagger.json b/docs/swagger.json index 0d6928bf..421e2f8f 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -6,17 +6,46 @@ "contact": {}, "version": "1.0" }, - "host": "localhost:3000", + "host": "localhost", "basePath": "/api/v1", "paths": { - "/api/call": { - "post": { - "security": [ - { - "BearerAuth": [] - } + "/api/auth/certs": { + "get": { + "description": "Retrieve authentication certificates for MC-IAM-Manager to be used in target frameworks for token validation.", + "consumes": [ + "application/json" ], - "description": "Executes a defined MCMP API action with query parameters and a request body.", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Get authentication certificates", + "operationId": "mciamAuthCerts", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/auth/login": { + "post": { + "description": "Authenticate user and issue JWT token.", "consumes": [ "application/json" ], @@ -24,29 +53,41 @@ "application/json" ], "tags": [ - "McmpAPI" + "auth" ], - "summary": "Call an external MCMP API action (Generic Request)", + "summary": "User login", + "operationId": "mciamLogin", "parameters": [ { - "description": "Generic API Call Request", - "name": "callRequest", + "description": "Login Credentials", + "name": "credentials", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/mcmpapi.ServiceApiCallRequest" + "$ref": "#/definitions/idp.UserLogin" } } ], + "responses": {} + } + }, + "/api/auth/logout": { + "post": { + "description": "Invalidate the user's refresh token and log out.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Logout user", + "operationId": "mciamLogout", "responses": { "200": { - "description": "External API Response (structure depends on the called API)", - "schema": { - "type": "object" - } - }, - "400": { - "description": "error: Invalid request body or parameters", + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -54,17 +95,53 @@ } } }, - "404": { - "description": "error: Service or action not found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } + } + } + } + }, + "/api/auth/refresh": { + "post": { + "description": "Refresh JWT access token using a valid refresh token.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Refresh access token", + "operationId": "mciamRefreshToken", + "parameters": [ + { + "description": "Refresh token", + "name": "refresh_token", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "New token information", + "schema": { + "type": "object", + "additionalProperties": true + } }, - "500": { - "description": "error: Internal server error or failed to call external API", + "400": { + "description": "error: Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -72,8 +149,8 @@ } } }, - "503": { - "description": "error: External API unavailable", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -84,9 +161,9 @@ } } }, - "/api/permissions": { + "/api/auth/temp-credential-csps": { "get": { - "description": "모든 권한 목록을 조회합니다.", + "description": "Get temporary credential provider information for AWS and GCP", "consumes": [ "application/json" ], @@ -94,23 +171,29 @@ "application/json" ], "tags": [ - "permissions" + "auth" ], - "summary": "권한 목록 조회", + "summary": "Get temporary credential CSP information", + "operationId": "mciamGetTempCredentialProviders", "responses": { "200": { - "description": "OK", + "description": "CSP temporary credential information", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Permission" - } + "type": "object", + "additionalProperties": true } } } - }, + } + }, + "/api/auth/validate": { "post": { - "description": "새로운 권한을 생성합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Validate the current access token and refresh if expired", "consumes": [ "application/json" ], @@ -118,33 +201,58 @@ "application/json" ], "tags": [ - "permissions" + "auth" ], - "summary": "권한 생성", + "summary": "Validate access token", + "operationId": "mciamValidateToken", "parameters": [ { - "description": "권한 정보", - "name": "permission", + "description": "Refresh token", + "name": "refresh_token", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Permission" + "type": "string" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "Token validation result with new token if refreshed", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "error: Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", "schema": { - "$ref": "#/definitions/model.Permission" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/permissions/{id}": { + "/api/csp-credentials": { "get": { - "description": "ID로 특정 권한을 조회합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "모든 CSP 인증 정보 목록을 조회합니다", "consumes": [ "application/json" ], @@ -152,29 +260,80 @@ "application/json" ], "tags": [ - "permissions" + "csp-credentials" + ], + "summary": "CSP 인증 정보 목록 조회", + "operationId": "mciamListCredentials", + "responses": {} + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "새로운 CSP 인증 정보를 생성합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" ], - "summary": "ID로 권한 조회", + "tags": [ + "csp-credentials" + ], + "summary": "새 CSP 인증 정보 생성", + "operationId": "mciamCreateCredential", + "responses": {} + } + }, + "/api/csp-credentials/{id}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "특정 CSP 인증 정보를 ID로 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "CSP 인증 정보 ID로 조회", + "operationId": "mciamGetCredentialByID", "parameters": [ { "type": "string", - "description": "권한 ID", + "description": "Credential ID", "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { - "$ref": "#/definitions/model.Permission" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } }, "put": { - "description": "기존 권한을 수정합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -182,38 +341,38 @@ "application/json" ], "tags": [ - "permissions" + "csp-credentials" ], - "summary": "권한 수정", + "summary": "CSP 인증 정보 업데이트", + "operationId": "mciamUpdateCredential", "parameters": [ { "type": "string", - "description": "권한 ID", + "description": "Credential ID", "name": "id", "in": "path", "required": true - }, - { - "description": "권한 정보", - "name": "permission", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Permission" - } } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { - "$ref": "#/definitions/model.Permission" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } }, "delete": { - "description": "권한을 삭제합니다.", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 삭제합니다", "consumes": [ "application/json" ], @@ -221,13 +380,14 @@ "application/json" ], "tags": [ - "permissions" + "csp-credentials" ], - "summary": "권한 삭제", + "summary": "CSP 인증 정보 삭제", + "operationId": "mciamDeleteCredential", "parameters": [ { "type": "string", - "description": "권한 ID", + "description": "Credential ID", "name": "id", "in": "path", "required": true @@ -236,13 +396,40 @@ "responses": { "204": { "description": "No Content" + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Credential not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } } }, - "/api/platform-roles": { - "get": { - "description": "모든 플랫폼 역할을 조회합니다.", + "/api/initial-admin": { + "post": { + "description": "Creates the initial platform admin user with necessary permissions. platform admin 생성인데", "consumes": [ "application/json" ], @@ -250,23 +437,34 @@ "application/json" ], "tags": [ - "platform-roles" + "admin" + ], + "summary": "Setup initial platform admin", + "operationId": "setupInitialAdmin", + "parameters": [ + { + "description": "Setup Initial Admin Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.SetupInitialAdminRequest" + } + } ], - "summary": "플랫폼 역할 목록 조회", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.PlatformRole" - } + "$ref": "#/definitions/model.Response" } } } - }, + } + }, + "/api/mcmp-api-permission-action-mappings": { "post": { - "description": "새로운 플랫폼 역할을 생성합니다.", + "description": "Creates a new mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -274,33 +472,31 @@ "application/json" ], "tags": [ - "platform-roles" + "mcmp-api-permission-action-mappings" ], - "summary": "플랫폼 역할 생성", + "summary": "Create permission-action mapping", + "operationId": "createMcmpApiPermissionActionMapping", "parameters": [ { - "description": "Platform Role", - "name": "role", + "description": "Mapping to create", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.PlatformRole" + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" } } ], "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/model.PlatformRole" - } + "204": { + "description": "No Content" } } } }, - "/api/platform-roles/{id}": { - "get": { - "description": "ID로 플랫폼 역할을 조회합니다.", + "/api/mcmp-api-permission-action-mappings/actions/list": { + "post": { + "description": "Returns all workspace actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -308,14 +504,15 @@ "application/json" ], "tags": [ - "platform-roles" + "mcmp-api-permission-action-mappings" ], - "summary": "플랫폼 역할 조회", + "summary": "Get workspace actions by permission ID", + "operationId": "listWorkspaceActionsByPermissionID", "parameters": [ { - "type": "integer", - "description": "Platform Role ID", - "name": "id", + "type": "string", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -324,13 +521,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.PlatformRole" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" + } } } } - }, - "put": { - "description": "기존 플랫폼 역할을 수정합니다.", + } + }, + "/api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions": { + "get": { + "description": "Returns all permissions mapped to a specific API action", "consumes": [ "application/json" ], @@ -338,67 +540,35 @@ "application/json" ], "tags": [ - "platform-roles" + "mcmp-api-permission-action-mappings" ], - "summary": "플랫폼 역할 수정", + "summary": "Get permissions by action ID", + "operationId": "listPermissionsByActionID", "parameters": [ { "type": "integer", - "description": "Platform Role ID", - "name": "id", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true - }, - { - "description": "Platform Role", - "name": "role", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.PlatformRole" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.PlatformRole" + "type": "array", + "items": { + "type": "string" + } } } } - }, - "delete": { - "description": "플랫폼 역할을 삭제합니다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "platform-roles" - ], - "summary": "플랫폼 역할 삭제", - "parameters": [ - { - "type": "integer", - "description": "Platform Role ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - } - } } }, - "/api/roles/{roleType}/{roleId}/permissions": { - "get": { - "description": "특정 역할의 권한 목록을 조회합니다.", + "/api/mcmp-api-permission-action-mappings/list": { + "post": { + "description": "Returns all platform actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -406,21 +576,15 @@ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "역할의 권한 목록 조회", + "summary": "List platform actions by permission ID", + "operationId": "listPlatformActions", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "역할 ID", - "name": "roleId", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -431,16 +595,16 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Permission" + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/api/roles/{roleType}/{roleId}/permissions/{permissionId}": { - "post": { - "description": "역할에 권한을 할당합니다.", + "/api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId}": { + "put": { + "description": "Updates an existing mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -448,40 +612,49 @@ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "역할에 권한 할당", + "summary": "Update permission-action mapping", + "operationId": "updateMapping", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true }, { "type": "integer", - "description": "역할 ID", - "name": "roleId", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true }, { - "type": "string", - "description": "권한 ID", - "name": "permissionId", - "in": "path", - "required": true + "description": "Updated mapping", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } }, "delete": { - "description": "역할에서 권한을 제거합니다.", + "description": "Deletes a mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -489,28 +662,22 @@ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "역할에서 권한 제거", + "summary": "Delete permission-action mapping", + "operationId": "deleteMapping", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true }, { "type": "integer", - "description": "역할 ID", - "name": "roleId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "권한 ID", - "name": "permissionId", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true } @@ -522,9 +689,9 @@ } } }, - "/auth/login": { - "post": { - "description": "사용자 ID와 비밀번호로 로그인하여 JWT 토큰을 발급받습니다.", + "/api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions": { + "get": { + "description": "Returns all platform actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -532,69 +699,34 @@ "application/json" ], "tags": [ - "auth" + "mcmp-api-permission-action-mappings" ], - "summary": "로그인", + "summary": "Get platform actions by permission ID", + "operationId": "getPlatformActionsByPermissionID", "parameters": [ { - "description": "로그인 정보 (Id, Password)", - "name": "login", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/idp.UserLogin" - } + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "로그인 성공 및 토큰 정보 (gocloak.JWT 구조체와 유사)", - "schema": { - "type": "object", - "additionalProperties": true - } - }, - "400": { - "description": "error: 잘못된 요청 형식", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "401": { - "description": "error: 인증 실패 (자격 증명 오류)", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: 계정이 비활성화되었거나 승인 대기 중입니다", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "error: 서버 내부 오류 (Keycloak 통신, DB 동기화 등)", + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/mcmp-apis": { - "get": { + "/api/mcmp-apis/list": { + "post": { "security": [ { "BearerAuth": [] @@ -611,6 +743,7 @@ "McmpAPI" ], "summary": "Get All Stored MCMP API Definitions", + "operationId": "listServicesAndActions", "parameters": [ { "type": "string", @@ -644,7 +777,7 @@ } } }, - "/mcmp-apis/call": { + "/api/mcmp-apis/mcmpApiCall": { "post": { "security": [ { @@ -662,6 +795,7 @@ "McmpAPI" ], "summary": "Call an external MCMP API action (Structured Request)", + "operationId": "mcmpApiCall", "parameters": [ { "description": "API Call Request", @@ -669,7 +803,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiCallRequest" + "$ref": "#/definitions/model.McmpApiCallRequest" } } ], @@ -719,109 +853,7 @@ } } }, - "/mcmp-apis/sync": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "McmpAPI // Updated tag" - ], - "summary": "Sync MCMP API Definitions", - "responses": { - "200": { - "description": "message: Successfully triggered MCMP API sync\" // Updated message", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "message: Failed to trigger MCMP API sync\" // Updated message", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/mcmp-apis/test/mc-infra-manager/getallns": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", - "produces": [ - "application/json" - ], - "tags": [ - "McmpAPI", - "Test" - ], - "summary": "Test Call to mc-infra-manager GetAllNs", - "responses": { - "200": { - "description": "Response from mc-infra-manager GetAllNs", - "schema": { - "type": "object" - } - }, - "400": { - "description": "error: Bad Request (e.g., invalid parameters)", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "error: Service or Action Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "error: Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "503": { - "description": "error: External API Service Unavailable", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/mcmp-apis/{serviceName}": { + "/api/mcmp-apis/name/{serviceName}": { "put": { "security": [ { @@ -839,6 +871,7 @@ "McmpAPI" ], "summary": "Update MCMP API Service Definition", + "operationId": "UpdateFrameworkService", "parameters": [ { "type": "string", @@ -897,7 +930,7 @@ } } }, - "/mcmp-apis/{serviceName}/versions/{version}/activate": { + "/api/mcmp-apis/name/{serviceName}/versions/{version}/activate": { "put": { "security": [ { @@ -915,6 +948,7 @@ "McmpAPI" ], "summary": "Set Active Version for a Service", + "operationId": "setActiveVersion", "parameters": [ { "type": "string", @@ -965,14 +999,14 @@ } } }, - "/menus": { - "get": { + "/api/mcmp-apis/syncMcmpAPIs": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "현재 로그인한 사용자의 Platform Role에 따라 접근 가능한 메뉴 목록을 트리 구조로 조회합니다.", + "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", "consumes": [ "application/json" ], @@ -980,21 +1014,13 @@ "application/json" ], "tags": [ - "menus" + "McmpAPI" ], - "summary": "현재 사용자의 메뉴 트리 조회", + "summary": "Sync MCMP API Definitions", + "operationId": "syncMcmpAPIs", "responses": { "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" - } - } - }, - "401": { - "description": "error: Unauthorized", + "description": "message: Successfully triggered MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -1003,7 +1029,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "message: Failed to trigger MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -1012,75 +1038,34 @@ } } } - }, - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "새로운 메뉴를 생성합니다", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "새 메뉴 생성", - "parameters": [ - { - "description": "Menu Info", - "name": "menu", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Menu" - } - } - ], - "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/model.Menu" - } - } - } } }, - "/menus/all": { + "/api/mcmp-apis/test/mc-infra-manager/getallns": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "모든 메뉴 목록을 트리 구조로 조회합니다. 관리자 권한이 필요합니다.", - "consumes": [ - "application/json" - ], + "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", "produces": [ "application/json" ], "tags": [ - "menus" + "McmpAPI", + "Test" ], - "summary": "모든 메뉴 트리 조회 (관리자용)", + "summary": "Test Call to mc-infra-manager GetAllNs", + "operationId": "testCallGetAllNs", "responses": { "200": { - "description": "OK", + "description": "Response from mc-infra-manager GetAllNs", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" - } + "type": "object" } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "error: Bad Request (e.g., invalid parameters)", "schema": { "type": "object", "additionalProperties": { @@ -1088,8 +1073,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "error: Service or Action Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1098,59 +1083,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/menus/register-from-body": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "요청 본문에 포함된 YAML 텍스트를 파싱하여 메뉴를 데이터베이스에 등록하거나 업데이트합니다. Content-Type은 text/plain, text/yaml, application/yaml 등을 권장합니다.", - "consumes": [ - "text/plain" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "요청 본문의 YAML 내용으로 메뉴 등록/업데이트", - "parameters": [ - { - "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", - "description": "Menu definitions in YAML format (must contain 'menus:' root key)", - "name": "yaml", - "in": "body", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "message: Successfully registered menus from request body", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", + "description": "error: Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1158,8 +1091,8 @@ } } }, - "500": { - "description": "error: 서버 내부 오류", + "503": { + "description": "error: External API Service Unavailable", "schema": { "type": "object", "additionalProperties": { @@ -1170,14 +1103,14 @@ } } }, - "/menus/register-from-yaml": { + "/api/menus": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "filePath 쿼리 파라미터로 지정된 로컬 YAML 파일 또는 파라미터가 없을 경우 .env 파일의 MCWEBCONSOLE_MENUYAML URL에서 메뉴를 가져와 데이터베이스에 등록/업데이트합니다. URL에서 가져올 경우 asset/menu/menu.yaml에 저장됩니다.", + "description": "Create a new menu", "consumes": [ "application/json" ], @@ -1187,45 +1120,37 @@ "tags": [ "menus" ], - "summary": "YAML 파일 또는 URL에서 메뉴 등록/업데이트", + "summary": "Create new menu", + "operationId": "createMenu", "parameters": [ { - "type": "string", - "description": "YAML 파일 경로 (선택 사항, 없으면 .env의 URL 또는 기본 로컬 경로 사용)", - "name": "filePath", - "in": "query" + "description": "Menu Info", + "name": "menu", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Menu" + } } ], "responses": { - "200": { - "description": "message: Successfully registered menus from YAML", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "error: 실패 메시지", + "201": { + "description": "Created", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } } }, - "/menus/{id}": { - "get": { + "/api/menus/id/{menuId}": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "특정 메뉴를 ID로 조회합니다", + "description": "Update menu information", "consumes": [ "application/json" ], @@ -1235,7 +1160,8 @@ "tags": [ "menus" ], - "summary": "메뉴 ID로 조회", + "summary": "Update menu information", + "operationId": "updateMenu", "parameters": [ { "type": "string", @@ -1243,6 +1169,15 @@ "name": "id", "in": "path", "required": true + }, + { + "description": "Menu Info", + "name": "menu", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Menu" + } } ], "responses": { @@ -1254,13 +1189,13 @@ } } }, - "put": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "메뉴 정보를 업데이트합니다", + "description": "Get menu details by ID", "consumes": [ "application/json" ], @@ -1270,23 +1205,15 @@ "tags": [ "menus" ], - "summary": "메뉴 정보 업데이트", + "summary": "Get menu by ID", + "operationId": "getMenuByID", "parameters": [ { "type": "string", "description": "Menu ID", - "name": "id", + "name": "menuId", "in": "path", "required": true - }, - { - "description": "Menu Info", - "name": "menu", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Menu" - } } ], "responses": { @@ -1304,7 +1231,7 @@ "BearerAuth": [] } ], - "description": "메뉴를 삭제합니다", + "description": "Delete a menu", "consumes": [ "application/json" ], @@ -1314,7 +1241,8 @@ "tags": [ "menus" ], - "summary": "메뉴 삭제", + "summary": "Delete menu", + "operationId": "deleteMenu", "parameters": [ { "type": "string", @@ -1331,14 +1259,14 @@ } } }, - "/projects": { - "get": { + "/api/menus/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "모든 프로젝트 목록을 조회합니다 (연결된 워크스페이스 정보 포함).", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -1346,16 +1274,35 @@ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "모든 프로젝트 조회", + "summary": "List all menus", + "operationId": "listMenus", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.MenuTreeNode" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -1369,14 +1316,16 @@ } } } - }, + } + }, + "/api/menus/platform-roles": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "새로운 프로젝트를 생성합니다.", + "description": "Create a new menu mapping", "consumes": [ "application/json" ], @@ -1384,17 +1333,18 @@ "application/json" ], "tags": [ - "projects" + "menu" ], - "summary": "프로젝트 생성", + "summary": "Create menu mapping", + "operationId": "createMenusRolesMapping", "parameters": [ { - "description": "프로젝트 정보 (ID, CreatedAt, UpdatedAt, Workspaces 제외)", - "name": "project", + "description": "Menu Mapping", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.CreateMenuMappingRequest" } } ], @@ -1402,11 +1352,14 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/model.Project" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "error: 잘못된 요청 형식", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1415,7 +1368,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1424,16 +1377,14 @@ } } } - } - }, - "/projects/name/{name}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "이름으로 특정 프로젝트를 조회합니다 (연결된 워크스페이스 정보 포함).", + "description": "Delete the mapping between a platform role and a menu.", "consumes": [ "application/json" ], @@ -1441,27 +1392,36 @@ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "이름으로 프로젝트 조회", + "summary": "Delete platform role-menu mapping", + "operationId": "deleteMenusRolesMapping", "parameters": [ { "type": "string", - "description": "프로젝트 이름", - "name": "name", - "in": "path", - "required": true + "description": "Platform Role ID", + "name": "roleId", + "in": "query" + }, + { + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "message: Menu mapping deleted successfully", "schema": { - "$ref": "#/definitions/model.Project" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "400": { + "description": "error: platform role and menu ID are required", "schema": { "type": "object", "additionalProperties": { @@ -1481,14 +1441,14 @@ } } }, - "/projects/{id}": { - "get": { + "/api/menus/platform-roles/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "ID로 특정 프로젝트를 조회합니다 (연결된 워크스페이스 정보 포함).", + "description": "List menus mapped to a specific platform role.", "consumes": [ "application/json" ], @@ -1496,36 +1456,36 @@ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "ID로 프로젝트 조회", + "summary": "List menus mapped to platform role", + "operationId": "listMappedMenusByRole", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Project" - } + "type": "string", + "description": "Platform Role ID", + "name": "roleId", + "in": "query" }, - "400": { - "description": "error: 잘못된 프로젝트 ID", + { + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" } } }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "400": { + "description": "error: platform role is required", "schema": { "type": "object", "additionalProperties": { @@ -1543,14 +1503,16 @@ } } } - }, - "put": { + } + }, + "/api/menus/setup/initial-menus": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "기존 프로젝트 정보를 부분적으로 수정합니다.", + "description": "Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml.", "consumes": [ "application/json" ], @@ -1558,45 +1520,21 @@ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "프로젝트 수정", + "summary": "Register/Update menus from YAML file or URL", + "operationId": "registerMenusFromYAML", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "수정할 필드와 값 (예: {\\", - "name": "updates", - "in": "body", - "required": true, - "schema": { - "type": "object" - } + "type": "string", + "description": "YAML file path (optional, uses .env URL or default local path if not provided)", + "name": "filePath", + "in": "query" } ], "responses": { "200": { - "description": "업데이트된 프로젝트 정보", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "400": { - "description": "error: 잘못된 요청 형식 또는 ID", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "description": "message: Successfully registered menus from YAML", "schema": { "type": "object", "additionalProperties": { @@ -1605,7 +1543,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "error: 실패 메시지", "schema": { "type": "object", "additionalProperties": { @@ -1614,39 +1552,42 @@ } } } - }, - "delete": { + } + }, + "/api/menus/setup/initial-menus2": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "프로젝트를 삭제합니다. 연결된 워크스페이스와의 관계도 해제됩니다.", + "description": "Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.", "consumes": [ - "application/json" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "projects" + "menus" ], - "summary": "프로젝트 삭제", + "summary": "Register/Update menus from YAML in request body", + "operationId": "registerMenusFromBody", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true + "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", + "description": "Menu definitions in YAML format (must contain 'menus:' root key)", + "name": "yaml", + "in": "body", + "required": true, + "schema": { + "type": "string" + } } ], "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 프로젝트 ID", + "200": { + "description": "message: Successfully registered menus from request body", "schema": { "type": "object", "additionalProperties": { @@ -1654,8 +1595,8 @@ } } }, - "404": { - "description": "error: 프로젝트를 찾을 수 없습니다", + "400": { + "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", "schema": { "type": "object", "additionalProperties": { @@ -1675,14 +1616,14 @@ } } }, - "/projects/{id}/workspaces/{workspaceId}": { + "/api/menus/tree/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 프로젝트에 워크스페이스를 연결합니다.", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -1690,31 +1631,22 @@ "application/json" ], "tags": [ - "projects" - ], - "summary": "프로젝트에 워크스페이스 연결", - "parameters": [ - { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true - } + "menus" ], + "summary": "List all menus Tree", + "operationId": "listMenusTree", "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } + } }, - "400": { - "description": "error: 잘못된 ID 형식", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -1722,8 +1654,8 @@ } } }, - "404": { - "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -1741,14 +1673,16 @@ } } } - }, - "delete": { + } + }, + "/api/menus/user-menu-tree": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "특정 프로젝트에서 워크스페이스 연결을 해제합니다.", + "description": "Get menu tree based on user's platform roles", "consumes": [ "application/json" ], @@ -1756,40 +1690,22 @@ "application/json" ], "tags": [ - "projects" - ], - "summary": "프로젝트에서 워크스페이스 연결 해제", - "parameters": [ - { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true - } + "menus" ], + "summary": "Get user menu tree by platform roles", + "operationId": "getUserMenuTree", "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 ID 형식", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" } } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1800,70 +1716,101 @@ } } }, - "/readyz": { - "get": { - "description": "애플리케이션의 준비 상태를 확인합니다. status=detail 쿼리 파라미터로 상세 상태를 확인할 수 있습니다.", + "/api/permissions/mciam": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new permission with the specified information.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Health" + "permissions" ], - "summary": "애플리케이션 준비 상태 확인", + "summary": "Create new permission", + "operationId": "createMciamPermission", "parameters": [ { - "type": "string", - "description": "상세 상태 확인 여부 ('detail')", - "name": "status", - "in": "query" + "description": "Permission Info", + "name": "permission", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.MciamPermission" + } } ], "responses": { - "200": { - "description": "상세 상태 정보 (status=detail)", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/service.HealthStatus" + "$ref": "#/definitions/model.MciamPermission" } }, - "503": { - "description": "상세 상태 확인 중 오류 발생 시", + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/service.HealthStatus" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/user/workspaces": { + "/api/permissions/mciam/id/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "현재 로그인한 사용자가 접근 가능한 워크스페이스 및 각 워크스페이스에서의 역할 목록을 조회합니다.", + "description": "Retrieve permission details by permission ID.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "users", - "workspaces", - "roles", - "me" + "permissions" + ], + "summary": "Get permission by ID", + "operationId": "getMciamPermissionByID", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } ], - "summary": "내 워크스페이스 및 역할 목록 조회", "responses": { "200": { - "description": "성공 시 워크스페이스 및 역할 정보 목록 반환", + "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/service.WorkspaceRoleInfo" - } + "$ref": "#/definitions/model.MciamPermission" } }, - "401": { - "description": "error: Unauthorized", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1872,7 +1819,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1883,51 +1830,37 @@ } } }, - "/users": { - "get": { + "/api/permissions/mciam/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "모든 사용자 목록을 조회합니다. 'admin' 또는 'platformAdmin' 역할이 필요합니다.", + "description": "Retrieve a list of all permissions.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "users" + "permissions" ], - "summary": "사용자 목록 조회 (관리자용)", + "summary": "List all permissions", + "operationId": "listMciamPermissions", "responses": { "200": { - "description": "성공 시 사용자 목록 반환", + "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.User" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: Forbidden (권한 부족)", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/model.MciamPermission" } } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1936,43 +1869,16 @@ } } } - }, - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "responses": {} } }, - "/users/{id}": { + "/api/permissions/mciam/{id}": { "put": { "security": [ { "BearerAuth": [] } ], - "parameters": [ - { - "type": "integer", - "description": "User DB ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": {} - } - }, - "/users/{id}/approve": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "지정된 사용자를 활성화하고 시스템 사용을 승인합니다. 'admin' 또는 'platformadmin' 역할이 필요합니다.", + "description": "Update the details of an existing permission.", "consumes": [ "application/json" ], @@ -1980,33 +1886,37 @@ "application/json" ], "tags": [ - "users" + "permissions" ], - "summary": "사용자 승인 (관리자용)", + "summary": "Update permission", + "operationId": "updateMciamPermission", "parameters": [ { "type": "string", - "description": "사용자 Keycloak ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true + }, + { + "description": "Permission Info", + "name": "permission", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.MciamPermission" + } } ], "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 사용자 ID", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.MciamPermission" } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2014,8 +1924,8 @@ } } }, - "403": { - "description": "error: Forbidden (권한 부족)", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2024,7 +1934,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2033,16 +1943,14 @@ } } } - } - }, - "/workspaces": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "모든 워크스페이스 목록을 조회합니다 (연결된 프로젝트 정보 포함).", + "description": "Delete a permission by its ID.", "consumes": [ "application/json" ], @@ -2050,21 +1958,34 @@ "application/json" ], "tags": [ - "workspaces" + "permissions" + ], + "summary": "Delete permission", + "operationId": "deleteMciamPermission", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } ], - "summary": "모든 워크스페이스 조회", "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" + "type": "object", + "additionalProperties": { + "type": "string" } } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2073,14 +1994,16 @@ } } } - }, + } + }, + "/api/projects": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "새로운 워크스페이스를 생성합니다.", + "description": "Create a new project with the specified information.", "consumes": [ "application/json" ], @@ -2088,17 +2011,18 @@ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스 생성", + "summary": "Create new project", + "operationId": "createProject", "parameters": [ { - "description": "워크스페이스 정보 (ID, CreatedAt, UpdatedAt, Projects 제외)", - "name": "workspace", + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } } ], @@ -2106,11 +2030,11 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } }, "400": { - "description": "error: 잘못된 요청 형식", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2119,7 +2043,48 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/projects/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all projects.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "projects" + ], + "summary": "List all projects", + "operationId": "listProjects", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2130,14 +2095,14 @@ } } }, - "/workspaces/name/{name}": { + "/api/projects/name/{projectName}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "이름으로 특정 워크스페이스를 조회합니다 (연결된 프로젝트 정보 포함).", + "description": "Get project details by name", "consumes": [ "application/json" ], @@ -2145,13 +2110,14 @@ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "이름으로 워크스페이스 조회", + "summary": "Get project by name", + "operationId": "getProjectByName", "parameters": [ { "type": "string", - "description": "워크스페이스 이름", + "description": "Project Name", "name": "name", "in": "path", "required": true @@ -2161,11 +2127,11 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2174,7 +2140,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2185,14 +2151,14 @@ } } }, - "/workspaces/{id}": { + "/api/projects/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "ID로 특정 워크스페이스를 조회합니다 (연결된 프로젝트 정보 포함).", + "description": "Retrieve project details by project ID.", "consumes": [ "application/json" ], @@ -2200,14 +2166,15 @@ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "ID로 워크스페이스 조회", + "summary": "Get project by ID", + "operationId": "getProjectByID", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", + "type": "string", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } @@ -2216,20 +2183,11 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "400": { - "description": "error: 잘못된 워크스페이스 ID", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Project" } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2238,7 +2196,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2254,7 +2212,7 @@ "BearerAuth": [] } ], - "description": "기존 워크스페이스 정보를 부분적으로 수정합니다.", + "description": "Update the details of an existing project.", "consumes": [ "application/json" ], @@ -2262,36 +2220,37 @@ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스 수정", + "summary": "Update project", + "operationId": "updateProject", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", + "type": "string", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "수정할 필드와 값 (예: {\\", - "name": "updates", + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "type": "object" + "$ref": "#/definitions/model.Project" } } ], "responses": { "200": { - "description": "업데이트된 워크스페이스 정보", + "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.Project" } }, "400": { - "description": "error: 잘못된 요청 형식 또는 ID", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2300,7 +2259,7 @@ } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2309,7 +2268,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2325,7 +2284,7 @@ "BearerAuth": [] } ], - "description": "워크스페이스를 삭제합니다. 연결된 프로젝트와의 관계도 해제됩니다.", + "description": "Delete a project by its ID.", "consumes": [ "application/json" ], @@ -2333,14 +2292,15 @@ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스 삭제", + "summary": "Delete project", + "operationId": "deleteProject", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", + "type": "string", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } @@ -2349,17 +2309,8 @@ "204": { "description": "No Content" }, - "400": { - "description": "error: 잘못된 워크스페이스 ID", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -2368,7 +2319,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2379,14 +2330,14 @@ } } }, - "/workspaces/{id}/projects": { - "get": { + "/api/projects/{id}/workspaces/{workspaceId}": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스 ID에 연결된 모든 프로젝트 목록을 조회합니다.", + "description": "프로젝트에 워크스페이스를 연결합니다.", "consumes": [ "application/json" ], @@ -2394,30 +2345,32 @@ "application/json" ], "tags": [ - "workspaces" + "projects" ], - "summary": "워크스페이스에 연결된 프로젝트 목록 조회", + "summary": "프로젝트에 워크스페이스 연결", + "operationId": "addWorkspaceToProject", "parameters": [ { "type": "integer", - "description": "워크스페이스 ID", + "description": "프로젝트 ID", "name": "id", "in": "path", "required": true + }, + { + "type": "integer", + "description": "워크스페이스 ID", + "name": "workspaceId", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "성공 시 프로젝트 목록 반환", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Project" - } - } + "204": { + "description": "No Content" }, "400": { - "description": "error: 잘못된 워크스페이스 ID", + "description": "error: 잘못된 ID 형식", "schema": { "type": "object", "additionalProperties": { @@ -2426,7 +2379,7 @@ } }, "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", "schema": { "type": "object", "additionalProperties": { @@ -2446,14 +2399,14 @@ } } }, - "/workspaces/{id}/projects/{projectId}": { + "/api/resource-types/cloud-resources": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스에 프로젝트를 연결합니다.", + "description": "새로운 리소스 타입을 생성합니다", "consumes": [ "application/json" ], @@ -2461,31 +2414,30 @@ "application/json" ], "tags": [ - "workspaces" + "resource-types" ], - "summary": "워크스페이스에 프로젝트 연결", + "summary": "Cloud에서 관리되는 Resource(vm, nlb, k8s 등의 그룹) 새 리소스 타입 생성", + "operationId": "createResourceType", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "프로젝트 ID", - "name": "projectId", - "in": "path", - "required": true + "description": "Resource Type Info", + "name": "resourceType", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.ResourceType" + } } ], "responses": { - "204": { - "description": "No Content" + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } }, "400": { - "description": "error: 잘못된 ID 형식", + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -2493,8 +2445,8 @@ } } }, - "404": { - "description": "error: 워크스페이스 또는 프로젝트를 찾을 수 없습니다", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2502,8 +2454,8 @@ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2512,14 +2464,16 @@ } } } - }, - "delete": { + } + }, + "/api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스에서 프로젝트 연결을 해제합니다.", + "description": "특정 리소스 타입을 ID로 조회합니다", "consumes": [ "application/json" ], @@ -2527,31 +2481,28 @@ "application/json" ], "tags": [ - "workspaces" + "resource-types" ], - "summary": "워크스페이스에서 프로젝트 연결 해제", + "summary": "리소스 타입 ID로 조회", + "operationId": "getCloudResourceTypeByID", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", + "type": "string", + "description": "Resource Type ID", "name": "id", "in": "path", "required": true - }, - { - "type": "integer", - "description": "프로젝트 ID", - "name": "projectId", - "in": "path", - "required": true } ], "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "error: 잘못된 ID 형식", + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } + }, + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2559,8 +2510,17 @@ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -2569,16 +2529,14 @@ } } } - } - }, - "/workspaces/{id}/users": { - "get": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스에 속한 모든 사용자와 각 사용자의 역할을 조회합니다.", + "description": "리소스 타입 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -2586,32 +2544,37 @@ "application/json" ], "tags": [ - "workspaces", - "users", - "roles" + "resource-types" ], - "summary": "워크스페이스 사용자 및 역할 목록 조회", + "summary": "리소스 타입 업데이트", + "operationId": "updateResourceType", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", + "type": "string", + "description": "Resource Type ID", "name": "id", "in": "path", "required": true + }, + { + "description": "Resource Type Info", + "name": "resourceType", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.ResourceType" + } } ], "responses": { "200": { - "description": "성공 시 사용자 및 역할 목록 반환", + "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/service.UserWithRoles" - } + "$ref": "#/definitions/model.ResourceType" } }, "400": { - "description": "error: 잘못된 워크스페이스 ID", + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -2619,8 +2582,8 @@ } } }, - "404": { - "description": "error: 워크스페이스를 찾을 수 없습니다", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2628,8 +2591,17 @@ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -2638,16 +2610,14 @@ } } } - } - }, - "/workspaces/{workspaceId}/users/{userId}/roles/{roleId}": { - "post": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스 내의 사용자에게 특정 워크스페이스 역할을 할당합니다.", + "description": "리소스 타입을 삭제합니다", "consumes": [ "application/json" ], @@ -2655,30 +2625,15 @@ "application/json" ], "tags": [ - "workspaces", - "roles", - "users" + "resource-types" ], - "summary": "워크스페이스 사용자에게 역할 할당", + "summary": "리소스 타입 삭제", + "operationId": "deleteResourceType", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "사용자 DB ID (db_id)", - "name": "userId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 역할 ID", - "name": "roleId", + "type": "string", + "description": "Resource Type ID", + "name": "id", "in": "path", "required": true } @@ -2687,8 +2642,17 @@ "204": { "description": "No Content" }, - "400": { - "description": "error: 잘못된 ID 형식", + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2697,16 +2661,48 @@ } }, "404": { - "description": "error: 사용자, 역할 또는 워크스페이스를 찾을 수 없습니다", + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { "type": "string" } } + } + } + } + }, + "/api/resource-types/cloud-resources/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "모든 리소스 타입 목록을 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "resource-types" + ], + "summary": "리소스 타입 목록 조회", + "operationId": "listCloudResourceTypes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ResourceType" + } + } }, - "409": { - "description": "error: 역할이 해당 워크스페이스에 속하지 않음", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -2714,8 +2710,8 @@ } } }, - "500": { - "description": "error: 서버 내부 오류", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2724,14 +2720,16 @@ } } } - }, - "delete": { + } + }, + "/api/roles": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "특정 워크스페이스 내의 사용자에게서 특정 워크스페이스 역할을 제거합니다.", + "description": "Create a new role", "consumes": [ "application/json" ], @@ -2739,40 +2737,91 @@ "application/json" ], "tags": [ - "workspaces", - "roles", - "users" + "roles" ], - "summary": "워크스페이스 사용자 역할 제거", + "summary": "Create role", + "operationId": "createRole", "parameters": [ { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } }, - { - "type": "integer", - "description": "사용자 DB ID (db_id)", - "name": "userId", - "in": "path", - "required": true + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/assign/platform-role": { + "post": { + "security": [ { - "type": "integer", - "description": "워크스페이스 역할 ID", - "name": "roleId", - "in": "path", - "required": true + "BearerAuth": [] + } + ], + "description": "Assign a platform role to a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Assign platform role", + "operationId": "assignPlatformRole", + "parameters": [ + { + "description": "Platform Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } }, "400": { - "description": "error: 잘못된 ID 형식", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2780,8 +2829,51 @@ } } }, - "404": { - "description": "error: 역할 또는 워크스페이스를 찾을 수 없습니다\" // User existence check is optional here", + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/assign/workspace-role": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Assign a workspace role to a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Assign workspace role", + "operationId": "assignWorkspaceRole", + "parameters": [ + { + "description": "Workspace Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignWorkspaceRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -2789,8 +2881,8 @@ } } }, - "409": { - "description": "error: 역할이 해당 워크스페이스에 속하지 않음", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -2799,7 +2891,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2809,176 +2901,4718 @@ } } } - } - }, - "definitions": { - "idp.UserLogin": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "password": { - "type": "string" + }, + "/api/roles/csp": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new csp role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create csp role", + "operationId": "createCspRole", + "parameters": [ + { + "description": "CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new mapping between role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create role-CSP role mapping", + "operationId": "addCspRoleMappings", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/batch": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create multiple new csp roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create multiple csp roles", + "operationId": "createCspRoles", + "parameters": [ + { + "description": "Multiple CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspRolesRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CspRole" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/id/:roleId": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a mapping between role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role-CSP role mapping", + "operationId": "getCspRoleMappingByRoleId", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/id/{roleId}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update role information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Update csp role", + "operationId": "updateCspRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete csp role", + "operationId": "deleteCspRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a mapping between role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role-CSP role mapping", + "operationId": "listCspRoleMappings", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get csp role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get csp role by ID", + "operationId": "getCspRoleByID", + "parameters": [ + { + "type": "string", + "description": "CSP Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a list of all csp roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List csp roles", + "operationId": "listCSPRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/csp/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get csp role details by Name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get csp role by Name", + "operationId": "getCspRoleByName", + "parameters": [ + { + "type": "string", + "description": "CSP Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role by ID", + "operationId": "getRoleByRoleID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Update role", + "operationId": "updateRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a role by its name.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete role", + "operationId": "deleteRole", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/id/{roleId}/assign": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Assign a role to a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Assign role", + "operationId": "assignRole", + "parameters": [ + { + "description": "Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/id/{roleId}/unassign": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a role from a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Remove role", + "operationId": "removeRole", + "parameters": [ + { + "description": "Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all roles.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List all roles", + "operationId": "listRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/csp-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by csp role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List users by csp role", + "operationId": "listUsersByCspRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List role master mappings", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List role master mappings", + "operationId": "listRoleMasterMappings", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/platform-roles/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by platform role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List users by platform role", + "operationId": "listUsersByPlatformRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/role/id/:roleId": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get role master mappings", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role master mappings", + "operationId": "getRoleMasterMappings", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/mappings/workspace-roles/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by workspace role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List users by workspace role", + "operationId": "listUsersByWorkspaceRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/menu-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a list of all menu roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List menu roles", + "operationId": "listPlatformRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve role details by role name.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get role by Name", + "operationId": "getRoleByRoleName", + "parameters": [ + { + "type": "string", + "description": "Role name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/platform-roles": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new menu role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create menu role", + "operationId": "createPlatformRole", + "parameters": [ + { + "description": "Menu Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/platform-roles/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get platform role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get platform role by ID", + "operationId": "getPlatformRoleByID", + "parameters": [ + { + "type": "string", + "description": "Platform Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a platform role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete platform role", + "operationId": "deletePlatformRole", + "parameters": [ + { + "type": "string", + "description": "Platform Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/platform-roles/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get menu role details by Name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get menu role by Name", + "operationId": "getPlatformRoleByName", + "parameters": [ + { + "type": "string", + "description": "Menu Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/unassign/csp-roles": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a mapping between workspace role and CSP role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete workspace role-CSP role mapping", + "operationId": "removeCspRoleMappings", + "parameters": [ + { + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/unassign/platform-role": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a platform role from a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Remove platform role", + "operationId": "removePlatformRole", + "parameters": [ + { + "description": "Platform Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/unassign/workspace-role": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a workspace role from a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Remove workspace role", + "operationId": "removeWorkspaceRole", + "parameters": [ + { + "description": "Workspace Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Create workspace role", + "operationId": "createWorkspaceRole", + "parameters": [ + { + "description": "Workspace Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles/id/{roleId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspace role details by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get workspace role by ID", + "operationId": "getWorkspaceRoleByID", + "parameters": [ + { + "type": "string", + "description": "Workspace Role ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a workspace role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Delete workspace role", + "operationId": "deleteWorkspaceRole", + "parameters": [ + { + "type": "string", + "description": "Workspace Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a list of all workspace roles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List workspace roles", + "operationId": "listWorkspaceRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/workspace-roles/name/{roleName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspace role details by Name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get workspace role by Name", + "operationId": "getWorkspaceRoleByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions": { + "get": { + "description": "특정 역할의 MC-IAM 권한 ID 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할의 MC-IAM 권한 목록 조회 - Renamed", + "operationId": "getRoleMciamPermissions", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "권한 ID 목록", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId}": { + "post": { + "description": "역할에 MC-IAM 권한을 할당합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에 MC-IAM 권한 할당 - Renamed", + "operationId": "assignMciamPermissionToRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + }, + "delete": { + "description": "역할에서 MC-IAM 권한을 제거합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에서 MC-IAM 권한 제거 - Renamed", + "operationId": "removeMciamPermissionFromRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/api/setup/check-user-roles": { + "get": { + "description": "Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Check user roles", + "operationId": "checkUserRoles", + "parameters": [ + { + "type": "string", + "description": "Username to check roles", + "name": "username", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/initial-role-menu-permission": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSV 파일을 읽어서 메뉴 권한을 초기화합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Initialize menu permissions from CSV", + "operationId": "initializeMenuPermissions", + "parameters": [ + { + "type": "string", + "description": "CSV file path (optional, uses default if not provided)", + "name": "filePath", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/sync-projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "projects" + ], + "summary": "mc-infra-manager와 프로젝트 동기화", + "operationId": "syncProjects", + "responses": { + "200": { + "description": "message: Project synchronization successful", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류 또는 동기화 실패", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new user with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Create new user", + "operationId": "createUser", + "parameters": [ + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve user details by user ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by ID", + "operationId": "getUserByID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/status": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update user status (active/inactive)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user status", + "operationId": "updateUserStatus", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Status", + "name": "status", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UserStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user and workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID and workspace ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspaces by user ID", + "operationId": "getUserWorkspacesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/kc/{kcUserId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by KcID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by KcID", + "operationId": "getUserByKcID", + "parameters": [ + { + "type": "string", + "description": "User KcID", + "name": "kcUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all users.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List all users", + "operationId": "listUsers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.User" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus-tree/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get the menu tree accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu tree", + "operationId": "listUserMenuTree", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus/list": { + "post": { + "description": "Get the menu list accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu list", + "operationId": "listUserMenu", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" + } + } + } + } + } + }, + "/api/users/name/{username}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by username", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by username", + "operationId": "getUserByUsername", + "parameters": [ + { + "type": "string", + "description": "Username", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List projects for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user projects by workspace", + "operationId": "listUserProjectsByWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspaces", + "operationId": "listUserWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces and roles for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspace and roles", + "operationId": "listUserWorkspaceAndWorkspaceRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing user.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user", + "operationId": "updateUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a user by their ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Delete user", + "operationId": "deleteUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Create new workspace", + "operationId": "createWorkspace", + "parameters": [ + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/assign/projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Add a project to a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Add project to workspace", + "operationId": "addProjectToWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "error: Invalid request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace or Project not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve workspace details by workspace ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by ID", + "operationId": "getWorkspaceByID", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing workspace.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Update workspace", + "operationId": "updateWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a workspace by its ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Delete workspace", + "operationId": "deleteWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "getWorkspaceProjectsByWorkspaceId", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get roles assigned to a user in a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get user workspace roles", + "operationId": "getUserWorkspaceRoles", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/list": { + "post": { + "description": "Retrieve users and roles list belonging to workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List users and roles by workspace", + "operationId": "listUsersAndRolesByWorkspace", + "parameters": [ + { + "type": "integer", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "400": { + "description": "error: Invalid workspace ID", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Internal server error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all workspaces.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List all workspaces", + "operationId": "listWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/name/{workspaceName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve specific workspace by name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by name", + "operationId": "getWorkspaceByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Name", + "name": "workspaceName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/projects/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "listWorkspaceProjects", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/temporary-credentials": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get temporary credentials for CSP", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "Get temporary credentials", + "operationId": "mciamGetTemporaryCredentials", + "responses": {} + } + }, + "/api/workspaces/unassign/projects": { + "delete": { + "description": "Remove a project from a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Remove project from workspace", + "operationId": "removeProjectFromWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, + "/api/workspaces/users-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve the list of users and roles assigned to the workspace.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List users and roles in workspace", + "operationId": "listAllWorkspaceUsersAndRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.WorkspaceWithUsersAndRoles" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Internal server error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List users by workspace criteria", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace users", + "operationId": "listWorkspaceUsers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.WorkspaceWithUsersAndRoles" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/workspace-ticket": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Set workspace ticket", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Set workspace ticket", + "operationId": "mciamWorkspaceTicket", + "responses": { + "200": { + "description": "message: Workspace ticket set successfully", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/{id}/users": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Add a user to a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Add user to workspace", + "operationId": "addUserToWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/{id}/users/{userId}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Remove a user from a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Remove user from workspace", + "operationId": "removeUserFromWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/readyz": { + "get": { + "description": "Check the health status of the service.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "health" + ], + "summary": "Health check", + "operationId": "mciamCheckHealth", + "parameters": [ + { + "type": "string", + "description": "Detail check components (nginx,db,keycloak,all)", + "name": "detail", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + } + }, + "definitions": { + "constants.AuthMethod": { + "type": "string", + "enum": [ + "OIDC", + "SAML" + ], + "x-enum-varnames": [ + "AuthMethodOIDC", + "AuthMethodSAML" + ] + }, + "constants.CSPType": { + "type": "string", + "enum": [ + "aws", + "gcp", + "azure" + ], + "x-enum-varnames": [ + "CSPTypeAWS", + "CSPTypeGCP", + "CSPTypeAzure" + ] + }, + "constants.IAMRoleType": { + "type": "string", + "enum": [ + "platform", + "workspace", + "csp" + ], + "x-enum-comments": { + "RoleTypeCSP": "CSP 역할", + "RoleTypePlatform": "플랫폼 역할", + "RoleTypeWorkspace": "워크스페이스 역할" + }, + "x-enum-descriptions": [ + "플랫폼 역할", + "워크스페이스 역할", + "CSP 역할" + ], + "x-enum-varnames": [ + "RoleTypePlatform", + "RoleTypeWorkspace", + "RoleTypeCSP" + ] + }, + "idp.UserLogin": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAction": { + "type": "object", + "properties": { + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "description": "Auto-incrementing primary key", + "type": "integer" + }, + "method": { + "type": "string" + }, + "resourcePath": { + "type": "string" + }, + "serviceName": { + "description": "Foreign key reference (indexed)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAuthInfo": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "type": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiDefinitions": { + "type": "object", + "properties": { + "serviceActions": { + "description": "Use renamed ServiceAction", + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" + } + } + }, + "services": { + "description": "Use renamed ServiceDefinition", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + } + } + } + }, + "mcmpapi.McmpApiPermissionActionMapping": { + "type": "object", + "properties": { + "actionID": { + "type": "integer" + }, + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "permissionID": { + "type": "string" + }, + "updatedAt": { + "type": "string" } } }, - "mcmpapi.ApiQueryParam": { + "mcmpapi.McmpApiServiceAction": { "type": "object", - "required": [ - "key", - "value" - ], "properties": { - "key": { + "description": { "type": "string" }, - "value": { + "method": { + "type": "string" + }, + "resourcePath": { "type": "string" } } }, - "mcmpapi.McmpApiAuthInfo": { + "mcmpapi.McmpApiServiceDefinition": { "type": "object", "properties": { - "password": { + "auth": { + "description": "Use renamed AuthInfo", + "allOf": [ + { + "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + } + ] + }, + "baseURL": { "type": "string" }, - "type": { + "version": { + "type": "string" + } + } + }, + "model.AssignRoleRequest": { + "type": "object", + "properties": { + "roleId": { + "description": "역할 ID (문자열로 받음)", + "type": "string" + }, + "roleName": { + "description": "역할명", + "type": "string" + }, + "roleType": { + "description": "역할 타입 (platform/workspace)", + "type": "string" + }, + "userId": { + "description": "사용자 ID (문자열로 받음)", "type": "string" }, "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", "type": "string" } } }, - "mcmpapi.McmpApiCallRequest": { + "model.AssignWorkspaceRoleRequest": { "type": "object", - "required": [ - "actionName", - "serviceName" - ], "properties": { - "actionName": { - "description": "Target action name (operationId)", + "roleId": { + "description": "역할 ID (문자열로 받음)", "type": "string" }, - "requestParams": { - "description": "Parameters for the external API call", - "allOf": [ - { - "$ref": "#/definitions/mcmpapi.McmpApiRequestParams" - } - ] + "roleName": { + "description": "역할명", + "type": "string" }, - "serviceName": { - "description": "Target service name", + "userId": { + "description": "사용자 ID (문자열로 받음)", + "type": "string" + }, + "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", "type": "string" } } }, - "mcmpapi.McmpApiDefinitions": { + "model.CreateCspRoleRequest": { "type": "object", "properties": { - "serviceActions": { - "description": "Use renamed ServiceAction", - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" - } - } + "cspRoleName": { + "description": "csp의 RoleName. 여러 role이 있기때문에 csp에 정의한 role로 구분하기 위해 사용", + "type": "string" }, - "services": { - "description": "Use renamed ServiceDefinition", - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + "cspType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "iamIdentifier": { + "type": "string" + }, + "iamRoleId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idpIdentifier": { + "type": "string" + }, + "path": { + "type": "string" + }, + "status": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Tag" + } + } + } + }, + "model.CreateCspRolesRequest": { + "type": "object", + "required": [ + "cspRoles" + ], + "properties": { + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" } } } }, - "mcmpapi.McmpApiRequestParams": { + "model.CreateMenuMappingRequest": { "type": "object", + "required": [ + "menuIds", + "roleId" + ], "properties": { - "body": { - "description": "Request body (accept any JSON structure) - Changed from json.RawMessage for swag compatibility" + "menuIds": { + "type": "array", + "items": { + "type": "string" + } }, - "pathParams": { - "description": "Parameters to replace in the resource path (e.g., {userId})", - "type": "object", - "additionalProperties": { + "roleId": { + "type": "string" + } + } + }, + "model.CreateRoleRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" + } + }, + "description": { + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { "type": "string" } }, - "queryParams": { - "description": "Parameters to append as query string (?key=value)", - "type": "object", - "additionalProperties": { + "name": { + "type": "string" + }, + "parentId": { + "type": "integer" + }, + "roleTypes": { + "description": "RoleTypes []constants.IAMRoleType `json:\"roleTypes\" validate:\"required,dive,oneof=platform workspace csp\"`", + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" + } + } + } + }, + "model.CspRole": { + "type": "object", + "properties": { + "create_date": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "csp_type": { + "type": "string" + }, + "deleted_at": { + "type": "string" + }, + "description": { + "type": "string" + }, + "iam_identifier": { + "type": "string" + }, + "iam_role_id": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "idp_identifier": { + "type": "string" + }, + "max_session_duration": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + }, + "permissions": { + "type": "array", + "items": { "type": "string" } + }, + "permissions_boundary": { + "type": "string" + }, + "role_last_used": { + "$ref": "#/definitions/model.RoleLastUsed" + }, + "status": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Tag" + } + }, + "updated_at": { + "type": "string" + } + } + }, + "model.FilterRoleMasterMappingRequest": { + "type": "object", + "properties": { + "authMethod": { + "type": "string" + }, + "cspRoleId": { + "type": "string" + }, + "cspRoleName": { + "type": "string" + }, + "cspType": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectName": { + "type": "string" + }, + "roleId": { + "type": "string" + }, + "roleTypes": { + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" + } + }, + "userId": { + "type": "string" + }, + "username": { + "type": "string" + }, + "workspaceId": { + "type": "string" + }, + "workspaceName": { + "type": "string" } } }, - "mcmpapi.McmpApiServiceAction": { + "model.MciamPermission": { "type": "object", "properties": { + "action": { + "description": "e.g., create, read, update, delete", + "type": "string" + }, + "createdAt": { + "description": "Match DB schema", + "type": "string" + }, "description": { "type": "string" }, - "method": { + "frameworkId": { + "description": "FK to mcmp_resource_types.framework_id", "type": "string" }, - "resourcePath": { + "id": { + "description": "Format: \u003cframework_id\u003e:\u003cresource_type_id\u003e:\u003caction\u003e", + "type": "string" + }, + "name": { + "type": "string" + }, + "resourceTypeId": { + "description": "FK to mcmp_resource_types.id", + "type": "string" + }, + "updatedAt": { + "description": "Match DB schema", "type": "string" } } }, - "mcmpapi.McmpApiServiceDefinition": { + "model.McmpApiCallRequest": { "type": "object", + "required": [ + "actionName", + "serviceName" + ], "properties": { - "auth": { - "description": "Use renamed AuthInfo", + "actionName": { + "description": "Target action name (operationId)", + "type": "string" + }, + "requestParams": { + "description": "Parameters for the external API call", "allOf": [ { - "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + "$ref": "#/definitions/model.McmpApiRequestParams" } - ] - }, - "baseURL": { - "type": "string" + ] }, - "version": { + "serviceName": { + "description": "Target service name", "type": "string" } } }, - "mcmpapi.ServiceApiCallRequest": { - "type": "object" + "model.McmpApiRequestParams": { + "type": "object", + "properties": { + "body": { + "description": "Request body (accept any JSON structure) - Changed from json.RawMessage for swag compatibility" + }, + "pathParams": { + "description": "Parameters to replace in the resource path (e.g., {userId})", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "queryParams": { + "description": "Parameters to append as query string (?key=value)", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } }, "model.Menu": { "type": "object", "properties": { - "display_name": { + "displayName": { "type": "string" }, "id": { "type": "string" }, - "is_action": { + "isAction": { "type": "boolean" }, - "menu_number": { + "menuNumber": { "type": "integer" }, - "parent_id": { + "parentId": { "type": "string" }, "priority": { "type": "integer" }, - "res_type": { + "resType": { "type": "string" } } @@ -2993,78 +7627,126 @@ "$ref": "#/definitions/model.MenuTreeNode" } }, - "display_name": { + "displayName": { "type": "string" }, "id": { "type": "string" }, - "is_action": { + "isAction": { "type": "boolean" }, - "menu_number": { + "menuNumber": { "type": "integer" }, - "parent_id": { + "parentId": { "type": "string" }, "priority": { "type": "integer" }, - "res_type": { + "resType": { "type": "string" } } }, - "model.Permission": { + "model.Project": { "type": "object", "properties": { "created_at": { "type": "string" }, "description": { - "description": "Increased size to match roles", "type": "string" }, "id": { - "description": "Changed to string", - "type": "string" + "type": "integer" }, "name": { - "description": "Assuming Name column exists or needs to be added", + "type": "string" + }, + "nsid": { + "description": "Namespace ID", "type": "string" }, "updated_at": { "type": "string" + }, + "workspaces": { + "description": "M:N relationship", + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } } } }, - "model.PlatformRole": { + "model.ResourceType": { "type": "object", "properties": { - "created_at": { + "createdAt": { "type": "string" }, "description": { "type": "string" }, + "frameworkId": { + "description": "Identifier of the framework (e.g., \"mc-iam-manager\", \"mc-infra-manager\")", + "type": "string" + }, "id": { - "type": "integer" + "description": "Unique identifier within the framework (e.g., \"workspace\", \"vm\")", + "type": "string" }, "name": { + "description": "Display name (e.g., \"Workspace\", \"Virtual Machine\")", "type": "string" }, - "updated_at": { + "updatedAt": { "type": "string" } } }, - "model.Project": { + "model.Response": { + "type": "object", + "properties": { + "error": { + "type": "boolean" + }, + "message": { + "type": "string" + } + } + }, + "model.RoleLastUsed": { + "type": "object", + "properties": { + "last_used_date": { + "type": "string" + }, + "region": { + "type": "string" + } + } + }, + "model.RoleMaster": { "type": "object", "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + }, "created_at": { "type": "string" }, + "csp_role_mappings": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterCspRoleMapping" + } + }, "description": { "type": "string" }, @@ -3074,19 +7756,141 @@ "name": { "type": "string" }, - "nsid": { - "description": "Namespace ID", - "type": "string" + "parent": { + "$ref": "#/definitions/model.RoleMaster" + }, + "parent_id": { + "type": "integer" + }, + "predefined": { + "type": "boolean" + }, + "role_subs": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleSub" + } }, "updated_at": { "type": "string" + } + } + }, + "model.RoleMasterCspRoleMapping": { + "type": "object", + "properties": { + "auth_method": { + "$ref": "#/definitions/constants.AuthMethod" + }, + "createdAt": { + "type": "string" }, - "workspaces": { - "description": "M:N relationship", + "cspRoles": { + "description": "서비스 레이어에서 조합", "type": "array", "items": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.CspRole" + } + }, + "description": { + "type": "string" + }, + "roleId": { + "type": "integer" + } + } + }, + "model.RoleMasterCspRoleMappingRequest": { + "type": "object", + "properties": { + "authMethod": { + "$ref": "#/definitions/constants.AuthMethod" + }, + "cspRoleId": { + "type": "string" + }, + "cspType": { + "$ref": "#/definitions/constants.CSPType" + }, + "description": { + "type": "string" + }, + "roleId": { + "type": "string" + } + } + }, + "model.RoleMasterMapping": { + "type": "object", + "properties": { + "role_id": { + "type": "integer" + }, + "role_master_csp_role_mappings": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterCspRoleMapping" + } + }, + "role_name": { + "type": "string" + }, + "user_platform_roles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserPlatformRole" } + }, + "user_workspace_roles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + } + }, + "model.RoleSub": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "role_id": { + "type": "integer" + }, + "role_type": { + "$ref": "#/definitions/constants.IAMRoleType" + }, + "updated_at": { + "type": "string" + } + } + }, + "model.SetupInitialAdminRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "model.Tag": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" } } }, @@ -3124,10 +7928,10 @@ "type": "string" }, "platform_roles": { - "description": "관계 정의 (Foreign Key는 DB ID인 'ID' 필드를 참조해야 함)", + "description": "관계 정의", "type": "array", "items": { - "$ref": "#/definitions/model.PlatformRole" + "$ref": "#/definitions/model.RoleMaster" } }, "updated_at": { @@ -3138,116 +7942,132 @@ "type": "string" }, "workspace_roles": { - "description": "Changed foreignKey to ID", "type": "array", "items": { - "$ref": "#/definitions/model.WorkspaceRole" + "$ref": "#/definitions/model.RoleMaster" } } } }, - "model.Workspace": { + "model.UserPlatformRole": { "type": "object", "properties": { "created_at": { "type": "string" }, - "description": { - "type": "string" - }, - "id": { + "role_id": { "type": "integer" }, - "name": { - "type": "string" - }, - "projects": { - "description": "M:N relationship", - "type": "array", - "items": { - "$ref": "#/definitions/model.Project" - } + "user_id": { + "type": "integer" }, - "updated_at": { + "username": { + "description": "사용자 정보 (JOIN으로 가져올 필드들)", "type": "string" } } }, - "model.WorkspaceRole": { + "model.UserStatusRequest": { "type": "object", "properties": { - "created_at": { - "type": "string" - }, - "description": { - "type": "string" - }, "id": { - "type": "integer" + "description": "DB에 저장되는 정보 (mcmp_users 테이블)", + "type": "string" }, - "name": { - "description": "이름은 고유해야 함", + "kc_id": { + "description": "Keycloak User ID", "type": "string" }, - "updated_at": { + "status": { + "description": "사용자 상태", "type": "string" } } }, - "service.HealthStatus": { + "model.UserWorkspaceRole": { "type": "object", "properties": { - "db_connection": { + "created_at": { "type": "string" }, - "keycloak_admin_login": { - "type": "string" + "role": { + "$ref": "#/definitions/model.RoleMaster" }, - "keycloak_client_check": { - "type": "string" + "role_id": { + "type": "integer" }, - "keycloak_realm_check": { + "role_name": { "type": "string" }, - "mcmp_actions_count": { - "type": "integer" + "user": { + "$ref": "#/definitions/model.User" }, - "mcmp_services_count": { + "user_id": { "type": "integer" }, - "menus_count": { - "type": "integer" + "username": { + "type": "string" }, - "platform_roles_count": { - "type": "integer" + "workspace": { + "$ref": "#/definitions/model.Workspace" }, - "workspace_roles_count": { + "workspace_id": { "type": "integer" + }, + "workspace_name": { + "type": "string" } } }, - "service.UserWithRoles": { + "model.Workspace": { "type": "object", "properties": { - "roles": { + "created_at": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "projects": { "type": "array", "items": { - "$ref": "#/definitions/model.WorkspaceRole" + "$ref": "#/definitions/model.Project" } }, - "user": { - "$ref": "#/definitions/model.User" + "updated_at": { + "type": "string" } } }, - "service.WorkspaceRoleInfo": { + "model.WorkspaceWithUsersAndRoles": { "type": "object", "properties": { - "role": { - "$ref": "#/definitions/model.WorkspaceRole" + "created_at": { + "type": "string" }, - "workspace": { - "$ref": "#/definitions/model.Workspace" + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } } } } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index fb1a3d4f..a3019661 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,5 +1,41 @@ basePath: /api/v1 definitions: + constants.AuthMethod: + enum: + - OIDC + - SAML + type: string + x-enum-varnames: + - AuthMethodOIDC + - AuthMethodSAML + constants.CSPType: + enum: + - aws + - gcp + - azure + type: string + x-enum-varnames: + - CSPTypeAWS + - CSPTypeGCP + - CSPTypeAzure + constants.IAMRoleType: + enum: + - platform + - workspace + - csp + type: string + x-enum-comments: + RoleTypeCSP: CSP 역할 + RoleTypePlatform: 플랫폼 역할 + RoleTypeWorkspace: 워크스페이스 역할 + x-enum-descriptions: + - 플랫폼 역할 + - 워크스페이스 역할 + - CSP 역할 + x-enum-varnames: + - RoleTypePlatform + - RoleTypeWorkspace + - RoleTypeCSP idp.UserLogin: properties: id: @@ -7,15 +43,26 @@ definitions: password: type: string type: object - mcmpapi.ApiQueryParam: + mcmpapi.McmpApiAction: properties: - key: + actionName: type: string - value: + createdAt: + type: string + description: + type: string + id: + description: Auto-incrementing primary key + type: integer + method: + type: string + resourcePath: + type: string + serviceName: + description: Foreign key reference (indexed) + type: string + updatedAt: type: string - required: - - key - - value type: object mcmpapi.McmpApiAuthInfo: properties: @@ -26,22 +73,6 @@ definitions: username: type: string type: object - mcmpapi.McmpApiCallRequest: - properties: - actionName: - description: Target action name (operationId) - type: string - requestParams: - allOf: - - $ref: '#/definitions/mcmpapi.McmpApiRequestParams' - description: Parameters for the external API call - serviceName: - description: Target service name - type: string - required: - - actionName - - serviceName - type: object mcmpapi.McmpApiDefinitions: properties: serviceActions: @@ -57,21 +88,20 @@ definitions: description: Use renamed ServiceDefinition type: object type: object - mcmpapi.McmpApiRequestParams: + mcmpapi.McmpApiPermissionActionMapping: properties: - body: - description: Request body (accept any JSON structure) - Changed from json.RawMessage - for swag compatibility - pathParams: - additionalProperties: - type: string - description: Parameters to replace in the resource path (e.g., {userId}) - type: object - queryParams: - additionalProperties: - type: string - description: Parameters to append as query string (?key=value) - type: object + actionID: + type: integer + actionName: + type: string + createdAt: + type: string + id: + type: integer + permissionID: + type: string + updatedAt: + type: string type: object mcmpapi.McmpApiServiceAction: properties: @@ -93,156 +123,286 @@ definitions: version: type: string type: object - mcmpapi.ServiceApiCallRequest: - type: object - model.Menu: + model.AssignRoleRequest: properties: - display_name: + roleId: + description: 역할 ID (문자열로 받음) type: string - id: + roleName: + description: 역할명 type: string - is_action: - type: boolean - menu_number: - type: integer - parent_id: + roleType: + description: 역할 타입 (platform/workspace) type: string - priority: - type: integer - res_type: + userId: + description: 사용자 ID (문자열로 받음) + type: string + username: + description: 사용자명 + type: string + workspaceId: + description: 워크스페이스 ID (문자열로 받음) type: string type: object - model.MenuTreeNode: + model.AssignWorkspaceRoleRequest: properties: - children: - description: Slice of pointers to child nodes - items: - $ref: '#/definitions/model.MenuTreeNode' - type: array - display_name: + roleId: + description: 역할 ID (문자열로 받음) type: string - id: + roleName: + description: 역할명 type: string - is_action: - type: boolean - menu_number: - type: integer - parent_id: + userId: + description: 사용자 ID (문자열로 받음) type: string - priority: - type: integer - res_type: + username: + description: 사용자명 + type: string + workspaceId: + description: 워크스페이스 ID (문자열로 받음) type: string type: object - model.Permission: + model.CreateCspRoleRequest: properties: - created_at: + cspRoleName: + description: csp의 RoleName. 여러 role이 있기때문에 csp에 정의한 role로 구분하기 위해 사용 + type: string + cspType: type: string description: - description: Increased size to match roles + type: string + iamIdentifier: + type: string + iamRoleId: type: string id: - description: Changed to string type: string - name: - description: Assuming Name column exists or needs to be added + idpIdentifier: type: string - updated_at: + path: + type: string + status: type: string + tags: + items: + $ref: '#/definitions/model.Tag' + type: array type: object - model.PlatformRole: + model.CreateCspRolesRequest: properties: - created_at: + cspRoles: + items: + $ref: '#/definitions/model.CreateCspRoleRequest' + type: array + required: + - cspRoles + type: object + model.CreateMenuMappingRequest: + properties: + menuIds: + items: + type: string + type: array + roleId: type: string + required: + - menuIds + - roleId + type: object + model.CreateRoleRequest: + properties: + cspRoles: + items: + $ref: '#/definitions/model.CreateCspRoleRequest' + type: array description: type: string - id: - type: integer + menuIds: + items: + type: string + type: array name: type: string - updated_at: - type: string + parentId: + type: integer + roleTypes: + description: RoleTypes []constants.IAMRoleType `json:"roleTypes" validate:"required,dive,oneof=platform + workspace csp"` + items: + $ref: '#/definitions/constants.IAMRoleType' + type: array + required: + - name type: object - model.Project: + model.CspRole: properties: + create_date: + type: string created_at: type: string + csp_type: + type: string + deleted_at: + type: string description: type: string + iam_identifier: + type: string + iam_role_id: + type: string id: type: integer + idp_identifier: + type: string + max_session_duration: + type: integer name: type: string - nsid: - description: Namespace ID + path: type: string - updated_at: + permissions: + items: + type: string + type: array + permissions_boundary: type: string - workspaces: - description: M:N relationship + role_last_used: + $ref: '#/definitions/model.RoleLastUsed' + status: + type: string + tags: items: - $ref: '#/definitions/model.Workspace' + $ref: '#/definitions/model.Tag' type: array + updated_at: + type: string type: object - model.User: + model.FilterRoleMasterMappingRequest: properties: - created_at: + authMethod: type: string - description: + cspRoleId: type: string - email: - description: Ignore Email for DB + cspRoleName: type: string - enabled: - description: Enabled status managed by Keycloak - type: boolean - firstName: - description: Ignore FirstName for DB + cspType: type: string - id: - description: DB에 저장되는 정보 (mcmp_users 테이블) - type: integer - kc_id: - description: Keycloak User ID + projectId: type: string - lastName: - description: Ignore LastName for DB + projectName: type: string - platform_roles: - description: 관계 정의 (Foreign Key는 DB ID인 'ID' 필드를 참조해야 함) + roleId: + type: string + roleTypes: items: - $ref: '#/definitions/model.PlatformRole' + $ref: '#/definitions/constants.IAMRoleType' type: array - updated_at: + userId: type: string username: - description: Keycloak 정보 type: string - workspace_roles: - description: Changed foreignKey to ID - items: - $ref: '#/definitions/model.WorkspaceRole' - type: array + workspaceId: + type: string + workspaceName: + type: string type: object - model.Workspace: + model.MciamPermission: properties: - created_at: + action: + description: e.g., create, read, update, delete + type: string + createdAt: + description: Match DB schema type: string description: type: string + frameworkId: + description: FK to mcmp_resource_types.framework_id + type: string id: - type: integer + description: 'Format: ::' + type: string name: type: string - projects: - description: M:N relationship + resourceTypeId: + description: FK to mcmp_resource_types.id + type: string + updatedAt: + description: Match DB schema + type: string + type: object + model.McmpApiCallRequest: + properties: + actionName: + description: Target action name (operationId) + type: string + requestParams: + allOf: + - $ref: '#/definitions/model.McmpApiRequestParams' + description: Parameters for the external API call + serviceName: + description: Target service name + type: string + required: + - actionName + - serviceName + type: object + model.McmpApiRequestParams: + properties: + body: + description: Request body (accept any JSON structure) - Changed from json.RawMessage + for swag compatibility + pathParams: + additionalProperties: + type: string + description: Parameters to replace in the resource path (e.g., {userId}) + type: object + queryParams: + additionalProperties: + type: string + description: Parameters to append as query string (?key=value) + type: object + type: object + model.Menu: + properties: + displayName: + type: string + id: + type: string + isAction: + type: boolean + menuNumber: + type: integer + parentId: + type: string + priority: + type: integer + resType: + type: string + type: object + model.MenuTreeNode: + properties: + children: + description: Slice of pointers to child nodes items: - $ref: '#/definitions/model.Project' + $ref: '#/definitions/model.MenuTreeNode' type: array - updated_at: + displayName: + type: string + id: + type: string + isAction: + type: boolean + menuNumber: + type: integer + parentId: + type: string + priority: + type: integer + resType: type: string type: object - model.WorkspaceRole: + model.Project: properties: created_at: type: string @@ -251,109 +411,2832 @@ definitions: id: type: integer name: - description: 이름은 고유해야 함 + type: string + nsid: + description: Namespace ID type: string updated_at: type: string + workspaces: + description: M:N relationship + items: + $ref: '#/definitions/model.Workspace' + type: array type: object - service.HealthStatus: + model.ResourceType: properties: - db_connection: + createdAt: type: string - keycloak_admin_login: + description: type: string - keycloak_client_check: + frameworkId: + description: Identifier of the framework (e.g., "mc-iam-manager", "mc-infra-manager") type: string - keycloak_realm_check: + id: + description: Unique identifier within the framework (e.g., "workspace", "vm") + type: string + name: + description: Display name (e.g., "Workspace", "Virtual Machine") + type: string + updatedAt: type: string - mcmp_actions_count: - type: integer - mcmp_services_count: - type: integer - menus_count: - type: integer - platform_roles_count: - type: integer - workspace_roles_count: - type: integer type: object - service.UserWithRoles: + model.Response: properties: - roles: - items: - $ref: '#/definitions/model.WorkspaceRole' - type: array - user: - $ref: '#/definitions/model.User' + error: + type: boolean + message: + type: string type: object - service.WorkspaceRoleInfo: + model.RoleLastUsed: properties: - role: - $ref: '#/definitions/model.WorkspaceRole' - workspace: - $ref: '#/definitions/model.Workspace' + last_used_date: + type: string + region: + type: string type: object -host: localhost:3000 -info: - contact: {} + model.RoleMaster: + properties: + children: + items: + $ref: '#/definitions/model.RoleMaster' + type: array + created_at: + type: string + csp_role_mappings: + items: + $ref: '#/definitions/model.RoleMasterCspRoleMapping' + type: array + description: + type: string + id: + type: integer + name: + type: string + parent: + $ref: '#/definitions/model.RoleMaster' + parent_id: + type: integer + predefined: + type: boolean + role_subs: + items: + $ref: '#/definitions/model.RoleSub' + type: array + updated_at: + type: string + type: object + model.RoleMasterCspRoleMapping: + properties: + auth_method: + $ref: '#/definitions/constants.AuthMethod' + createdAt: + type: string + cspRoles: + description: 서비스 레이어에서 조합 + items: + $ref: '#/definitions/model.CspRole' + type: array + description: + type: string + roleId: + type: integer + type: object + model.RoleMasterCspRoleMappingRequest: + properties: + authMethod: + $ref: '#/definitions/constants.AuthMethod' + cspRoleId: + type: string + cspType: + $ref: '#/definitions/constants.CSPType' + description: + type: string + roleId: + type: string + type: object + model.RoleMasterMapping: + properties: + role_id: + type: integer + role_master_csp_role_mappings: + items: + $ref: '#/definitions/model.RoleMasterCspRoleMapping' + type: array + role_name: + type: string + user_platform_roles: + items: + $ref: '#/definitions/model.UserPlatformRole' + type: array + user_workspace_roles: + items: + $ref: '#/definitions/model.UserWorkspaceRole' + type: array + type: object + model.RoleSub: + properties: + created_at: + type: string + id: + type: integer + role_id: + type: integer + role_type: + $ref: '#/definitions/constants.IAMRoleType' + updated_at: + type: string + type: object + model.SetupInitialAdminRequest: + properties: + email: + type: string + password: + type: string + username: + type: string + type: object + model.Tag: + properties: + key: + type: string + value: + type: string + type: object + model.User: + properties: + created_at: + type: string + description: + type: string + email: + description: Ignore Email for DB + type: string + enabled: + description: Enabled status managed by Keycloak + type: boolean + firstName: + description: Ignore FirstName for DB + type: string + id: + description: DB에 저장되는 정보 (mcmp_users 테이블) + type: integer + kc_id: + description: Keycloak User ID + type: string + lastName: + description: Ignore LastName for DB + type: string + platform_roles: + description: 관계 정의 + items: + $ref: '#/definitions/model.RoleMaster' + type: array + updated_at: + type: string + username: + description: Keycloak 정보 + type: string + workspace_roles: + items: + $ref: '#/definitions/model.RoleMaster' + type: array + type: object + model.UserPlatformRole: + properties: + created_at: + type: string + role_id: + type: integer + user_id: + type: integer + username: + description: 사용자 정보 (JOIN으로 가져올 필드들) + type: string + type: object + model.UserStatusRequest: + properties: + id: + description: DB에 저장되는 정보 (mcmp_users 테이블) + type: string + kc_id: + description: Keycloak User ID + type: string + status: + description: 사용자 상태 + type: string + type: object + model.UserWorkspaceRole: + properties: + created_at: + type: string + role: + $ref: '#/definitions/model.RoleMaster' + role_id: + type: integer + role_name: + type: string + user: + $ref: '#/definitions/model.User' + user_id: + type: integer + username: + type: string + workspace: + $ref: '#/definitions/model.Workspace' + workspace_id: + type: integer + workspace_name: + type: string + type: object + model.Workspace: + properties: + created_at: + type: string + description: + type: string + id: + type: integer + name: + type: string + projects: + items: + $ref: '#/definitions/model.Project' + type: array + updated_at: + type: string + type: object + model.WorkspaceWithUsersAndRoles: + properties: + created_at: + type: string + description: + type: string + id: + type: integer + name: + type: string + updated_at: + type: string + users: + items: + $ref: '#/definitions/model.UserWorkspaceRole' + type: array + type: object +host: localhost +info: + contact: {} description: MC IAM Manager API Documentation title: MC IAM Manager API version: "1.0" paths: - /api/call: + /api/auth/certs: + get: + consumes: + - application/json + description: Retrieve authentication certificates for MC-IAM-Manager to be used + in target frameworks for token validation. + operationId: mciamAuthCerts + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + summary: Get authentication certificates + tags: + - auth + /api/auth/login: + post: + consumes: + - application/json + description: Authenticate user and issue JWT token. + operationId: mciamLogin + parameters: + - description: Login Credentials + in: body + name: credentials + required: true + schema: + $ref: '#/definitions/idp.UserLogin' + produces: + - application/json + responses: {} + summary: User login + tags: + - auth + /api/auth/logout: + post: + consumes: + - application/json + description: Invalidate the user's refresh token and log out. + operationId: mciamLogout + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + summary: Logout user + tags: + - auth + /api/auth/refresh: + post: + consumes: + - application/json + description: Refresh JWT access token using a valid refresh token. + operationId: mciamRefreshToken + parameters: + - description: Refresh token + in: body + name: refresh_token + required: true + schema: + type: string + produces: + - application/json + responses: + "200": + description: New token information + schema: + additionalProperties: true + type: object + "400": + description: 'error: Bad Request' + schema: + additionalProperties: + type: string + type: object + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + summary: Refresh access token + tags: + - auth + /api/auth/temp-credential-csps: + get: + consumes: + - application/json + description: Get temporary credential provider information for AWS and GCP + operationId: mciamGetTempCredentialProviders + produces: + - application/json + responses: + "200": + description: CSP temporary credential information + schema: + additionalProperties: true + type: object + summary: Get temporary credential CSP information + tags: + - auth + /api/auth/validate: + post: + consumes: + - application/json + description: Validate the current access token and refresh if expired + operationId: mciamValidateToken + parameters: + - description: Refresh token + in: body + name: refresh_token + required: true + schema: + type: string + produces: + - application/json + responses: + "200": + description: Token validation result with new token if refreshed + schema: + additionalProperties: true + type: object + "400": + description: 'error: Bad Request' + schema: + additionalProperties: + type: string + type: object + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Validate access token + tags: + - auth + /api/csp-credentials: + get: + consumes: + - application/json + description: 모든 CSP 인증 정보 목록을 조회합니다 + operationId: mciamListCredentials + produces: + - application/json + responses: {} + security: + - BearerAuth: [] + summary: CSP 인증 정보 목록 조회 + tags: + - csp-credentials + post: + consumes: + - application/json + description: 새로운 CSP 인증 정보를 생성합니다 + operationId: mciamCreateCredential + produces: + - application/json + responses: {} + security: + - BearerAuth: [] + summary: 새 CSP 인증 정보 생성 + tags: + - csp-credentials + /api/csp-credentials/{id}: + delete: + consumes: + - application/json + description: CSP 인증 정보를 삭제합니다 + operationId: mciamDeleteCredential + parameters: + - description: Credential ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Credential not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: CSP 인증 정보 삭제 + tags: + - csp-credentials + get: + consumes: + - application/json + description: 특정 CSP 인증 정보를 ID로 조회합니다 + operationId: mciamGetCredentialByID + parameters: + - description: Credential ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "404": + description: 'error: Credential not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: CSP 인증 정보 ID로 조회 + tags: + - csp-credentials + put: + consumes: + - application/json + description: CSP 인증 정보를 업데이트합니다 + operationId: mciamUpdateCredential + parameters: + - description: Credential ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "404": + description: 'error: Credential not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: CSP 인증 정보 업데이트 + tags: + - csp-credentials + /api/initial-admin: + post: + consumes: + - application/json + description: Creates the initial platform admin user with necessary permissions. + platform admin 생성인데 + operationId: setupInitialAdmin + parameters: + - description: Setup Initial Admin Request + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.SetupInitialAdminRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Response' + summary: Setup initial platform admin + tags: + - admin + /api/mcmp-api-permission-action-mappings: + post: + consumes: + - application/json + description: Creates a new mapping between a permission and an API action + operationId: createMcmpApiPermissionActionMapping + parameters: + - description: Mapping to create + in: body + name: mapping + required: true + schema: + $ref: '#/definitions/mcmpapi.McmpApiPermissionActionMapping' + produces: + - application/json + responses: + "204": + description: No Content + summary: Create permission-action mapping + tags: + - mcmp-api-permission-action-mappings + /api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions: + get: + consumes: + - application/json + description: Returns all permissions mapped to a specific API action + operationId: listPermissionsByActionID + parameters: + - description: Action ID + in: path + name: actionId + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Get permissions by action ID + tags: + - mcmp-api-permission-action-mappings + /api/mcmp-api-permission-action-mappings/actions/list: + post: + consumes: + - application/json + description: Returns all workspace actions mapped to a specific permission + operationId: listWorkspaceActionsByPermissionID + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/mcmpapi.McmpApiAction' + type: array + summary: Get workspace actions by permission ID + tags: + - mcmp-api-permission-action-mappings + /api/mcmp-api-permission-action-mappings/list: + post: + consumes: + - application/json + description: Returns all platform actions mapped to a specific permission + operationId: listPlatformActions + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/mcmpapi.McmpApiAction' + type: array + summary: List platform actions by permission ID + tags: + - mcmp-api-permission-action-mappings + /api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId}: + delete: + consumes: + - application/json + description: Deletes a mapping between a permission and an API action + operationId: deleteMapping + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + - description: Action ID + in: path + name: actionId + required: true + type: integer + produces: + - application/json + responses: + "204": + description: No Content + summary: Delete permission-action mapping + tags: + - mcmp-api-permission-action-mappings + put: + consumes: + - application/json + description: Updates an existing mapping between a permission and an API action + operationId: updateMapping + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + - description: Action ID + in: path + name: actionId + required: true + type: integer + - description: Updated mapping + in: body + name: mapping + required: true + schema: + $ref: '#/definitions/mcmpapi.McmpApiPermissionActionMapping' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + summary: Update permission-action mapping + tags: + - mcmp-api-permission-action-mappings + /api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions: + get: + consumes: + - application/json + description: Returns all platform actions mapped to a specific permission + operationId: getPlatformActionsByPermissionID + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/mcmpapi.McmpApiAction' + type: array + summary: Get platform actions by permission ID + tags: + - mcmp-api-permission-action-mappings + /api/mcmp-apis/list: + post: + consumes: + - application/json + description: Retrieves all MCMP API service and action definitions currently + stored in the database. + operationId: listServicesAndActions + parameters: + - description: Filter by service name + in: query + name: serviceName + type: string + - description: Filter by action name (operationId) + in: query + name: actionName + type: string + produces: + - application/json + responses: + "200": + description: Successfully retrieved API definitions + schema: + $ref: '#/definitions/mcmpapi.McmpApiDefinitions' + "500": + description: 'message: Failed to retrieve API definitions' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get All Stored MCMP API Definitions + tags: + - McmpAPI + /api/mcmp-apis/mcmpApiCall: + post: + consumes: + - application/json + description: Executes a defined MCMP API action with parameters structured in + McmpApiCallRequest. + operationId: mcmpApiCall + parameters: + - description: API Call Request + in: body + name: callRequest + required: true + schema: + $ref: '#/definitions/model.McmpApiCallRequest' + produces: + - application/json + responses: + "200": + description: External API Response (structure depends on the called API) + schema: + type: object + "400": + description: 'error: Invalid request body or parameters' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Service or action not found' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Internal server error or failed to call external API' + schema: + additionalProperties: + type: string + type: object + "503": + description: 'error: External API unavailable' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Call an external MCMP API action (Structured Request) + tags: + - McmpAPI + /api/mcmp-apis/name/{serviceName}: + put: + consumes: + - application/json + description: Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API + service definition identified by its name. Cannot update name or version. + operationId: UpdateFrameworkService + parameters: + - description: Service Name to update + in: path + name: serviceName + required: true + type: string + - description: Fields to update (e.g., {\ + in: body + name: updates + required: true + schema: + type: object + produces: + - application/json + responses: + "200": + description: 'message: Service updated successfully" // Or return updated + service?' + schema: + additionalProperties: + type: string + type: object + "400": + description: 'error: Invalid service name or request body' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Service not found' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Failed to update service' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Update MCMP API Service Definition + tags: + - McmpAPI + /api/mcmp-apis/name/{serviceName}/versions/{version}/activate: + put: + consumes: + - application/json + description: Sets the specified version of an MCMP API service as the active + one. + operationId: setActiveVersion + parameters: + - description: Service Name + in: path + name: serviceName + required: true + type: string + - description: Version to activate + in: path + name: version + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: 'error: Invalid service name or version' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Service or version not found' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Failed to set active version' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Set Active Version for a Service + tags: + - McmpAPI + /api/mcmp-apis/syncMcmpAPIs: + post: + consumes: + - application/json + description: Triggers the synchronization of MCMP API definitions from the configured + YAML URL to the database. + operationId: syncMcmpAPIs + produces: + - application/json + responses: + "200": + description: 'message: Successfully triggered MCMP API sync' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'message: Failed to trigger MCMP API sync' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Sync MCMP API Definitions + tags: + - McmpAPI + /api/mcmp-apis/test/mc-infra-manager/getallns: + get: + description: Calls the GetAllNs action of the mc-infra-manager service via the + CallApi service. + operationId: testCallGetAllNs + produces: + - application/json + responses: + "200": + description: Response from mc-infra-manager GetAllNs + schema: + type: object + "400": + description: 'error: Bad Request (e.g., invalid parameters)' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Service or Action Not Found' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Internal Server Error' + schema: + additionalProperties: + type: string + type: object + "503": + description: 'error: External API Service Unavailable' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Test Call to mc-infra-manager GetAllNs + tags: + - McmpAPI + - Test + /api/menus: + post: + consumes: + - application/json + description: Create a new menu + operationId: createMenu + parameters: + - description: Menu Info + in: body + name: menu + required: true + schema: + $ref: '#/definitions/model.Menu' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.Menu' + security: + - BearerAuth: [] + summary: Create new menu + tags: + - menus + /api/menus/id/{menuId}: + delete: + consumes: + - application/json + description: Delete a menu + operationId: deleteMenu + parameters: + - description: Menu ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + security: + - BearerAuth: [] + summary: Delete menu + tags: + - menus + post: + consumes: + - application/json + description: Get menu details by ID + operationId: getMenuByID + parameters: + - description: Menu ID + in: path + name: menuId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Menu' + security: + - BearerAuth: [] + summary: Get menu by ID + tags: + - menus + put: + consumes: + - application/json + description: Update menu information + operationId: updateMenu + parameters: + - description: Menu ID + in: path + name: id + required: true + type: string + - description: Menu Info + in: body + name: menu + required: true + schema: + $ref: '#/definitions/model.Menu' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Menu' + security: + - BearerAuth: [] + summary: Update menu information + tags: + - menus + /api/menus/list: + post: + consumes: + - application/json + description: List all menus as a tree structure. Admin permission required. + operationId: listMenus + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.MenuTreeNode' + type: array + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: 서버 내부 오류' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List all menus + tags: + - menus + /api/menus/platform-roles: + delete: + consumes: + - application/json + description: Delete the mapping between a platform role and a menu. + operationId: deleteMenusRolesMapping + parameters: + - description: Platform Role ID + in: query + name: roleId + type: string + - description: Menu ID + in: query + name: menuId + type: string + produces: + - application/json + responses: + "200": + description: 'message: Menu mapping deleted successfully' + schema: + additionalProperties: + type: string + type: object + "400": + description: 'error: platform role and menu ID are required' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: 서버 내부 오류' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete platform role-menu mapping + tags: + - menus + post: + consumes: + - application/json + description: Create a new menu mapping + operationId: createMenusRolesMapping + parameters: + - description: Menu Mapping + in: body + name: mapping + required: true + schema: + $ref: '#/definitions/model.CreateMenuMappingRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create menu mapping + tags: + - menu + /api/menus/platform-roles/list: + post: + consumes: + - application/json + description: List menus mapped to a specific platform role. + operationId: listMappedMenusByRole + parameters: + - description: Platform Role ID + in: query + name: roleId + type: string + - description: Menu ID + in: query + name: menuId + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Menu' + type: array + "400": + description: 'error: platform role is required' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: 서버 내부 오류' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List menus mapped to platform role + tags: + - menus + /api/menus/setup/initial-menus: + post: + consumes: + - application/json + description: Register or update menus from a local YAML file specified by the + filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if + not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml. + operationId: registerMenusFromYAML + parameters: + - description: YAML file path (optional, uses .env URL or default local path + if not provided) + in: query + name: filePath + type: string + produces: + - application/json + responses: + "200": + description: 'message: Successfully registered menus from YAML' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: 실패 메시지' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Register/Update menus from YAML file or URL + tags: + - menus + /api/menus/setup/initial-menus2: + post: + consumes: + - text/plain + description: 'Parse YAML text in the request body and register or update menus + in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.' + operationId: registerMenusFromBody + parameters: + - description: Menu definitions in YAML format (must contain 'menus:' root key) + example: '"menus:\n - id: new-item\n parentid: dashboard\n displayname: + New Menu Item\n restype: menu\n isaction: false\n priority: 10\n menunumber: + 9999"' + in: body + name: yaml + required: true + schema: + type: string + produces: + - application/json + responses: + "200": + description: 'message: Successfully registered menus from request body' + schema: + additionalProperties: + type: string + type: object + "400": + description: 'error: 잘못된 요청 본문 또는 YAML 형식 오류' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: 서버 내부 오류' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Register/Update menus from YAML in request body + tags: + - menus + /api/menus/tree/list: + post: + consumes: + - application/json + description: List all menus as a tree structure. Admin permission required. + operationId: listMenusTree + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.MenuTreeNode' + type: array + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: 서버 내부 오류' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List all menus Tree + tags: + - menus + /api/menus/user-menu-tree: + get: + consumes: + - application/json + description: Get menu tree based on user's platform roles + operationId: getUserMenuTree + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.MenuTreeNode' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get user menu tree by platform roles + tags: + - menus + /api/permissions/mciam: + post: + consumes: + - application/json + description: Create a new permission with the specified information. + operationId: createMciamPermission + parameters: + - description: Permission Info + in: body + name: permission + required: true + schema: + $ref: '#/definitions/model.MciamPermission' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.MciamPermission' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create new permission + tags: + - permissions + /api/permissions/mciam/{id}: + delete: + consumes: + - application/json + description: Delete a permission by its ID. + operationId: deleteMciamPermission + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete permission + tags: + - permissions + put: + consumes: + - application/json + description: Update the details of an existing permission. + operationId: updateMciamPermission + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + - description: Permission Info + in: body + name: permission + required: true + schema: + $ref: '#/definitions/model.MciamPermission' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.MciamPermission' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Update permission + tags: + - permissions + /api/permissions/mciam/id/{id}: + get: + consumes: + - application/json + description: Retrieve permission details by permission ID. + operationId: getMciamPermissionByID + parameters: + - description: Permission ID + in: path + name: permissionId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.MciamPermission' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get permission by ID + tags: + - permissions + /api/permissions/mciam/list: + post: + consumes: + - application/json + description: Retrieve a list of all permissions. + operationId: listMciamPermissions + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.MciamPermission' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List all permissions + tags: + - permissions + /api/projects: + post: + consumes: + - application/json + description: Create a new project with the specified information. + operationId: createProject + parameters: + - description: Project Info + in: body + name: project + required: true + schema: + $ref: '#/definitions/model.Project' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.Project' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create new project + tags: + - projects + /api/projects/{id}: + delete: + consumes: + - application/json + description: Delete a project by its ID. + operationId: deleteProject + parameters: + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete project + tags: + - projects + get: + consumes: + - application/json + description: Retrieve project details by project ID. + operationId: getProjectByID + parameters: + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Project' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get project by ID + tags: + - projects + put: + consumes: + - application/json + description: Update the details of an existing project. + operationId: updateProject + parameters: + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Info + in: body + name: project + required: true + schema: + $ref: '#/definitions/model.Project' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Project' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Update project + tags: + - projects + /api/projects/{id}/workspaces/{workspaceId}: + post: + consumes: + - application/json + description: 프로젝트에 워크스페이스를 연결합니다. + operationId: addWorkspaceToProject + parameters: + - description: 프로젝트 ID + in: path + name: id + required: true + type: integer + - description: 워크스페이스 ID + in: path + name: workspaceId + required: true + type: integer + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: 'error: 잘못된 ID 형식' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: 서버 내부 오류' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: 프로젝트에 워크스페이스 연결 + tags: + - projects + /api/projects/list: + post: + consumes: + - application/json + description: Retrieve a list of all projects. + operationId: listProjects + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Project' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List all projects + tags: + - projects + /api/projects/name/{projectName}: + get: + consumes: + - application/json + description: Get project details by name + operationId: getProjectByName + parameters: + - description: Project Name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Project' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get project by name + tags: + - projects + /api/resource-types/cloud-resources: + post: + consumes: + - application/json + description: 새로운 리소스 타입을 생성합니다 + operationId: createResourceType + parameters: + - description: Resource Type Info + in: body + name: resourceType + required: true + schema: + $ref: '#/definitions/model.ResourceType' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.ResourceType' + "400": + description: 'error: Invalid request' + schema: + additionalProperties: + type: string + type: object + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Cloud에서 관리되는 Resource(vm, nlb, k8s 등의 그룹) 새 리소스 타입 생성 + tags: + - resource-types + /api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId: + delete: + consumes: + - application/json + description: 리소스 타입을 삭제합니다 + operationId: deleteResourceType + parameters: + - description: Resource Type ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Resource Type not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: 리소스 타입 삭제 + tags: + - resource-types + get: + consumes: + - application/json + description: 특정 리소스 타입을 ID로 조회합니다 + operationId: getCloudResourceTypeByID + parameters: + - description: Resource Type ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.ResourceType' + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Resource Type not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: 리소스 타입 ID로 조회 + tags: + - resource-types + put: + consumes: + - application/json + description: 리소스 타입 정보를 업데이트합니다 + operationId: updateResourceType + parameters: + - description: Resource Type ID + in: path + name: id + required: true + type: string + - description: Resource Type Info + in: body + name: resourceType + required: true + schema: + $ref: '#/definitions/model.ResourceType' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.ResourceType' + "400": + description: 'error: Invalid request' + schema: + additionalProperties: + type: string + type: object + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Resource Type not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: 리소스 타입 업데이트 + tags: + - resource-types + /api/resource-types/cloud-resources/list: + post: + consumes: + - application/json + description: 모든 리소스 타입 목록을 조회합니다 + operationId: listCloudResourceTypes + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.ResourceType' + type: array + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: 리소스 타입 목록 조회 + tags: + - resource-types + /api/roles: + post: + consumes: + - application/json + description: Create a new role + operationId: createRole + parameters: + - description: Role Info + in: body + name: role + required: true + schema: + $ref: '#/definitions/model.CreateRoleRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.RoleMaster' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create role + tags: + - roles + /api/roles/{roleType}/{roleId}/mciam-permissions: + get: + consumes: + - application/json + description: 특정 역할의 MC-IAM 권한 ID 목록을 조회합니다. + operationId: getRoleMciamPermissions + parameters: + - description: 역할 타입 ('platform' or 'workspace') + in: path + name: roleType + required: true + type: string + - description: 역할 ID + in: path + name: roleId + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 권한 ID 목록 + schema: + items: + type: string + type: array + summary: 역할의 MC-IAM 권한 목록 조회 - Renamed + tags: + - roles + - mciam-permissions + /api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId}: + delete: + consumes: + - application/json + description: 역할에서 MC-IAM 권한을 제거합니다. + operationId: removeMciamPermissionFromRole + parameters: + - description: 역할 타입 ('platform' or 'workspace') + in: path + name: roleType + required: true + type: string + - description: 역할 ID + in: path + name: roleId + required: true + type: integer + - description: MC-IAM 권한 ID + in: path + name: permissionId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + summary: 역할에서 MC-IAM 권한 제거 - Renamed + tags: + - roles + - mciam-permissions + post: + consumes: + - application/json + description: 역할에 MC-IAM 권한을 할당합니다. + operationId: assignMciamPermissionToRole + parameters: + - description: 역할 타입 ('platform' or 'workspace') + in: path + name: roleType + required: true + type: string + - description: 역할 ID + in: path + name: roleId + required: true + type: integer + - description: MC-IAM 권한 ID + in: path + name: permissionId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + summary: 역할에 MC-IAM 권한 할당 - Renamed + tags: + - roles + - mciam-permissions + /api/roles/assign/platform-role: + post: + consumes: + - application/json + description: Assign a platform role to a user + operationId: assignPlatformRole + parameters: + - description: Platform Role Assignment Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.AssignRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Assign platform role + tags: + - roles + /api/roles/assign/workspace-role: + post: + consumes: + - application/json + description: Assign a workspace role to a user + operationId: assignWorkspaceRole + parameters: + - description: Workspace Role Assignment Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.AssignWorkspaceRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Assign workspace role + tags: + - roles + /api/roles/csp: + post: + consumes: + - application/json + description: Create a new csp role + operationId: createCspRole + parameters: + - description: CSP Role Creation Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.CreateRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create csp role + tags: + - roles + /api/roles/csp-roles: + post: + consumes: + - application/json + description: Create a new mapping between role and CSP role + operationId: addCspRoleMappings + parameters: + - description: Mapping Info + in: body + name: mapping + required: true + schema: + $ref: '#/definitions/model.RoleMasterCspRoleMappingRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.RoleMasterCspRoleMappingRequest' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create role-CSP role mapping + tags: + - roles + /api/roles/csp-roles/batch: + post: + consumes: + - application/json + description: Create multiple new csp roles + operationId: createCspRoles + parameters: + - description: Multiple CSP Role Creation Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.CreateCspRolesRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + items: + $ref: '#/definitions/model.CspRole' + type: array + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create multiple csp roles + tags: + - roles + /api/roles/csp-roles/id/:roleId: + get: + consumes: + - application/json + description: Get a mapping between role and CSP role + operationId: getCspRoleMappingByRoleId + parameters: + - description: Mapping Info + in: body + name: mapping + required: true + schema: + $ref: '#/definitions/model.RoleMasterCspRoleMappingRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMasterCspRoleMappingRequest' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get role-CSP role mapping + tags: + - roles + /api/roles/csp-roles/id/{roleId}: + delete: + consumes: + - application/json + description: Delete a role + operationId: deleteCspRole + parameters: + - description: Role ID + in: path + name: roleId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete csp role + tags: + - roles + put: + consumes: + - application/json + description: Update role information + operationId: updateCspRole + parameters: + - description: Role ID + in: path + name: roleId + required: true + type: string + - description: Role Info + in: body + name: role + required: true + schema: + $ref: '#/definitions/model.CreateRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMaster' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Update csp role + tags: + - roles + /api/roles/csp-roles/list: + post: + consumes: + - application/json + description: Get a mapping between role and CSP role + operationId: listCspRoleMappings + parameters: + - description: Mapping Info + in: body + name: mapping + required: true + schema: + $ref: '#/definitions/model.RoleMasterCspRoleMappingRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMasterCspRoleMappingRequest' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get role-CSP role mapping + tags: + - roles + /api/roles/csp/id/{roleId}: + get: + consumes: + - application/json + description: Get csp role details by ID + operationId: getCspRoleByID + parameters: + - description: CSP Role ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMaster' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get csp role by ID + tags: + - roles + /api/roles/csp/list: + post: + consumes: + - application/json + description: Get a list of all csp roles + operationId: listCSPRoles + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.RoleMaster' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List csp roles + tags: + - roles + /api/roles/csp/name/{roleName}: + get: + consumes: + - application/json + description: Get csp role details by Name + operationId: getCspRoleByName + parameters: + - description: CSP Role Name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMaster' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get csp role by Name + tags: + - roles + /api/roles/id/{roleId}: + delete: + consumes: + - application/json + description: Delete a role by its name. + operationId: deleteRole + parameters: + - description: Role ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete role + tags: + - roles + get: + consumes: + - application/json + description: Get role details by ID + operationId: getRoleByRoleID + parameters: + - description: Role ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMaster' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get role by ID + tags: + - roles + put: + consumes: + - application/json + description: Update the details of an existing role. + operationId: updateRole + parameters: + - description: Role ID + in: path + name: id + required: true + type: string + - description: Role Info + in: body + name: role + required: true + schema: + $ref: '#/definitions/model.CreateRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMaster' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Update role + tags: + - roles + /api/roles/id/{roleId}/assign: post: consumes: - application/json - description: Executes a defined MCMP API action with query parameters and a - request body. + description: Assign a role to a user + operationId: assignRole parameters: - - description: Generic API Call Request + - description: Role Assignment Info in: body - name: callRequest + name: request required: true schema: - $ref: '#/definitions/mcmpapi.ServiceApiCallRequest' + $ref: '#/definitions/model.AssignRoleRequest' produces: - application/json responses: "200": - description: External API Response (structure depends on the called API) + description: OK schema: + additionalProperties: + type: string type: object "400": - description: 'error: Invalid request body or parameters' + description: Bad Request schema: additionalProperties: type: string type: object - "404": - description: 'error: Service or action not found' + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object - "500": - description: 'error: Internal server error or failed to call external API' + security: + - BearerAuth: [] + summary: Assign role + tags: + - roles + /api/roles/id/{roleId}/unassign: + delete: + consumes: + - application/json + description: Remove a role from a user + operationId: removeRole + parameters: + - description: Role Removal Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.AssignRoleRequest' + produces: + - application/json + responses: + "200": + description: OK schema: additionalProperties: type: string type: object - "503": - description: 'error: External API unavailable' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: Call an external MCMP API action (Generic Request) + summary: Remove role tags: - - McmpAPI - /api/permissions: - get: + - roles + /api/roles/list: + post: consumes: - application/json - description: 모든 권한 목록을 조회합니다. + description: Retrieve a list of all roles. + operationId: listRoles produces: - application/json responses: @@ -361,102 +3244,71 @@ paths: description: OK schema: items: - $ref: '#/definitions/model.Permission' + $ref: '#/definitions/model.RoleMaster' type: array - summary: 권한 목록 조회 + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List all roles tags: - - permissions + - roles + /api/roles/mappings/csp-roles/list: post: consumes: - application/json - description: 새로운 권한을 생성합니다. + description: List users by csp role + operationId: listUsersByCspRole parameters: - - description: 권한 정보 + - description: Filter Role Master Mapping Request in: body - name: permission + name: request required: true schema: - $ref: '#/definitions/model.Permission' - produces: - - application/json - responses: - "201": - description: Created - schema: - $ref: '#/definitions/model.Permission' - summary: 권한 생성 - tags: - - permissions - /api/permissions/{id}: - delete: - consumes: - - application/json - description: 권한을 삭제합니다. - parameters: - - description: 권한 ID - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "204": - description: No Content - summary: 권한 삭제 - tags: - - permissions - get: - consumes: - - application/json - description: ID로 특정 권한을 조회합니다. - parameters: - - description: 권한 ID - in: path - name: id - required: true - type: string + $ref: '#/definitions/model.FilterRoleMasterMappingRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/model.Permission' - summary: ID로 권한 조회 + items: + $ref: '#/definitions/model.RoleMasterMapping' + type: array + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List users by csp role tags: - - permissions - put: + - roles + /api/roles/mappings/list: + post: consumes: - application/json - description: 기존 권한을 수정합니다. + description: List role master mappings + operationId: listRoleMasterMappings parameters: - - description: 권한 ID - in: path - name: id - required: true - type: string - - description: 권한 정보 + - description: Filter Role Master Mapping Request in: body - name: permission + name: request required: true schema: - $ref: '#/definitions/model.Permission' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/model.Permission' - summary: 권한 수정 - tags: - - permissions - /api/platform-roles: - get: - consumes: - - application/json - description: 모든 플랫폼 역할을 조회합니다. + $ref: '#/definitions/model.FilterRoleMasterMappingRequest' produces: - application/json responses: @@ -464,113 +3316,146 @@ paths: description: OK schema: items: - $ref: '#/definitions/model.PlatformRole' + $ref: '#/definitions/model.RoleMasterMapping' type: array - summary: 플랫폼 역할 목록 조회 + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List role master mappings tags: - - platform-roles + - roles + /api/roles/mappings/platform-roles/users/list: post: consumes: - application/json - description: 새로운 플랫폼 역할을 생성합니다. + description: List users by platform role + operationId: listUsersByPlatformRole parameters: - - description: Platform Role + - description: Filter Role Master Mapping Request in: body - name: role + name: request required: true schema: - $ref: '#/definitions/model.PlatformRole' + $ref: '#/definitions/model.FilterRoleMasterMappingRequest' produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/model.PlatformRole' - summary: 플랫폼 역할 생성 - tags: - - platform-roles - /api/platform-roles/{id}: - delete: - consumes: - - application/json - description: 플랫폼 역할을 삭제합니다. - parameters: - - description: Platform Role ID - in: path - name: id - required: true - type: integer - produces: - - application/json - responses: - "204": - description: No Content - summary: 플랫폼 역할 삭제 + items: + $ref: '#/definitions/model.RoleMasterMapping' + type: array + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List users by platform role tags: - - platform-roles + - roles + /api/roles/mappings/role/id/:roleId: get: consumes: - application/json - description: ID로 플랫폼 역할을 조회합니다. + description: Get role master mappings + operationId: getRoleMasterMappings parameters: - - description: Platform Role ID - in: path - name: id + - description: Filter Role Master Mapping Request + in: body + name: request required: true - type: integer + schema: + $ref: '#/definitions/model.FilterRoleMasterMappingRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/model.PlatformRole' - summary: 플랫폼 역할 조회 + $ref: '#/definitions/model.RoleMasterMapping' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get role master mappings tags: - - platform-roles - put: + - roles + /api/roles/mappings/workspace-roles/users/list: + post: consumes: - application/json - description: 기존 플랫폼 역할을 수정합니다. + description: List users by workspace role + operationId: listUsersByWorkspaceRole parameters: - - description: Platform Role ID - in: path - name: id - required: true - type: integer - - description: Platform Role + - description: Filter Role Master Mapping Request in: body - name: role + name: request required: true schema: - $ref: '#/definitions/model.PlatformRole' + $ref: '#/definitions/model.FilterRoleMasterMappingRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/model.PlatformRole' - summary: 플랫폼 역할 수정 + items: + $ref: '#/definitions/model.RoleMasterMapping' + type: array + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List users by workspace role tags: - - platform-roles - /api/roles/{roleType}/{roleId}/permissions: - get: + - roles + /api/roles/menu-roles/list: + post: consumes: - application/json - description: 특정 역할의 권한 목록을 조회합니다. - parameters: - - description: 역할 타입 ('platform' or 'workspace') - in: path - name: roleType - required: true - type: string - - description: 역할 ID - in: path - name: roleId - required: true - type: integer + description: Get a list of all menu roles + operationId: listPlatformRoles produces: - application/json responses: @@ -578,444 +3463,492 @@ paths: description: OK schema: items: - $ref: '#/definitions/model.Permission' + $ref: '#/definitions/model.RoleMaster' type: array - summary: 역할의 권한 목록 조회 - tags: - - permissions - /api/roles/{roleType}/{roleId}/permissions/{permissionId}: - delete: - consumes: - - application/json - description: 역할에서 권한을 제거합니다. - parameters: - - description: 역할 타입 ('platform' or 'workspace') - in: path - name: roleType - required: true - type: string - - description: 역할 ID - in: path - name: roleId - required: true - type: integer - - description: 권한 ID - in: path - name: permissionId - required: true - type: string - produces: - - application/json - responses: - "204": - description: No Content - summary: 역할에서 권한 제거 - tags: - - permissions - post: + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List menu roles + tags: + - roles + /api/roles/name/{roleName}: + get: consumes: - application/json - description: 역할에 권한을 할당합니다. + description: Retrieve role details by role name. + operationId: getRoleByRoleName parameters: - - description: 역할 타입 ('platform' or 'workspace') - in: path - name: roleType - required: true - type: string - - description: 역할 ID - in: path - name: roleId - required: true - type: integer - - description: 권한 ID + - description: Role name in: path - name: permissionId + name: name required: true type: string produces: - application/json responses: - "204": - description: No Content - summary: 역할에 권한 할당 + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMaster' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get role by Name tags: - - permissions - /auth/login: + - roles + /api/roles/platform-roles: post: consumes: - application/json - description: 사용자 ID와 비밀번호로 로그인하여 JWT 토큰을 발급받습니다. + description: Create a new menu role + operationId: createPlatformRole parameters: - - description: 로그인 정보 (Id, Password) + - description: Menu Role Creation Info in: body - name: login + name: request required: true schema: - $ref: '#/definitions/idp.UserLogin' + $ref: '#/definitions/model.CreateRoleRequest' produces: - application/json responses: "200": - description: 로그인 성공 및 토큰 정보 (gocloak.JWT 구조체와 유사) + description: OK schema: - additionalProperties: true + additionalProperties: + type: string type: object "400": - description: 'error: 잘못된 요청 형식' + description: Bad Request schema: additionalProperties: type: string type: object - "401": - description: 'error: 인증 실패 (자격 증명 오류)' + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object - "403": - description: 'error: 계정이 비활성화되었거나 승인 대기 중입니다' + security: + - BearerAuth: [] + summary: Create menu role + tags: + - roles + /api/roles/platform-roles/id/{roleId}: + delete: + consumes: + - application/json + description: Delete a platform role + operationId: deletePlatformRole + parameters: + - description: Platform Role ID + in: path + name: roleId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류 (Keycloak 통신, DB 동기화 등)' + description: Internal Server Error schema: additionalProperties: type: string type: object - summary: 로그인 + security: + - BearerAuth: [] + summary: Delete platform role tags: - - auth - /mcmp-apis: + - roles get: consumes: - application/json - description: Retrieves all MCMP API service and action definitions currently - stored in the database. + description: Get platform role details by ID + operationId: getPlatformRoleByID parameters: - - description: Filter by service name - in: query - name: serviceName - type: string - - description: Filter by action name (operationId) - in: query - name: actionName + - description: Platform Role ID + in: path + name: id + required: true type: string produces: - application/json responses: "200": - description: Successfully retrieved API definitions + description: OK schema: - $ref: '#/definitions/mcmpapi.McmpApiDefinitions' + $ref: '#/definitions/model.RoleMaster' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object "500": - description: 'message: Failed to retrieve API definitions' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: Get All Stored MCMP API Definitions + summary: Get platform role by ID tags: - - McmpAPI - /mcmp-apis/{serviceName}: - put: + - roles + /api/roles/platform-roles/name/{roleName}: + get: consumes: - application/json - description: Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API - service definition identified by its name. Cannot update name or version. + description: Get menu role details by Name + operationId: getPlatformRoleByName parameters: - - description: Service Name to update + - description: Menu Role Name in: path - name: serviceName + name: name required: true type: string - - description: Fields to update (e.g., {\ - in: body - name: updates - required: true - schema: - type: object produces: - application/json responses: "200": - description: 'message: Service updated successfully" // Or return updated - service?' - schema: - additionalProperties: - type: string - type: object - "400": - description: 'error: Invalid service name or request body' + description: OK schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/model.RoleMaster' "404": - description: 'error: Service not found' + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: Failed to update service' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: Update MCMP API Service Definition + summary: Get menu role by Name tags: - - McmpAPI - /mcmp-apis/{serviceName}/versions/{version}/activate: - put: + - roles + /api/roles/unassign/csp-roles: + delete: consumes: - application/json - description: Sets the specified version of an MCMP API service as the active - one. + description: Delete a mapping between workspace role and CSP role + operationId: removeCspRoleMappings parameters: - - description: Service Name - in: path - name: serviceName - required: true - type: string - - description: Version to activate - in: path - name: version + - description: Mapping Info + in: body + name: mapping required: true - type: string + schema: + $ref: '#/definitions/model.RoleMasterCspRoleMappingRequest' produces: - application/json responses: "204": description: No Content "400": - description: 'error: Invalid service name or version' - schema: - additionalProperties: - type: string - type: object - "404": - description: 'error: Service or version not found' + description: Bad Request schema: additionalProperties: type: string type: object "500": - description: 'error: Failed to set active version' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: Set Active Version for a Service + summary: Delete workspace role-CSP role mapping tags: - - McmpAPI - /mcmp-apis/call: - post: + - roles + /api/roles/unassign/platform-role: + delete: consumes: - application/json - description: Executes a defined MCMP API action with parameters structured in - McmpApiCallRequest. + description: Remove a platform role from a user + operationId: removePlatformRole parameters: - - description: API Call Request + - description: Platform Role Removal Info in: body - name: callRequest + name: request required: true schema: - $ref: '#/definitions/mcmpapi.McmpApiCallRequest' + $ref: '#/definitions/model.AssignRoleRequest' produces: - application/json responses: "200": - description: External API Response (structure depends on the called API) - schema: - type: object - "400": - description: 'error: Invalid request body or parameters' + description: OK schema: additionalProperties: type: string type: object - "404": - description: 'error: Service or action not found' + "400": + description: Bad Request schema: additionalProperties: type: string type: object "500": - description: 'error: Internal server error or failed to call external API' - schema: - additionalProperties: - type: string - type: object - "503": - description: 'error: External API unavailable' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: Call an external MCMP API action (Structured Request) + summary: Remove platform role tags: - - McmpAPI - /mcmp-apis/sync: - post: + - roles + /api/roles/unassign/workspace-role: + delete: consumes: - application/json - description: Triggers the synchronization of MCMP API definitions from the configured - YAML URL to the database. + description: Remove a workspace role from a user + operationId: removeWorkspaceRole + parameters: + - description: Workspace Role Removal Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.AssignRoleRequest' produces: - application/json responses: "200": - description: 'message: Successfully triggered MCMP API sync" // Updated - message' + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request schema: additionalProperties: type: string type: object "500": - description: 'message: Failed to trigger MCMP API sync" // Updated message' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: Sync MCMP API Definitions + summary: Remove workspace role tags: - - McmpAPI // Updated tag - /mcmp-apis/test/mc-infra-manager/getallns: - get: - description: Calls the GetAllNs action of the mc-infra-manager service via the - CallApi service. + - roles + /api/roles/workspace-roles: + post: + consumes: + - application/json + description: Create a new workspace role + operationId: createWorkspaceRole + parameters: + - description: Workspace Role Creation Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.CreateRoleRequest' produces: - application/json responses: "200": - description: Response from mc-infra-manager GetAllNs + description: OK schema: + additionalProperties: + type: string type: object "400": - description: 'error: Bad Request (e.g., invalid parameters)' + description: Bad Request schema: additionalProperties: type: string type: object - "404": - description: 'error: Service or Action Not Found' + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object - "500": - description: 'error: Internal Server Error' + security: + - BearerAuth: [] + summary: Create workspace role + tags: + - roles + /api/roles/workspace-roles/id/{roleId}: + delete: + consumes: + - application/json + description: Delete a workspace role + operationId: deleteWorkspaceRole + parameters: + - description: Workspace Role ID + in: path + name: roleId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found schema: additionalProperties: type: string type: object - "503": - description: 'error: External API Service Unavailable' + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: Test Call to mc-infra-manager GetAllNs + summary: Delete workspace role tags: - - McmpAPI - - Test - /menus: + - roles get: consumes: - application/json - description: 현재 로그인한 사용자의 Platform Role에 따라 접근 가능한 메뉴 목록을 트리 구조로 조회합니다. + description: Get workspace role details by ID + operationId: getWorkspaceRoleByID + parameters: + - description: Workspace Role ID + in: path + name: id + required: true + type: string produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/model.MenuTreeNode' - type: array - "401": - description: 'error: Unauthorized' + $ref: '#/definitions/model.RoleMaster' + "404": + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 현재 사용자의 메뉴 트리 조회 - tags: - - menus - post: - consumes: - - application/json - description: 새로운 메뉴를 생성합니다 - parameters: - - description: Menu Info - in: body - name: menu - required: true - schema: - $ref: '#/definitions/model.Menu' + summary: Get workspace role by ID + tags: + - roles + /api/roles/workspace-roles/list: + post: + consumes: + - application/json + description: Get a list of all workspace roles + operationId: listWorkspaceRoles produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/model.Menu' + items: + $ref: '#/definitions/model.RoleMaster' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object security: - BearerAuth: [] - summary: 새 메뉴 생성 + summary: List workspace roles tags: - - menus - /menus/{id}: - delete: + - roles + /api/roles/workspace-roles/name/{roleName}: + get: consumes: - application/json - description: 메뉴를 삭제합니다 + description: Get workspace role details by Name + operationId: getWorkspaceRoleByName parameters: - - description: Menu ID + - description: Workspace Role Name in: path - name: id + name: name required: true type: string produces: - application/json responses: - "204": - description: No Content + "200": + description: OK + schema: + $ref: '#/definitions/model.RoleMaster' + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object security: - BearerAuth: [] - summary: 메뉴 삭제 + summary: Get workspace role by Name tags: - - menus + - roles + /api/setup/check-user-roles: get: consumes: - application/json - description: 특정 메뉴를 ID로 조회합니다 + description: Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다. + operationId: checkUserRoles parameters: - - description: Menu ID - in: path - name: id + - description: Username to check roles + in: query + name: username required: true type: string produces: @@ -1024,401 +3957,457 @@ paths: "200": description: OK schema: - $ref: '#/definitions/model.Menu' - security: - - BearerAuth: [] - summary: 메뉴 ID로 조회 + $ref: '#/definitions/model.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/model.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/model.Response' + summary: Check user roles tags: - - menus - put: + - admin + /api/setup/initial-role-menu-permission: + get: consumes: - application/json - description: 메뉴 정보를 업데이트합니다 + description: CSV 파일을 읽어서 메뉴 권한을 초기화합니다 + operationId: initializeMenuPermissions parameters: - - description: Menu ID - in: path - name: id - required: true + - description: CSV file path (optional, uses default if not provided) + in: query + name: filePath type: string - - description: Menu Info - in: body - name: menu - required: true - schema: - $ref: '#/definitions/model.Menu' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/model.Menu' + $ref: '#/definitions/model.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/model.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/model.Response' security: - BearerAuth: [] - summary: 메뉴 정보 업데이트 + summary: Initialize menu permissions from CSV tags: - - menus - /menus/all: - get: + - admin + /api/setup/sync-projects: + post: consumes: - application/json - description: 모든 메뉴 목록을 트리 구조로 조회합니다. 관리자 권한이 필요합니다. + description: mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다. + operationId: syncProjects produces: - application/json responses: "200": - description: OK - schema: - items: - $ref: '#/definitions/model.MenuTreeNode' - type: array - "401": - description: 'error: Unauthorized' - schema: - additionalProperties: - type: string - type: object - "403": - description: 'error: Forbidden' + description: 'message: Project synchronization successful' schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: 'error: 서버 내부 오류 또는 동기화 실패' schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 모든 메뉴 트리 조회 (관리자용) + summary: mc-infra-manager와 프로젝트 동기화 tags: - - menus - /menus/register-from-body: + - projects + /api/users: post: consumes: - - text/plain - description: 요청 본문에 포함된 YAML 텍스트를 파싱하여 메뉴를 데이터베이스에 등록하거나 업데이트합니다. Content-Type은 - text/plain, text/yaml, application/yaml 등을 권장합니다. + - application/json + description: Create a new user with the specified information. + operationId: createUser parameters: - - description: Menu definitions in YAML format (must contain 'menus:' root key) - example: '"menus:\n - id: new-item\n parentid: dashboard\n displayname: - New Menu Item\n restype: menu\n isaction: false\n priority: 10\n menunumber: - 9999"' + - description: User Info in: body - name: yaml + name: user required: true schema: - type: string + $ref: '#/definitions/model.User' produces: - application/json responses: - "200": - description: 'message: Successfully registered menus from request body' + "201": + description: Created schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/model.User' "400": - description: 'error: 잘못된 요청 본문 또는 YAML 형식 오류' + description: Bad Request schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 요청 본문의 YAML 내용으로 메뉴 등록/업데이트 + summary: Create new user tags: - - menus - /menus/register-from-yaml: - post: + - users + /api/users/{id}: + delete: consumes: - application/json - description: filePath 쿼리 파라미터로 지정된 로컬 YAML 파일 또는 파라미터가 없을 경우 .env 파일의 MCWEBCONSOLE_MENUYAML - URL에서 메뉴를 가져와 데이터베이스에 등록/업데이트합니다. URL에서 가져올 경우 asset/menu/menu.yaml에 저장됩니다. + description: Delete a user by their ID. + operationId: deleteUser parameters: - - description: YAML 파일 경로 (선택 사항, 없으면 .env의 URL 또는 기본 로컬 경로 사용) - in: query - name: filePath + - description: User ID + in: path + name: id + required: true type: string produces: - application/json responses: - "200": - description: 'message: Successfully registered menus from YAML' + "204": + description: No Content + "404": + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 실패 메시지' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: YAML 파일 또는 URL에서 메뉴 등록/업데이트 + summary: Delete user tags: - - menus - /projects: - get: + - users + put: consumes: - application/json - description: 모든 프로젝트 목록을 조회합니다 (연결된 워크스페이스 정보 포함). + description: Update the details of an existing user. + operationId: updateUser + parameters: + - description: User ID + in: path + name: id + required: true + type: string + - description: User Info + in: body + name: user + required: true + schema: + $ref: '#/definitions/model.User' produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/model.Project' - type: array + $ref: '#/definitions/model.User' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 모든 프로젝트 조회 + summary: Update user tags: - - projects - post: + - users + /api/users/id/{userId}: + get: consumes: - application/json - description: 새로운 프로젝트를 생성합니다. + description: Retrieve user details by user ID. + operationId: getUserByID parameters: - - description: 프로젝트 정보 (ID, CreatedAt, UpdatedAt, Workspaces 제외) - in: body - name: project + - description: User ID + in: path + name: userId required: true - schema: - $ref: '#/definitions/model.Project' + type: string produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/model.Project' - "400": - description: 'error: 잘못된 요청 형식' + $ref: '#/definitions/model.User' + "404": + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 프로젝트 생성 + summary: Get user by ID tags: - - projects - /projects/{id}: - delete: + - users + /api/users/id/{userId}/status: + post: consumes: - application/json - description: 프로젝트를 삭제합니다. 연결된 워크스페이스와의 관계도 해제됩니다. + description: Update user status (active/inactive) + operationId: updateUserStatus parameters: - - description: 프로젝트 ID + - description: User ID in: path name: id required: true - type: integer + type: string + - description: User Status + in: body + name: status + required: true + schema: + $ref: '#/definitions/model.UserStatusRequest' produces: - application/json responses: - "204": - description: No Content + "200": + description: OK + schema: + $ref: '#/definitions/model.User' "400": - description: 'error: 잘못된 프로젝트 ID' + description: Bad Request schema: additionalProperties: type: string type: object "404": - description: 'error: 프로젝트를 찾을 수 없습니다' + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 프로젝트 삭제 + summary: Update user status tags: - - projects + - users + /api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list: get: consumes: - application/json - description: ID로 특정 프로젝트를 조회합니다 (연결된 워크스페이스 정보 포함). + description: Get workspaces and roles for a specific user and workspace + operationId: getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID parameters: - - description: 프로젝트 ID + - description: User ID in: path - name: id + name: userId required: true - type: integer + type: string + - description: Workspace ID + in: path + name: workspaceId + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/model.Project' - "400": - description: 'error: 잘못된 프로젝트 ID' + items: + $ref: '#/definitions/model.UserWorkspaceRole' + type: array + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object - "404": - description: 'error: 프로젝트를 찾을 수 없습니다' + security: + - BearerAuth: [] + summary: Get user workspace and workspace roles by user ID and workspace ID + tags: + - users + /api/users/id/{userId}/workspaces/list: + get: + consumes: + - application/json + description: Get workspaces for a specific user + operationId: getUserWorkspacesByUserID + parameters: + - description: User ID + in: path + name: userId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Workspace' + type: array + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object + security: + - BearerAuth: [] + summary: Get user workspaces by user ID + tags: + - users + /api/users/id/{userId}/workspaces/roles/list: + get: + consumes: + - application/json + description: Get workspaces and roles for a specific user + operationId: getUserWorkspaceAndWorkspaceRolesByUserID + parameters: + - description: User ID + in: path + name: userId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.UserWorkspaceRole' + type: array "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: ID로 프로젝트 조회 + summary: Get user workspace and workspace roles by user ID tags: - - projects - put: + - users + /api/users/kc/{kcUserId}: + get: consumes: - application/json - description: 기존 프로젝트 정보를 부분적으로 수정합니다. + description: Get user details by KcID + operationId: getUserByKcID parameters: - - description: 프로젝트 ID - in: path - name: id - required: true - type: integer - - description: '수정할 필드와 값 (예: {\' - in: body - name: updates + - description: User KcID + in: path + name: kcUserId required: true - schema: - type: object + type: string produces: - application/json responses: "200": - description: 업데이트된 프로젝트 정보 - schema: - $ref: '#/definitions/model.Project' - "400": - description: 'error: 잘못된 요청 형식 또는 ID' + description: OK schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/model.User' "404": - description: 'error: 프로젝트를 찾을 수 없습니다' + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 프로젝트 수정 + summary: Get user by KcID tags: - - projects - /projects/{id}/workspaces/{workspaceId}: - delete: + - users + /api/users/list: + post: consumes: - application/json - description: 특정 프로젝트에서 워크스페이스 연결을 해제합니다. - parameters: - - description: 프로젝트 ID - in: path - name: id - required: true - type: integer - - description: 워크스페이스 ID - in: path - name: workspaceId - required: true - type: integer + description: Retrieve a list of all users. + operationId: listUsers produces: - application/json responses: - "204": - description: No Content - "400": - description: 'error: 잘못된 ID 형식' + "200": + description: OK schema: - additionalProperties: - type: string - type: object + items: + $ref: '#/definitions/model.User' + type: array "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 프로젝트에서 워크스페이스 연결 해제 + summary: List all users tags: - - projects + - users + /api/users/menus-tree/list: post: consumes: - application/json - description: 특정 프로젝트에 워크스페이스를 연결합니다. - parameters: - - description: 프로젝트 ID - in: path - name: id - required: true - type: integer - - description: 워크스페이스 ID - in: path - name: workspaceId - required: true - type: integer + description: Get the menu tree accessible to the current user's platform role. + operationId: listUserMenuTree produces: - application/json responses: - "204": - description: No Content - "400": - description: 'error: 잘못된 ID 형식' + "200": + description: OK schema: - additionalProperties: - type: string - type: object - "404": - description: 'error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다' + items: + $ref: '#/definitions/model.MenuTreeNode' + type: array + "401": + description: 'error: Unauthorized' schema: additionalProperties: type: string @@ -1431,16 +4420,35 @@ paths: type: object security: - BearerAuth: [] - summary: 프로젝트에 워크스페이스 연결 + summary: Get current user's menu tree tags: - - projects - /projects/name/{name}: + - menus + /api/users/menus/list: + post: + consumes: + - application/json + description: Get the menu list accessible to the current user's platform role. + operationId: listUserMenu + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Menu' + type: array + summary: Get current user's menu list + tags: + - menus + /api/users/name/{username}: get: consumes: - application/json - description: 이름으로 특정 프로젝트를 조회합니다 (연결된 워크스페이스 정보 포함). + description: Get user details by username + operationId: getUserByUsername parameters: - - description: 프로젝트 이름 + - description: Username in: path name: name required: true @@ -1451,282 +4459,342 @@ paths: "200": description: OK schema: - $ref: '#/definitions/model.Project' + $ref: '#/definitions/model.User' "404": - description: 'error: 프로젝트를 찾을 수 없습니다' + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 이름으로 프로젝트 조회 + summary: Get user by username tags: - - projects - /readyz: + - users + /api/users/workspaces/id/{workspaceId}/projects/list: get: - description: 애플리케이션의 준비 상태를 확인합니다. status=detail 쿼리 파라미터로 상세 상태를 확인할 수 있습니다. + consumes: + - application/json + description: List projects for the current user + operationId: listUserProjectsByWorkspace parameters: - - description: 상세 상태 확인 여부 ('detail') - in: query - name: status + - description: Workspace ID + in: path + name: workspaceId + required: true type: string produces: - application/json responses: "200": - description: 상세 상태 정보 (status=detail) + description: OK schema: - $ref: '#/definitions/service.HealthStatus' - "503": - description: 상세 상태 확인 중 오류 발생 시 + items: + $ref: '#/definitions/model.Project' + type: array + "500": + description: Internal Server Error schema: - $ref: '#/definitions/service.HealthStatus' - summary: 애플리케이션 준비 상태 확인 + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List user projects by workspace tags: - - Health - /user/workspaces: - get: - description: 현재 로그인한 사용자가 접근 가능한 워크스페이스 및 각 워크스페이스에서의 역할 목록을 조회합니다. + - users + /api/users/workspaces/list: + post: + consumes: + - application/json + description: List workspaces for the current user + operationId: listUserWorkspaces produces: - application/json responses: "200": - description: 성공 시 워크스페이스 및 역할 정보 목록 반환 + description: OK schema: items: - $ref: '#/definitions/service.WorkspaceRoleInfo' + $ref: '#/definitions/model.Workspace' type: array - "401": - description: 'error: Unauthorized' - schema: - additionalProperties: - type: string - type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 내 워크스페이스 및 역할 목록 조회 + summary: List user workspaces tags: - users - - workspaces - - roles - - me - /users: - get: - description: 모든 사용자 목록을 조회합니다. 'admin' 또는 'platformAdmin' 역할이 필요합니다. + /api/users/workspaces/roles/list: + post: + consumes: + - application/json + description: List workspaces and roles for the current user + operationId: listUserWorkspaceAndWorkspaceRoles produces: - application/json responses: "200": - description: 성공 시 사용자 목록 반환 + description: OK schema: items: - $ref: '#/definitions/model.User' + $ref: '#/definitions/model.RoleMaster' type: array - "401": - description: 'error: Unauthorized' + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object - "403": - description: 'error: Forbidden (권한 부족)' + security: + - BearerAuth: [] + summary: List user workspace and roles + tags: + - users + /api/workspaces: + post: + consumes: + - application/json + description: Create a new workspace with the specified information. + operationId: createWorkspace + parameters: + - description: Workspace Info + in: body + name: workspace + required: true + schema: + $ref: '#/definitions/model.Workspace' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.Workspace' + "400": + description: Bad Request schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 사용자 목록 조회 (관리자용) + summary: Create new workspace tags: - - users - post: - responses: {} - security: - - BearerAuth: [] - /users/{id}: - put: - parameters: - - description: User DB ID - in: path - name: id - required: true - type: integer - responses: {} - security: - - BearerAuth: [] - /users/{id}/approve: + - workspaces + /api/workspaces/{id}/users: post: consumes: - application/json - description: 지정된 사용자를 활성화하고 시스템 사용을 승인합니다. 'admin' 또는 'platformadmin' 역할이 필요합니다. + description: Add a user to a workspace + operationId: addUserToWorkspace parameters: - - description: 사용자 Keycloak ID + - description: Workspace ID in: path name: id required: true type: string + - description: User Info + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.AssignRoleRequest' produces: - application/json responses: - "204": - description: No Content - "400": - description: 'error: 잘못된 사용자 ID' + "200": + description: OK schema: additionalProperties: type: string type: object - "401": - description: 'error: Unauthorized' + "400": + description: Bad Request schema: additionalProperties: type: string type: object - "403": - description: 'error: Forbidden (권한 부족)' + "404": + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 사용자 승인 (관리자용) + summary: Add user to workspace tags: - - users - /workspaces: - get: + - workspaces + /api/workspaces/{id}/users/{userId}: + delete: consumes: - application/json - description: 모든 워크스페이스 목록을 조회합니다 (연결된 프로젝트 정보 포함). + description: Remove a user from a workspace + operationId: removeUserFromWorkspace + parameters: + - description: Workspace ID + in: path + name: id + required: true + type: string + - description: User ID + in: path + name: userId + required: true + type: string produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/model.Workspace' - type: array + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 모든 워크스페이스 조회 + summary: Remove user from workspace tags: - workspaces + /api/workspaces/assign/projects: post: consumes: - application/json - description: 새로운 워크스페이스를 생성합니다. + description: Add a project to a workspace + operationId: addProjectToWorkspace parameters: - - description: 워크스페이스 정보 (ID, CreatedAt, UpdatedAt, Projects 제외) - in: body - name: workspace + - description: Workspace ID + in: path + name: id required: true - schema: - $ref: '#/definitions/model.Workspace' + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: $ref: '#/definitions/model.Workspace' "400": - description: 'error: 잘못된 요청 형식' + description: 'error: Invalid request' schema: additionalProperties: type: string type: object - "500": - description: 'error: 서버 내부 오류' + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Workspace or Project not found' schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스 생성 + summary: Add project to workspace tags: - workspaces - /workspaces/{id}: + /api/workspaces/id/{workspaceId}: delete: consumes: - application/json - description: 워크스페이스를 삭제합니다. 연결된 프로젝트와의 관계도 해제됩니다. + description: Delete a workspace by its ID. + operationId: deleteWorkspace parameters: - - description: 워크스페이스 ID + - description: Workspace ID in: path name: id required: true - type: integer + type: string produces: - application/json - responses: - "204": - description: No Content - "400": - description: 'error: 잘못된 워크스페이스 ID' - schema: - additionalProperties: - type: string - type: object + responses: + "204": + description: No Content "404": - description: 'error: 워크스페이스를 찾을 수 없습니다' + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스 삭제 + summary: Delete workspace tags: - workspaces get: consumes: - application/json - description: ID로 특정 워크스페이스를 조회합니다 (연결된 프로젝트 정보 포함). + description: Retrieve workspace details by workspace ID. + operationId: getWorkspaceByID parameters: - - description: 워크스페이스 ID + - description: Workspace ID in: path - name: id + name: workspaceId required: true - type: integer + type: string produces: - application/json responses: @@ -1734,393 +4802,462 @@ paths: description: OK schema: $ref: '#/definitions/model.Workspace' - "400": - description: 'error: 잘못된 워크스페이스 ID' - schema: - additionalProperties: - type: string - type: object "404": - description: 'error: 워크스페이스를 찾을 수 없습니다' + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: ID로 워크스페이스 조회 + summary: Get workspace by ID tags: - workspaces put: consumes: - application/json - description: 기존 워크스페이스 정보를 부분적으로 수정합니다. + description: Update the details of an existing workspace. + operationId: updateWorkspace parameters: - - description: 워크스페이스 ID + - description: Workspace ID in: path name: id required: true - type: integer - - description: '수정할 필드와 값 (예: {\' + type: string + - description: Workspace Info in: body - name: updates + name: workspace required: true schema: - type: object + $ref: '#/definitions/model.Workspace' produces: - application/json responses: "200": - description: 업데이트된 워크스페이스 정보 + description: OK schema: $ref: '#/definitions/model.Workspace' "400": - description: 'error: 잘못된 요청 형식 또는 ID' + description: Bad Request schema: additionalProperties: type: string type: object "404": - description: 'error: 워크스페이스를 찾을 수 없습니다' + description: Not Found schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스 수정 + summary: Update workspace tags: - workspaces - /workspaces/{id}/projects: + /api/workspaces/id/{workspaceId}/projects/list: get: consumes: - application/json - description: 특정 워크스페이스 ID에 연결된 모든 프로젝트 목록을 조회합니다. + description: Retrieve project list belonging to specific workspace + operationId: getWorkspaceProjectsByWorkspaceId parameters: - - description: 워크스페이스 ID + - description: Workspace ID in: path - name: id + name: workspaceId required: true - type: integer + type: string produces: - application/json responses: "200": - description: 성공 시 프로젝트 목록 반환 + description: OK schema: items: $ref: '#/definitions/model.Project' type: array - "400": - description: 'error: 잘못된 워크스페이스 ID' + "401": + description: 'error: Unauthorized' schema: additionalProperties: type: string type: object - "404": - description: 'error: 워크스페이스를 찾을 수 없습니다' + "403": + description: 'error: Forbidden' schema: additionalProperties: type: string type: object - "500": - description: 'error: 서버 내부 오류' + "404": + description: 'error: Workspace not found' schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스에 연결된 프로젝트 목록 조회 + summary: List workspace projects tags: - workspaces - /workspaces/{id}/projects/{projectId}: - delete: + /api/workspaces/id/{workspaceId}/users/id/{userId}: + get: consumes: - application/json - description: 특정 워크스페이스에서 프로젝트 연결을 해제합니다. + description: Get roles assigned to a user in a workspace + operationId: getUserWorkspaceRoles parameters: - - description: 워크스페이스 ID + - description: User ID in: path - name: id + name: userId required: true - type: integer - - description: 프로젝트 ID + type: string + - description: Workspace ID in: path - name: projectId + name: workspaceId required: true - type: integer + type: string produces: - application/json responses: - "204": - description: No Content + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.RoleMaster' + type: array "400": - description: 'error: 잘못된 ID 형식' + description: Bad Request schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스에서 프로젝트 연결 해제 + summary: Get user workspace roles tags: - - workspaces + - roles + /api/workspaces/id/{workspaceId}/users/list: post: consumes: - application/json - description: 특정 워크스페이스에 프로젝트를 연결합니다. + description: Retrieve users and roles list belonging to workspace + operationId: listUsersAndRolesByWorkspace parameters: - - description: 워크스페이스 ID - in: path - name: id - required: true - type: integer - - description: 프로젝트 ID + - description: Workspace ID in: path - name: projectId + name: workspaceId required: true type: integer produces: - application/json responses: - "204": - description: No Content + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.UserWorkspaceRole' + type: array "400": - description: 'error: 잘못된 ID 형식' + description: 'error: Invalid workspace ID' schema: additionalProperties: type: string type: object "404": - description: 'error: 워크스페이스 또는 프로젝트를 찾을 수 없습니다' + description: 'error: Workspace not found' schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: 'error: Internal server error' + schema: + additionalProperties: + type: string + type: object + summary: List users and roles by workspace + tags: + - workspaces + /api/workspaces/list: + post: + consumes: + - application/json + description: Retrieve a list of all workspaces. + operationId: listWorkspaces + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Workspace' + type: array + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스에 프로젝트 연결 + summary: List all workspaces tags: - workspaces - /workspaces/{id}/users: + /api/workspaces/name/{workspaceName}: get: consumes: - application/json - description: 특정 워크스페이스에 속한 모든 사용자와 각 사용자의 역할을 조회합니다. + description: Retrieve specific workspace by name + operationId: getWorkspaceByName parameters: - - description: 워크스페이스 ID + - description: Workspace Name in: path - name: id + name: workspaceName required: true - type: integer + type: string produces: - application/json responses: "200": - description: 성공 시 사용자 및 역할 목록 반환 + description: OK schema: - items: - $ref: '#/definitions/service.UserWithRoles' - type: array - "400": - description: 'error: 잘못된 워크스페이스 ID' + $ref: '#/definitions/model.Workspace' + "401": + description: 'error: Unauthorized' schema: additionalProperties: type: string type: object - "404": - description: 'error: 워크스페이스를 찾을 수 없습니다' + "403": + description: 'error: Forbidden' schema: additionalProperties: type: string type: object - "500": - description: 'error: 서버 내부 오류' + "404": + description: 'error: Workspace not found' schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스 사용자 및 역할 목록 조회 + summary: Get workspace by name tags: - workspaces - - users - - roles - /workspaces/{workspaceId}/users/{userId}/roles/{roleId}: - delete: + /api/workspaces/projects/list: + post: consumes: - application/json - description: 특정 워크스페이스 내의 사용자에게서 특정 워크스페이스 역할을 제거합니다. + description: Retrieve project list belonging to specific workspace + operationId: listWorkspaceProjects parameters: - - description: 워크스페이스 ID + - description: Workspace ID in: path name: workspaceId required: true - type: integer - - description: 사용자 DB ID (db_id) - in: path - name: userId - required: true - type: integer - - description: 워크스페이스 역할 ID - in: path - name: roleId - required: true - type: integer + type: string produces: - application/json responses: - "204": - description: No Content - "400": - description: 'error: 잘못된 ID 형식' + "200": + description: OK schema: - additionalProperties: - type: string - type: object - "404": - description: 'error: 역할 또는 워크스페이스를 찾을 수 없습니다" // User existence check is - optional here' + items: + $ref: '#/definitions/model.Project' + type: array + "401": + description: 'error: Unauthorized' schema: additionalProperties: type: string type: object - "409": - description: 'error: 역할이 해당 워크스페이스에 속하지 않음' + "403": + description: 'error: Forbidden' schema: additionalProperties: type: string type: object - "500": - description: 'error: 서버 내부 오류' + "404": + description: 'error: Workspace not found' schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스 사용자 역할 제거 + summary: List workspace projects tags: - workspaces - - roles - - users + /api/workspaces/temporary-credentials: post: consumes: - application/json - description: 특정 워크스페이스 내의 사용자에게 특정 워크스페이스 역할을 할당합니다. + description: Get temporary credentials for CSP + operationId: mciamGetTemporaryCredentials + produces: + - application/json + responses: {} + security: + - BearerAuth: [] + summary: Get temporary credentials + tags: + - csp-credentials + /api/workspaces/unassign/projects: + delete: + consumes: + - application/json + description: Remove a project from a workspace + operationId: removeProjectFromWorkspace parameters: - - description: 워크스페이스 ID - in: path - name: workspaceId - required: true - type: integer - - description: 사용자 DB ID (db_id) - in: path - name: userId - required: true - type: integer - - description: 워크스페이스 역할 ID + - description: Workspace ID in: path - name: roleId + name: id required: true - type: integer + type: string + produces: + - application/json + responses: {} + summary: Remove project from workspace + tags: + - workspaces + /api/workspaces/users-roles/list: + post: + consumes: + - application/json + description: Retrieve the list of users and roles assigned to the workspace. + operationId: listAllWorkspaceUsersAndRoles produces: - application/json responses: - "204": - description: No Content - "400": - description: 'error: 잘못된 ID 형식' + "200": + description: OK schema: - additionalProperties: - type: string - type: object - "404": - description: 'error: 사용자, 역할 또는 워크스페이스를 찾을 수 없습니다' + items: + $ref: '#/definitions/model.WorkspaceWithUsersAndRoles' + type: array + "401": + description: 'error: Unauthorized' schema: additionalProperties: type: string type: object - "409": - description: 'error: 역할이 해당 워크스페이스에 속하지 않음' + "403": + description: 'error: Forbidden' schema: additionalProperties: type: string type: object "500": - description: 'error: 서버 내부 오류' + description: 'error: Internal server error' schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 워크스페이스 사용자에게 역할 할당 + summary: List users and roles in workspace tags: - workspaces - - roles - - users - /workspaces/name/{name}: - get: + /api/workspaces/users/list: + post: consumes: - application/json - description: 이름으로 특정 워크스페이스를 조회합니다 (연결된 프로젝트 정보 포함). - parameters: - - description: 워크스페이스 이름 - in: path - name: name - required: true - type: string + description: List users by workspace criteria + operationId: listWorkspaceUsers produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/model.Workspace' - "404": - description: 'error: 워크스페이스를 찾을 수 없습니다' + items: + $ref: '#/definitions/model.WorkspaceWithUsersAndRoles' + type: array + "401": + description: 'error: Unauthorized' schema: additionalProperties: type: string type: object - "500": - description: 'error: 서버 내부 오류' + "403": + description: 'error: Forbidden' schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: 이름으로 워크스페이스 조회 + summary: List workspace users tags: - workspaces + /api/workspaces/workspace-ticket: + post: + consumes: + - application/json + description: Set workspace ticket + operationId: mciamWorkspaceTicket + produces: + - application/json + responses: + "200": + description: 'message: Workspace ticket set successfully' + schema: + additionalProperties: + type: string + type: object + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Set workspace ticket + tags: + - auth + /readyz: + get: + consumes: + - application/json + description: Check the health status of the service. + operationId: mciamCheckHealth + parameters: + - description: Detail check components (nginx,db,keycloak,all) + in: query + name: detail + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + summary: Health check + tags: + - health securityDefinitions: BearerAuth: description: Type "Bearer" followed by a space and JWT token. diff --git a/readme.md b/readme.md index 2f8928d1..c5536134 100644 --- a/readme.md +++ b/readme.md @@ -127,6 +127,73 @@ cd ./src go run main.go ``` +### Docker Deployment with Local Build + +The `mc-iam-manager` service is configured to use the local `Dockerfile.mciammanager` for building the container image. + +#### Build Configuration + +In `docker-compose.yaml`, the service is configured as: + +```yaml +mc-iam-manager: + build: + context: . + dockerfile: Dockerfile.mciammanager + image: cloudbaristaorg/mc-iam-manager:edge +``` + +#### Deployment Options + +**1. Build and Run mc-iam-manager:** +```bash +# Build from local Dockerfile and start +docker-compose up --build mc-iam-manager + +# Run in background +docker-compose up --build -d mc-iam-manager +``` + +**2. Run All Services:** +```bash +# Build and start all services +docker-compose up --build -d +``` + +**3. Rebuild from Scratch:** +```bash +# Force rebuild without cache +docker-compose build --no-cache mc-iam-manager +docker-compose up -d mc-iam-manager +``` + +**4. Run with Dependencies Only:** +```bash +# Start mc-iam-manager with required services +docker-compose up -d mc-iam-manager-db mc-iam-manager-kc mc-iam-manager +``` + +#### Service Dependencies + +The `mc-iam-manager` service requires: +- `mc-iam-manager-db` (PostgreSQL database) +- `mc-iam-manager-kc` (Keycloak for authentication) + +These dependencies are automatically started when you run `mc-iam-manager`. + +#### Image Management + +```bash +# Pull latest images (if using pre-built images) +docker-compose pull + +# List Docker images +docker images | grep mc-iam-manager + +# Remove old images +docker rmi cloudbaristaorg/mc-iam-manager:edge +``` + #### Step 5: Operation Verification ```bash diff --git a/readme_kr.md b/readme_kr.md index 439c61d1..f9932b2e 100644 --- a/readme_kr.md +++ b/readme_kr.md @@ -128,6 +128,73 @@ cd ./src go run main.go ``` +### Docker 로컬 빌드 배포 + +`mc-iam-manager` 서비스는 로컬의 `Dockerfile.mciammanager`를 사용하여 컨테이너 이미지를 빌드하도록 구성되어 있습니다. + +#### 빌드 설정 + +`docker-compose.yaml`에서 다음과 같이 설정되어 있습니다: + +```yaml +mc-iam-manager: + build: + context: . + dockerfile: Dockerfile.mciammanager + image: cloudbaristaorg/mc-iam-manager:edge +``` + +#### 배포 방법 + +**1. mc-iam-manager 빌드 및 실행:** +```bash +# 로컬 Dockerfile로 빌드하고 시작 +docker-compose up --build mc-iam-manager + +# 백그라운드로 실행 +docker-compose up --build -d mc-iam-manager +``` + +**2. 전체 서비스 실행:** +```bash +# 모든 서비스 빌드 및 시작 +docker-compose up --build -d +``` + +**3. 완전 재빌드:** +```bash +# 캐시 없이 강제 재빌드 +docker-compose build --no-cache mc-iam-manager +docker-compose up -d mc-iam-manager +``` + +**4. 의존성 서비스와 함께 실행:** +```bash +# 필수 서비스와 함께 mc-iam-manager 시작 +docker-compose up -d mc-iam-manager-db mc-iam-manager-kc mc-iam-manager +``` + +#### 서비스 의존성 + +`mc-iam-manager` 서비스는 다음 서비스가 필요합니다: +- `mc-iam-manager-db` (PostgreSQL 데이터베이스) +- `mc-iam-manager-kc` (인증을 위한 Keycloak) + +`mc-iam-manager`를 실행하면 의존성 서비스가 자동으로 시작됩니다. + +#### 이미지 관리 + +```bash +# 최신 이미지 가져오기 (사전 빌드된 이미지 사용 시) +docker-compose pull + +# Docker 이미지 목록 확인 +docker images | grep mc-iam-manager + +# 이전 이미지 제거 +docker rmi cloudbaristaorg/mc-iam-manager:edge +``` + #### 5단계: 가동 확인 ```bash diff --git a/src/csp/interface.go b/src/csp/interface.go index 95299951..008d2f3c 100644 --- a/src/csp/interface.go +++ b/src/csp/interface.go @@ -76,3 +76,109 @@ type IAMClientConfig struct { WebIdentityToken string WorkspaceTicket string } + +// AssumeRoleConfig STS AssumeRole 요청 설정 +type AssumeRoleConfig struct { + RoleArn string `json:"role_arn"` + RoleSessionName string `json:"role_session_name"` + WebIdentityToken string `json:"web_identity_token,omitempty"` + DurationSeconds int32 `json:"duration_seconds,omitempty"` + ExternalID string `json:"external_id,omitempty"` + Policy string `json:"policy,omitempty"` + PolicyArns []string `json:"policy_arns,omitempty"` + Tags map[string]string `json:"tags,omitempty"` +} + +// CredentialResponse 임시 자격 증명 응답 +type CredentialResponse struct { + AccessKeyID string `json:"access_key_id"` + SecretAccessKey string `json:"secret_access_key"` + SessionToken string `json:"session_token"` + Expiration time.Time `json:"expiration"` + Provider string `json:"provider"` +} + +// CredentialService CSP 자격 증명 서비스 인터페이스 +type CredentialService interface { + // AssumeRoleWithWebIdentity OIDC 토큰으로 역할 인수 + AssumeRoleWithWebIdentity(ctx context.Context, config *AssumeRoleConfig) (*CredentialResponse, error) + + // AssumeRoleWithSAML SAML assertion으로 역할 인수 + AssumeRoleWithSAML(ctx context.Context, config *AssumeRoleConfig, samlAssertion string) (*CredentialResponse, error) + + // AssumeRole Secret Key로 역할 인수 + AssumeRole(ctx context.Context, config *AssumeRoleConfig) (*CredentialResponse, error) + + // ValidateCredentials 자격 증명 유효성 검증 + ValidateCredentials(ctx context.Context, credentials map[string]string) error + + // GetCspType CSP 타입 반환 + GetCspType() string +} + +// PolicyDefinition 정책 정의 +type PolicyDefinition struct { + Name string `json:"name"` + Description string `json:"description,omitempty"` + PolicyDoc map[string]interface{} `json:"policy_doc"` + Path string `json:"path,omitempty"` + Tags map[string]string `json:"tags,omitempty"` +} + +// PolicyInfo 정책 정보 +type PolicyInfo struct { + Arn string `json:"arn"` + Name string `json:"name"` + PolicyID string `json:"policy_id"` + Description string `json:"description,omitempty"` + PolicyDoc map[string]interface{} `json:"policy_doc,omitempty"` + Path string `json:"path,omitempty"` + DefaultVersion string `json:"default_version,omitempty"` + AttachmentCount int `json:"attachment_count"` + IsAttachable bool `json:"is_attachable"` + CreateDate time.Time `json:"create_date"` + UpdateDate time.Time `json:"update_date"` +} + +// PolicyFilter 정책 조회 필터 +type PolicyFilter struct { + Scope string `json:"scope,omitempty"` // All, AWS, Local + PathPrefix string `json:"path_prefix,omitempty"` // 경로 접두사 + PolicyUsageType string `json:"policy_usage_type,omitempty"` // PermissionsPolicy, PermissionsBoundary + OnlyAttached bool `json:"only_attached,omitempty"` // 연결된 정책만 + MaxItems int `json:"max_items,omitempty"` + Marker string `json:"marker,omitempty"` +} + +// PolicyManager CSP 정책 관리 인터페이스 +type PolicyManager interface { + // CreatePolicy 정책 생성 + CreatePolicy(ctx context.Context, policy *PolicyDefinition) (*PolicyInfo, error) + + // GetPolicy 정책 조회 + GetPolicy(ctx context.Context, policyArn string) (*PolicyInfo, error) + + // GetPolicyDocument 정책 문서 조회 + GetPolicyDocument(ctx context.Context, policyArn string, versionId string) (map[string]interface{}, error) + + // UpdatePolicy 정책 수정 (새 버전 생성) + UpdatePolicy(ctx context.Context, policyArn string, policy *PolicyDefinition) (*PolicyInfo, error) + + // DeletePolicy 정책 삭제 + DeletePolicy(ctx context.Context, policyArn string) error + + // ListPolicies 정책 목록 조회 + ListPolicies(ctx context.Context, filter *PolicyFilter) ([]*PolicyInfo, string, error) + + // AttachPolicyToRole 역할에 정책 연결 + AttachPolicyToRole(ctx context.Context, roleName, policyArn string) error + + // DetachPolicyFromRole 역할에서 정책 분리 + DetachPolicyFromRole(ctx context.Context, roleName, policyArn string) error + + // ListAttachedRolePolicies 역할에 연결된 정책 목록 조회 + ListAttachedRolePolicies(ctx context.Context, roleName string) ([]*PolicyInfo, error) + + // GetCspType CSP 타입 반환 + GetCspType() string +} diff --git a/src/docs/docs.go b/src/docs/docs.go index bc98c2c1..3efe9df1 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -127,7 +127,44 @@ const docTemplate = `{ ], "summary": "Refresh access token", "operationId": "mciamRefreshToken", - "responses": {} + "parameters": [ + { + "description": "Refresh token", + "name": "refresh_token", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "New token information", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "error: Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } } }, "/api/auth/temp-credential-csps": { @@ -174,6 +211,17 @@ const docTemplate = `{ ], "summary": "Validate access token", "operationId": "mciamValidateToken", + "parameters": [ + { + "description": "Refresh token", + "name": "refresh_token", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "Token validation result with new token if refreshed", @@ -182,6 +230,15 @@ const docTemplate = `{ "additionalProperties": true } }, + "400": { + "description": "error: Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "401": { "description": "error: Unauthorized", "schema": { @@ -194,14 +251,14 @@ const docTemplate = `{ } } }, - "/api/csp-credentials": { - "get": { + "/api/csp-accounts": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "모든 CSP 인증 정보 목록을 조회합니다", + "description": "Create a new CSP account", "consumes": [ "application/json" ], @@ -209,41 +266,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 목록 조회", - "operationId": "mciamListCredentials", - "responses": {} - }, - "post": { - "security": [ + "summary": "Create CSP account", + "operationId": "createCspAccount", + "parameters": [ { - "BearerAuth": [] + "description": "CSP Account Info", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspAccountRequest" + } } ], - "description": "새로운 CSP 인증 정보를 생성합니다", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "csp-credentials" - ], - "summary": "새 CSP 인증 정보 생성", - "operationId": "mciamCreateCredential", - "responses": {} + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.CspAccount" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } } }, - "/api/csp-credentials/{id}": { + "/api/csp-accounts/id/{accountId}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "특정 CSP 인증 정보를 ID로 조회합니다", + "description": "Retrieve CSP account details by ID", "consumes": [ "application/json" ], @@ -251,22 +324,46 @@ const docTemplate = `{ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 ID로 조회", - "operationId": "mciamGetCredentialByID", + "summary": "Get CSP account by ID", + "operationId": "getCspAccountByID", "parameters": [ { "type": "string", - "description": "Credential ID", - "name": "id", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true } ], "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.CspAccount" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "404": { - "description": "error: Credential not found", + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -282,7 +379,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "CSP 인증 정보를 업데이트합니다", + "description": "Update CSP account details", "consumes": [ "application/json" ], @@ -290,22 +387,55 @@ const docTemplate = `{ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 업데이트", - "operationId": "mciamUpdateCredential", + "summary": "Update CSP account", + "operationId": "updateCspAccount", "parameters": [ { "type": "string", - "description": "Credential ID", - "name": "id", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true + }, + { + "description": "CSP Account Info", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UpdateCspAccountRequest" + } } ], "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.CspAccount" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "404": { - "description": "error: Credential not found", + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -321,7 +451,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "CSP 인증 정보를 삭제합니다", + "description": "Delete a CSP account by ID", "consumes": [ "application/json" ], @@ -329,15 +459,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 삭제", - "operationId": "mciamDeleteCredential", + "summary": "Delete CSP account", + "operationId": "deleteCspAccount", "parameters": [ { "type": "string", - "description": "Credential ID", - "name": "id", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true } @@ -346,8 +476,8 @@ const docTemplate = `{ "204": { "description": "No Content" }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -355,8 +485,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -364,8 +494,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Credential not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -376,9 +506,14 @@ const docTemplate = `{ } } }, - "/api/initial-admin": { + "/api/csp-accounts/id/{accountId}/activate": { "post": { - "description": "Creates the initial platform admin user with necessary permissions. platform admin 생성인데", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Activate a CSP account", "consumes": [ "application/json" ], @@ -386,34 +521,67 @@ const docTemplate = `{ "application/json" ], "tags": [ - "admin" + "csp-accounts" ], - "summary": "Setup initial platform admin", - "operationId": "setupInitialAdmin", + "summary": "Activate CSP account", + "operationId": "activateCspAccount", "parameters": [ { - "description": "Setup Initial Admin Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.SetupInitialAdminRequest" - } + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/mcmp-api-permission-action-mappings": { + "/api/csp-accounts/id/{accountId}/deactivate": { "post": { - "description": "Creates a new mapping between a permission and an API action", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deactivate a CSP account", "consumes": [ "application/json" ], @@ -421,31 +589,67 @@ const docTemplate = `{ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-accounts" ], - "summary": "Create permission-action mapping", - "operationId": "createMcmpApiPermissionActionMapping", + "summary": "Deactivate CSP account", + "operationId": "deactivateCspAccount", "parameters": [ { - "description": "Mapping to create", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" - } + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } } }, - "/api/mcmp-api-permission-action-mappings/actions/list": { + "/api/csp-accounts/id/{accountId}/validate": { "post": { - "description": "Returns all workspace actions mapped to a specific permission", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Validate CSP account configuration", "consumes": [ "application/json" ], @@ -453,15 +657,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-accounts" ], - "summary": "Get workspace actions by permission ID", - "operationId": "listWorkspaceActionsByPermissionID", + "summary": "Validate CSP account", + "operationId": "validateCspAccount", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true } @@ -470,18 +674,50 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/mcmpapi.McmpApiAction" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } } } } }, - "/api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions": { - "get": { - "description": "Returns all permissions mapped to a specific API action", + "/api/csp-accounts/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of CSP accounts with optional filters", "consumes": [ "application/json" ], @@ -489,17 +725,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-accounts" ], - "summary": "Get permissions by action ID", - "operationId": "listPermissionsByActionID", + "summary": "List CSP accounts", + "operationId": "listCspAccounts", "parameters": [ { - "type": "integer", - "description": "Action ID", - "name": "actionId", - "in": "path", - "required": true + "description": "Filter options", + "name": "filter", + "in": "body", + "schema": { + "$ref": "#/definitions/model.CspAccountFilter" + } } ], "responses": { @@ -508,6 +745,15 @@ const docTemplate = `{ "schema": { "type": "array", "items": { + "$ref": "#/definitions/model.CspAccount" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { "type": "string" } } @@ -515,9 +761,34 @@ const docTemplate = `{ } } }, - "/api/mcmp-api-permission-action-mappings/list": { + "/api/csp-credentials": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "모든 CSP 인증 정보 목록을 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "CSP 인증 정보 목록 조회", + "operationId": "mciamListCredentials", + "responses": {} + }, "post": { - "description": "Returns all platform actions mapped to a specific permission", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "새로운 CSP 인증 정보를 생성합니다", "consumes": [ "application/json" ], @@ -525,35 +796,60 @@ const docTemplate = `{ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-credentials" ], - "summary": "List platform actions by permission ID", - "operationId": "listPlatformActions", + "summary": "새 CSP 인증 정보 생성", + "operationId": "mciamCreateCredential", + "responses": {} + } + }, + "/api/csp-credentials/{id}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "특정 CSP 인증 정보를 ID로 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "CSP 인증 정보 ID로 조회", + "operationId": "mciamGetCredentialByID", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", + "description": "Credential ID", + "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/mcmpapi.McmpApiAction" + "type": "object", + "additionalProperties": { + "type": "string" } } } } - } - }, - "/api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId}": { + }, "put": { - "description": "Updates an existing mapping between a permission and an API action", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -561,38 +857,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-credentials" ], - "summary": "Update permission-action mapping", - "operationId": "updateMapping", + "summary": "CSP 인증 정보 업데이트", + "operationId": "mciamUpdateCredential", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "Action ID", - "name": "actionId", + "description": "Credential ID", + "name": "id", "in": "path", "required": true - }, - { - "description": "Updated mapping", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" - } } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { "type": "object", "additionalProperties": { @@ -603,7 +883,12 @@ const docTemplate = `{ } }, "delete": { - "description": "Deletes a mapping between a permission and an API action", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 삭제합니다", "consumes": [ "application/json" ], @@ -611,22 +896,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-credentials" ], - "summary": "Delete permission-action mapping", - "operationId": "deleteMapping", + "summary": "CSP 인증 정보 삭제", + "operationId": "mciamDeleteCredential", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "Action ID", - "name": "actionId", + "description": "Credential ID", + "name": "id", "in": "path", "required": true } @@ -634,54 +912,45 @@ const docTemplate = `{ "responses": { "204": { "description": "No Content" - } - } - } - }, - "/api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions": { - "get": { - "description": "Returns all platform actions mapped to a specific permission", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "mcmp-api-permission-action-mappings" - ], - "summary": "Get platform actions by permission ID", - "operationId": "getPlatformActionsByPermissionID", - "parameters": [ - { - "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + "401": { + "description": "error: Unauthorized", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/mcmpapi.McmpApiAction" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Credential not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } } } } }, - "/api/mcmp-apis/list": { + "/api/csp-idp-configs": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieves all MCMP API service and action definitions currently stored in the database.", + "description": "Create a new CSP IDP configuration", "consumes": [ "application/json" ], @@ -689,33 +958,39 @@ const docTemplate = `{ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Get All Stored MCMP API Definitions", - "operationId": "listServicesAndActions", + "summary": "Create CSP IDP config", + "operationId": "createCspIdpConfig", "parameters": [ { - "type": "string", - "description": "Filter by service name", - "name": "serviceName", - "in": "query" - }, - { - "type": "string", - "description": "Filter by action name (operationId)", - "name": "actionName", - "in": "query" + "description": "CSP IDP Config Info", + "name": "config", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspIdpConfigRequest" + } } ], "responses": { - "200": { - "description": "Successfully retrieved API definitions", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiDefinitions" + "$ref": "#/definitions/model.CspIdpConfig" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "500": { - "description": "message: Failed to retrieve API definitions", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -726,14 +1001,14 @@ const docTemplate = `{ } } }, - "/api/mcmp-apis/mcmpApiCall": { - "post": { + "/api/csp-idp-configs/id/{configId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Executes a defined MCMP API action with parameters structured in McmpApiCallRequest.", + "description": "Retrieve CSP IDP configuration details by ID", "consumes": [ "application/json" ], @@ -741,30 +1016,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Call an external MCMP API action (Structured Request)", - "operationId": "mcmpApiCall", + "summary": "Get CSP IDP config by ID", + "operationId": "getCspIdpConfigByID", "parameters": [ { - "description": "API Call Request", - "name": "callRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.McmpApiCallRequest" - } + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "External API Response (structure depends on the called API)", + "description": "OK", "schema": { - "type": "object" + "$ref": "#/definitions/model.CspIdpConfig" } }, "400": { - "description": "error: Invalid request body or parameters", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -773,7 +1046,7 @@ const docTemplate = `{ } }, "404": { - "description": "error: Service or action not found", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -782,16 +1055,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: Internal server error or failed to call external API", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "503": { - "description": "error: External API unavailable", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -800,16 +1064,14 @@ const docTemplate = `{ } } } - } - }, - "/api/mcmp-apis/name/{serviceName}": { + }, "put": { "security": [ { "BearerAuth": [] } ], - "description": "Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API service definition identified by its name. Cannot update name or version.", + "description": "Update CSP IDP configuration details", "consumes": [ "application/json" ], @@ -817,40 +1079,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Update MCMP API Service Definition", - "operationId": "UpdateFrameworkService", + "summary": "Update CSP IDP config", + "operationId": "updateCspIdpConfig", "parameters": [ { "type": "string", - "description": "Service Name to update", - "name": "serviceName", + "description": "Config ID", + "name": "configId", "in": "path", "required": true }, { - "description": "Fields to update (e.g., {\\", - "name": "updates", + "description": "CSP IDP Config Info", + "name": "config", "in": "body", "required": true, "schema": { - "type": "object" + "$ref": "#/definitions/model.UpdateCspIdpConfigRequest" } } ], "responses": { "200": { - "description": "message: Service updated successfully\" // Or return updated service?", + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.CspIdpConfig" } }, "400": { - "description": "error: Invalid service name or request body", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -859,7 +1118,7 @@ const docTemplate = `{ } }, "404": { - "description": "error: Service not found", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -868,7 +1127,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: Failed to update service", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -877,16 +1136,14 @@ const docTemplate = `{ } } } - } - }, - "/api/mcmp-apis/name/{serviceName}/versions/{version}/activate": { - "put": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Sets the specified version of an MCMP API service as the active one.", + "description": "Delete a CSP IDP configuration by ID", "consumes": [ "application/json" ], @@ -894,22 +1151,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Set Active Version for a Service", - "operationId": "setActiveVersion", + "summary": "Delete CSP IDP config", + "operationId": "deleteCspIdpConfig", "parameters": [ { "type": "string", - "description": "Service Name", - "name": "serviceName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Version to activate", - "name": "version", + "description": "Config ID", + "name": "configId", "in": "path", "required": true } @@ -919,7 +1169,7 @@ const docTemplate = `{ "description": "No Content" }, "400": { - "description": "error: Invalid service name or version", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -928,7 +1178,7 @@ const docTemplate = `{ } }, "404": { - "description": "error: Service or version not found", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -937,7 +1187,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: Failed to set active version", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -948,14 +1198,14 @@ const docTemplate = `{ } } }, - "/api/mcmp-apis/syncMcmpAPIs": { + "/api/csp-idp-configs/id/{configId}/activate": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", + "description": "Activate a CSP IDP configuration", "consumes": [ "application/json" ], @@ -963,13 +1213,40 @@ const docTemplate = `{ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" + ], + "summary": "Activate CSP IDP config", + "operationId": "activateCspIdpConfig", + "parameters": [ + { + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true + } ], - "summary": "Sync MCMP API Definitions", - "operationId": "syncMcmpAPIs", "responses": { "200": { - "description": "message: Successfully triggered MCMP API sync", + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -978,7 +1255,7 @@ const docTemplate = `{ } }, "500": { - "description": "message: Failed to trigger MCMP API sync", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -989,32 +1266,37 @@ const docTemplate = `{ } } }, - "/api/mcmp-apis/test/mc-infra-manager/getallns": { - "get": { + "/api/csp-idp-configs/id/{configId}/deactivate": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", + "description": "Deactivate a CSP IDP configuration", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "McmpAPI", - "Test" + "csp-idp-configs" + ], + "summary": "Deactivate CSP IDP config", + "operationId": "deactivateCspIdpConfig", + "parameters": [ + { + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true + } ], - "summary": "Test Call to mc-infra-manager GetAllNs", - "operationId": "testCallGetAllNs", "responses": { "200": { - "description": "Response from mc-infra-manager GetAllNs", - "schema": { - "type": "object" - } - }, - "400": { - "description": "error: Bad Request (e.g., invalid parameters)", + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -1022,8 +1304,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Service or Action Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1031,8 +1313,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "error: Internal Server Error", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1040,8 +1322,8 @@ const docTemplate = `{ } } }, - "503": { - "description": "error: External API Service Unavailable", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1052,14 +1334,14 @@ const docTemplate = `{ } } }, - "/api/menus": { + "/api/csp-idp-configs/id/{configId}/test": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new menu", + "description": "Test connection to CSP using IDP configuration", "consumes": [ "application/json" ], @@ -1067,39 +1349,67 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-idp-configs" ], - "summary": "Create new menu", - "operationId": "createMenu", + "summary": "Test CSP IDP connection", + "operationId": "testCspIdpConnection", "parameters": [ { - "description": "Menu Info", - "name": "menu", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Menu" - } + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.Menu" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/menus/id/{menuId}": { - "put": { + "/api/csp-idp-configs/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update menu information", + "description": "Retrieve a list of CSP IDP configurations with optional filters", "consumes": [ "application/json" ], @@ -1107,25 +1417,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-idp-configs" ], - "summary": "Update menu information", - "operationId": "updateMenu", + "summary": "List CSP IDP configs", + "operationId": "listCspIdpConfigs", "parameters": [ { - "type": "string", - "description": "Menu ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Menu Info", - "name": "menu", + "description": "Filter options", + "name": "filter", "in": "body", - "required": true, "schema": { - "$ref": "#/definitions/model.Menu" + "$ref": "#/definitions/model.CspIdpConfigFilter" } } ], @@ -1133,18 +1435,32 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Menu" + "type": "array", + "items": { + "$ref": "#/definitions/model.CspIdpConfig" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } - }, + } + }, + "/api/csp-policies": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get menu details by ID", + "description": "Create a new CSP policy", "consumes": [ "application/json" ], @@ -1152,35 +1468,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Get menu by ID", - "operationId": "getMenuByID", + "summary": "Create CSP policy", + "operationId": "createCspPolicy", "parameters": [ { - "type": "string", - "description": "Menu ID", - "name": "menuId", - "in": "path", - "required": true + "description": "CSP Policy Info", + "name": "policy", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspPolicyRequest" + } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/model.Menu" + "$ref": "#/definitions/model.CspPolicy" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } - }, - "delete": { + } + }, + "/api/csp-policies/attach": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a menu", + "description": "Attach a CSP policy to a CSP role", "consumes": [ "application/json" ], @@ -1188,57 +1526,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Delete menu", - "operationId": "deleteMenu", + "summary": "Attach policy to role", + "operationId": "attachPolicyToRole", "parameters": [ { - "type": "string", - "description": "Menu ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - } - } - } - }, - "/api/menus/list": { - "post": { - "security": [ - { - "BearerAuth": [] + "description": "Attach Policy Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AttachPolicyRequest" + } } ], - "description": "List all menus as a tree structure. Admin permission required.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "List all menus", - "operationId": "listMenus", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" + "type": "object", + "additionalProperties": { + "type": "string" } } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1246,8 +1560,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1256,7 +1570,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1267,14 +1581,14 @@ const docTemplate = `{ } } }, - "/api/menus/platform-roles": { + "/api/csp-policies/detach": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new menu mapping", + "description": "Detach a CSP policy from a CSP role", "consumes": [ "application/json" ], @@ -1282,24 +1596,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menu" + "csp-policies" ], - "summary": "Create menu mapping", - "operationId": "createMenusRolesMapping", + "summary": "Detach policy from role", + "operationId": "detachPolicyFromRole", "parameters": [ { - "description": "Menu Mapping", - "name": "mapping", + "description": "Detach Policy Request", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateMenuMappingRequest" + "$ref": "#/definitions/model.AttachPolicyRequest" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -1316,6 +1630,15 @@ const docTemplate = `{ } } }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "500": { "description": "Internal Server Error", "schema": { @@ -1326,14 +1649,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/csp-policies/id/{policyId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Delete the mapping between a platform role and a menu.", + "description": "Retrieve CSP policy details by ID", "consumes": [ "application/json" ], @@ -1341,27 +1666,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Delete platform role-menu mapping", - "operationId": "deleteMenusRolesMapping", + "summary": "Get CSP policy by ID", + "operationId": "getCspPolicyByID", "parameters": [ { "type": "string", - "description": "Platform Role ID", - "name": "roleId", - "in": "query" - }, - { - "type": "string", - "description": "Menu ID", - "name": "menuId", - "in": "query" + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "message: Menu mapping deleted successfully", + "description": "OK", + "schema": { + "$ref": "#/definitions/model.CspPolicy" + } + }, + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1369,8 +1695,8 @@ const docTemplate = `{ } } }, - "400": { - "description": "error: platform role and menu ID are required", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1379,7 +1705,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1388,16 +1714,14 @@ const docTemplate = `{ } } } - } - }, - "/api/menus/platform-roles/list": { - "post": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "List menus mapped to a specific platform role.", + "description": "Update CSP policy details", "consumes": [ "application/json" ], @@ -1405,36 +1729,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "List menus mapped to platform role", - "operationId": "listMappedMenusByRole", + "summary": "Update CSP policy", + "operationId": "updateCspPolicy", "parameters": [ { "type": "string", - "description": "Platform Role ID", - "name": "roleId", - "in": "query" + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true }, { - "type": "string", - "description": "Menu ID", - "name": "menuId", - "in": "query" + "description": "CSP Policy Info", + "name": "policy", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UpdateCspPolicyRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Menu" - } + "$ref": "#/definitions/model.CspPolicy" } }, "400": { - "description": "error: platform role is required", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1442,48 +1767,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "error: 서버 내부 오류", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/api/menus/setup/initial-menus": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "Register/Update menus from YAML file or URL", - "operationId": "registerMenusFromYAML", - "parameters": [ - { - "type": "string", - "description": "YAML file path (optional, uses .env URL or default local path if not provided)", - "name": "filePath", - "in": "query" - } - ], - "responses": { - "200": { - "description": "message: Successfully registered menus from YAML", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1492,7 +1777,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 실패 메시지", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1501,42 +1786,40 @@ const docTemplate = `{ } } } - } - }, - "/api/menus/setup/initial-menus2": { - "post": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.", + "description": "Delete a CSP policy by ID", "consumes": [ - "text/plain" + "application/json" ], "produces": [ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Register/Update menus from YAML in request body", - "operationId": "registerMenusFromBody", + "summary": "Delete CSP policy", + "operationId": "deleteCspPolicy", "parameters": [ { - "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", - "description": "Menu definitions in YAML format (must contain 'menus:' root key)", - "name": "yaml", - "in": "body", - "required": true, - "schema": { - "type": "string" - } + "type": "string", + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "message: Successfully registered menus from request body", + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1544,8 +1827,8 @@ const docTemplate = `{ } } }, - "400": { - "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1554,7 +1837,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1565,14 +1848,14 @@ const docTemplate = `{ } } }, - "/api/menus/tree/list": { - "post": { + "/api/csp-policies/id/{policyId}/document": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "List all menus as a tree structure. Admin permission required.", + "description": "Get the policy document content", "consumes": [ "application/json" ], @@ -1580,22 +1863,29 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-policies" + ], + "summary": "Get policy document", + "operationId": "getPolicyDocument", + "parameters": [ + { + "type": "string", + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true + } ], - "summary": "List all menus Tree", - "operationId": "listMenusTree", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" - } + "type": "object", + "additionalProperties": true } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1603,8 +1893,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1613,7 +1903,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1624,14 +1914,14 @@ const docTemplate = `{ } } }, - "/api/menus/user-menu-tree": { - "get": { + "/api/csp-policies/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get menu tree based on user's platform roles", + "description": "Retrieve a list of CSP policies with optional filters", "consumes": [ "application/json" ], @@ -1639,17 +1929,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "csp-policies" + ], + "summary": "List CSP policies", + "operationId": "listCspPolicies", + "parameters": [ + { + "description": "Filter options", + "name": "filter", + "in": "body", + "schema": { + "$ref": "#/definitions/model.CspPolicyFilter" + } + } ], - "summary": "Get user menu tree by platform roles", - "operationId": "getUserMenuTree", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.MenuTreeNode" + "$ref": "#/definitions/model.CspPolicy" } } }, @@ -1665,14 +1965,14 @@ const docTemplate = `{ } } }, - "/api/permissions/mciam": { - "post": { + "/api/csp-policies/role/{roleId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new permission with the specified information.", + "description": "Get list of policies attached to a CSP role", "consumes": [ "application/json" ], @@ -1680,26 +1980,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "csp-policies" ], - "summary": "Create new permission", - "operationId": "createMciamPermission", + "summary": "Get policies attached to role", + "operationId": "getRolePolicies", "parameters": [ { - "description": "Permission Info", - "name": "permission", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.MciamPermission" - } + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.MciamPermission" + "type": "array", + "items": { + "$ref": "#/definitions/model.CspPolicy" + } } }, "400": { @@ -1723,14 +2024,14 @@ const docTemplate = `{ } } }, - "/api/permissions/mciam/id/{id}": { - "get": { + "/api/csp-policies/sync": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve permission details by permission ID.", + "description": "Synchronize policies from the CSP cloud", "consumes": [ "application/json" ], @@ -1738,28 +2039,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "csp-policies" ], - "summary": "Get permission by ID", - "operationId": "getMciamPermissionByID", + "summary": "Sync CSP policies from cloud", + "operationId": "syncCspPolicies", "parameters": [ { - "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true + "description": "Sync Policies Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.SyncPoliciesRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.MciamPermission" + "type": "array", + "items": { + "$ref": "#/definitions/model.CspPolicy" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1779,14 +2085,9 @@ const docTemplate = `{ } } }, - "/api/permissions/mciam/list": { + "/api/initial-admin": { "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Retrieve a list of all permissions.", + "description": "Creates the initial platform admin user with necessary permissions. platform admin 생성인데", "consumes": [ "application/json" ], @@ -1794,40 +2095,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "admin" + ], + "summary": "Setup initial platform admin", + "operationId": "setupInitialAdmin", + "parameters": [ + { + "description": "Setup Initial Admin Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.SetupInitialAdminRequest" + } + } ], - "summary": "List all permissions", - "operationId": "listMciamPermissions", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MciamPermission" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Response" } } } } }, - "/api/permissions/mciam/{id}": { - "put": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Update the details of an existing permission.", + "/api/mcmp-api-permission-action-mappings": { + "post": { + "description": "Creates a new mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -1835,71 +2130,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "Update permission", - "operationId": "updateMciamPermission", + "summary": "Create permission-action mapping", + "operationId": "createMcmpApiPermissionActionMapping", "parameters": [ { - "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - }, - { - "description": "Permission Info", - "name": "permission", + "description": "Mapping to create", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.MciamPermission" + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" } } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.MciamPermission" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } + "204": { + "description": "No Content" } } - }, - "delete": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Delete a permission by its ID.", + } + }, + "/api/mcmp-api-permission-action-mappings/actions/list": { + "post": { + "description": "Returns all workspace actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -1907,10 +2162,10 @@ const docTemplate = `{ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "Delete permission", - "operationId": "deleteMciamPermission", + "summary": "Get workspace actions by permission ID", + "operationId": "listWorkspaceActionsByPermissionID", "parameters": [ { "type": "string", @@ -1921,38 +2176,21 @@ const docTemplate = `{ } ], "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/api/projects": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Create a new project with the specified information.", + "/api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions": { + "get": { + "description": "Returns all permissions mapped to a specific API action", "consumes": [ "application/json" ], @@ -1960,42 +2198,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" ], - "summary": "Create new project", - "operationId": "createProject", + "summary": "Get permissions by action ID", + "operationId": "listPermissionsByActionID", "parameters": [ { - "description": "Project Info", - "name": "project", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Project" - } + "type": "integer", + "description": "Action ID", + "name": "actionId", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { + "type": "array", + "items": { "type": "string" } } @@ -2003,14 +2224,9 @@ const docTemplate = `{ } } }, - "/api/projects/list": { + "/api/mcmp-api-permission-action-mappings/list": { "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Retrieve a list of all projects.", + "description": "Returns all platform actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -2018,40 +2234,35 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" + ], + "summary": "List platform actions by permission ID", + "operationId": "listPlatformActions", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } ], - "summary": "List all projects", - "operationId": "listProjects", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/api/projects/name/{projectName}": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get project details by name", + "/api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId}": { + "put": { + "description": "Updates an existing mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -2059,37 +2270,38 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" ], - "summary": "Get project by name", - "operationId": "getProjectByName", + "summary": "Update permission-action mapping", + "operationId": "updateMapping", "parameters": [ { "type": "string", - "description": "Project Name", - "name": "name", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true + }, + { + "description": "Updated mapping", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2098,16 +2310,9 @@ const docTemplate = `{ } } } - } - }, - "/api/projects/{id}": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Retrieve project details by project ID.", + }, + "delete": { + "description": "Deletes a mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -2115,53 +2320,77 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" ], - "summary": "Get project by ID", - "operationId": "getProjectByID", + "summary": "Delete permission-action mapping", + "operationId": "deleteMapping", "parameters": [ { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", + "204": { + "description": "No Content" + } + } + } + }, + "/api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions": { + "get": { + "description": "Returns all platform actions mapped to a specific permission", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcmp-api-permission-action-mappings" + ], + "summary": "Get platform actions by permission ID", + "operationId": "getPlatformActionsByPermissionID", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } - }, - "put": { + } + }, + "/api/mcmp-apis/import": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing project.", + "description": "Fetches API specifications from remote URLs and imports them to the database. Supports swagger and openapi source types.", "consumes": [ "application/json" ], @@ -2169,46 +2398,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "McmpAPI" ], - "summary": "Update project", - "operationId": "updateProject", + "summary": "Import MCMP APIs from Remote Sources", + "operationId": "importAPIs", "parameters": [ { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "description": "Project Info", - "name": "project", + "description": "Frameworks to import", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.ImportApiRequest" } } ], "responses": { "200": { - "description": "OK", + "description": "Import results", "schema": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.ImportApiResponse" } }, "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "Not Found", + "description": "error: Invalid request body", "schema": { "type": "object", "additionalProperties": { @@ -2217,7 +2430,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: Failed to import APIs", "schema": { "type": "object", "additionalProperties": { @@ -2226,14 +2439,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/mcmp-apis/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a project by its ID.", + "description": "Retrieves all MCMP API service and action definitions currently stored in the database.", "consumes": [ "application/json" ], @@ -2241,34 +2456,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "McmpAPI" ], - "summary": "Delete project", - "operationId": "deleteProject", + "summary": "Get All Stored MCMP API Definitions", + "operationId": "listServicesAndActions", "parameters": [ { "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true + "description": "Filter by service name", + "name": "serviceName", + "in": "query" + }, + { + "type": "string", + "description": "Filter by action name (operationId)", + "name": "actionName", + "in": "query" } ], "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", + "200": { + "description": "Successfully retrieved API definitions", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/mcmpapi.McmpApiDefinitions" } }, "500": { - "description": "Internal Server Error", + "description": "message: Failed to retrieve API definitions", "schema": { "type": "object", "additionalProperties": { @@ -2279,14 +2493,14 @@ const docTemplate = `{ } } }, - "/api/projects/{id}/workspaces/{workspaceId}": { + "/api/mcmp-apis/mcmpApiCall": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "프로젝트에 워크스페이스를 연결합니다.", + "description": "Executes a defined MCMP API action with parameters structured in McmpApiCallRequest.", "consumes": [ "application/json" ], @@ -2294,32 +2508,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "McmpAPI" ], - "summary": "프로젝트에 워크스페이스 연결", - "operationId": "addWorkspaceToProject", + "summary": "Call an external MCMP API action (Structured Request)", + "operationId": "mcmpApiCall", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "API Call Request", + "name": "callRequest", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.McmpApiCallRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "External API Response (structure depends on the called API)", + "schema": { + "type": "object" + } }, "400": { - "description": "error: 잘못된 ID 형식", + "description": "error: Invalid request body or parameters", "schema": { "type": "object", "additionalProperties": { @@ -2328,7 +2540,7 @@ const docTemplate = `{ } }, "404": { - "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", + "description": "error: Service or action not found", "schema": { "type": "object", "additionalProperties": { @@ -2337,7 +2549,16 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "error: Internal server error or failed to call external API", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "503": { + "description": "error: External API unavailable", "schema": { "type": "object", "additionalProperties": { @@ -2348,14 +2569,14 @@ const docTemplate = `{ } } }, - "/api/resource-types/cloud-resources": { - "post": { + "/api/mcmp-apis/name/{serviceName}": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "새로운 리소스 타입을 생성합니다", + "description": "Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API service definition identified by its name. Cannot update name or version.", "consumes": [ "application/json" ], @@ -2363,30 +2584,40 @@ const docTemplate = `{ "application/json" ], "tags": [ - "resource-types" + "McmpAPI" ], - "summary": "Cloud에서 관리되는 Resource(vm, nlb, k8s 등의 그룹) 새 리소스 타입 생성", - "operationId": "createResourceType", + "summary": "Update MCMP API Service Definition", + "operationId": "UpdateFrameworkService", "parameters": [ { - "description": "Resource Type Info", - "name": "resourceType", + "type": "string", + "description": "Service Name to update", + "name": "serviceName", + "in": "path", + "required": true + }, + { + "description": "Fields to update (e.g., {\\", + "name": "updates", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.ResourceType" + "type": "object" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "message: Service updated successfully\" // Or return updated service?", "schema": { - "$ref": "#/definitions/model.ResourceType" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "error: Invalid request", + "description": "error: Invalid service name or request body", "schema": { "type": "object", "additionalProperties": { @@ -2394,8 +2625,8 @@ const docTemplate = `{ } } }, - "401": { - "description": "error: Unauthorized", + "404": { + "description": "error: Service not found", "schema": { "type": "object", "additionalProperties": { @@ -2403,8 +2634,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "500": { + "description": "error: Failed to update service", "schema": { "type": "object", "additionalProperties": { @@ -2415,14 +2646,14 @@ const docTemplate = `{ } } }, - "/api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId": { - "get": { + "/api/mcmp-apis/name/{serviceName}/versions/{version}/activate": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "특정 리소스 타입을 ID로 조회합니다", + "description": "Sets the specified version of an MCMP API service as the active one.", "consumes": [ "application/json" ], @@ -2430,28 +2661,32 @@ const docTemplate = `{ "application/json" ], "tags": [ - "resource-types" + "McmpAPI" ], - "summary": "리소스 타입 ID로 조회", - "operationId": "getCloudResourceTypeByID", + "summary": "Set Active Version for a Service", + "operationId": "setActiveVersion", "parameters": [ { "type": "string", - "description": "Resource Type ID", - "name": "id", + "description": "Service Name", + "name": "serviceName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Version to activate", + "name": "version", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.ResourceType" - } + "204": { + "description": "No Content" }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "error: Invalid service name or version", "schema": { "type": "object", "additionalProperties": { @@ -2459,8 +2694,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "error: Service or version not found", "schema": { "type": "object", "additionalProperties": { @@ -2468,8 +2703,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Resource Type not found", + "500": { + "description": "error: Failed to set active version", "schema": { "type": "object", "additionalProperties": { @@ -2478,14 +2713,16 @@ const docTemplate = `{ } } } - }, - "put": { + } + }, + "/api/mcmp-apis/syncMcmpAPIs": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "리소스 타입 정보를 업데이트합니다", + "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", "consumes": [ "application/json" ], @@ -2493,55 +2730,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "resource-types" - ], - "summary": "리소스 타입 업데이트", - "operationId": "updateResourceType", - "parameters": [ - { - "type": "string", - "description": "Resource Type ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Resource Type Info", - "name": "resourceType", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.ResourceType" - } - } + "McmpAPI" ], + "summary": "Sync MCMP API Definitions", + "operationId": "syncMcmpAPIs", "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.ResourceType" - } - }, - "400": { - "description": "error: Invalid request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: Forbidden", + "description": "message: Successfully triggered MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -2549,8 +2744,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Resource Type not found", + "500": { + "description": "message: Failed to trigger MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -2559,49 +2754,34 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/mcmp-apis/test/mc-infra-manager/getallns": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "리소스 타입을 삭제합니다", - "consumes": [ - "application/json" - ], + "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", "produces": [ "application/json" ], "tags": [ - "resource-types" - ], - "summary": "리소스 타입 삭제", - "operationId": "deleteResourceType", - "parameters": [ - { - "type": "string", - "description": "Resource Type ID", - "name": "id", - "in": "path", - "required": true - } + "McmpAPI", + "Test" ], + "summary": "Test Call to mc-infra-manager GetAllNs", + "operationId": "testCallGetAllNs", "responses": { - "204": { - "description": "No Content" - }, - "401": { - "description": "error: Unauthorized", + "200": { + "description": "Response from mc-infra-manager GetAllNs", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "type": "object" } }, - "403": { - "description": "error: Forbidden", + "400": { + "description": "error: Bad Request (e.g., invalid parameters)", "schema": { "type": "object", "additionalProperties": { @@ -2610,48 +2790,16 @@ const docTemplate = `{ } }, "404": { - "description": "error: Resource Type not found", + "description": "error: Service or Action Not Found", "schema": { "type": "object", "additionalProperties": { "type": "string" } } - } - } - } - }, - "/api/resource-types/cloud-resources/list": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "모든 리소스 타입 목록을 조회합니다", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "resource-types" - ], - "summary": "리소스 타입 목록 조회", - "operationId": "listCloudResourceTypes", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.ResourceType" - } - } }, - "401": { - "description": "error: Unauthorized", + "500": { + "description": "error: Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2659,8 +2807,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "503": { + "description": "error: External API Service Unavailable", "schema": { "type": "object", "additionalProperties": { @@ -2671,14 +2819,14 @@ const docTemplate = `{ } } }, - "/api/roles": { + "/api/menus": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new role", + "description": "Create a new menu", "consumes": [ "application/json" ], @@ -2686,18 +2834,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Create role", - "operationId": "createRole", + "summary": "Create new menu", + "operationId": "createMenu", "parameters": [ { - "description": "Role Info", - "name": "role", + "description": "Menu Info", + "name": "menu", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.Menu" } } ], @@ -2705,38 +2853,20 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/model.RoleMaster" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } } }, - "/api/roles/assign/platform-role": { - "post": { + "/api/menus/id/{menuId}": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "Assign a platform role to a user", + "description": "Update menu information", "consumes": [ "application/json" ], @@ -2744,18 +2874,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Assign platform role", - "operationId": "assignPlatformRole", + "summary": "Update menu information", + "operationId": "updateMenu", "parameters": [ { - "description": "Platform Role Assignment Info", - "name": "request", + "type": "string", + "description": "Menu ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Menu Info", + "name": "menu", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.Menu" } } ], @@ -2763,41 +2900,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } - } - }, - "/api/roles/assign/workspace-role": { + }, "post": { "security": [ { "BearerAuth": [] } ], - "description": "Assign a workspace role to a user", + "description": "Get menu details by ID", "consumes": [ "application/json" ], @@ -2805,60 +2919,35 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Assign workspace role", - "operationId": "assignWorkspaceRole", + "summary": "Get menu by ID", + "operationId": "getMenuByID", "parameters": [ { - "description": "Workspace Role Assignment Info", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.AssignWorkspaceRoleRequest" - } + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } - } - }, - "/api/roles/csp": { - "post": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new csp role", + "description": "Delete a menu", "consumes": [ "application/json" ], @@ -2866,60 +2955,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Create csp role", - "operationId": "createCspRole", + "summary": "Delete menu", + "operationId": "deleteMenu", "parameters": [ { - "description": "CSP Role Creation Info", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" - } + "type": "string", + "description": "Menu ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } + "204": { + "description": "No Content" } } } }, - "/api/roles/csp-roles": { + "/api/menus/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new mapping between role and CSP role", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -2927,30 +2990,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Create role-CSP role mapping", - "operationId": "addCspRoleMappings", - "parameters": [ - { - "description": "Mapping Info", - "name": "mapping", - "in": "body", - "required": true, + "summary": "List all menus", + "operationId": "listMenus", + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } } - } - ], - "responses": { - "201": { - "description": "Created", + }, + "401": { + "description": "error: Unauthorized", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2959,7 +3023,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -2970,14 +3034,14 @@ const docTemplate = `{ } } }, - "/api/roles/csp-roles/batch": { + "/api/menus/platform-roles": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create multiple new csp roles", + "description": "Create a new menu mapping", "consumes": [ "application/json" ], @@ -2985,18 +3049,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menu" ], - "summary": "Create multiple csp roles", - "operationId": "createCspRoles", + "summary": "Create menu mapping", + "operationId": "createMenusRolesMapping", "parameters": [ { - "description": "Multiple CSP Role Creation Info", - "name": "request", + "description": "Menu Mapping", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateCspRolesRequest" + "$ref": "#/definitions/model.CreateMenuMappingRequest" } } ], @@ -3004,9 +3068,9 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.CspRole" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -3029,16 +3093,14 @@ const docTemplate = `{ } } } - } - }, - "/api/roles/csp-roles/id/:roleId": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get a mapping between role and CSP role", + "description": "Delete the mapping between a platform role and a menu.", "consumes": [ "application/json" ], @@ -3046,30 +3108,36 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Get role-CSP role mapping", - "operationId": "getCspRoleMappingByRoleId", + "summary": "Delete platform role-menu mapping", + "operationId": "deleteMenusRolesMapping", "parameters": [ { - "description": "Mapping Info", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" - } + "type": "string", + "description": "Platform Role ID", + "name": "roleId", + "in": "query" + }, + { + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "message: Menu mapping deleted successfully", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "Bad Request", + "description": "error: platform role and menu ID are required", "schema": { "type": "object", "additionalProperties": { @@ -3078,7 +3146,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3089,14 +3157,14 @@ const docTemplate = `{ } } }, - "/api/roles/csp-roles/id/{roleId}": { - "put": { + "/api/menus/platform-roles/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update role information", + "description": "List menus mapped to a specific platform role.", "consumes": [ "application/json" ], @@ -3104,46 +3172,36 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Update csp role", - "operationId": "updateCspRole", + "summary": "List menus mapped to platform role", + "operationId": "listMappedMenusByRole", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Platform Role ID", "name": "roleId", - "in": "path", - "required": true + "in": "query" }, { - "description": "Role Info", - "name": "role", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" - } + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" } } }, - "404": { - "description": "Not Found", + "400": { + "description": "error: platform role is required", "schema": { "type": "object", "additionalProperties": { @@ -3152,7 +3210,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3161,14 +3219,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/menus/setup/initial-menus": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a role", + "description": "Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml.", "consumes": [ "application/json" ], @@ -3176,25 +3236,21 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Delete csp role", - "operationId": "deleteCspRole", + "summary": "Register/Update menus from YAML file or URL", + "operationId": "registerMenusFromYAML", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "roleId", - "in": "path", - "required": true + "description": "YAML file path (optional, uses .env URL or default local path if not provided)", + "name": "filePath", + "in": "query" } ], "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", + "200": { + "description": "message: Successfully registered menus from YAML", "schema": { "type": "object", "additionalProperties": { @@ -3203,7 +3259,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: 실패 메시지", "schema": { "type": "object", "additionalProperties": { @@ -3214,45 +3270,49 @@ const docTemplate = `{ } } }, - "/api/roles/csp-roles/list": { + "/api/menus/setup/initial-menus2": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get a mapping between role and CSP role", + "description": "Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.", "consumes": [ - "application/json" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Get role-CSP role mapping", - "operationId": "listCspRoleMappings", + "summary": "Register/Update menus from YAML in request body", + "operationId": "registerMenusFromBody", "parameters": [ { - "description": "Mapping Info", - "name": "mapping", + "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", + "description": "Menu definitions in YAML format (must contain 'menus:' root key)", + "name": "yaml", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "string" } } ], "responses": { "200": { - "description": "OK", + "description": "message: Successfully registered menus from request body", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "Bad Request", + "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", "schema": { "type": "object", "additionalProperties": { @@ -3261,7 +3321,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3272,14 +3332,14 @@ const docTemplate = `{ } } }, - "/api/roles/csp/id/{roleId}": { - "get": { + "/api/menus/tree/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get csp role details by ID", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -3287,28 +3347,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" - ], - "summary": "Get csp role by ID", - "operationId": "getCspRoleByID", - "parameters": [ - { - "type": "string", - "description": "CSP Role ID", - "name": "id", - "in": "path", - "required": true - } + "menus" ], + "summary": "List all menus Tree", + "operationId": "listMenusTree", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } } }, - "404": { - "description": "Not Found", + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -3317,7 +3380,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3328,14 +3391,14 @@ const docTemplate = `{ } } }, - "/api/roles/csp/list": { - "post": { + "/api/menus/user-menu-tree": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get a list of all csp roles", + "description": "Get menu tree based on user's platform roles", "consumes": [ "application/json" ], @@ -3343,17 +3406,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "List csp roles", - "operationId": "listCSPRoles", + "summary": "Get user menu tree by platform roles", + "operationId": "getUserMenuTree", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MenuTreeNode" } } }, @@ -3369,14 +3432,14 @@ const docTemplate = `{ } } }, - "/api/roles/csp/name/{roleName}": { - "get": { + "/api/permissions/mciam": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get csp role details by Name", + "description": "Create a new permission with the specified information.", "consumes": [ "application/json" ], @@ -3384,28 +3447,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Get csp role by Name", - "operationId": "getCspRoleByName", + "summary": "Create new permission", + "operationId": "createMciamPermission", "parameters": [ { - "type": "string", - "description": "CSP Role Name", - "name": "name", - "in": "path", - "required": true + "description": "Permission Info", + "name": "permission", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.MciamPermission" + } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MciamPermission" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -3425,14 +3490,14 @@ const docTemplate = `{ } } }, - "/api/roles/id/{roleId}": { + "/api/permissions/mciam/id/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get role details by ID", + "description": "Retrieve permission details by permission ID.", "consumes": [ "application/json" ], @@ -3440,15 +3505,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Get role by ID", - "operationId": "getRoleByRoleID", + "summary": "Get permission by ID", + "operationId": "getMciamPermissionByID", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -3457,7 +3522,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MciamPermission" } }, "404": { @@ -3479,14 +3544,57 @@ const docTemplate = `{ } } } - }, + } + }, + "/api/permissions/mciam/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all permissions.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "permissions" + ], + "summary": "List all permissions", + "operationId": "listMciamPermissions", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MciamPermission" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/permissions/mciam/{id}": { "put": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing role.", + "description": "Update the details of an existing permission.", "consumes": [ "application/json" ], @@ -3494,25 +3602,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Update role", - "operationId": "updateRole", + "summary": "Update permission", + "operationId": "updateMciamPermission", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true }, { - "description": "Role Info", - "name": "role", + "description": "Permission Info", + "name": "permission", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.MciamPermission" } } ], @@ -3520,7 +3628,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MciamPermission" } }, "400": { @@ -3558,7 +3666,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Delete a role by its name.", + "description": "Delete a permission by its ID.", "consumes": [ "application/json" ], @@ -3566,15 +3674,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Delete role", - "operationId": "deleteRole", + "summary": "Delete permission", + "operationId": "deleteMciamPermission", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -3604,14 +3712,14 @@ const docTemplate = `{ } } }, - "/api/roles/id/{roleId}/assign": { + "/api/projects": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Assign a role to a user", + "description": "Create a new project with the specified information. Optionally specify a workspace to assign the project to.", "consumes": [ "application/json" ], @@ -3619,24 +3727,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Assign role", - "operationId": "assignRole", + "summary": "Create new project", + "operationId": "createProject", "parameters": [ { - "description": "Role Assignment Info", - "name": "request", + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.CreateProjectRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.Project" + } + }, + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -3644,8 +3758,8 @@ const docTemplate = `{ } } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -3665,14 +3779,14 @@ const docTemplate = `{ } } }, - "/api/roles/id/{roleId}/unassign": { - "delete": { + "/api/projects/assign/workspaces": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Remove a role from a user", + "description": "프로젝트에 워크스페이스를 연결합니다.", "consumes": [ "application/json" ], @@ -3680,24 +3794,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Remove role", - "operationId": "removeRole", + "summary": "프로젝트에 워크스페이스 연결", + "operationId": "addWorkspaceToProject", "parameters": [ { - "description": "Role Removal Info", + "description": "Workspace and Project IDs", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.WorkspaceProjectMappingRequest" } } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "400": { + "description": "error: 잘못된 ID 형식", "schema": { "type": "object", "additionalProperties": { @@ -3705,8 +3822,8 @@ const docTemplate = `{ } } }, - "400": { - "description": "Bad Request", + "404": { + "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", "schema": { "type": "object", "additionalProperties": { @@ -3715,7 +3832,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3726,14 +3843,14 @@ const docTemplate = `{ } } }, - "/api/roles/list": { - "post": { + "/api/projects/id/{projectId}/workspaces": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve a list of all roles.", + "description": "Retrieve list of workspaces that the project is assigned to", "consumes": [ "application/json" ], @@ -3741,22 +3858,49 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" + ], + "summary": "Get workspaces assigned to project", + "operationId": "getProjectWorkspaces", + "parameters": [ + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } ], - "summary": "List all roles", - "operationId": "listRoles", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.Workspace" + } + } + }, + "400": { + "description": "error: Invalid project ID", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Project not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, "500": { - "description": "Internal Server Error", + "description": "error: Internal server error", "schema": { "type": "object", "additionalProperties": { @@ -3767,14 +3911,14 @@ const docTemplate = `{ } } }, - "/api/roles/mappings/csp-roles/list": { + "/api/projects/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "List users by csp role", + "description": "Retrieve a list of all projects.", "consumes": [ "application/json" ], @@ -3782,37 +3926,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" - ], - "summary": "List users by csp role", - "operationId": "listUsersByCspRole", - "parameters": [ - { - "description": "Filter Role Master Mapping Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" - } - } + "projects" ], + "summary": "List all projects", + "operationId": "listProjects", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/model.Project" } } }, @@ -3828,14 +3952,14 @@ const docTemplate = `{ } } }, - "/api/roles/mappings/list": { - "post": { + "/api/projects/name/{projectName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "List role master mappings", + "description": "Get project details by name", "consumes": [ "application/json" ], @@ -3843,33 +3967,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "List role master mappings", - "operationId": "listRoleMasterMappings", + "summary": "Get project by name", + "operationId": "getProjectByName", "parameters": [ { - "description": "Filter Role Master Mapping Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" - } + "type": "string", + "description": "Project Name", + "name": "name", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } + "$ref": "#/definitions/model.Project" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -3889,14 +4008,14 @@ const docTemplate = `{ } } }, - "/api/roles/mappings/platform-roles/users/list": { - "post": { + "/api/projects/unassign/workspaces": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "List users by platform role", + "description": "Remove a workspace from a project", "consumes": [ "application/json" ], @@ -3904,33 +4023,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "List users by platform role", - "operationId": "listUsersByPlatformRole", + "summary": "Remove workspace from project", + "operationId": "removeWorkspaceFromProject", "parameters": [ { - "description": "Filter Role Master Mapping Request", + "description": "Workspace and Project IDs", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + "$ref": "#/definitions/model.WorkspaceProjectMappingRequest" } } ], "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } - } + "204": { + "description": "No Content" }, "400": { - "description": "Bad Request", + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -3939,7 +4052,7 @@ const docTemplate = `{ } }, "500": { - "description": "Internal Server Error", + "description": "error: Internal server error", "schema": { "type": "object", "additionalProperties": { @@ -3950,14 +4063,14 @@ const docTemplate = `{ } } }, - "/api/roles/mappings/role/id/:roleId": { + "/api/projects/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get role master mappings", + "description": "Retrieve project details by project ID.", "consumes": [ "application/json" ], @@ -3965,30 +4078,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Get role master mappings", - "operationId": "getRoleMasterMappings", + "summary": "Get project by ID", + "operationId": "getProjectByID", "parameters": [ { - "description": "Filter Role Master Mapping Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" - } + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMasterMapping" + "$ref": "#/definitions/model.Project" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -4006,16 +4117,14 @@ const docTemplate = `{ } } } - } - }, - "/api/roles/mappings/workspace-roles/users/list": { - "post": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "List users by workspace role", + "description": "Update the details of an existing project.", "consumes": [ "application/json" ], @@ -4023,18 +4132,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "List users by workspace role", - "operationId": "listUsersByWorkspaceRole", + "summary": "Update project", + "operationId": "updateProject", "parameters": [ { - "description": "Filter Role Master Mapping Request", - "name": "request", + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + "$ref": "#/definitions/model.Project" } } ], @@ -4042,10 +4158,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } + "$ref": "#/definitions/model.Project" } }, "400": { @@ -4057,46 +4170,14 @@ const docTemplate = `{ } } }, - "500": { - "description": "Internal Server Error", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { "type": "string" } } - } - } - } - }, - "/api/roles/menu-roles/list": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get a list of all menu roles", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "roles" - ], - "summary": "List menu roles", - "operationId": "listPlatformRoles", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMaster" - } - } }, "500": { "description": "Internal Server Error", @@ -4108,16 +4189,14 @@ const docTemplate = `{ } } } - } - }, - "/api/roles/name/{roleName}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve role details by role name.", + "description": "Delete a project by its ID.", "consumes": [ "application/json" ], @@ -4125,25 +4204,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Get role by Name", - "operationId": "getRoleByRoleName", + "summary": "Delete project", + "operationId": "deleteProject", "parameters": [ { "type": "string", - "description": "Role name", - "name": "name", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.RoleMaster" - } + "204": { + "description": "No Content" }, "404": { "description": "Not Found", @@ -4166,14 +4242,14 @@ const docTemplate = `{ } } }, - "/api/roles/platform-roles": { + "/api/resource-types/cloud-resources": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new menu role", + "description": "새로운 리소스 타입을 생성합니다", "consumes": [ "application/json" ], @@ -4181,24 +4257,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Create menu role", - "operationId": "createPlatformRole", + "summary": "Cloud에서 관리되는 Resource(vm, nlb, k8s 등의 그룹) 새 리소스 타입 생성", + "operationId": "createResourceType", "parameters": [ { - "description": "Menu Role Creation Info", - "name": "request", + "description": "Resource Type Info", + "name": "resourceType", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.ResourceType" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } + }, + "400": { + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -4206,8 +4288,8 @@ const docTemplate = `{ } } }, - "400": { - "description": "Bad Request", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -4215,8 +4297,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "Internal Server Error", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -4227,14 +4309,14 @@ const docTemplate = `{ } } }, - "/api/roles/platform-roles/id/{roleId}": { + "/api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get platform role details by ID", + "description": "특정 리소스 타입을 ID로 조회합니다", "consumes": [ "application/json" ], @@ -4242,14 +4324,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Get platform role by ID", - "operationId": "getPlatformRoleByID", + "summary": "리소스 타입 ID로 조회", + "operationId": "getCloudResourceTypeByID", "parameters": [ { "type": "string", - "description": "Platform Role ID", + "description": "Resource Type ID", "name": "id", "in": "path", "required": true @@ -4259,11 +4341,11 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.ResourceType" } }, - "404": { - "description": "Not Found", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -4271,8 +4353,17 @@ const docTemplate = `{ } } }, - "500": { - "description": "Internal Server Error", + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -4282,13 +4373,13 @@ const docTemplate = `{ } } }, - "delete": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a platform role", + "description": "리소스 타입 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -4296,25 +4387,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Delete platform role", - "operationId": "deletePlatformRole", + "summary": "리소스 타입 업데이트", + "operationId": "updateResourceType", "parameters": [ { "type": "string", - "description": "Platform Role ID", - "name": "roleId", + "description": "Resource Type ID", + "name": "id", "in": "path", "required": true + }, + { + "description": "Resource Type Info", + "name": "resourceType", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.ResourceType" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } }, - "404": { - "description": "Not Found", + "400": { + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -4322,8 +4425,26 @@ const docTemplate = `{ } } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -4332,16 +4453,14 @@ const docTemplate = `{ } } } - } - }, - "/api/roles/platform-roles/name/{roleName}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get menu role details by Name", + "description": "리소스 타입을 삭제합니다", "consumes": [ "application/json" ], @@ -4349,28 +4468,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Get menu role by Name", - "operationId": "getPlatformRoleByName", + "summary": "리소스 타입 삭제", + "operationId": "deleteResourceType", "parameters": [ { "type": "string", - "description": "Menu Role Name", - "name": "name", + "description": "Resource Type ID", + "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "401": { + "description": "error: Unauthorized", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "Not Found", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -4378,8 +4503,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "Internal Server Error", + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -4390,14 +4515,14 @@ const docTemplate = `{ } } }, - "/api/roles/unassign/csp-roles": { - "delete": { + "/api/resource-types/cloud-resources/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a mapping between workspace role and CSP role", + "description": "모든 리소스 타입 목록을 조회합니다", "consumes": [ "application/json" ], @@ -4405,27 +4530,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Delete workspace role-CSP role mapping", - "operationId": "removeCspRoleMappings", - "parameters": [ - { - "description": "Mapping Info", - "name": "mapping", - "in": "body", - "required": true, + "summary": "리소스 타입 목록 조회", + "operationId": "listCloudResourceTypes", + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "array", + "items": { + "$ref": "#/definitions/model.ResourceType" + } } - } - ], - "responses": { - "204": { - "description": "No Content" }, - "400": { - "description": "Bad Request", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -4433,8 +4553,8 @@ const docTemplate = `{ } } }, - "500": { - "description": "Internal Server Error", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -4445,14 +4565,14 @@ const docTemplate = `{ } } }, - "/api/roles/unassign/platform-role": { - "delete": { + "/api/roles": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Remove a platform role from a user", + "description": "Create a new role", "consumes": [ "application/json" ], @@ -4462,27 +4582,24 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "Remove platform role", - "operationId": "removePlatformRole", + "summary": "Create role", + "operationId": "createRole", "parameters": [ { - "description": "Platform Role Removal Info", - "name": "request", + "description": "Role Info", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.CreateRoleRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.RoleMaster" } }, "400": { @@ -4506,14 +4623,14 @@ const docTemplate = `{ } } }, - "/api/roles/unassign/workspace-role": { - "delete": { + "/api/roles/assign/platform-role": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Remove a workspace role from a user", + "description": "Assign a platform role to a user", "consumes": [ "application/json" ], @@ -4523,11 +4640,11 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "Remove workspace role", - "operationId": "removeWorkspaceRole", + "summary": "Assign platform role", + "operationId": "assignPlatformRole", "parameters": [ { - "description": "Workspace Role Removal Info", + "description": "Platform Role Assignment Info", "name": "request", "in": "body", "required": true, @@ -4567,14 +4684,14 @@ const docTemplate = `{ } } }, - "/api/roles/workspace-roles": { + "/api/roles/assign/workspace-role": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new workspace role", + "description": "Assign a workspace role to a user", "consumes": [ "application/json" ], @@ -4584,16 +4701,16 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "Create workspace role", - "operationId": "createWorkspaceRole", + "summary": "Assign workspace role", + "operationId": "assignWorkspaceRole", "parameters": [ { - "description": "Workspace Role Creation Info", + "description": "Workspace Role Assignment Info", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.AssignWorkspaceRoleRequest" } } ], @@ -4628,14 +4745,14 @@ const docTemplate = `{ } } }, - "/api/roles/workspace-roles/id/{roleId}": { - "get": { + "/api/roles/csp": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspace role details by ID", + "description": "Create a new csp role", "consumes": [ "application/json" ], @@ -4645,26 +4762,31 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "Get workspace role by ID", - "operationId": "getWorkspaceRoleByID", + "summary": "Create csp role", + "operationId": "createCspRole", "parameters": [ { - "type": "string", - "description": "Workspace Role ID", - "name": "id", - "in": "path", - "required": true + "description": "CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -4682,14 +4804,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/roles/csp-roles": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a workspace role", + "description": "Create a new mapping between role and CSP role", "consumes": [ "application/json" ], @@ -4699,23 +4823,28 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "Delete workspace role", - "operationId": "deleteWorkspaceRole", + "summary": "Create role-CSP role mapping", + "operationId": "addCspRoleMappings", "parameters": [ { - "type": "string", - "description": "Workspace Role ID", - "name": "roleId", - "in": "path", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -4735,14 +4864,14 @@ const docTemplate = `{ } } }, - "/api/roles/workspace-roles/list": { + "/api/roles/csp-roles/batch": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get a list of all workspace roles", + "description": "Create multiple new csp roles", "consumes": [ "application/json" ], @@ -4752,15 +4881,35 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "List workspace roles", - "operationId": "listWorkspaceRoles", + "summary": "Create multiple csp roles", + "operationId": "createCspRoles", + "parameters": [ + { + "description": "Multiple CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspRolesRequest" + } + } + ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.CspRole" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -4776,14 +4925,14 @@ const docTemplate = `{ } } }, - "/api/roles/workspace-roles/name/{roleName}": { + "/api/roles/csp-roles/id/:roleId": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspace role details by Name", + "description": "Get a mapping between role and CSP role", "consumes": [ "application/json" ], @@ -4793,26 +4942,28 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "Get workspace role by Name", - "operationId": "getWorkspaceRoleByName", + "summary": "Get role-CSP role mapping", + "operationId": "getCspRoleMappingByRoleId", "parameters": [ { - "type": "string", - "description": "Workspace Role Name", - "name": "name", - "in": "path", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -4832,9 +4983,14 @@ const docTemplate = `{ } } }, - "/api/roles/{roleType}/{roleId}/mciam-permissions": { - "get": { - "description": "특정 역할의 MC-IAM 권한 ID 목록을 조회합니다.", + "/api/roles/csp-roles/id/{roleId}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update role information", "consumes": [ "application/json" ], @@ -4842,43 +4998,71 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles", - "mciam-permissions" + "roles" ], - "summary": "역할의 MC-IAM 권한 목록 조회 - Renamed", - "operationId": "getRoleMciamPermissions", + "summary": "Update csp role", + "operationId": "updateCspRole", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true }, { - "type": "integer", - "description": "역할 ID", - "name": "roleId", - "in": "path", - "required": true + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } } ], "responses": { "200": { - "description": "권한 ID 목록", + "description": "OK", "schema": { - "type": "array", - "items": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { "type": "string" } } } } - } - }, - "/api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId}": { - "post": { - "description": "역할에 MC-IAM 권한을 할당합니다.", + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a role", "consumes": [ "application/json" ], @@ -4886,42 +5070,52 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles", - "mciam-permissions" + "roles" ], - "summary": "역할에 MC-IAM 권한 할당 - Renamed", - "operationId": "assignMciamPermissionToRole", + "summary": "Delete csp role", + "operationId": "deleteCspRole", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "역할 ID", + "description": "Role ID", "name": "roleId", "in": "path", "required": true - }, - { - "type": "string", - "description": "MC-IAM 권한 ID", - "name": "permissionId", - "in": "path", - "required": true } ], "responses": { "204": { "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } - }, - "delete": { - "description": "역할에서 MC-IAM 권한을 제거합니다.", + } + }, + "/api/roles/csp-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a mapping between role and CSP role", "consumes": [ "application/json" ], @@ -4929,94 +5123,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles", - "mciam-permissions" + "roles" ], - "summary": "역할에서 MC-IAM 권한 제거 - Renamed", - "operationId": "removeMciamPermissionFromRole", + "summary": "Get role-CSP role mapping", + "operationId": "listCspRoleMappings", "parameters": [ { - "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "역할 ID", - "name": "roleId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "MC-IAM 권한 ID", - "name": "permissionId", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - } - } - } - }, - "/api/setup/check-user-roles": { - "get": { - "description": "Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "Check user roles", - "operationId": "checkUserRoles", - "parameters": [ - { - "type": "string", - "description": "Username to check roles", - "name": "username", - "in": "query", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Response" + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/setup/initial-role-menu-permission": { + "/api/roles/csp/id/{roleId}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "CSV 파일을 읽어서 메뉴 권한을 초기화합니다", + "description": "Get csp role details by ID", "consumes": [ "application/json" ], @@ -5024,48 +5181,55 @@ const docTemplate = `{ "application/json" ], "tags": [ - "admin" + "roles" ], - "summary": "Initialize menu permissions from CSV", - "operationId": "initializeMenuPermissions", + "summary": "Get csp role by ID", + "operationId": "getCspRoleByID", "parameters": [ { "type": "string", - "description": "CSV file path (optional, uses default if not provided)", - "name": "filePath", - "in": "query" + "description": "CSP Role ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Response" + "$ref": "#/definitions/model.RoleMaster" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/setup/sync-projects": { + "/api/roles/csp/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다.", + "description": "Get a list of all csp roles", "consumes": [ "application/json" ], @@ -5073,22 +5237,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "projects" + "roles" ], - "summary": "mc-infra-manager와 프로젝트 동기화", - "operationId": "syncProjects", + "summary": "List csp roles", + "operationId": "listCSPRoles", "responses": { "200": { - "description": "message: Project synchronization successful", + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" } } }, "500": { - "description": "error: 서버 내부 오류 또는 동기화 실패", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -5099,14 +5263,14 @@ const docTemplate = `{ } } }, - "/api/users": { - "post": { + "/api/roles/csp/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new user with the specified information.", + "description": "Get csp role details by Name", "consumes": [ "application/json" ], @@ -5114,30 +5278,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Create new user", - "operationId": "createUser", + "summary": "Get csp role by Name", + "operationId": "getCspRoleByName", "parameters": [ { - "description": "User Info", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.User" - } + "type": "string", + "description": "CSP Role Name", + "name": "name", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -5157,14 +5319,14 @@ const docTemplate = `{ } } }, - "/api/users/id/{userId}": { + "/api/roles/id/{roleId}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve user details by user ID.", + "description": "Get role details by ID", "consumes": [ "application/json" ], @@ -5172,15 +5334,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user by ID", - "operationId": "getUserByID", + "summary": "Get role by ID", + "operationId": "getRoleByRoleID", "parameters": [ { "type": "string", - "description": "User ID", - "name": "userId", + "description": "Role ID", + "name": "id", "in": "path", "required": true } @@ -5189,7 +5351,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } }, "404": { @@ -5211,16 +5373,14 @@ const docTemplate = `{ } } } - } - }, - "/api/users/id/{userId}/status": { - "post": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "Update user status (active/inactive)", + "description": "Update the details of an existing role.", "consumes": [ "application/json" ], @@ -5228,25 +5388,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Update user status", - "operationId": "updateUserStatus", + "summary": "Update role", + "operationId": "updateRole", "parameters": [ { "type": "string", - "description": "User ID", + "description": "Role ID", "name": "id", "in": "path", "required": true }, { - "description": "User Status", - "name": "status", + "description": "Role Info", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.UserStatusRequest" + "$ref": "#/definitions/model.CreateRoleRequest" } } ], @@ -5254,7 +5414,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } }, "400": { @@ -5285,16 +5445,14 @@ const docTemplate = `{ } } } - } - }, - "/api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspaces and roles for a specific user and workspace", + "description": "Delete a role by its name.", "consumes": [ "application/json" ], @@ -5302,33 +5460,29 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user workspace and workspace roles by user ID and workspace ID", - "operationId": "getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID", + "summary": "Delete role", + "operationId": "deleteRole", "parameters": [ { "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", + "description": "Role ID", + "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.UserWorkspaceRole" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5344,14 +5498,14 @@ const docTemplate = `{ } } }, - "/api/users/id/{userId}/workspaces/list": { - "get": { + "/api/roles/id/{roleId}/assign": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspaces for a specific user", + "description": "Assign a role to a user", "consumes": [ "application/json" ], @@ -5359,76 +5513,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user workspaces by user ID", - "operationId": "getUserWorkspacesByUserID", + "summary": "Assign role", + "operationId": "assignRole", "parameters": [ { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true + "description": "Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" - } - } - }, - "500": { - "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } - } - } - } - }, - "/api/users/id/{userId}/workspaces/roles/list": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get workspaces and roles for a specific user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Get user workspace and workspace roles by user ID", - "operationId": "getUserWorkspaceAndWorkspaceRolesByUserID", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + "400": { + "description": "Bad Request", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.UserWorkspaceRole" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5444,14 +5559,14 @@ const docTemplate = `{ } } }, - "/api/users/kc/{kcUserId}": { - "get": { + "/api/roles/id/{roleId}/unassign": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get user details by KcID", + "description": "Remove a role from a user", "consumes": [ "application/json" ], @@ -5459,28 +5574,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user by KcID", - "operationId": "getUserByKcID", + "summary": "Remove role", + "operationId": "removeRole", "parameters": [ { - "type": "string", - "description": "User KcID", - "name": "kcUserId", - "in": "path", - "required": true + "description": "Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -5500,14 +5620,14 @@ const docTemplate = `{ } } }, - "/api/users/list": { + "/api/roles/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve a list of all users.", + "description": "Retrieve a list of all roles.", "consumes": [ "application/json" ], @@ -5515,17 +5635,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "List all users", - "operationId": "listUsers", + "summary": "List all roles", + "operationId": "listRoles", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } } }, @@ -5541,14 +5661,14 @@ const docTemplate = `{ } } }, - "/api/users/menus-tree/list": { + "/api/roles/mappings/csp-roles/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get the menu tree accessible to the current user's platform role.", + "description": "List users by csp role", "consumes": [ "application/json" ], @@ -5556,22 +5676,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "menus" + "roles" + ], + "summary": "List users by csp role", + "operationId": "listUsersByCspRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } ], - "summary": "Get current user's menu tree", - "operationId": "listUserMenuTree", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.MenuTreeNode" + "$ref": "#/definitions/model.RoleMasterMapping" } } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -5580,7 +5711,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -5591,41 +5722,14 @@ const docTemplate = `{ } } }, - "/api/users/menus/list": { + "/api/roles/mappings/list": { "post": { - "description": "Get the menu list accessible to the current user's platform role.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "Get current user's menu list", - "operationId": "listUserMenu", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Menu" - } - } - } - } - } - }, - "/api/users/name/{username}": { - "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get user details by username", + "description": "List role master mappings", "consumes": [ "application/json" ], @@ -5633,28 +5737,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user by username", - "operationId": "getUserByUsername", + "summary": "List role master mappings", + "operationId": "listRoleMasterMappings", "parameters": [ { - "type": "string", - "description": "Username", - "name": "name", - "in": "path", - "required": true + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -5674,14 +5783,14 @@ const docTemplate = `{ } } }, - "/api/users/workspaces/id/{workspaceId}/projects/list": { - "get": { + "/api/roles/mappings/platform-roles/users/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "List projects for the current user", + "description": "List users by platform role", "consumes": [ "application/json" ], @@ -5689,17 +5798,19 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "List user projects by workspace", - "operationId": "listUserProjectsByWorkspace", + "summary": "List users by platform role", + "operationId": "listUsersByPlatformRole", "parameters": [ { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } } ], "responses": { @@ -5708,7 +5819,16 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5724,14 +5844,14 @@ const docTemplate = `{ } } }, - "/api/users/workspaces/list": { - "post": { + "/api/roles/mappings/role/id/:roleId": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "List workspaces for the current user", + "description": "Get role master mappings", "consumes": [ "application/json" ], @@ -5739,17 +5859,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" + ], + "summary": "Get role master mappings", + "operationId": "getRoleMasterMappings", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } ], - "summary": "List user workspaces", - "operationId": "listUserWorkspaces", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.RoleMasterMapping" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5765,14 +5902,14 @@ const docTemplate = `{ } } }, - "/api/users/workspaces/roles/list": { + "/api/roles/mappings/workspace-roles/users/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "List workspaces and roles for the current user", + "description": "List users by workspace role", "consumes": [ "application/json" ], @@ -5780,17 +5917,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" + ], + "summary": "List users by workspace role", + "operationId": "listUsersByWorkspaceRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } ], - "summary": "List user workspace and roles", - "operationId": "listUserWorkspaceAndWorkspaceRoles", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5806,14 +5963,14 @@ const docTemplate = `{ } } }, - "/api/users/{id}": { - "put": { + "/api/roles/menu-roles/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing user.", + "description": "Get a list of all menu roles", "consumes": [ "application/json" ], @@ -5821,50 +5978,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" - ], - "summary": "Update user", - "operationId": "updateUser", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "User Info", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.User" - } - } + "roles" ], + "summary": "List menu roles", + "operationId": "listPlatformRoles", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" } } }, @@ -5878,14 +6002,16 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/roles/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a user by their ID.", + "description": "Retrieve role details by role name.", "consumes": [ "application/json" ], @@ -5893,22 +6019,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Delete user", - "operationId": "deleteUser", + "summary": "Get role by Name", + "operationId": "getRoleByRoleName", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Role name", + "name": "name", "in": "path", "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } }, "404": { "description": "Not Found", @@ -5931,14 +6060,14 @@ const docTemplate = `{ } } }, - "/api/workspaces": { + "/api/roles/platform-roles": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new workspace with the specified information.", + "description": "Create a new menu role", "consumes": [ "application/json" ], @@ -5946,26 +6075,29 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Create new workspace", - "operationId": "createWorkspace", + "summary": "Create menu role", + "operationId": "createPlatformRole", "parameters": [ { - "description": "Workspace Info", - "name": "workspace", + "description": "Menu Role Creation Info", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.CreateRoleRequest" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { @@ -5989,14 +6121,14 @@ const docTemplate = `{ } } }, - "/api/workspaces/assign/projects": { - "post": { + "/api/roles/platform-roles/id/{roleId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Add a project to a workspace", + "description": "Get platform role details by ID", "consumes": [ "application/json" ], @@ -6004,53 +6136,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Add project to workspace", - "operationId": "addProjectToWorkspace", + "summary": "Get platform role by ID", + "operationId": "getPlatformRoleByID", "parameters": [ { "type": "string", - "description": "Workspace ID", + "description": "Platform Role ID", "name": "id", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "400": { - "description": "error: Invalid request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.RoleMaster" } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -6058,8 +6165,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Workspace or Project not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6068,16 +6175,14 @@ const docTemplate = `{ } } } - } - }, - "/api/workspaces/id/{workspaceId}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve workspace details by workspace ID.", + "description": "Delete a platform role", "consumes": [ "application/json" ], @@ -6085,25 +6190,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Get workspace by ID", - "operationId": "getWorkspaceByID", + "summary": "Delete platform role", + "operationId": "deletePlatformRole", "parameters": [ { "type": "string", - "description": "Workspace ID", - "name": "workspaceId", + "description": "Platform Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Workspace" - } + "204": { + "description": "No Content" }, "404": { "description": "Not Found", @@ -6124,14 +6226,16 @@ const docTemplate = `{ } } } - }, - "put": { + } + }, + "/api/roles/platform-roles/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing workspace.", + "description": "Get menu role details by Name", "consumes": [ "application/json" ], @@ -6139,42 +6243,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Update workspace", - "operationId": "updateWorkspace", + "summary": "Get menu role by Name", + "operationId": "getPlatformRoleByName", "parameters": [ { "type": "string", - "description": "Workspace ID", - "name": "id", + "description": "Menu Role Name", + "name": "name", "in": "path", "required": true - }, - { - "description": "Workspace Info", - "name": "workspace", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Workspace" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.RoleMaster" } }, "404": { @@ -6196,14 +6282,16 @@ const docTemplate = `{ } } } - }, + } + }, + "/api/roles/unassign/csp-roles": { "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a workspace by its ID.", + "description": "Delete a mapping between workspace role and CSP role", "consumes": [ "application/json" ], @@ -6211,25 +6299,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Delete workspace", - "operationId": "deleteWorkspace", + "summary": "Delete workspace role-CSP role mapping", + "operationId": "removeCspRoleMappings", "parameters": [ { - "type": "string", - "description": "Workspace ID", - "name": "id", - "in": "path", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { "204": { "description": "No Content" }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -6249,14 +6339,14 @@ const docTemplate = `{ } } }, - "/api/workspaces/id/{workspaceId}/projects/list": { - "get": { + "/api/roles/unassign/platform-role": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve project list belonging to specific workspace", + "description": "Remove a platform role from a user", "consumes": [ "application/json" ], @@ -6264,31 +6354,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "List workspace projects", - "operationId": "getWorkspaceProjectsByWorkspaceId", + "summary": "Remove platform role", + "operationId": "removePlatformRole", "parameters": [ { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Platform Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Project" - } - } - }, - "401": { - "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -6296,8 +6379,8 @@ const docTemplate = `{ } } }, - "403": { - "description": "error: Forbidden", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -6305,8 +6388,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Workspace not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6317,14 +6400,14 @@ const docTemplate = `{ } } }, - "/api/workspaces/id/{workspaceId}/users/id/{userId}": { - "get": { + "/api/roles/unassign/workspace-role": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get roles assigned to a user in a workspace", + "description": "Remove a workspace role from a user", "consumes": [ "application/json" ], @@ -6334,31 +6417,26 @@ const docTemplate = `{ "tags": [ "roles" ], - "summary": "Get user workspace roles", - "operationId": "getUserWorkspaceRoles", + "summary": "Remove workspace role", + "operationId": "removeWorkspaceRole", "parameters": [ { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Workspace Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMaster" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -6383,9 +6461,14 @@ const docTemplate = `{ } } }, - "/api/workspaces/id/{workspaceId}/users/list": { + "/api/roles/workspace-roles": { "post": { - "description": "Retrieve users and roles list belonging to workspace", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace role", "consumes": [ "application/json" ], @@ -6393,31 +6476,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "List users and roles by workspace", - "operationId": "listUsersAndRolesByWorkspace", + "summary": "Create workspace role", + "operationId": "createWorkspaceRole", "parameters": [ { - "type": "integer", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Workspace Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.UserWorkspaceRole" - } - } - }, - "400": { - "description": "error: Invalid workspace ID", "schema": { "type": "object", "additionalProperties": { @@ -6425,8 +6501,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Workspace not found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -6435,7 +6511,7 @@ const docTemplate = `{ } }, "500": { - "description": "error: Internal server error", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6446,14 +6522,14 @@ const docTemplate = `{ } } }, - "/api/workspaces/list": { - "post": { + "/api/roles/workspace-roles/id/{roleId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve a list of all workspaces.", + "description": "Get workspace role details by ID", "consumes": [ "application/json" ], @@ -6461,17 +6537,32 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" + ], + "summary": "Get workspace role by ID", + "operationId": "getWorkspaceRoleByID", + "parameters": [ + { + "type": "string", + "description": "Workspace Role ID", + "name": "id", + "in": "path", + "required": true + } ], - "summary": "List all workspaces", - "operationId": "listWorkspaces", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -6485,16 +6576,14 @@ const docTemplate = `{ } } } - } - }, - "/api/workspaces/name/{workspaceName}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve specific workspace by name", + "description": "Delete a workspace role", "consumes": [ "application/json" ], @@ -6502,37 +6591,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Get workspace by name", - "operationId": "getWorkspaceByName", + "summary": "Delete workspace role", + "operationId": "deleteWorkspaceRole", "parameters": [ { "type": "string", - "description": "Workspace Name", - "name": "workspaceName", + "description": "Workspace Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } + "204": { + "description": "No Content" }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -6540,8 +6617,8 @@ const docTemplate = `{ } } }, - "404": { - "description": "error: Workspace not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6552,14 +6629,14 @@ const docTemplate = `{ } } }, - "/api/workspaces/projects/list": { + "/api/roles/workspace-roles/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve project list belonging to specific workspace", + "description": "Get a list of all workspace roles", "consumes": [ "application/json" ], @@ -6567,49 +6644,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "workspaces" - ], - "summary": "List workspace projects", - "operationId": "listWorkspaceProjects", - "parameters": [ - { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true - } + "roles" ], + "summary": "List workspace roles", + "operationId": "listRolesOfWorkspaceType", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: Forbidden", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/model.RoleMaster" } } }, - "404": { - "description": "error: Workspace not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6620,14 +6670,14 @@ const docTemplate = `{ } } }, - "/api/workspaces/temporary-credentials": { - "post": { + "/api/roles/workspace-roles/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get temporary credentials for CSP", + "description": "Get workspace role details by Name", "consumes": [ "application/json" ], @@ -6635,10 +6685,1915 @@ const docTemplate = `{ "application/json" ], "tags": [ - "csp-credentials" + "roles" ], - "summary": "Get temporary credentials", - "operationId": "mciamGetTemporaryCredentials", + "summary": "Get workspace role by Name", + "operationId": "getWorkspaceRoleByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions": { + "get": { + "description": "특정 역할의 MC-IAM 권한 ID 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할의 MC-IAM 권한 목록 조회 - Renamed", + "operationId": "getRoleMciamPermissions", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "권한 ID 목록", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId}": { + "post": { + "description": "역할에 MC-IAM 권한을 할당합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에 MC-IAM 권한 할당 - Renamed", + "operationId": "assignMciamPermissionToRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + }, + "delete": { + "description": "역할에서 MC-IAM 권한을 제거합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에서 MC-IAM 권한 제거 - Renamed", + "operationId": "removeMciamPermissionFromRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/api/setup/check-user-roles": { + "get": { + "description": "Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Check user roles", + "operationId": "checkUserRoles", + "parameters": [ + { + "type": "string", + "description": "Username to check roles", + "name": "username", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/initial-role-menu-permission": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSV 파일을 읽어서 메뉴 권한을 초기화합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Initialize menu permissions from CSV", + "operationId": "initializeMenuPermissions", + "parameters": [ + { + "type": "string", + "description": "CSV file path (optional, uses default if not provided)", + "name": "filePath", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/sync-projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "projects" + ], + "summary": "mc-infra-manager와 프로젝트 동기화", + "operationId": "syncProjects", + "responses": { + "200": { + "description": "message: Project synchronization successful", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류 또는 동기화 실패", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new user with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Create new user", + "operationId": "createUser", + "parameters": [ + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve user details by user ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by ID", + "operationId": "getUserByID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/status": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update user status (active/inactive)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user status", + "operationId": "updateUserStatus", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Status", + "name": "status", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UserStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user and workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID and workspace ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspaces by user ID", + "operationId": "getUserWorkspacesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/kc/{kcUserId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by KcID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by KcID", + "operationId": "getUserByKcID", + "parameters": [ + { + "type": "string", + "description": "User KcID", + "name": "kcUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all users.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List all users", + "operationId": "listUsers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.User" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus-tree/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get the menu tree accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu tree", + "operationId": "listUserMenuTree", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus/list": { + "post": { + "description": "Get the menu list accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu list", + "operationId": "listUserMenu", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" + } + } + } + } + } + }, + "/api/users/name/{username}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by username", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by username", + "operationId": "getUserByUsername", + "parameters": [ + { + "type": "string", + "description": "Username", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List projects for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user projects by workspace", + "operationId": "listUserProjectsByWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspaces", + "operationId": "listUserWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces and roles for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspace and roles", + "operationId": "listUserWorkspaceAndWorkspaceRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing user.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user", + "operationId": "updateUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a user by their ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Delete user", + "operationId": "deleteUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Create new workspace", + "operationId": "createWorkspace", + "parameters": [ + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/assign/projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Add a project to a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Add project to workspace", + "operationId": "addProjectToWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "error: Invalid request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace or Project not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve workspace details by workspace ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by ID", + "operationId": "getWorkspaceByID", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing workspace.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Update workspace", + "operationId": "updateWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a workspace by its ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Delete workspace", + "operationId": "deleteWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "getWorkspaceProjectsByWorkspaceId", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get roles assigned to a user in a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get user workspace roles", + "operationId": "getUserWorkspaceRoles", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/list": { + "post": { + "description": "Retrieve users and roles list belonging to workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List users and roles by workspace", + "operationId": "listUsersAndRolesByWorkspace", + "parameters": [ + { + "type": "integer", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "400": { + "description": "error: Invalid workspace ID", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Internal server error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all workspaces.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List all workspaces", + "operationId": "listWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/name/{workspaceName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve specific workspace by name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by name", + "operationId": "getWorkspaceByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Name", + "name": "workspaceName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/projects/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "listWorkspaceProjects", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve all workspace-level roles with optional filtering", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace roles", + "operationId": "listWorkspaceRoles", + "parameters": [ + { + "description": "Role filter parameters", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleFilterRequest" + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved workspace roles", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "400": { + "description": "error: Invalid request format", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Failed to retrieve workspace roles", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/temporary-credentials": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get temporary credentials for CSP", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "Get temporary credentials", + "operationId": "mciamGetTemporaryCredentials", "responses": {} } }, @@ -6984,6 +8939,14 @@ const docTemplate = `{ ], "summary": "Health check", "operationId": "mciamCheckHealth", + "parameters": [ + { + "type": "string", + "description": "Detail check components (nginx,db,keycloak,all)", + "name": "detail", + "in": "query" + } + ], "responses": { "200": { "description": "OK", @@ -7040,304 +9003,617 @@ const docTemplate = `{ "워크스페이스 역할", "CSP 역할" ], - "x-enum-varnames": [ - "RoleTypePlatform", - "RoleTypeWorkspace", - "RoleTypeCSP" - ] + "x-enum-varnames": [ + "RoleTypePlatform", + "RoleTypeWorkspace", + "RoleTypeCSP" + ] + }, + "idp.UserLogin": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAction": { + "type": "object", + "properties": { + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "description": "Auto-incrementing primary key", + "type": "integer" + }, + "method": { + "type": "string" + }, + "resourcePath": { + "type": "string" + }, + "serviceName": { + "description": "Foreign key reference (indexed)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAuthInfo": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "type": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiDefinitions": { + "type": "object", + "properties": { + "serviceActions": { + "description": "Use renamed ServiceAction", + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" + } + } + }, + "services": { + "description": "Use renamed ServiceDefinition", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + } + } + } + }, + "mcmpapi.McmpApiPermissionActionMapping": { + "type": "object", + "properties": { + "actionID": { + "type": "integer" + }, + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "permissionID": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiServiceAction": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "method": { + "type": "string" + }, + "resourcePath": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiServiceDefinition": { + "type": "object", + "properties": { + "auth": { + "description": "Use renamed AuthInfo", + "allOf": [ + { + "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + } + ] + }, + "baseURL": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "model.AssignRoleRequest": { + "type": "object", + "properties": { + "roleId": { + "description": "역할 ID (문자열로 받음)", + "type": "string" + }, + "roleName": { + "description": "역할명", + "type": "string" + }, + "roleType": { + "description": "역할 타입 (platform/workspace)", + "type": "string" + }, + "userId": { + "description": "사용자 ID (문자열로 받음)", + "type": "string" + }, + "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", + "type": "string" + } + } + }, + "model.AssignWorkspaceRoleRequest": { + "type": "object", + "properties": { + "roleId": { + "description": "역할 ID (문자열로 받음)", + "type": "string" + }, + "roleName": { + "description": "역할명", + "type": "string" + }, + "userId": { + "description": "사용자 ID (문자열로 받음)", + "type": "string" + }, + "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", + "type": "string" + } + } + }, + "model.AttachPolicyRequest": { + "type": "object", + "required": [ + "csp_policy_id", + "csp_role_id" + ], + "properties": { + "csp_policy_id": { + "type": "integer" + }, + "csp_role_id": { + "type": "integer" + } + } + }, + "model.AuthMethodType": { + "type": "string", + "enum": [ + "OIDC", + "SAML", + "SECRET_KEY" + ], + "x-enum-varnames": [ + "AuthMethodOIDC", + "AuthMethodSAML", + "AuthMethodSecretKey" + ] + }, + "model.CreateCspAccountRequest": { + "type": "object", + "required": [ + "csp_type", + "name" + ], + "properties": { + "account_info": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "csp_type": { + "type": "string", + "enum": [ + "aws", + "gcp", + "azure" + ] + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "model.CreateCspIdpConfigRequest": { + "type": "object", + "required": [ + "auth_method", + "config", + "csp_account_id", + "name" + ], + "properties": { + "auth_method": { + "enum": [ + "OIDC", + "SAML", + "SECRET_KEY" + ], + "allOf": [ + { + "$ref": "#/definitions/model.AuthMethodType" + } + ] + }, + "config": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "csp_account_id": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } }, - "idp.UserLogin": { + "model.CreateCspPolicyRequest": { "type": "object", + "required": [ + "csp_account_id", + "name", + "policy_type" + ], "properties": { - "id": { + "csp_account_id": { + "type": "integer" + }, + "description": { "type": "string" }, - "password": { + "name": { + "type": "string" + }, + "policy_arn": { "type": "string" + }, + "policy_doc": { + "type": "object", + "additionalProperties": true + }, + "policy_type": { + "enum": [ + "inline", + "managed", + "custom" + ], + "allOf": [ + { + "$ref": "#/definitions/model.PolicyType" + } + ] } } }, - "mcmpapi.McmpApiAction": { + "model.CreateCspRoleRequest": { "type": "object", "properties": { - "actionName": { + "cspRoleName": { + "description": "csp의 RoleName. 여러 role이 있기때문에 csp에 정의한 role로 구분하기 위해 사용", "type": "string" }, - "createdAt": { + "cspType": { "type": "string" }, "description": { "type": "string" }, + "iamIdentifier": { + "type": "string" + }, + "iamRoleId": { + "type": "string" + }, "id": { - "description": "Auto-incrementing primary key", - "type": "integer" + "type": "string" }, - "method": { + "idpIdentifier": { "type": "string" }, - "resourcePath": { + "path": { "type": "string" }, - "serviceName": { - "description": "Foreign key reference (indexed)", + "status": { "type": "string" }, - "updatedAt": { + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Tag" + } + } + } + }, + "model.CreateCspRolesRequest": { + "type": "object", + "required": [ + "cspRoles" + ], + "properties": { + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" + } + } + } + }, + "model.CreateMenuMappingRequest": { + "type": "object", + "required": [ + "menuIds", + "roleId" + ], + "properties": { + "menuIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "roleId": { "type": "string" } } }, - "mcmpapi.McmpApiAuthInfo": { + "model.CreateProjectRequest": { "type": "object", + "required": [ + "name" + ], "properties": { - "password": { + "description": { "type": "string" }, - "type": { + "name": { "type": "string" }, - "username": { + "workspaceId": { + "description": "optional workspace to assign project to", "type": "string" } } }, - "mcmpapi.McmpApiDefinitions": { + "model.CreateRoleRequest": { "type": "object", + "required": [ + "name" + ], "properties": { - "serviceActions": { - "description": "Use renamed ServiceAction", - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" - } + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" } }, - "services": { - "description": "Use renamed ServiceDefinition", - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + "description": { + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "name": { + "type": "string" + }, + "parentId": { + "type": "integer" + }, + "roleTypes": { + "description": "RoleTypes []constants.IAMRoleType ` + "`" + `json:\"roleTypes\" validate:\"required,dive,oneof=platform workspace csp\"` + "`" + `", + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" } } } }, - "mcmpapi.McmpApiPermissionActionMapping": { + "model.CspAccount": { "type": "object", "properties": { - "actionID": { - "type": "integer" + "account_info": { + "type": "object", + "additionalProperties": { + "type": "string" + } }, - "actionName": { + "created_at": { "type": "string" }, - "createdAt": { + "csp_type": { + "description": "aws, gcp, azure", + "type": "string" + }, + "description": { "type": "string" }, "id": { "type": "integer" }, - "permissionID": { + "is_active": { + "type": "boolean" + }, + "name": { "type": "string" }, - "updatedAt": { + "updated_at": { "type": "string" } } }, - "mcmpapi.McmpApiServiceAction": { + "model.CspAccountFilter": { "type": "object", "properties": { - "description": { + "csp_type": { "type": "string" }, - "method": { - "type": "string" + "is_active": { + "type": "boolean" }, - "resourcePath": { + "name": { "type": "string" } } }, - "mcmpapi.McmpApiServiceDefinition": { + "model.CspIdpConfig": { "type": "object", "properties": { - "auth": { - "description": "Use renamed AuthInfo", + "auth_method": { + "description": "OIDC, SAML, SECRET_KEY", "allOf": [ { - "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + "$ref": "#/definitions/model.AuthMethodType" } ] }, - "baseURL": { - "type": "string" + "config": { + "type": "object", + "additionalProperties": { + "type": "string" + } }, - "version": { - "type": "string" - } - } - }, - "model.AssignRoleRequest": { - "type": "object", - "properties": { - "roleId": { - "description": "역할 ID (문자열로 받음)", + "created_at": { "type": "string" }, - "roleName": { - "description": "역할명", - "type": "string" + "csp_account": { + "$ref": "#/definitions/model.CspAccount" }, - "roleType": { - "description": "역할 타입 (platform/workspace)", - "type": "string" + "csp_account_id": { + "type": "integer" }, - "userId": { - "description": "사용자 ID (문자열로 받음)", + "description": { "type": "string" }, - "username": { - "description": "사용자명", + "id": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "name": { "type": "string" }, - "workspaceId": { - "description": "워크스페이스 ID (문자열로 받음)", + "updated_at": { "type": "string" } } }, - "model.AssignWorkspaceRoleRequest": { + "model.CspIdpConfigFilter": { "type": "object", "properties": { - "roleId": { - "description": "역할 ID (문자열로 받음)", - "type": "string" - }, - "roleName": { - "description": "역할명", - "type": "string" - }, - "userId": { - "description": "사용자 ID (문자열로 받음)", - "type": "string" + "auth_method": { + "$ref": "#/definitions/model.AuthMethodType" }, - "username": { - "description": "사용자명", - "type": "string" + "csp_account_id": { + "type": "integer" }, - "workspaceId": { - "description": "워크스페이스 ID (문자열로 받음)", + "is_active": { + "type": "boolean" + }, + "name": { "type": "string" } } }, - "model.CreateCspRoleRequest": { + "model.CspPolicy": { "type": "object", "properties": { - "cspRoleName": { - "description": "csp의 RoleName. 여러 role이 있기때문에 csp에 정의한 role로 구분하기 위해 사용", - "type": "string" - }, - "cspType": { + "created_at": { "type": "string" }, - "description": { - "type": "string" + "csp_account": { + "$ref": "#/definitions/model.CspAccount" }, - "iamIdentifier": { - "type": "string" + "csp_account_id": { + "type": "integer" }, - "iamRoleId": { + "description": { "type": "string" }, "id": { - "type": "string" + "type": "integer" }, - "idpIdentifier": { + "name": { "type": "string" }, - "path": { + "policy_arn": { "type": "string" }, - "status": { - "type": "string" + "policy_doc": { + "type": "object", + "additionalProperties": true }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Tag" - } - } - } - }, - "model.CreateCspRolesRequest": { - "type": "object", - "required": [ - "cspRoles" - ], - "properties": { - "cspRoles": { - "type": "array", - "items": { - "$ref": "#/definitions/model.CreateCspRoleRequest" - } - } - } - }, - "model.CreateMenuMappingRequest": { - "type": "object", - "required": [ - "menuIds", - "roleId" - ], - "properties": { - "menuIds": { - "type": "array", - "items": { - "type": "string" - } + "policy_type": { + "description": "inline, managed, custom", + "allOf": [ + { + "$ref": "#/definitions/model.PolicyType" + } + ] }, - "roleId": { + "updated_at": { "type": "string" } } }, - "model.CreateRoleRequest": { + "model.CspPolicyFilter": { "type": "object", - "required": [ - "name" - ], "properties": { - "cspRoles": { - "type": "array", - "items": { - "$ref": "#/definitions/model.CreateCspRoleRequest" - } - }, - "description": { - "type": "string" - }, - "menuIds": { - "type": "array", - "items": { - "type": "string" - } + "csp_account_id": { + "type": "integer" }, "name": { "type": "string" }, - "parentId": { - "type": "integer" - }, - "roleTypes": { - "description": "RoleTypes []constants.IAMRoleType ` + "`" + `json:\"roleTypes\" validate:\"required,dive,oneof=platform workspace csp\"` + "`" + `", - "type": "array", - "items": { - "$ref": "#/definitions/constants.IAMRoleType" - } + "policy_type": { + "$ref": "#/definitions/model.PolicyType" } } }, @@ -7350,6 +9626,19 @@ const docTemplate = `{ "created_at": { "type": "string" }, + "csp_account": { + "$ref": "#/definitions/model.CspAccount" + }, + "csp_account_id": { + "description": "CSP 계정 및 IDP 설정 참조 (신규 추가)", + "type": "integer" + }, + "csp_idp_config": { + "$ref": "#/definitions/model.CspIdpConfig" + }, + "csp_idp_config_id": { + "type": "integer" + }, "csp_type": { "type": "string" }, @@ -7359,6 +9648,10 @@ const docTemplate = `{ "description": { "type": "string" }, + "extended_config": { + "type": "object", + "additionalProperties": true + }, "iam_identifier": { "type": "string" }, @@ -7450,6 +9743,101 @@ const docTemplate = `{ } } }, + "model.ImportApiFramework": { + "type": "object", + "required": [ + "name", + "sourceType", + "sourceUrl", + "version" + ], + "properties": { + "name": { + "description": "Framework name (e.g., \"mc-infra-manager\")", + "type": "string" + }, + "repository": { + "description": "Repository URL (e.g., \"https://github.com/...\")", + "type": "string" + }, + "sourceType": { + "description": "Source type: \"swagger\" or \"openapi\"", + "type": "string" + }, + "sourceUrl": { + "description": "URL to fetch the API specification from", + "type": "string" + }, + "version": { + "description": "Framework version (e.g., \"0.9.22\")", + "type": "string" + } + } + }, + "model.ImportApiFrameworkResult": { + "type": "object", + "properties": { + "actionCount": { + "description": "Number of actions imported (on success)", + "type": "integer" + }, + "errorMessage": { + "description": "Error message (on failure)", + "type": "string" + }, + "name": { + "description": "Framework name", + "type": "string" + }, + "success": { + "description": "Whether the import was successful", + "type": "boolean" + }, + "version": { + "description": "Framework version", + "type": "string" + } + } + }, + "model.ImportApiRequest": { + "type": "object", + "required": [ + "frameworks" + ], + "properties": { + "frameworks": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/model.ImportApiFramework" + } + } + } + }, + "model.ImportApiResponse": { + "type": "object", + "properties": { + "failureCount": { + "description": "Number of failed frameworks", + "type": "integer" + }, + "frameworkResults": { + "description": "Detailed results for each framework", + "type": "array", + "items": { + "$ref": "#/definitions/model.ImportApiFrameworkResult" + } + }, + "successCount": { + "description": "Number of successfully imported frameworks", + "type": "integer" + }, + "totalFrameworks": { + "description": "Total number of frameworks in request", + "type": "integer" + } + } + }, "model.MciamPermission": { "type": "object", "properties": { @@ -7591,6 +9979,29 @@ const docTemplate = `{ } } }, + "model.PolicyType": { + "type": "string", + "enum": [ + "inline", + "managed", + "custom" + ], + "x-enum-comments": { + "PolicyTypeCustom": "사용자 정의 정책", + "PolicyTypeInline": "인라인 정책 (역할에 직접 포함)", + "PolicyTypeManaged": "관리형 정책 (독립 정책)" + }, + "x-enum-descriptions": [ + "인라인 정책 (역할에 직접 포함)", + "관리형 정책 (독립 정책)", + "사용자 정의 정책" + ], + "x-enum-varnames": [ + "PolicyTypeInline", + "PolicyTypeManaged", + "PolicyTypeCustom" + ] + }, "model.Project": { "type": "object", "properties": { @@ -7659,6 +10070,23 @@ const docTemplate = `{ } } }, + "model.RoleFilterRequest": { + "type": "object", + "properties": { + "roleId": { + "type": "string" + }, + "roleName": { + "type": "string" + }, + "roleTypes": { + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" + } + } + } + }, "model.RoleLastUsed": { "type": "object", "properties": { @@ -7824,6 +10252,21 @@ const docTemplate = `{ } } }, + "model.SyncPoliciesRequest": { + "type": "object", + "required": [ + "csp_account_id" + ], + "properties": { + "csp_account_id": { + "type": "integer" + }, + "policy_scope": { + "description": "All, AWS, Local", + "type": "string" + } + } + }, "model.Tag": { "type": "object", "properties": { @@ -7835,6 +10278,64 @@ const docTemplate = `{ } } }, + "model.UpdateCspAccountRequest": { + "type": "object", + "properties": { + "account_info": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "model.UpdateCspIdpConfigRequest": { + "type": "object", + "properties": { + "config": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "model.UpdateCspPolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "policy_arn": { + "type": "string" + }, + "policy_doc": { + "type": "object", + "additionalProperties": true + } + } + }, "model.User": { "type": "object", "properties": { @@ -7986,6 +10487,24 @@ const docTemplate = `{ } } }, + "model.WorkspaceProjectMappingRequest": { + "type": "object", + "required": [ + "projectIds", + "workspaceId" + ], + "properties": { + "projectIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "workspaceId": { + "type": "string" + } + } + }, "model.WorkspaceWithUsersAndRoles": { "type": "object", "properties": { diff --git a/src/docs/swagger.json b/src/docs/swagger.json index f17fc3c6..c22c0df0 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -121,7 +121,44 @@ ], "summary": "Refresh access token", "operationId": "mciamRefreshToken", - "responses": {} + "parameters": [ + { + "description": "Refresh token", + "name": "refresh_token", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "New token information", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "error: Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } } }, "/api/auth/temp-credential-csps": { @@ -168,6 +205,17 @@ ], "summary": "Validate access token", "operationId": "mciamValidateToken", + "parameters": [ + { + "description": "Refresh token", + "name": "refresh_token", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "Token validation result with new token if refreshed", @@ -176,6 +224,15 @@ "additionalProperties": true } }, + "400": { + "description": "error: Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "401": { "description": "error: Unauthorized", "schema": { @@ -188,14 +245,14 @@ } } }, - "/api/csp-credentials": { - "get": { + "/api/csp-accounts": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "모든 CSP 인증 정보 목록을 조회합니다", + "description": "Create a new CSP account", "consumes": [ "application/json" ], @@ -203,41 +260,57 @@ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 목록 조회", - "operationId": "mciamListCredentials", - "responses": {} - }, - "post": { - "security": [ + "summary": "Create CSP account", + "operationId": "createCspAccount", + "parameters": [ { - "BearerAuth": [] + "description": "CSP Account Info", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspAccountRequest" + } } ], - "description": "새로운 CSP 인증 정보를 생성합니다", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "csp-credentials" - ], - "summary": "새 CSP 인증 정보 생성", - "operationId": "mciamCreateCredential", - "responses": {} + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.CspAccount" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } } }, - "/api/csp-credentials/{id}": { + "/api/csp-accounts/id/{accountId}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "특정 CSP 인증 정보를 ID로 조회합니다", + "description": "Retrieve CSP account details by ID", "consumes": [ "application/json" ], @@ -245,22 +318,46 @@ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 ID로 조회", - "operationId": "mciamGetCredentialByID", + "summary": "Get CSP account by ID", + "operationId": "getCspAccountByID", "parameters": [ { "type": "string", - "description": "Credential ID", - "name": "id", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true } ], "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.CspAccount" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "404": { - "description": "error: Credential not found", + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -276,7 +373,7 @@ "BearerAuth": [] } ], - "description": "CSP 인증 정보를 업데이트합니다", + "description": "Update CSP account details", "consumes": [ "application/json" ], @@ -284,22 +381,55 @@ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 업데이트", - "operationId": "mciamUpdateCredential", + "summary": "Update CSP account", + "operationId": "updateCspAccount", "parameters": [ { "type": "string", - "description": "Credential ID", - "name": "id", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true + }, + { + "description": "CSP Account Info", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UpdateCspAccountRequest" + } } ], "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.CspAccount" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "404": { - "description": "error: Credential not found", + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -315,7 +445,7 @@ "BearerAuth": [] } ], - "description": "CSP 인증 정보를 삭제합니다", + "description": "Delete a CSP account by ID", "consumes": [ "application/json" ], @@ -323,15 +453,15 @@ "application/json" ], "tags": [ - "csp-credentials" + "csp-accounts" ], - "summary": "CSP 인증 정보 삭제", - "operationId": "mciamDeleteCredential", + "summary": "Delete CSP account", + "operationId": "deleteCspAccount", "parameters": [ { "type": "string", - "description": "Credential ID", - "name": "id", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true } @@ -340,8 +470,8 @@ "204": { "description": "No Content" }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -349,8 +479,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -358,8 +488,8 @@ } } }, - "404": { - "description": "error: Credential not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -370,9 +500,14 @@ } } }, - "/api/initial-admin": { + "/api/csp-accounts/id/{accountId}/activate": { "post": { - "description": "Creates the initial platform admin user with necessary permissions. platform admin 생성인데", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Activate a CSP account", "consumes": [ "application/json" ], @@ -380,34 +515,67 @@ "application/json" ], "tags": [ - "admin" + "csp-accounts" ], - "summary": "Setup initial platform admin", - "operationId": "setupInitialAdmin", + "summary": "Activate CSP account", + "operationId": "activateCspAccount", "parameters": [ { - "description": "Setup Initial Admin Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.SetupInitialAdminRequest" - } + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/mcmp-api-permission-action-mappings": { + "/api/csp-accounts/id/{accountId}/deactivate": { "post": { - "description": "Creates a new mapping between a permission and an API action", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deactivate a CSP account", "consumes": [ "application/json" ], @@ -415,31 +583,67 @@ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-accounts" ], - "summary": "Create permission-action mapping", - "operationId": "createMcmpApiPermissionActionMapping", + "summary": "Deactivate CSP account", + "operationId": "deactivateCspAccount", "parameters": [ { - "description": "Mapping to create", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" - } + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } } }, - "/api/mcmp-api-permission-action-mappings/actions/list": { + "/api/csp-accounts/id/{accountId}/validate": { "post": { - "description": "Returns all workspace actions mapped to a specific permission", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Validate CSP account configuration", "consumes": [ "application/json" ], @@ -447,15 +651,15 @@ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-accounts" ], - "summary": "Get workspace actions by permission ID", - "operationId": "listWorkspaceActionsByPermissionID", + "summary": "Validate CSP account", + "operationId": "validateCspAccount", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", + "description": "Account ID", + "name": "accountId", "in": "path", "required": true } @@ -464,18 +668,50 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/mcmpapi.McmpApiAction" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } } } } }, - "/api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions": { - "get": { - "description": "Returns all permissions mapped to a specific API action", + "/api/csp-accounts/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of CSP accounts with optional filters", "consumes": [ "application/json" ], @@ -483,17 +719,18 @@ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-accounts" ], - "summary": "Get permissions by action ID", - "operationId": "listPermissionsByActionID", + "summary": "List CSP accounts", + "operationId": "listCspAccounts", "parameters": [ { - "type": "integer", - "description": "Action ID", - "name": "actionId", - "in": "path", - "required": true + "description": "Filter options", + "name": "filter", + "in": "body", + "schema": { + "$ref": "#/definitions/model.CspAccountFilter" + } } ], "responses": { @@ -502,6 +739,15 @@ "schema": { "type": "array", "items": { + "$ref": "#/definitions/model.CspAccount" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { "type": "string" } } @@ -509,9 +755,34 @@ } } }, - "/api/mcmp-api-permission-action-mappings/list": { + "/api/csp-credentials": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "모든 CSP 인증 정보 목록을 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "CSP 인증 정보 목록 조회", + "operationId": "mciamListCredentials", + "responses": {} + }, "post": { - "description": "Returns all platform actions mapped to a specific permission", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "새로운 CSP 인증 정보를 생성합니다", "consumes": [ "application/json" ], @@ -519,35 +790,60 @@ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-credentials" ], - "summary": "List platform actions by permission ID", - "operationId": "listPlatformActions", + "summary": "새 CSP 인증 정보 생성", + "operationId": "mciamCreateCredential", + "responses": {} + } + }, + "/api/csp-credentials/{id}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "특정 CSP 인증 정보를 ID로 조회합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "CSP 인증 정보 ID로 조회", + "operationId": "mciamGetCredentialByID", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", + "description": "Credential ID", + "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/mcmpapi.McmpApiAction" + "type": "object", + "additionalProperties": { + "type": "string" } } } } - } - }, - "/api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId}": { + }, "put": { - "description": "Updates an existing mapping between a permission and an API action", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -555,38 +851,22 @@ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-credentials" ], - "summary": "Update permission-action mapping", - "operationId": "updateMapping", + "summary": "CSP 인증 정보 업데이트", + "operationId": "mciamUpdateCredential", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "Action ID", - "name": "actionId", + "description": "Credential ID", + "name": "id", "in": "path", "required": true - }, - { - "description": "Updated mapping", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" - } } ], "responses": { - "200": { - "description": "OK", + "404": { + "description": "error: Credential not found", "schema": { "type": "object", "additionalProperties": { @@ -597,7 +877,12 @@ } }, "delete": { - "description": "Deletes a mapping between a permission and an API action", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSP 인증 정보를 삭제합니다", "consumes": [ "application/json" ], @@ -605,22 +890,15 @@ "application/json" ], "tags": [ - "mcmp-api-permission-action-mappings" + "csp-credentials" ], - "summary": "Delete permission-action mapping", - "operationId": "deleteMapping", + "summary": "CSP 인증 정보 삭제", + "operationId": "mciamDeleteCredential", "parameters": [ { "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "Action ID", - "name": "actionId", + "description": "Credential ID", + "name": "id", "in": "path", "required": true } @@ -628,54 +906,45 @@ "responses": { "204": { "description": "No Content" - } - } - } - }, - "/api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions": { - "get": { - "description": "Returns all platform actions mapped to a specific permission", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "mcmp-api-permission-action-mappings" - ], - "summary": "Get platform actions by permission ID", - "operationId": "getPlatformActionsByPermissionID", - "parameters": [ - { - "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + "401": { + "description": "error: Unauthorized", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/mcmpapi.McmpApiAction" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Credential not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } } } } }, - "/api/mcmp-apis/list": { + "/api/csp-idp-configs": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieves all MCMP API service and action definitions currently stored in the database.", + "description": "Create a new CSP IDP configuration", "consumes": [ "application/json" ], @@ -683,33 +952,39 @@ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Get All Stored MCMP API Definitions", - "operationId": "listServicesAndActions", + "summary": "Create CSP IDP config", + "operationId": "createCspIdpConfig", "parameters": [ { - "type": "string", - "description": "Filter by service name", - "name": "serviceName", - "in": "query" - }, - { - "type": "string", - "description": "Filter by action name (operationId)", - "name": "actionName", - "in": "query" + "description": "CSP IDP Config Info", + "name": "config", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspIdpConfigRequest" + } } ], "responses": { - "200": { - "description": "Successfully retrieved API definitions", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/mcmpapi.McmpApiDefinitions" + "$ref": "#/definitions/model.CspIdpConfig" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "500": { - "description": "message: Failed to retrieve API definitions", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -720,14 +995,14 @@ } } }, - "/api/mcmp-apis/mcmpApiCall": { - "post": { + "/api/csp-idp-configs/id/{configId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Executes a defined MCMP API action with parameters structured in McmpApiCallRequest.", + "description": "Retrieve CSP IDP configuration details by ID", "consumes": [ "application/json" ], @@ -735,30 +1010,28 @@ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Call an external MCMP API action (Structured Request)", - "operationId": "mcmpApiCall", + "summary": "Get CSP IDP config by ID", + "operationId": "getCspIdpConfigByID", "parameters": [ { - "description": "API Call Request", - "name": "callRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.McmpApiCallRequest" - } + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "External API Response (structure depends on the called API)", + "description": "OK", "schema": { - "type": "object" + "$ref": "#/definitions/model.CspIdpConfig" } }, "400": { - "description": "error: Invalid request body or parameters", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -767,7 +1040,7 @@ } }, "404": { - "description": "error: Service or action not found", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -776,16 +1049,7 @@ } }, "500": { - "description": "error: Internal server error or failed to call external API", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "503": { - "description": "error: External API unavailable", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -794,16 +1058,14 @@ } } } - } - }, - "/api/mcmp-apis/name/{serviceName}": { + }, "put": { "security": [ { "BearerAuth": [] } ], - "description": "Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API service definition identified by its name. Cannot update name or version.", + "description": "Update CSP IDP configuration details", "consumes": [ "application/json" ], @@ -811,40 +1073,37 @@ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Update MCMP API Service Definition", - "operationId": "UpdateFrameworkService", + "summary": "Update CSP IDP config", + "operationId": "updateCspIdpConfig", "parameters": [ { "type": "string", - "description": "Service Name to update", - "name": "serviceName", + "description": "Config ID", + "name": "configId", "in": "path", "required": true }, { - "description": "Fields to update (e.g., {\\", - "name": "updates", + "description": "CSP IDP Config Info", + "name": "config", "in": "body", "required": true, "schema": { - "type": "object" + "$ref": "#/definitions/model.UpdateCspIdpConfigRequest" } } ], "responses": { "200": { - "description": "message: Service updated successfully\" // Or return updated service?", + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.CspIdpConfig" } }, "400": { - "description": "error: Invalid service name or request body", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -853,7 +1112,7 @@ } }, "404": { - "description": "error: Service not found", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -862,7 +1121,7 @@ } }, "500": { - "description": "error: Failed to update service", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -871,16 +1130,14 @@ } } } - } - }, - "/api/mcmp-apis/name/{serviceName}/versions/{version}/activate": { - "put": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Sets the specified version of an MCMP API service as the active one.", + "description": "Delete a CSP IDP configuration by ID", "consumes": [ "application/json" ], @@ -888,22 +1145,15 @@ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" ], - "summary": "Set Active Version for a Service", - "operationId": "setActiveVersion", + "summary": "Delete CSP IDP config", + "operationId": "deleteCspIdpConfig", "parameters": [ { "type": "string", - "description": "Service Name", - "name": "serviceName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Version to activate", - "name": "version", + "description": "Config ID", + "name": "configId", "in": "path", "required": true } @@ -913,7 +1163,7 @@ "description": "No Content" }, "400": { - "description": "error: Invalid service name or version", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -922,7 +1172,7 @@ } }, "404": { - "description": "error: Service or version not found", + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -931,7 +1181,7 @@ } }, "500": { - "description": "error: Failed to set active version", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -942,14 +1192,14 @@ } } }, - "/api/mcmp-apis/syncMcmpAPIs": { + "/api/csp-idp-configs/id/{configId}/activate": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", + "description": "Activate a CSP IDP configuration", "consumes": [ "application/json" ], @@ -957,13 +1207,40 @@ "application/json" ], "tags": [ - "McmpAPI" + "csp-idp-configs" + ], + "summary": "Activate CSP IDP config", + "operationId": "activateCspIdpConfig", + "parameters": [ + { + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true + } ], - "summary": "Sync MCMP API Definitions", - "operationId": "syncMcmpAPIs", "responses": { "200": { - "description": "message: Successfully triggered MCMP API sync", + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -972,7 +1249,7 @@ } }, "500": { - "description": "message: Failed to trigger MCMP API sync", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -983,32 +1260,37 @@ } } }, - "/api/mcmp-apis/test/mc-infra-manager/getallns": { - "get": { + "/api/csp-idp-configs/id/{configId}/deactivate": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", + "description": "Deactivate a CSP IDP configuration", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "McmpAPI", - "Test" + "csp-idp-configs" + ], + "summary": "Deactivate CSP IDP config", + "operationId": "deactivateCspIdpConfig", + "parameters": [ + { + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true + } ], - "summary": "Test Call to mc-infra-manager GetAllNs", - "operationId": "testCallGetAllNs", "responses": { "200": { - "description": "Response from mc-infra-manager GetAllNs", - "schema": { - "type": "object" - } - }, - "400": { - "description": "error: Bad Request (e.g., invalid parameters)", + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -1016,8 +1298,8 @@ } } }, - "404": { - "description": "error: Service or Action Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1025,8 +1307,8 @@ } } }, - "500": { - "description": "error: Internal Server Error", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1034,8 +1316,8 @@ } } }, - "503": { - "description": "error: External API Service Unavailable", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1046,14 +1328,14 @@ } } }, - "/api/menus": { + "/api/csp-idp-configs/id/{configId}/test": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new menu", + "description": "Test connection to CSP using IDP configuration", "consumes": [ "application/json" ], @@ -1061,39 +1343,67 @@ "application/json" ], "tags": [ - "menus" + "csp-idp-configs" ], - "summary": "Create new menu", - "operationId": "createMenu", + "summary": "Test CSP IDP connection", + "operationId": "testCspIdpConnection", "parameters": [ { - "description": "Menu Info", - "name": "menu", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Menu" - } + "type": "string", + "description": "Config ID", + "name": "configId", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.Menu" + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/menus/id/{menuId}": { - "put": { + "/api/csp-idp-configs/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update menu information", + "description": "Retrieve a list of CSP IDP configurations with optional filters", "consumes": [ "application/json" ], @@ -1101,25 +1411,17 @@ "application/json" ], "tags": [ - "menus" + "csp-idp-configs" ], - "summary": "Update menu information", - "operationId": "updateMenu", + "summary": "List CSP IDP configs", + "operationId": "listCspIdpConfigs", "parameters": [ { - "type": "string", - "description": "Menu ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Menu Info", - "name": "menu", + "description": "Filter options", + "name": "filter", "in": "body", - "required": true, "schema": { - "$ref": "#/definitions/model.Menu" + "$ref": "#/definitions/model.CspIdpConfigFilter" } } ], @@ -1127,18 +1429,32 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Menu" + "type": "array", + "items": { + "$ref": "#/definitions/model.CspIdpConfig" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } - }, + } + }, + "/api/csp-policies": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get menu details by ID", + "description": "Create a new CSP policy", "consumes": [ "application/json" ], @@ -1146,35 +1462,57 @@ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Get menu by ID", - "operationId": "getMenuByID", + "summary": "Create CSP policy", + "operationId": "createCspPolicy", "parameters": [ { - "type": "string", - "description": "Menu ID", - "name": "menuId", - "in": "path", - "required": true + "description": "CSP Policy Info", + "name": "policy", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspPolicyRequest" + } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/model.Menu" + "$ref": "#/definitions/model.CspPolicy" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } - }, - "delete": { + } + }, + "/api/csp-policies/attach": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a menu", + "description": "Attach a CSP policy to a CSP role", "consumes": [ "application/json" ], @@ -1182,57 +1520,33 @@ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Delete menu", - "operationId": "deleteMenu", + "summary": "Attach policy to role", + "operationId": "attachPolicyToRole", "parameters": [ { - "type": "string", - "description": "Menu ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - } - } - } - }, - "/api/menus/list": { - "post": { - "security": [ - { - "BearerAuth": [] + "description": "Attach Policy Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AttachPolicyRequest" + } } ], - "description": "List all menus as a tree structure. Admin permission required.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "List all menus", - "operationId": "listMenus", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" + "type": "object", + "additionalProperties": { + "type": "string" } } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1240,8 +1554,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1250,7 +1564,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1261,14 +1575,14 @@ } } }, - "/api/menus/platform-roles": { + "/api/csp-policies/detach": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new menu mapping", + "description": "Detach a CSP policy from a CSP role", "consumes": [ "application/json" ], @@ -1276,24 +1590,24 @@ "application/json" ], "tags": [ - "menu" + "csp-policies" ], - "summary": "Create menu mapping", - "operationId": "createMenusRolesMapping", + "summary": "Detach policy from role", + "operationId": "detachPolicyFromRole", "parameters": [ { - "description": "Menu Mapping", - "name": "mapping", + "description": "Detach Policy Request", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateMenuMappingRequest" + "$ref": "#/definitions/model.AttachPolicyRequest" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { "type": "object", "additionalProperties": { @@ -1310,6 +1624,15 @@ } } }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, "500": { "description": "Internal Server Error", "schema": { @@ -1320,14 +1643,16 @@ } } } - }, - "delete": { + } + }, + "/api/csp-policies/id/{policyId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Delete the mapping between a platform role and a menu.", + "description": "Retrieve CSP policy details by ID", "consumes": [ "application/json" ], @@ -1335,27 +1660,28 @@ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Delete platform role-menu mapping", - "operationId": "deleteMenusRolesMapping", + "summary": "Get CSP policy by ID", + "operationId": "getCspPolicyByID", "parameters": [ { "type": "string", - "description": "Platform Role ID", - "name": "roleId", - "in": "query" - }, - { - "type": "string", - "description": "Menu ID", - "name": "menuId", - "in": "query" + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "message: Menu mapping deleted successfully", + "description": "OK", + "schema": { + "$ref": "#/definitions/model.CspPolicy" + } + }, + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1363,8 +1689,8 @@ } } }, - "400": { - "description": "error: platform role and menu ID are required", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1373,7 +1699,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1382,16 +1708,14 @@ } } } - } - }, - "/api/menus/platform-roles/list": { - "post": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "List menus mapped to a specific platform role.", + "description": "Update CSP policy details", "consumes": [ "application/json" ], @@ -1399,36 +1723,37 @@ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "List menus mapped to platform role", - "operationId": "listMappedMenusByRole", + "summary": "Update CSP policy", + "operationId": "updateCspPolicy", "parameters": [ { "type": "string", - "description": "Platform Role ID", - "name": "roleId", - "in": "query" + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true }, { - "type": "string", - "description": "Menu ID", - "name": "menuId", - "in": "query" + "description": "CSP Policy Info", + "name": "policy", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UpdateCspPolicyRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Menu" - } + "$ref": "#/definitions/model.CspPolicy" } }, "400": { - "description": "error: platform role is required", + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1436,48 +1761,8 @@ } } }, - "500": { - "description": "error: 서버 내부 오류", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "/api/menus/setup/initial-menus": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "Register/Update menus from YAML file or URL", - "operationId": "registerMenusFromYAML", - "parameters": [ - { - "type": "string", - "description": "YAML file path (optional, uses .env URL or default local path if not provided)", - "name": "filePath", - "in": "query" - } - ], - "responses": { - "200": { - "description": "message: Successfully registered menus from YAML", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1486,7 +1771,7 @@ } }, "500": { - "description": "error: 실패 메시지", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1495,42 +1780,40 @@ } } } - } - }, - "/api/menus/setup/initial-menus2": { - "post": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.", + "description": "Delete a CSP policy by ID", "consumes": [ - "text/plain" + "application/json" ], "produces": [ "application/json" ], "tags": [ - "menus" + "csp-policies" ], - "summary": "Register/Update menus from YAML in request body", - "operationId": "registerMenusFromBody", + "summary": "Delete CSP policy", + "operationId": "deleteCspPolicy", "parameters": [ { - "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", - "description": "Menu definitions in YAML format (must contain 'menus:' root key)", - "name": "yaml", - "in": "body", - "required": true, - "schema": { - "type": "string" - } + "type": "string", + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "message: Successfully registered menus from request body", + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1538,8 +1821,8 @@ } } }, - "400": { - "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1548,7 +1831,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1559,14 +1842,14 @@ } } }, - "/api/menus/tree/list": { - "post": { + "/api/csp-policies/id/{policyId}/document": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "List all menus as a tree structure. Admin permission required.", + "description": "Get the policy document content", "consumes": [ "application/json" ], @@ -1574,22 +1857,29 @@ "application/json" ], "tags": [ - "menus" + "csp-policies" + ], + "summary": "Get policy document", + "operationId": "getPolicyDocument", + "parameters": [ + { + "type": "string", + "description": "Policy ID", + "name": "policyId", + "in": "path", + "required": true + } ], - "summary": "List all menus Tree", - "operationId": "listMenusTree", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MenuTreeNode" - } + "type": "object", + "additionalProperties": true } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1597,8 +1887,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -1607,7 +1897,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -1618,14 +1908,14 @@ } } }, - "/api/menus/user-menu-tree": { - "get": { + "/api/csp-policies/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get menu tree based on user's platform roles", + "description": "Retrieve a list of CSP policies with optional filters", "consumes": [ "application/json" ], @@ -1633,17 +1923,27 @@ "application/json" ], "tags": [ - "menus" + "csp-policies" + ], + "summary": "List CSP policies", + "operationId": "listCspPolicies", + "parameters": [ + { + "description": "Filter options", + "name": "filter", + "in": "body", + "schema": { + "$ref": "#/definitions/model.CspPolicyFilter" + } + } ], - "summary": "Get user menu tree by platform roles", - "operationId": "getUserMenuTree", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.MenuTreeNode" + "$ref": "#/definitions/model.CspPolicy" } } }, @@ -1659,14 +1959,14 @@ } } }, - "/api/permissions/mciam": { - "post": { + "/api/csp-policies/role/{roleId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new permission with the specified information.", + "description": "Get list of policies attached to a CSP role", "consumes": [ "application/json" ], @@ -1674,26 +1974,27 @@ "application/json" ], "tags": [ - "permissions" + "csp-policies" ], - "summary": "Create new permission", - "operationId": "createMciamPermission", + "summary": "Get policies attached to role", + "operationId": "getRolePolicies", "parameters": [ { - "description": "Permission Info", - "name": "permission", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.MciamPermission" - } + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.MciamPermission" + "type": "array", + "items": { + "$ref": "#/definitions/model.CspPolicy" + } } }, "400": { @@ -1717,14 +2018,14 @@ } } }, - "/api/permissions/mciam/id/{id}": { - "get": { + "/api/csp-policies/sync": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve permission details by permission ID.", + "description": "Synchronize policies from the CSP cloud", "consumes": [ "application/json" ], @@ -1732,28 +2033,33 @@ "application/json" ], "tags": [ - "permissions" + "csp-policies" ], - "summary": "Get permission by ID", - "operationId": "getMciamPermissionByID", + "summary": "Sync CSP policies from cloud", + "operationId": "syncCspPolicies", "parameters": [ { - "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true + "description": "Sync Policies Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.SyncPoliciesRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.MciamPermission" + "type": "array", + "items": { + "$ref": "#/definitions/model.CspPolicy" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -1773,14 +2079,9 @@ } } }, - "/api/permissions/mciam/list": { + "/api/initial-admin": { "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Retrieve a list of all permissions.", + "description": "Creates the initial platform admin user with necessary permissions. platform admin 생성인데", "consumes": [ "application/json" ], @@ -1788,40 +2089,34 @@ "application/json" ], "tags": [ - "permissions" + "admin" + ], + "summary": "Setup initial platform admin", + "operationId": "setupInitialAdmin", + "parameters": [ + { + "description": "Setup Initial Admin Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.SetupInitialAdminRequest" + } + } ], - "summary": "List all permissions", - "operationId": "listMciamPermissions", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.MciamPermission" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Response" } } } } }, - "/api/permissions/mciam/{id}": { - "put": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Update the details of an existing permission.", + "/api/mcmp-api-permission-action-mappings": { + "post": { + "description": "Creates a new mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -1829,71 +2124,31 @@ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "Update permission", - "operationId": "updateMciamPermission", + "summary": "Create permission-action mapping", + "operationId": "createMcmpApiPermissionActionMapping", "parameters": [ { - "type": "string", - "description": "Permission ID", - "name": "permissionId", - "in": "path", - "required": true - }, - { - "description": "Permission Info", - "name": "permission", + "description": "Mapping to create", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.MciamPermission" + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" } } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.MciamPermission" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } + "204": { + "description": "No Content" } } - }, - "delete": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Delete a permission by its ID.", + } + }, + "/api/mcmp-api-permission-action-mappings/actions/list": { + "post": { + "description": "Returns all workspace actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -1901,10 +2156,10 @@ "application/json" ], "tags": [ - "permissions" + "mcmp-api-permission-action-mappings" ], - "summary": "Delete permission", - "operationId": "deleteMciamPermission", + "summary": "Get workspace actions by permission ID", + "operationId": "listWorkspaceActionsByPermissionID", "parameters": [ { "type": "string", @@ -1915,38 +2170,21 @@ } ], "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/api/projects": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Create a new project with the specified information.", + "/api/mcmp-api-permission-action-mappings/actions/{actionId}/permissions": { + "get": { + "description": "Returns all permissions mapped to a specific API action", "consumes": [ "application/json" ], @@ -1954,42 +2192,25 @@ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" ], - "summary": "Create new project", - "operationId": "createProject", + "summary": "Get permissions by action ID", + "operationId": "listPermissionsByActionID", "parameters": [ { - "description": "Project Info", - "name": "project", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Project" - } + "type": "integer", + "description": "Action ID", + "name": "actionId", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { + "type": "array", + "items": { "type": "string" } } @@ -1997,14 +2218,9 @@ } } }, - "/api/projects/list": { + "/api/mcmp-api-permission-action-mappings/list": { "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Retrieve a list of all projects.", + "description": "Returns all platform actions mapped to a specific permission", "consumes": [ "application/json" ], @@ -2012,40 +2228,35 @@ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" + ], + "summary": "List platform actions by permission ID", + "operationId": "listPlatformActions", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } ], - "summary": "List all projects", - "operationId": "listProjects", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } } }, - "/api/projects/name/{projectName}": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get project details by name", + "/api/mcmp-api-permission-action-mappings/permissions/{permissionId}/actions/{actionId}": { + "put": { + "description": "Updates an existing mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -2053,37 +2264,38 @@ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" ], - "summary": "Get project by name", - "operationId": "getProjectByName", + "summary": "Update permission-action mapping", + "operationId": "updateMapping", "parameters": [ { "type": "string", - "description": "Project Name", - "name": "name", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true + }, + { + "description": "Updated mapping", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/mcmpapi.McmpApiPermissionActionMapping" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2092,16 +2304,9 @@ } } } - } - }, - "/api/projects/{id}": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Retrieve project details by project ID.", + }, + "delete": { + "description": "Deletes a mapping between a permission and an API action", "consumes": [ "application/json" ], @@ -2109,53 +2314,77 @@ "application/json" ], "tags": [ - "projects" + "mcmp-api-permission-action-mappings" ], - "summary": "Get project by ID", - "operationId": "getProjectByID", + "summary": "Delete permission-action mapping", + "operationId": "deleteMapping", "parameters": [ { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Action ID", + "name": "actionId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Project" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", + "204": { + "description": "No Content" + } + } + } + }, + "/api/mcmp-api-permission-action-mappings/platforms/id/{permissionId}/actions": { + "get": { + "description": "Returns all platform actions mapped to a specific permission", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcmp-api-permission-action-mappings" + ], + "summary": "Get platform actions by permission ID", + "operationId": "getPlatformActionsByPermissionID", + "parameters": [ + { + "type": "string", + "description": "Permission ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/mcmpapi.McmpApiAction" } } } } - }, - "put": { + } + }, + "/api/mcmp-apis/import": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing project.", + "description": "Fetches API specifications from remote URLs and imports them to the database. Supports swagger and openapi source types.", "consumes": [ "application/json" ], @@ -2163,46 +2392,30 @@ "application/json" ], "tags": [ - "projects" + "McmpAPI" ], - "summary": "Update project", - "operationId": "updateProject", + "summary": "Import MCMP APIs from Remote Sources", + "operationId": "importAPIs", "parameters": [ { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "description": "Project Info", - "name": "project", + "description": "Frameworks to import", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.ImportApiRequest" } } ], "responses": { "200": { - "description": "OK", + "description": "Import results", "schema": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.ImportApiResponse" } }, "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "Not Found", + "description": "error: Invalid request body", "schema": { "type": "object", "additionalProperties": { @@ -2211,7 +2424,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: Failed to import APIs", "schema": { "type": "object", "additionalProperties": { @@ -2220,14 +2433,16 @@ } } } - }, - "delete": { + } + }, + "/api/mcmp-apis/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a project by its ID.", + "description": "Retrieves all MCMP API service and action definitions currently stored in the database.", "consumes": [ "application/json" ], @@ -2235,34 +2450,33 @@ "application/json" ], "tags": [ - "projects" + "McmpAPI" ], - "summary": "Delete project", - "operationId": "deleteProject", + "summary": "Get All Stored MCMP API Definitions", + "operationId": "listServicesAndActions", "parameters": [ { "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true + "description": "Filter by service name", + "name": "serviceName", + "in": "query" + }, + { + "type": "string", + "description": "Filter by action name (operationId)", + "name": "actionName", + "in": "query" } ], "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", + "200": { + "description": "Successfully retrieved API definitions", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/mcmpapi.McmpApiDefinitions" } }, "500": { - "description": "Internal Server Error", + "description": "message: Failed to retrieve API definitions", "schema": { "type": "object", "additionalProperties": { @@ -2273,14 +2487,14 @@ } } }, - "/api/projects/{id}/workspaces/{workspaceId}": { + "/api/mcmp-apis/mcmpApiCall": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "프로젝트에 워크스페이스를 연결합니다.", + "description": "Executes a defined MCMP API action with parameters structured in McmpApiCallRequest.", "consumes": [ "application/json" ], @@ -2288,32 +2502,30 @@ "application/json" ], "tags": [ - "projects" + "McmpAPI" ], - "summary": "프로젝트에 워크스페이스 연결", - "operationId": "addWorkspaceToProject", + "summary": "Call an external MCMP API action (Structured Request)", + "operationId": "mcmpApiCall", "parameters": [ { - "type": "integer", - "description": "프로젝트 ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "워크스페이스 ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "API Call Request", + "name": "callRequest", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.McmpApiCallRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "External API Response (structure depends on the called API)", + "schema": { + "type": "object" + } }, "400": { - "description": "error: 잘못된 ID 형식", + "description": "error: Invalid request body or parameters", "schema": { "type": "object", "additionalProperties": { @@ -2322,7 +2534,7 @@ } }, "404": { - "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", + "description": "error: Service or action not found", "schema": { "type": "object", "additionalProperties": { @@ -2331,7 +2543,16 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "error: Internal server error or failed to call external API", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "503": { + "description": "error: External API unavailable", "schema": { "type": "object", "additionalProperties": { @@ -2342,14 +2563,14 @@ } } }, - "/api/resource-types/cloud-resources": { - "post": { + "/api/mcmp-apis/name/{serviceName}": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "새로운 리소스 타입을 생성합니다", + "description": "Updates specific fields (e.g., BaseURL, Auth info) of an MCMP API service definition identified by its name. Cannot update name or version.", "consumes": [ "application/json" ], @@ -2357,30 +2578,40 @@ "application/json" ], "tags": [ - "resource-types" + "McmpAPI" ], - "summary": "Cloud에서 관리되는 Resource(vm, nlb, k8s 등의 그룹) 새 리소스 타입 생성", - "operationId": "createResourceType", + "summary": "Update MCMP API Service Definition", + "operationId": "UpdateFrameworkService", "parameters": [ { - "description": "Resource Type Info", - "name": "resourceType", + "type": "string", + "description": "Service Name to update", + "name": "serviceName", + "in": "path", + "required": true + }, + { + "description": "Fields to update (e.g., {\\", + "name": "updates", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.ResourceType" + "type": "object" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "message: Service updated successfully\" // Or return updated service?", "schema": { - "$ref": "#/definitions/model.ResourceType" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "error: Invalid request", + "description": "error: Invalid service name or request body", "schema": { "type": "object", "additionalProperties": { @@ -2388,8 +2619,8 @@ } } }, - "401": { - "description": "error: Unauthorized", + "404": { + "description": "error: Service not found", "schema": { "type": "object", "additionalProperties": { @@ -2397,8 +2628,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "500": { + "description": "error: Failed to update service", "schema": { "type": "object", "additionalProperties": { @@ -2409,14 +2640,14 @@ } } }, - "/api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId": { - "get": { + "/api/mcmp-apis/name/{serviceName}/versions/{version}/activate": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "특정 리소스 타입을 ID로 조회합니다", + "description": "Sets the specified version of an MCMP API service as the active one.", "consumes": [ "application/json" ], @@ -2424,28 +2655,32 @@ "application/json" ], "tags": [ - "resource-types" + "McmpAPI" ], - "summary": "리소스 타입 ID로 조회", - "operationId": "getCloudResourceTypeByID", + "summary": "Set Active Version for a Service", + "operationId": "setActiveVersion", "parameters": [ { "type": "string", - "description": "Resource Type ID", - "name": "id", + "description": "Service Name", + "name": "serviceName", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Version to activate", + "name": "version", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.ResourceType" - } + "204": { + "description": "No Content" }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "error: Invalid service name or version", "schema": { "type": "object", "additionalProperties": { @@ -2453,8 +2688,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "error: Service or version not found", "schema": { "type": "object", "additionalProperties": { @@ -2462,8 +2697,8 @@ } } }, - "404": { - "description": "error: Resource Type not found", + "500": { + "description": "error: Failed to set active version", "schema": { "type": "object", "additionalProperties": { @@ -2472,14 +2707,16 @@ } } } - }, - "put": { + } + }, + "/api/mcmp-apis/syncMcmpAPIs": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "리소스 타입 정보를 업데이트합니다", + "description": "Triggers the synchronization of MCMP API definitions from the configured YAML URL to the database.", "consumes": [ "application/json" ], @@ -2487,55 +2724,13 @@ "application/json" ], "tags": [ - "resource-types" - ], - "summary": "리소스 타입 업데이트", - "operationId": "updateResourceType", - "parameters": [ - { - "type": "string", - "description": "Resource Type ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Resource Type Info", - "name": "resourceType", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.ResourceType" - } - } + "McmpAPI" ], + "summary": "Sync MCMP API Definitions", + "operationId": "syncMcmpAPIs", "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.ResourceType" - } - }, - "400": { - "description": "error: Invalid request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: Forbidden", + "description": "message: Successfully triggered MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -2543,8 +2738,8 @@ } } }, - "404": { - "description": "error: Resource Type not found", + "500": { + "description": "message: Failed to trigger MCMP API sync", "schema": { "type": "object", "additionalProperties": { @@ -2553,49 +2748,34 @@ } } } - }, - "delete": { + } + }, + "/api/mcmp-apis/test/mc-infra-manager/getallns": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "리소스 타입을 삭제합니다", - "consumes": [ - "application/json" - ], + "description": "Calls the GetAllNs action of the mc-infra-manager service via the CallApi service.", "produces": [ "application/json" ], "tags": [ - "resource-types" - ], - "summary": "리소스 타입 삭제", - "operationId": "deleteResourceType", - "parameters": [ - { - "type": "string", - "description": "Resource Type ID", - "name": "id", - "in": "path", - "required": true - } + "McmpAPI", + "Test" ], + "summary": "Test Call to mc-infra-manager GetAllNs", + "operationId": "testCallGetAllNs", "responses": { - "204": { - "description": "No Content" - }, - "401": { - "description": "error: Unauthorized", + "200": { + "description": "Response from mc-infra-manager GetAllNs", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "type": "object" } }, - "403": { - "description": "error: Forbidden", + "400": { + "description": "error: Bad Request (e.g., invalid parameters)", "schema": { "type": "object", "additionalProperties": { @@ -2604,48 +2784,16 @@ } }, "404": { - "description": "error: Resource Type not found", + "description": "error: Service or Action Not Found", "schema": { "type": "object", "additionalProperties": { "type": "string" } } - } - } - } - }, - "/api/resource-types/cloud-resources/list": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "모든 리소스 타입 목록을 조회합니다", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "resource-types" - ], - "summary": "리소스 타입 목록 조회", - "operationId": "listCloudResourceTypes", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.ResourceType" - } - } }, - "401": { - "description": "error: Unauthorized", + "500": { + "description": "error: Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -2653,8 +2801,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "503": { + "description": "error: External API Service Unavailable", "schema": { "type": "object", "additionalProperties": { @@ -2665,14 +2813,14 @@ } } }, - "/api/roles": { + "/api/menus": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new role", + "description": "Create a new menu", "consumes": [ "application/json" ], @@ -2680,18 +2828,18 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Create role", - "operationId": "createRole", + "summary": "Create new menu", + "operationId": "createMenu", "parameters": [ { - "description": "Role Info", - "name": "role", + "description": "Menu Info", + "name": "menu", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.Menu" } } ], @@ -2699,38 +2847,20 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/model.RoleMaster" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } } }, - "/api/roles/assign/platform-role": { - "post": { + "/api/menus/id/{menuId}": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "Assign a platform role to a user", + "description": "Update menu information", "consumes": [ "application/json" ], @@ -2738,18 +2868,25 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Assign platform role", - "operationId": "assignPlatformRole", + "summary": "Update menu information", + "operationId": "updateMenu", "parameters": [ { - "description": "Platform Role Assignment Info", - "name": "request", + "type": "string", + "description": "Menu ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Menu Info", + "name": "menu", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.Menu" } } ], @@ -2757,41 +2894,18 @@ "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } - } - }, - "/api/roles/assign/workspace-role": { + }, "post": { "security": [ { "BearerAuth": [] } ], - "description": "Assign a workspace role to a user", + "description": "Get menu details by ID", "consumes": [ "application/json" ], @@ -2799,60 +2913,35 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Assign workspace role", - "operationId": "assignWorkspaceRole", + "summary": "Get menu by ID", + "operationId": "getMenuByID", "parameters": [ { - "description": "Workspace Role Assignment Info", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.AssignWorkspaceRoleRequest" - } + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.Menu" } } } - } - }, - "/api/roles/csp": { - "post": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new csp role", + "description": "Delete a menu", "consumes": [ "application/json" ], @@ -2860,60 +2949,34 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Create csp role", - "operationId": "createCspRole", + "summary": "Delete menu", + "operationId": "deleteMenu", "parameters": [ { - "description": "CSP Role Creation Info", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" - } + "type": "string", + "description": "Menu ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } + "204": { + "description": "No Content" } } } }, - "/api/roles/csp-roles": { + "/api/menus/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new mapping between role and CSP role", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -2921,30 +2984,31 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Create role-CSP role mapping", - "operationId": "addCspRoleMappings", - "parameters": [ - { - "description": "Mapping Info", - "name": "mapping", - "in": "body", - "required": true, + "summary": "List all menus", + "operationId": "listMenus", + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } } - } - ], - "responses": { - "201": { - "description": "Created", + }, + "401": { + "description": "error: Unauthorized", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "400": { - "description": "Bad Request", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -2953,7 +3017,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -2964,14 +3028,14 @@ } } }, - "/api/roles/csp-roles/batch": { + "/api/menus/platform-roles": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create multiple new csp roles", + "description": "Create a new menu mapping", "consumes": [ "application/json" ], @@ -2979,18 +3043,18 @@ "application/json" ], "tags": [ - "roles" + "menu" ], - "summary": "Create multiple csp roles", - "operationId": "createCspRoles", + "summary": "Create menu mapping", + "operationId": "createMenusRolesMapping", "parameters": [ { - "description": "Multiple CSP Role Creation Info", - "name": "request", + "description": "Menu Mapping", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateCspRolesRequest" + "$ref": "#/definitions/model.CreateMenuMappingRequest" } } ], @@ -2998,9 +3062,9 @@ "201": { "description": "Created", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.CspRole" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -3023,16 +3087,14 @@ } } } - } - }, - "/api/roles/csp-roles/id/:roleId": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get a mapping between role and CSP role", + "description": "Delete the mapping between a platform role and a menu.", "consumes": [ "application/json" ], @@ -3040,30 +3102,36 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Get role-CSP role mapping", - "operationId": "getCspRoleMappingByRoleId", + "summary": "Delete platform role-menu mapping", + "operationId": "deleteMenusRolesMapping", "parameters": [ { - "description": "Mapping Info", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" - } + "type": "string", + "description": "Platform Role ID", + "name": "roleId", + "in": "query" + }, + { + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "message: Menu mapping deleted successfully", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "Bad Request", + "description": "error: platform role and menu ID are required", "schema": { "type": "object", "additionalProperties": { @@ -3072,7 +3140,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3083,14 +3151,14 @@ } } }, - "/api/roles/csp-roles/id/{roleId}": { - "put": { + "/api/menus/platform-roles/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update role information", + "description": "List menus mapped to a specific platform role.", "consumes": [ "application/json" ], @@ -3098,46 +3166,36 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Update csp role", - "operationId": "updateCspRole", + "summary": "List menus mapped to platform role", + "operationId": "listMappedMenusByRole", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Platform Role ID", "name": "roleId", - "in": "path", - "required": true + "in": "query" }, { - "description": "Role Info", - "name": "role", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" - } + "type": "string", + "description": "Menu ID", + "name": "menuId", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" } } }, - "404": { - "description": "Not Found", + "400": { + "description": "error: platform role is required", "schema": { "type": "object", "additionalProperties": { @@ -3146,7 +3204,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3155,14 +3213,16 @@ } } } - }, - "delete": { + } + }, + "/api/menus/setup/initial-menus": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a role", + "description": "Register or update menus from a local YAML file specified by the filePath query parameter, or from the MCWEBCONSOLE_MENUYAML URL in .env if not provided. If loaded from URL, the file is saved to asset/menu/menu.yaml.", "consumes": [ "application/json" ], @@ -3170,25 +3230,21 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Delete csp role", - "operationId": "deleteCspRole", + "summary": "Register/Update menus from YAML file or URL", + "operationId": "registerMenusFromYAML", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "roleId", - "in": "path", - "required": true + "description": "YAML file path (optional, uses .env URL or default local path if not provided)", + "name": "filePath", + "in": "query" } ], "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", + "200": { + "description": "message: Successfully registered menus from YAML", "schema": { "type": "object", "additionalProperties": { @@ -3197,7 +3253,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: 실패 메시지", "schema": { "type": "object", "additionalProperties": { @@ -3208,45 +3264,49 @@ } } }, - "/api/roles/csp-roles/list": { + "/api/menus/setup/initial-menus2": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get a mapping between role and CSP role", + "description": "Parse YAML text in the request body and register or update menus in the database. Recommended Content-Type: text/plain, text/yaml, application/yaml.", "consumes": [ - "application/json" + "text/plain" ], "produces": [ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "Get role-CSP role mapping", - "operationId": "listCspRoleMappings", + "summary": "Register/Update menus from YAML in request body", + "operationId": "registerMenusFromBody", "parameters": [ { - "description": "Mapping Info", - "name": "mapping", + "example": "\"menus:\\n - id: new-item\\n parentid: dashboard\\n displayname: New Menu Item\\n restype: menu\\n isaction: false\\n priority: 10\\n menunumber: 9999\"", + "description": "Menu definitions in YAML format (must contain 'menus:' root key)", + "name": "yaml", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "string" } } ], "responses": { "200": { - "description": "OK", + "description": "message: Successfully registered menus from request body", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { - "description": "Bad Request", + "description": "error: 잘못된 요청 본문 또는 YAML 형식 오류", "schema": { "type": "object", "additionalProperties": { @@ -3255,7 +3315,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3266,14 +3326,14 @@ } } }, - "/api/roles/csp/id/{roleId}": { - "get": { + "/api/menus/tree/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get csp role details by ID", + "description": "List all menus as a tree structure. Admin permission required.", "consumes": [ "application/json" ], @@ -3281,28 +3341,31 @@ "application/json" ], "tags": [ - "roles" - ], - "summary": "Get csp role by ID", - "operationId": "getCspRoleByID", - "parameters": [ - { - "type": "string", - "description": "CSP Role ID", - "name": "id", - "in": "path", - "required": true - } + "menus" ], + "summary": "List all menus Tree", + "operationId": "listMenusTree", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } } }, - "404": { - "description": "Not Found", + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -3311,7 +3374,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3322,14 +3385,14 @@ } } }, - "/api/roles/csp/list": { - "post": { + "/api/menus/user-menu-tree": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get a list of all csp roles", + "description": "Get menu tree based on user's platform roles", "consumes": [ "application/json" ], @@ -3337,17 +3400,17 @@ "application/json" ], "tags": [ - "roles" + "menus" ], - "summary": "List csp roles", - "operationId": "listCSPRoles", + "summary": "Get user menu tree by platform roles", + "operationId": "getUserMenuTree", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MenuTreeNode" } } }, @@ -3363,14 +3426,14 @@ } } }, - "/api/roles/csp/name/{roleName}": { - "get": { + "/api/permissions/mciam": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get csp role details by Name", + "description": "Create a new permission with the specified information.", "consumes": [ "application/json" ], @@ -3378,28 +3441,30 @@ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Get csp role by Name", - "operationId": "getCspRoleByName", + "summary": "Create new permission", + "operationId": "createMciamPermission", "parameters": [ { - "type": "string", - "description": "CSP Role Name", - "name": "name", - "in": "path", - "required": true + "description": "Permission Info", + "name": "permission", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.MciamPermission" + } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MciamPermission" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -3419,14 +3484,14 @@ } } }, - "/api/roles/id/{roleId}": { + "/api/permissions/mciam/id/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get role details by ID", + "description": "Retrieve permission details by permission ID.", "consumes": [ "application/json" ], @@ -3434,15 +3499,15 @@ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Get role by ID", - "operationId": "getRoleByRoleID", + "summary": "Get permission by ID", + "operationId": "getMciamPermissionByID", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -3451,7 +3516,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MciamPermission" } }, "404": { @@ -3473,14 +3538,57 @@ } } } - }, + } + }, + "/api/permissions/mciam/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all permissions.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "permissions" + ], + "summary": "List all permissions", + "operationId": "listMciamPermissions", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MciamPermission" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/permissions/mciam/{id}": { "put": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing role.", + "description": "Update the details of an existing permission.", "consumes": [ "application/json" ], @@ -3488,25 +3596,25 @@ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Update role", - "operationId": "updateRole", + "summary": "Update permission", + "operationId": "updateMciamPermission", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true }, { - "description": "Role Info", - "name": "role", + "description": "Permission Info", + "name": "permission", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.MciamPermission" } } ], @@ -3514,7 +3622,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.MciamPermission" } }, "400": { @@ -3552,7 +3660,7 @@ "BearerAuth": [] } ], - "description": "Delete a role by its name.", + "description": "Delete a permission by its ID.", "consumes": [ "application/json" ], @@ -3560,15 +3668,15 @@ "application/json" ], "tags": [ - "roles" + "permissions" ], - "summary": "Delete role", - "operationId": "deleteRole", + "summary": "Delete permission", + "operationId": "deleteMciamPermission", "parameters": [ { "type": "string", - "description": "Role ID", - "name": "id", + "description": "Permission ID", + "name": "permissionId", "in": "path", "required": true } @@ -3598,14 +3706,14 @@ } } }, - "/api/roles/id/{roleId}/assign": { + "/api/projects": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Assign a role to a user", + "description": "Create a new project with the specified information. Optionally specify a workspace to assign the project to.", "consumes": [ "application/json" ], @@ -3613,24 +3721,30 @@ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Assign role", - "operationId": "assignRole", + "summary": "Create new project", + "operationId": "createProject", "parameters": [ { - "description": "Role Assignment Info", - "name": "request", + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.CreateProjectRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.Project" + } + }, + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -3638,8 +3752,8 @@ } } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -3659,14 +3773,14 @@ } } }, - "/api/roles/id/{roleId}/unassign": { - "delete": { + "/api/projects/assign/workspaces": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Remove a role from a user", + "description": "프로젝트에 워크스페이스를 연결합니다.", "consumes": [ "application/json" ], @@ -3674,24 +3788,27 @@ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Remove role", - "operationId": "removeRole", + "summary": "프로젝트에 워크스페이스 연결", + "operationId": "addWorkspaceToProject", "parameters": [ { - "description": "Role Removal Info", + "description": "Workspace and Project IDs", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.WorkspaceProjectMappingRequest" } } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "400": { + "description": "error: 잘못된 ID 형식", "schema": { "type": "object", "additionalProperties": { @@ -3699,8 +3816,8 @@ } } }, - "400": { - "description": "Bad Request", + "404": { + "description": "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다", "schema": { "type": "object", "additionalProperties": { @@ -3709,7 +3826,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: 서버 내부 오류", "schema": { "type": "object", "additionalProperties": { @@ -3720,14 +3837,14 @@ } } }, - "/api/roles/list": { - "post": { + "/api/projects/id/{projectId}/workspaces": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve a list of all roles.", + "description": "Retrieve list of workspaces that the project is assigned to", "consumes": [ "application/json" ], @@ -3735,22 +3852,49 @@ "application/json" ], "tags": [ - "roles" + "projects" + ], + "summary": "Get workspaces assigned to project", + "operationId": "getProjectWorkspaces", + "parameters": [ + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } ], - "summary": "List all roles", - "operationId": "listRoles", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.Workspace" + } + } + }, + "400": { + "description": "error: Invalid project ID", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Project not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, "500": { - "description": "Internal Server Error", + "description": "error: Internal server error", "schema": { "type": "object", "additionalProperties": { @@ -3761,14 +3905,14 @@ } } }, - "/api/roles/mappings/csp-roles/list": { + "/api/projects/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "List users by csp role", + "description": "Retrieve a list of all projects.", "consumes": [ "application/json" ], @@ -3776,37 +3920,17 @@ "application/json" ], "tags": [ - "roles" - ], - "summary": "List users by csp role", - "operationId": "listUsersByCspRole", - "parameters": [ - { - "description": "Filter Role Master Mapping Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" - } - } + "projects" ], + "summary": "List all projects", + "operationId": "listProjects", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/model.Project" } } }, @@ -3822,14 +3946,14 @@ } } }, - "/api/roles/mappings/list": { - "post": { + "/api/projects/name/{projectName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "List role master mappings", + "description": "Get project details by name", "consumes": [ "application/json" ], @@ -3837,33 +3961,28 @@ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "List role master mappings", - "operationId": "listRoleMasterMappings", + "summary": "Get project by name", + "operationId": "getProjectByName", "parameters": [ { - "description": "Filter Role Master Mapping Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" - } + "type": "string", + "description": "Project Name", + "name": "name", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } + "$ref": "#/definitions/model.Project" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -3883,14 +4002,14 @@ } } }, - "/api/roles/mappings/platform-roles/users/list": { - "post": { + "/api/projects/unassign/workspaces": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "List users by platform role", + "description": "Remove a workspace from a project", "consumes": [ "application/json" ], @@ -3898,33 +4017,27 @@ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "List users by platform role", - "operationId": "listUsersByPlatformRole", + "summary": "Remove workspace from project", + "operationId": "removeWorkspaceFromProject", "parameters": [ { - "description": "Filter Role Master Mapping Request", + "description": "Workspace and Project IDs", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + "$ref": "#/definitions/model.WorkspaceProjectMappingRequest" } } ], "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } - } + "204": { + "description": "No Content" }, "400": { - "description": "Bad Request", + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -3933,7 +4046,7 @@ } }, "500": { - "description": "Internal Server Error", + "description": "error: Internal server error", "schema": { "type": "object", "additionalProperties": { @@ -3944,14 +4057,14 @@ } } }, - "/api/roles/mappings/role/id/:roleId": { + "/api/projects/{id}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get role master mappings", + "description": "Retrieve project details by project ID.", "consumes": [ "application/json" ], @@ -3959,30 +4072,28 @@ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Get role master mappings", - "operationId": "getRoleMasterMappings", + "summary": "Get project by ID", + "operationId": "getProjectByID", "parameters": [ { - "description": "Filter Role Master Mapping Request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" - } + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMasterMapping" + "$ref": "#/definitions/model.Project" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -4000,16 +4111,14 @@ } } } - } - }, - "/api/roles/mappings/workspace-roles/users/list": { - "post": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "List users by workspace role", + "description": "Update the details of an existing project.", "consumes": [ "application/json" ], @@ -4017,18 +4126,25 @@ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "List users by workspace role", - "operationId": "listUsersByWorkspaceRole", + "summary": "Update project", + "operationId": "updateProject", "parameters": [ { - "description": "Filter Role Master Mapping Request", - "name": "request", + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Project Info", + "name": "project", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + "$ref": "#/definitions/model.Project" } } ], @@ -4036,10 +4152,7 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMasterMapping" - } + "$ref": "#/definitions/model.Project" } }, "400": { @@ -4051,46 +4164,14 @@ } } }, - "500": { - "description": "Internal Server Error", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { "type": "string" } } - } - } - } - }, - "/api/roles/menu-roles/list": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get a list of all menu roles", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "roles" - ], - "summary": "List menu roles", - "operationId": "listPlatformRoles", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMaster" - } - } }, "500": { "description": "Internal Server Error", @@ -4102,16 +4183,14 @@ } } } - } - }, - "/api/roles/name/{roleName}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve role details by role name.", + "description": "Delete a project by its ID.", "consumes": [ "application/json" ], @@ -4119,25 +4198,22 @@ "application/json" ], "tags": [ - "roles" + "projects" ], - "summary": "Get role by Name", - "operationId": "getRoleByRoleName", + "summary": "Delete project", + "operationId": "deleteProject", "parameters": [ { "type": "string", - "description": "Role name", - "name": "name", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.RoleMaster" - } + "204": { + "description": "No Content" }, "404": { "description": "Not Found", @@ -4160,14 +4236,14 @@ } } }, - "/api/roles/platform-roles": { + "/api/resource-types/cloud-resources": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new menu role", + "description": "새로운 리소스 타입을 생성합니다", "consumes": [ "application/json" ], @@ -4175,24 +4251,30 @@ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Create menu role", - "operationId": "createPlatformRole", + "summary": "Cloud에서 관리되는 Resource(vm, nlb, k8s 등의 그룹) 새 리소스 타입 생성", + "operationId": "createResourceType", "parameters": [ { - "description": "Menu Role Creation Info", - "name": "request", + "description": "Resource Type Info", + "name": "resourceType", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.ResourceType" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } + }, + "400": { + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -4200,8 +4282,8 @@ } } }, - "400": { - "description": "Bad Request", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -4209,8 +4291,8 @@ } } }, - "500": { - "description": "Internal Server Error", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -4221,14 +4303,14 @@ } } }, - "/api/roles/platform-roles/id/{roleId}": { + "/api/resource-types/cloud-resources/framework/:frameworkId/id/:resourceTypeId": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get platform role details by ID", + "description": "특정 리소스 타입을 ID로 조회합니다", "consumes": [ "application/json" ], @@ -4236,14 +4318,14 @@ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Get platform role by ID", - "operationId": "getPlatformRoleByID", + "summary": "리소스 타입 ID로 조회", + "operationId": "getCloudResourceTypeByID", "parameters": [ { "type": "string", - "description": "Platform Role ID", + "description": "Resource Type ID", "name": "id", "in": "path", "required": true @@ -4253,11 +4335,11 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.ResourceType" } }, - "404": { - "description": "Not Found", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -4265,8 +4347,17 @@ } } }, - "500": { - "description": "Internal Server Error", + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -4276,13 +4367,13 @@ } } }, - "delete": { + "put": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a platform role", + "description": "리소스 타입 정보를 업데이트합니다", "consumes": [ "application/json" ], @@ -4290,25 +4381,37 @@ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Delete platform role", - "operationId": "deletePlatformRole", + "summary": "리소스 타입 업데이트", + "operationId": "updateResourceType", "parameters": [ { "type": "string", - "description": "Platform Role ID", - "name": "roleId", + "description": "Resource Type ID", + "name": "id", "in": "path", "required": true + }, + { + "description": "Resource Type Info", + "name": "resourceType", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.ResourceType" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.ResourceType" + } }, - "404": { - "description": "Not Found", + "400": { + "description": "error: Invalid request", "schema": { "type": "object", "additionalProperties": { @@ -4316,8 +4419,26 @@ } } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -4326,16 +4447,14 @@ } } } - } - }, - "/api/roles/platform-roles/name/{roleName}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get menu role details by Name", + "description": "리소스 타입을 삭제합니다", "consumes": [ "application/json" ], @@ -4343,28 +4462,34 @@ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Get menu role by Name", - "operationId": "getPlatformRoleByName", + "summary": "리소스 타입 삭제", + "operationId": "deleteResourceType", "parameters": [ { "type": "string", - "description": "Menu Role Name", - "name": "name", + "description": "Resource Type ID", + "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "401": { + "description": "error: Unauthorized", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "Not Found", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -4372,8 +4497,8 @@ } } }, - "500": { - "description": "Internal Server Error", + "404": { + "description": "error: Resource Type not found", "schema": { "type": "object", "additionalProperties": { @@ -4384,14 +4509,14 @@ } } }, - "/api/roles/unassign/csp-roles": { - "delete": { + "/api/resource-types/cloud-resources/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a mapping between workspace role and CSP role", + "description": "모든 리소스 타입 목록을 조회합니다", "consumes": [ "application/json" ], @@ -4399,27 +4524,22 @@ "application/json" ], "tags": [ - "roles" + "resource-types" ], - "summary": "Delete workspace role-CSP role mapping", - "operationId": "removeCspRoleMappings", - "parameters": [ - { - "description": "Mapping Info", - "name": "mapping", - "in": "body", - "required": true, + "summary": "리소스 타입 목록 조회", + "operationId": "listCloudResourceTypes", + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + "type": "array", + "items": { + "$ref": "#/definitions/model.ResourceType" + } } - } - ], - "responses": { - "204": { - "description": "No Content" }, - "400": { - "description": "Bad Request", + "401": { + "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -4427,8 +4547,8 @@ } } }, - "500": { - "description": "Internal Server Error", + "403": { + "description": "error: Forbidden", "schema": { "type": "object", "additionalProperties": { @@ -4439,14 +4559,14 @@ } } }, - "/api/roles/unassign/platform-role": { - "delete": { + "/api/roles": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Remove a platform role from a user", + "description": "Create a new role", "consumes": [ "application/json" ], @@ -4456,27 +4576,24 @@ "tags": [ "roles" ], - "summary": "Remove platform role", - "operationId": "removePlatformRole", + "summary": "Create role", + "operationId": "createRole", "parameters": [ { - "description": "Platform Role Removal Info", - "name": "request", + "description": "Role Info", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.AssignRoleRequest" + "$ref": "#/definitions/model.CreateRoleRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.RoleMaster" } }, "400": { @@ -4500,14 +4617,14 @@ } } }, - "/api/roles/unassign/workspace-role": { - "delete": { + "/api/roles/assign/platform-role": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Remove a workspace role from a user", + "description": "Assign a platform role to a user", "consumes": [ "application/json" ], @@ -4517,11 +4634,11 @@ "tags": [ "roles" ], - "summary": "Remove workspace role", - "operationId": "removeWorkspaceRole", + "summary": "Assign platform role", + "operationId": "assignPlatformRole", "parameters": [ { - "description": "Workspace Role Removal Info", + "description": "Platform Role Assignment Info", "name": "request", "in": "body", "required": true, @@ -4561,14 +4678,14 @@ } } }, - "/api/roles/workspace-roles": { + "/api/roles/assign/workspace-role": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new workspace role", + "description": "Assign a workspace role to a user", "consumes": [ "application/json" ], @@ -4578,16 +4695,16 @@ "tags": [ "roles" ], - "summary": "Create workspace role", - "operationId": "createWorkspaceRole", + "summary": "Assign workspace role", + "operationId": "assignWorkspaceRole", "parameters": [ { - "description": "Workspace Role Creation Info", + "description": "Workspace Role Assignment Info", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.CreateRoleRequest" + "$ref": "#/definitions/model.AssignWorkspaceRoleRequest" } } ], @@ -4622,14 +4739,14 @@ } } }, - "/api/roles/workspace-roles/id/{roleId}": { - "get": { + "/api/roles/csp": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspace role details by ID", + "description": "Create a new csp role", "consumes": [ "application/json" ], @@ -4639,26 +4756,31 @@ "tags": [ "roles" ], - "summary": "Get workspace role by ID", - "operationId": "getWorkspaceRoleByID", + "summary": "Create csp role", + "operationId": "createCspRole", "parameters": [ { - "type": "string", - "description": "Workspace Role ID", - "name": "id", - "in": "path", - "required": true + "description": "CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -4676,14 +4798,16 @@ } } } - }, - "delete": { + } + }, + "/api/roles/csp-roles": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a workspace role", + "description": "Create a new mapping between role and CSP role", "consumes": [ "application/json" ], @@ -4693,23 +4817,28 @@ "tags": [ "roles" ], - "summary": "Delete workspace role", - "operationId": "deleteWorkspaceRole", + "summary": "Create role-CSP role mapping", + "operationId": "addCspRoleMappings", "parameters": [ { - "type": "string", - "description": "Workspace Role ID", - "name": "roleId", - "in": "path", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -4729,14 +4858,14 @@ } } }, - "/api/roles/workspace-roles/list": { + "/api/roles/csp-roles/batch": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get a list of all workspace roles", + "description": "Create multiple new csp roles", "consumes": [ "application/json" ], @@ -4746,15 +4875,35 @@ "tags": [ "roles" ], - "summary": "List workspace roles", - "operationId": "listWorkspaceRoles", + "summary": "Create multiple csp roles", + "operationId": "createCspRoles", + "parameters": [ + { + "description": "Multiple CSP Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateCspRolesRequest" + } + } + ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.CspRole" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -4770,14 +4919,14 @@ } } }, - "/api/roles/workspace-roles/name/{roleName}": { + "/api/roles/csp-roles/id/:roleId": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspace role details by Name", + "description": "Get a mapping between role and CSP role", "consumes": [ "application/json" ], @@ -4787,26 +4936,28 @@ "tags": [ "roles" ], - "summary": "Get workspace role by Name", - "operationId": "getWorkspaceRoleByName", + "summary": "Get role-CSP role mapping", + "operationId": "getCspRoleMappingByRoleId", "parameters": [ { - "type": "string", - "description": "Workspace Role Name", - "name": "name", - "in": "path", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -4826,9 +4977,14 @@ } } }, - "/api/roles/{roleType}/{roleId}/mciam-permissions": { - "get": { - "description": "특정 역할의 MC-IAM 권한 ID 목록을 조회합니다.", + "/api/roles/csp-roles/id/{roleId}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update role information", "consumes": [ "application/json" ], @@ -4836,43 +4992,71 @@ "application/json" ], "tags": [ - "roles", - "mciam-permissions" + "roles" ], - "summary": "역할의 MC-IAM 권한 목록 조회 - Renamed", - "operationId": "getRoleMciamPermissions", + "summary": "Update csp role", + "operationId": "updateCspRole", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true }, { - "type": "integer", - "description": "역할 ID", - "name": "roleId", - "in": "path", - "required": true + "description": "Role Info", + "name": "role", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } } ], "responses": { "200": { - "description": "권한 ID 목록", + "description": "OK", "schema": { - "type": "array", - "items": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { "type": "string" } } } } - } - }, - "/api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId}": { - "post": { - "description": "역할에 MC-IAM 권한을 할당합니다.", + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a role", "consumes": [ "application/json" ], @@ -4880,42 +5064,52 @@ "application/json" ], "tags": [ - "roles", - "mciam-permissions" + "roles" ], - "summary": "역할에 MC-IAM 권한 할당 - Renamed", - "operationId": "assignMciamPermissionToRole", + "summary": "Delete csp role", + "operationId": "deleteCspRole", "parameters": [ { "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "역할 ID", + "description": "Role ID", "name": "roleId", "in": "path", "required": true - }, - { - "type": "string", - "description": "MC-IAM 권한 ID", - "name": "permissionId", - "in": "path", - "required": true } ], "responses": { "204": { "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } } } - }, - "delete": { - "description": "역할에서 MC-IAM 권한을 제거합니다.", + } + }, + "/api/roles/csp-roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get a mapping between role and CSP role", "consumes": [ "application/json" ], @@ -4923,94 +5117,57 @@ "application/json" ], "tags": [ - "roles", - "mciam-permissions" + "roles" ], - "summary": "역할에서 MC-IAM 권한 제거 - Renamed", - "operationId": "removeMciamPermissionFromRole", + "summary": "Get role-CSP role mapping", + "operationId": "listCspRoleMappings", "parameters": [ { - "type": "string", - "description": "역할 타입 ('platform' or 'workspace')", - "name": "roleType", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "역할 ID", - "name": "roleId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "MC-IAM 권한 ID", - "name": "permissionId", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - } - } - } - }, - "/api/setup/check-user-roles": { - "get": { - "description": "Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "Check user roles", - "operationId": "checkUserRoles", - "parameters": [ - { - "type": "string", - "description": "Username to check roles", - "name": "username", - "in": "query", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Response" + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/setup/initial-role-menu-permission": { + "/api/roles/csp/id/{roleId}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "CSV 파일을 읽어서 메뉴 권한을 초기화합니다", + "description": "Get csp role details by ID", "consumes": [ "application/json" ], @@ -5018,48 +5175,55 @@ "application/json" ], "tags": [ - "admin" + "roles" ], - "summary": "Initialize menu permissions from CSV", - "operationId": "initializeMenuPermissions", + "summary": "Get csp role by ID", + "operationId": "getCspRoleByID", "parameters": [ { "type": "string", - "description": "CSV file path (optional, uses default if not provided)", - "name": "filePath", - "in": "query" + "description": "CSP Role ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Response" + "$ref": "#/definitions/model.RoleMaster" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/model.Response" + "type": "object", + "additionalProperties": { + "type": "string" + } } } } } }, - "/api/setup/sync-projects": { + "/api/roles/csp/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다.", + "description": "Get a list of all csp roles", "consumes": [ "application/json" ], @@ -5067,22 +5231,22 @@ "application/json" ], "tags": [ - "projects" + "roles" ], - "summary": "mc-infra-manager와 프로젝트 동기화", - "operationId": "syncProjects", + "summary": "List csp roles", + "operationId": "listCSPRoles", "responses": { "200": { - "description": "message: Project synchronization successful", + "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" } } }, "500": { - "description": "error: 서버 내부 오류 또는 동기화 실패", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -5093,14 +5257,14 @@ } } }, - "/api/users": { - "post": { + "/api/roles/csp/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new user with the specified information.", + "description": "Get csp role details by Name", "consumes": [ "application/json" ], @@ -5108,30 +5272,28 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Create new user", - "operationId": "createUser", + "summary": "Get csp role by Name", + "operationId": "getCspRoleByName", "parameters": [ { - "description": "User Info", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.User" - } + "type": "string", + "description": "CSP Role Name", + "name": "name", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -5151,14 +5313,14 @@ } } }, - "/api/users/id/{userId}": { + "/api/roles/id/{roleId}": { "get": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve user details by user ID.", + "description": "Get role details by ID", "consumes": [ "application/json" ], @@ -5166,15 +5328,15 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user by ID", - "operationId": "getUserByID", + "summary": "Get role by ID", + "operationId": "getRoleByRoleID", "parameters": [ { "type": "string", - "description": "User ID", - "name": "userId", + "description": "Role ID", + "name": "id", "in": "path", "required": true } @@ -5183,7 +5345,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } }, "404": { @@ -5205,16 +5367,14 @@ } } } - } - }, - "/api/users/id/{userId}/status": { - "post": { + }, + "put": { "security": [ { "BearerAuth": [] } ], - "description": "Update user status (active/inactive)", + "description": "Update the details of an existing role.", "consumes": [ "application/json" ], @@ -5222,25 +5382,25 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Update user status", - "operationId": "updateUserStatus", + "summary": "Update role", + "operationId": "updateRole", "parameters": [ { "type": "string", - "description": "User ID", + "description": "Role ID", "name": "id", "in": "path", "required": true }, { - "description": "User Status", - "name": "status", + "description": "Role Info", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.UserStatusRequest" + "$ref": "#/definitions/model.CreateRoleRequest" } } ], @@ -5248,7 +5408,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } }, "400": { @@ -5279,16 +5439,14 @@ } } } - } - }, - "/api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspaces and roles for a specific user and workspace", + "description": "Delete a role by its name.", "consumes": [ "application/json" ], @@ -5296,33 +5454,29 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user workspace and workspace roles by user ID and workspace ID", - "operationId": "getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID", + "summary": "Delete role", + "operationId": "deleteRole", "parameters": [ { "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", + "description": "Role ID", + "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.UserWorkspaceRole" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5338,14 +5492,14 @@ } } }, - "/api/users/id/{userId}/workspaces/list": { - "get": { + "/api/roles/id/{roleId}/assign": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get workspaces for a specific user", + "description": "Assign a role to a user", "consumes": [ "application/json" ], @@ -5353,76 +5507,37 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user workspaces by user ID", - "operationId": "getUserWorkspacesByUserID", + "summary": "Assign role", + "operationId": "assignRole", "parameters": [ { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true + "description": "Role Assignment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" - } - } - }, - "500": { - "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } - } - } - } - }, - "/api/users/id/{userId}/workspaces/roles/list": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get workspaces and roles for a specific user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Get user workspace and workspace roles by user ID", - "operationId": "getUserWorkspaceAndWorkspaceRolesByUserID", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + "400": { + "description": "Bad Request", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.UserWorkspaceRole" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5438,14 +5553,14 @@ } } }, - "/api/users/kc/{kcUserId}": { - "get": { + "/api/roles/id/{roleId}/unassign": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get user details by KcID", + "description": "Remove a role from a user", "consumes": [ "application/json" ], @@ -5453,28 +5568,33 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user by KcID", - "operationId": "getUserByKcID", + "summary": "Remove role", + "operationId": "removeRole", "parameters": [ { - "type": "string", - "description": "User KcID", - "name": "kcUserId", - "in": "path", - "required": true + "description": "Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -5494,14 +5614,14 @@ } } }, - "/api/users/list": { + "/api/roles/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve a list of all users.", + "description": "Retrieve a list of all roles.", "consumes": [ "application/json" ], @@ -5509,17 +5629,17 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "List all users", - "operationId": "listUsers", + "summary": "List all roles", + "operationId": "listRoles", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.User" + "$ref": "#/definitions/model.RoleMaster" } } }, @@ -5535,14 +5655,14 @@ } } }, - "/api/users/menus-tree/list": { + "/api/roles/mappings/csp-roles/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Get the menu tree accessible to the current user's platform role.", + "description": "List users by csp role", "consumes": [ "application/json" ], @@ -5550,22 +5670,33 @@ "application/json" ], "tags": [ - "menus" + "roles" + ], + "summary": "List users by csp role", + "operationId": "listUsersByCspRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } ], - "summary": "Get current user's menu tree", - "operationId": "listUserMenuTree", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.MenuTreeNode" + "$ref": "#/definitions/model.RoleMasterMapping" } } }, - "401": { - "description": "error: Unauthorized", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -5574,7 +5705,7 @@ } }, "500": { - "description": "error: 서버 내부 오류", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -5585,41 +5716,14 @@ } } }, - "/api/users/menus/list": { + "/api/roles/mappings/list": { "post": { - "description": "Get the menu list accessible to the current user's platform role.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "menus" - ], - "summary": "Get current user's menu list", - "operationId": "listUserMenu", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Menu" - } - } - } - } - } - }, - "/api/users/name/{username}": { - "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get user details by username", + "description": "List role master mappings", "consumes": [ "application/json" ], @@ -5627,28 +5731,33 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Get user by username", - "operationId": "getUserByUsername", + "summary": "List role master mappings", + "operationId": "listRoleMasterMappings", "parameters": [ { - "type": "string", - "description": "Username", - "name": "name", - "in": "path", - "required": true + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMasterMapping" + } } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -5668,14 +5777,14 @@ } } }, - "/api/users/workspaces/id/{workspaceId}/projects/list": { - "get": { + "/api/roles/mappings/platform-roles/users/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "List projects for the current user", + "description": "List users by platform role", "consumes": [ "application/json" ], @@ -5683,17 +5792,19 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "List user projects by workspace", - "operationId": "listUserProjectsByWorkspace", + "summary": "List users by platform role", + "operationId": "listUsersByPlatformRole", "parameters": [ { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } } ], "responses": { @@ -5702,7 +5813,16 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5718,14 +5838,14 @@ } } }, - "/api/users/workspaces/list": { - "post": { + "/api/roles/mappings/role/id/:roleId": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "List workspaces for the current user", + "description": "Get role master mappings", "consumes": [ "application/json" ], @@ -5733,17 +5853,34 @@ "application/json" ], "tags": [ - "users" + "roles" + ], + "summary": "Get role master mappings", + "operationId": "getRoleMasterMappings", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } ], - "summary": "List user workspaces", - "operationId": "listUserWorkspaces", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.RoleMasterMapping" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5759,14 +5896,14 @@ } } }, - "/api/users/workspaces/roles/list": { + "/api/roles/mappings/workspace-roles/users/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "List workspaces and roles for the current user", + "description": "List users by workspace role", "consumes": [ "application/json" ], @@ -5774,17 +5911,37 @@ "application/json" ], "tags": [ - "users" + "roles" + ], + "summary": "List users by workspace role", + "operationId": "listUsersByWorkspaceRole", + "parameters": [ + { + "description": "Filter Role Master Mapping Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.FilterRoleMasterMappingRequest" + } + } ], - "summary": "List user workspace and roles", - "operationId": "listUserWorkspaceAndWorkspaceRoles", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.RoleMaster" + "$ref": "#/definitions/model.RoleMasterMapping" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -5800,14 +5957,14 @@ } } }, - "/api/users/{id}": { - "put": { + "/api/roles/menu-roles/list": { + "post": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing user.", + "description": "Get a list of all menu roles", "consumes": [ "application/json" ], @@ -5815,50 +5972,17 @@ "application/json" ], "tags": [ - "users" - ], - "summary": "Update user", - "operationId": "updateUser", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "User Info", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.User" - } - } + "roles" ], + "summary": "List menu roles", + "operationId": "listPlatformRoles", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.User" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" } } }, @@ -5872,14 +5996,16 @@ } } } - }, - "delete": { + } + }, + "/api/roles/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a user by their ID.", + "description": "Retrieve role details by role name.", "consumes": [ "application/json" ], @@ -5887,22 +6013,25 @@ "application/json" ], "tags": [ - "users" + "roles" ], - "summary": "Delete user", - "operationId": "deleteUser", + "summary": "Get role by Name", + "operationId": "getRoleByRoleName", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Role name", + "name": "name", "in": "path", "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } }, "404": { "description": "Not Found", @@ -5925,14 +6054,14 @@ } } }, - "/api/workspaces": { + "/api/roles/platform-roles": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Create a new workspace with the specified information.", + "description": "Create a new menu role", "consumes": [ "application/json" ], @@ -5940,26 +6069,29 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Create new workspace", - "operationId": "createWorkspace", + "summary": "Create menu role", + "operationId": "createPlatformRole", "parameters": [ { - "description": "Workspace Info", - "name": "workspace", + "description": "Menu Role Creation Info", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.CreateRoleRequest" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "400": { @@ -5983,14 +6115,14 @@ } } }, - "/api/workspaces/assign/projects": { - "post": { + "/api/roles/platform-roles/id/{roleId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Add a project to a workspace", + "description": "Get platform role details by ID", "consumes": [ "application/json" ], @@ -5998,53 +6130,28 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Add project to workspace", - "operationId": "addProjectToWorkspace", + "summary": "Get platform role by ID", + "operationId": "getPlatformRoleByID", "parameters": [ { "type": "string", - "description": "Workspace ID", + "description": "Platform Role ID", "name": "id", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "400": { - "description": "error: Invalid request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.RoleMaster" } }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -6052,8 +6159,8 @@ } } }, - "404": { - "description": "error: Workspace or Project not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6062,16 +6169,14 @@ } } } - } - }, - "/api/workspaces/id/{workspaceId}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve workspace details by workspace ID.", + "description": "Delete a platform role", "consumes": [ "application/json" ], @@ -6079,25 +6184,22 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Get workspace by ID", - "operationId": "getWorkspaceByID", + "summary": "Delete platform role", + "operationId": "deletePlatformRole", "parameters": [ { "type": "string", - "description": "Workspace ID", - "name": "workspaceId", + "description": "Platform Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Workspace" - } + "204": { + "description": "No Content" }, "404": { "description": "Not Found", @@ -6118,14 +6220,16 @@ } } } - }, - "put": { + } + }, + "/api/roles/platform-roles/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Update the details of an existing workspace.", + "description": "Get menu role details by Name", "consumes": [ "application/json" ], @@ -6133,42 +6237,24 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Update workspace", - "operationId": "updateWorkspace", + "summary": "Get menu role by Name", + "operationId": "getPlatformRoleByName", "parameters": [ { "type": "string", - "description": "Workspace ID", - "name": "id", + "description": "Menu Role Name", + "name": "name", "in": "path", "required": true - }, - { - "description": "Workspace Info", - "name": "workspace", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/model.Workspace" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/model.RoleMaster" } }, "404": { @@ -6190,14 +6276,16 @@ } } } - }, + } + }, + "/api/roles/unassign/csp-roles": { "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Delete a workspace by its ID.", + "description": "Delete a mapping between workspace role and CSP role", "consumes": [ "application/json" ], @@ -6205,25 +6293,27 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Delete workspace", - "operationId": "deleteWorkspace", + "summary": "Delete workspace role-CSP role mapping", + "operationId": "removeCspRoleMappings", "parameters": [ { - "type": "string", - "description": "Workspace ID", - "name": "id", - "in": "path", - "required": true + "description": "Mapping Info", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleMasterCspRoleMappingRequest" + } } ], "responses": { "204": { "description": "No Content" }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -6243,14 +6333,14 @@ } } }, - "/api/workspaces/id/{workspaceId}/projects/list": { - "get": { + "/api/roles/unassign/platform-role": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve project list belonging to specific workspace", + "description": "Remove a platform role from a user", "consumes": [ "application/json" ], @@ -6258,31 +6348,24 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "List workspace projects", - "operationId": "getWorkspaceProjectsByWorkspaceId", + "summary": "Remove platform role", + "operationId": "removePlatformRole", "parameters": [ { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Platform Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Project" - } - } - }, - "401": { - "description": "error: Unauthorized", "schema": { "type": "object", "additionalProperties": { @@ -6290,8 +6373,8 @@ } } }, - "403": { - "description": "error: Forbidden", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -6299,8 +6382,8 @@ } } }, - "404": { - "description": "error: Workspace not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6311,14 +6394,14 @@ } } }, - "/api/workspaces/id/{workspaceId}/users/id/{userId}": { - "get": { + "/api/roles/unassign/workspace-role": { + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Get roles assigned to a user in a workspace", + "description": "Remove a workspace role from a user", "consumes": [ "application/json" ], @@ -6328,31 +6411,26 @@ "tags": [ "roles" ], - "summary": "Get user workspace roles", - "operationId": "getUserWorkspaceRoles", + "summary": "Remove workspace role", + "operationId": "removeWorkspaceRole", "parameters": [ { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Workspace Role Removal Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AssignRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.RoleMaster" + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -6377,9 +6455,14 @@ } } }, - "/api/workspaces/id/{workspaceId}/users/list": { + "/api/roles/workspace-roles": { "post": { - "description": "Retrieve users and roles list belonging to workspace", + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace role", "consumes": [ "application/json" ], @@ -6387,31 +6470,24 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "List users and roles by workspace", - "operationId": "listUsersAndRolesByWorkspace", + "summary": "Create workspace role", + "operationId": "createWorkspaceRole", "parameters": [ { - "type": "integer", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true + "description": "Workspace Role Creation Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.CreateRoleRequest" + } } ], "responses": { "200": { "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.UserWorkspaceRole" - } - } - }, - "400": { - "description": "error: Invalid workspace ID", "schema": { "type": "object", "additionalProperties": { @@ -6419,8 +6495,8 @@ } } }, - "404": { - "description": "error: Workspace not found", + "400": { + "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { @@ -6429,7 +6505,7 @@ } }, "500": { - "description": "error: Internal server error", + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6440,14 +6516,14 @@ } } }, - "/api/workspaces/list": { - "post": { + "/api/roles/workspace-roles/id/{roleId}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve a list of all workspaces.", + "description": "Get workspace role details by ID", "consumes": [ "application/json" ], @@ -6455,17 +6531,32 @@ "application/json" ], "tags": [ - "workspaces" + "roles" + ], + "summary": "Get workspace role by ID", + "operationId": "getWorkspaceRoleByID", + "parameters": [ + { + "type": "string", + "description": "Workspace Role ID", + "name": "id", + "in": "path", + "required": true + } ], - "summary": "List all workspaces", - "operationId": "listWorkspaces", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Workspace" + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" } } }, @@ -6479,16 +6570,14 @@ } } } - } - }, - "/api/workspaces/name/{workspaceName}": { - "get": { + }, + "delete": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve specific workspace by name", + "description": "Delete a workspace role", "consumes": [ "application/json" ], @@ -6496,37 +6585,25 @@ "application/json" ], "tags": [ - "workspaces" + "roles" ], - "summary": "Get workspace by name", - "operationId": "getWorkspaceByName", + "summary": "Delete workspace role", + "operationId": "deleteWorkspaceRole", "parameters": [ { "type": "string", - "description": "Workspace Name", - "name": "workspaceName", + "description": "Workspace Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Workspace" - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } + "204": { + "description": "No Content" }, - "403": { - "description": "error: Forbidden", + "404": { + "description": "Not Found", "schema": { "type": "object", "additionalProperties": { @@ -6534,8 +6611,8 @@ } } }, - "404": { - "description": "error: Workspace not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6546,14 +6623,14 @@ } } }, - "/api/workspaces/projects/list": { + "/api/roles/workspace-roles/list": { "post": { "security": [ { "BearerAuth": [] } ], - "description": "Retrieve project list belonging to specific workspace", + "description": "Get a list of all workspace roles", "consumes": [ "application/json" ], @@ -6561,49 +6638,22 @@ "application/json" ], "tags": [ - "workspaces" - ], - "summary": "List workspace projects", - "operationId": "listWorkspaceProjects", - "parameters": [ - { - "type": "string", - "description": "Workspace ID", - "name": "workspaceId", - "in": "path", - "required": true - } + "roles" ], + "summary": "List workspace roles", + "operationId": "listRolesOfWorkspaceType", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/model.Project" - } - } - }, - "401": { - "description": "error: Unauthorized", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "403": { - "description": "error: Forbidden", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" + "$ref": "#/definitions/model.RoleMaster" } } }, - "404": { - "description": "error: Workspace not found", + "500": { + "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { @@ -6614,14 +6664,14 @@ } } }, - "/api/workspaces/temporary-credentials": { - "post": { + "/api/roles/workspace-roles/name/{roleName}": { + "get": { "security": [ { "BearerAuth": [] } ], - "description": "Get temporary credentials for CSP", + "description": "Get workspace role details by Name", "consumes": [ "application/json" ], @@ -6629,10 +6679,1915 @@ "application/json" ], "tags": [ - "csp-credentials" + "roles" ], - "summary": "Get temporary credentials", - "operationId": "mciamGetTemporaryCredentials", + "summary": "Get workspace role by Name", + "operationId": "getWorkspaceRoleByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Role Name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.RoleMaster" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions": { + "get": { + "description": "특정 역할의 MC-IAM 권한 ID 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할의 MC-IAM 권한 목록 조회 - Renamed", + "operationId": "getRoleMciamPermissions", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "권한 ID 목록", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/api/roles/{roleType}/{roleId}/mciam-permissions/{permissionId}": { + "post": { + "description": "역할에 MC-IAM 권한을 할당합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에 MC-IAM 권한 할당 - Renamed", + "operationId": "assignMciamPermissionToRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + }, + "delete": { + "description": "역할에서 MC-IAM 권한을 제거합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles", + "mciam-permissions" + ], + "summary": "역할에서 MC-IAM 권한 제거 - Renamed", + "operationId": "removeMciamPermissionFromRole", + "parameters": [ + { + "type": "string", + "description": "역할 타입 ('platform' or 'workspace')", + "name": "roleType", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "역할 ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "MC-IAM 권한 ID", + "name": "permissionId", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/api/setup/check-user-roles": { + "get": { + "description": "Check all roles assigned to a user. 특정 유저가 가진 role 목록을 조회합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Check user roles", + "operationId": "checkUserRoles", + "parameters": [ + { + "type": "string", + "description": "Username to check roles", + "name": "username", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/initial-role-menu-permission": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "CSV 파일을 읽어서 메뉴 권한을 초기화합니다", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Initialize menu permissions from CSV", + "operationId": "initializeMenuPermissions", + "parameters": [ + { + "type": "string", + "description": "CSV file path (optional, uses default if not provided)", + "name": "filePath", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/model.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/model.Response" + } + } + } + } + }, + "/api/setup/sync-projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "projects" + ], + "summary": "mc-infra-manager와 프로젝트 동기화", + "operationId": "syncProjects", + "responses": { + "200": { + "description": "message: Project synchronization successful", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류 또는 동기화 실패", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new user with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Create new user", + "operationId": "createUser", + "parameters": [ + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve user details by user ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by ID", + "operationId": "getUserByID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/status": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update user status (active/inactive)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user status", + "operationId": "updateUserStatus", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Status", + "name": "status", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UserStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/id/{workspaceId}/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user and workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID and workspace ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserIDAndWorkspaceID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspaces by user ID", + "operationId": "getUserWorkspacesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/id/{userId}/workspaces/roles/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get workspaces and roles for a specific user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user workspace and workspace roles by user ID", + "operationId": "getUserWorkspaceAndWorkspaceRolesByUserID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/kc/{kcUserId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by KcID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by KcID", + "operationId": "getUserByKcID", + "parameters": [ + { + "type": "string", + "description": "User KcID", + "name": "kcUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all users.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List all users", + "operationId": "listUsers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.User" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus-tree/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get the menu tree accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu tree", + "operationId": "listUserMenuTree", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MenuTreeNode" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: 서버 내부 오류", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/menus/list": { + "post": { + "description": "Get the menu list accessible to the current user's platform role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "menus" + ], + "summary": "Get current user's menu list", + "operationId": "listUserMenu", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Menu" + } + } + } + } + } + }, + "/api/users/name/{username}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get user details by username", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Get user by username", + "operationId": "getUserByUsername", + "parameters": [ + { + "type": "string", + "description": "Username", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List projects for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user projects by workspace", + "operationId": "listUserProjectsByWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspaces", + "operationId": "listUserWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/workspaces/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List workspaces and roles for the current user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "List user workspace and roles", + "operationId": "listUserWorkspaceAndWorkspaceRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/users/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing user.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Update user", + "operationId": "updateUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User Info", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.User" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a user by their ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "users" + ], + "summary": "Delete user", + "operationId": "deleteUser", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new workspace with the specified information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Create new workspace", + "operationId": "createWorkspace", + "parameters": [ + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/assign/projects": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Add a project to a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Add project to workspace", + "operationId": "addProjectToWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "error: Invalid request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace or Project not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve workspace details by workspace ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by ID", + "operationId": "getWorkspaceByID", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update the details of an existing workspace.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Update workspace", + "operationId": "updateWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Workspace Info", + "name": "workspace", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Workspace" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a workspace by its ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Delete workspace", + "operationId": "deleteWorkspace", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/projects/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "getWorkspaceProjectsByWorkspaceId", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/id/{userId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get roles assigned to a user in a workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "Get user workspace roles", + "operationId": "getUserWorkspaceRoles", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/id/{workspaceId}/users/list": { + "post": { + "description": "Retrieve users and roles list belonging to workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List users and roles by workspace", + "operationId": "listUsersAndRolesByWorkspace", + "parameters": [ + { + "type": "integer", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserWorkspaceRole" + } + } + }, + "400": { + "description": "error: Invalid workspace ID", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Internal server error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve a list of all workspaces.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List all workspaces", + "operationId": "listWorkspaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Workspace" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/name/{workspaceName}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve specific workspace by name", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "Get workspace by name", + "operationId": "getWorkspaceByName", + "parameters": [ + { + "type": "string", + "description": "Workspace Name", + "name": "workspaceName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Workspace" + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/projects/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve project list belonging to specific workspace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace projects", + "operationId": "listWorkspaceProjects", + "parameters": [ + { + "type": "string", + "description": "Workspace ID", + "name": "workspaceId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Project" + } + } + }, + "401": { + "description": "error: Unauthorized", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "403": { + "description": "error: Forbidden", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "404": { + "description": "error: Workspace not found", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/roles/list": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Retrieve all workspace-level roles with optional filtering", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "workspaces" + ], + "summary": "List workspace roles", + "operationId": "listWorkspaceRoles", + "parameters": [ + { + "description": "Role filter parameters", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.RoleFilterRequest" + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved workspace roles", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.RoleMaster" + } + } + }, + "400": { + "description": "error: Invalid request format", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "error: Failed to retrieve workspace roles", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, + "/api/workspaces/temporary-credentials": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get temporary credentials for CSP", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "csp-credentials" + ], + "summary": "Get temporary credentials", + "operationId": "mciamGetTemporaryCredentials", "responses": {} } }, @@ -6978,6 +8933,14 @@ ], "summary": "Health check", "operationId": "mciamCheckHealth", + "parameters": [ + { + "type": "string", + "description": "Detail check components (nginx,db,keycloak,all)", + "name": "detail", + "in": "query" + } + ], "responses": { "200": { "description": "OK", @@ -7034,304 +8997,617 @@ "워크스페이스 역할", "CSP 역할" ], - "x-enum-varnames": [ - "RoleTypePlatform", - "RoleTypeWorkspace", - "RoleTypeCSP" - ] + "x-enum-varnames": [ + "RoleTypePlatform", + "RoleTypeWorkspace", + "RoleTypeCSP" + ] + }, + "idp.UserLogin": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAction": { + "type": "object", + "properties": { + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "description": "Auto-incrementing primary key", + "type": "integer" + }, + "method": { + "type": "string" + }, + "resourcePath": { + "type": "string" + }, + "serviceName": { + "description": "Foreign key reference (indexed)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiAuthInfo": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "type": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiDefinitions": { + "type": "object", + "properties": { + "serviceActions": { + "description": "Use renamed ServiceAction", + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" + } + } + }, + "services": { + "description": "Use renamed ServiceDefinition", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + } + } + } + }, + "mcmpapi.McmpApiPermissionActionMapping": { + "type": "object", + "properties": { + "actionID": { + "type": "integer" + }, + "actionName": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "permissionID": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiServiceAction": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "method": { + "type": "string" + }, + "resourcePath": { + "type": "string" + } + } + }, + "mcmpapi.McmpApiServiceDefinition": { + "type": "object", + "properties": { + "auth": { + "description": "Use renamed AuthInfo", + "allOf": [ + { + "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + } + ] + }, + "baseURL": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "model.AssignRoleRequest": { + "type": "object", + "properties": { + "roleId": { + "description": "역할 ID (문자열로 받음)", + "type": "string" + }, + "roleName": { + "description": "역할명", + "type": "string" + }, + "roleType": { + "description": "역할 타입 (platform/workspace)", + "type": "string" + }, + "userId": { + "description": "사용자 ID (문자열로 받음)", + "type": "string" + }, + "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", + "type": "string" + } + } + }, + "model.AssignWorkspaceRoleRequest": { + "type": "object", + "properties": { + "roleId": { + "description": "역할 ID (문자열로 받음)", + "type": "string" + }, + "roleName": { + "description": "역할명", + "type": "string" + }, + "userId": { + "description": "사용자 ID (문자열로 받음)", + "type": "string" + }, + "username": { + "description": "사용자명", + "type": "string" + }, + "workspaceId": { + "description": "워크스페이스 ID (문자열로 받음)", + "type": "string" + } + } + }, + "model.AttachPolicyRequest": { + "type": "object", + "required": [ + "csp_policy_id", + "csp_role_id" + ], + "properties": { + "csp_policy_id": { + "type": "integer" + }, + "csp_role_id": { + "type": "integer" + } + } + }, + "model.AuthMethodType": { + "type": "string", + "enum": [ + "OIDC", + "SAML", + "SECRET_KEY" + ], + "x-enum-varnames": [ + "AuthMethodOIDC", + "AuthMethodSAML", + "AuthMethodSecretKey" + ] + }, + "model.CreateCspAccountRequest": { + "type": "object", + "required": [ + "csp_type", + "name" + ], + "properties": { + "account_info": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "csp_type": { + "type": "string", + "enum": [ + "aws", + "gcp", + "azure" + ] + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "model.CreateCspIdpConfigRequest": { + "type": "object", + "required": [ + "auth_method", + "config", + "csp_account_id", + "name" + ], + "properties": { + "auth_method": { + "enum": [ + "OIDC", + "SAML", + "SECRET_KEY" + ], + "allOf": [ + { + "$ref": "#/definitions/model.AuthMethodType" + } + ] + }, + "config": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "csp_account_id": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } }, - "idp.UserLogin": { + "model.CreateCspPolicyRequest": { "type": "object", + "required": [ + "csp_account_id", + "name", + "policy_type" + ], "properties": { - "id": { + "csp_account_id": { + "type": "integer" + }, + "description": { "type": "string" }, - "password": { + "name": { + "type": "string" + }, + "policy_arn": { "type": "string" + }, + "policy_doc": { + "type": "object", + "additionalProperties": true + }, + "policy_type": { + "enum": [ + "inline", + "managed", + "custom" + ], + "allOf": [ + { + "$ref": "#/definitions/model.PolicyType" + } + ] } } }, - "mcmpapi.McmpApiAction": { + "model.CreateCspRoleRequest": { "type": "object", "properties": { - "actionName": { + "cspRoleName": { + "description": "csp의 RoleName. 여러 role이 있기때문에 csp에 정의한 role로 구분하기 위해 사용", "type": "string" }, - "createdAt": { + "cspType": { "type": "string" }, "description": { "type": "string" }, + "iamIdentifier": { + "type": "string" + }, + "iamRoleId": { + "type": "string" + }, "id": { - "description": "Auto-incrementing primary key", - "type": "integer" + "type": "string" }, - "method": { + "idpIdentifier": { "type": "string" }, - "resourcePath": { + "path": { "type": "string" }, - "serviceName": { - "description": "Foreign key reference (indexed)", + "status": { "type": "string" }, - "updatedAt": { + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Tag" + } + } + } + }, + "model.CreateCspRolesRequest": { + "type": "object", + "required": [ + "cspRoles" + ], + "properties": { + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" + } + } + } + }, + "model.CreateMenuMappingRequest": { + "type": "object", + "required": [ + "menuIds", + "roleId" + ], + "properties": { + "menuIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "roleId": { "type": "string" } } }, - "mcmpapi.McmpApiAuthInfo": { + "model.CreateProjectRequest": { "type": "object", + "required": [ + "name" + ], "properties": { - "password": { + "description": { "type": "string" }, - "type": { + "name": { "type": "string" }, - "username": { + "workspaceId": { + "description": "optional workspace to assign project to", "type": "string" } } }, - "mcmpapi.McmpApiDefinitions": { + "model.CreateRoleRequest": { "type": "object", + "required": [ + "name" + ], "properties": { - "serviceActions": { - "description": "Use renamed ServiceAction", - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceAction" - } + "cspRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/model.CreateCspRoleRequest" } }, - "services": { - "description": "Use renamed ServiceDefinition", - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/mcmpapi.McmpApiServiceDefinition" + "description": { + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "name": { + "type": "string" + }, + "parentId": { + "type": "integer" + }, + "roleTypes": { + "description": "RoleTypes []constants.IAMRoleType `json:\"roleTypes\" validate:\"required,dive,oneof=platform workspace csp\"`", + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" } } } }, - "mcmpapi.McmpApiPermissionActionMapping": { + "model.CspAccount": { "type": "object", "properties": { - "actionID": { - "type": "integer" + "account_info": { + "type": "object", + "additionalProperties": { + "type": "string" + } }, - "actionName": { + "created_at": { "type": "string" }, - "createdAt": { + "csp_type": { + "description": "aws, gcp, azure", + "type": "string" + }, + "description": { "type": "string" }, "id": { "type": "integer" }, - "permissionID": { + "is_active": { + "type": "boolean" + }, + "name": { "type": "string" }, - "updatedAt": { + "updated_at": { "type": "string" } } }, - "mcmpapi.McmpApiServiceAction": { + "model.CspAccountFilter": { "type": "object", "properties": { - "description": { + "csp_type": { "type": "string" }, - "method": { - "type": "string" + "is_active": { + "type": "boolean" }, - "resourcePath": { + "name": { "type": "string" } } }, - "mcmpapi.McmpApiServiceDefinition": { + "model.CspIdpConfig": { "type": "object", "properties": { - "auth": { - "description": "Use renamed AuthInfo", + "auth_method": { + "description": "OIDC, SAML, SECRET_KEY", "allOf": [ { - "$ref": "#/definitions/mcmpapi.McmpApiAuthInfo" + "$ref": "#/definitions/model.AuthMethodType" } ] }, - "baseURL": { - "type": "string" + "config": { + "type": "object", + "additionalProperties": { + "type": "string" + } }, - "version": { - "type": "string" - } - } - }, - "model.AssignRoleRequest": { - "type": "object", - "properties": { - "roleId": { - "description": "역할 ID (문자열로 받음)", + "created_at": { "type": "string" }, - "roleName": { - "description": "역할명", - "type": "string" + "csp_account": { + "$ref": "#/definitions/model.CspAccount" }, - "roleType": { - "description": "역할 타입 (platform/workspace)", - "type": "string" + "csp_account_id": { + "type": "integer" }, - "userId": { - "description": "사용자 ID (문자열로 받음)", + "description": { "type": "string" }, - "username": { - "description": "사용자명", + "id": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "name": { "type": "string" }, - "workspaceId": { - "description": "워크스페이스 ID (문자열로 받음)", + "updated_at": { "type": "string" } } }, - "model.AssignWorkspaceRoleRequest": { + "model.CspIdpConfigFilter": { "type": "object", "properties": { - "roleId": { - "description": "역할 ID (문자열로 받음)", - "type": "string" - }, - "roleName": { - "description": "역할명", - "type": "string" - }, - "userId": { - "description": "사용자 ID (문자열로 받음)", - "type": "string" + "auth_method": { + "$ref": "#/definitions/model.AuthMethodType" }, - "username": { - "description": "사용자명", - "type": "string" + "csp_account_id": { + "type": "integer" }, - "workspaceId": { - "description": "워크스페이스 ID (문자열로 받음)", + "is_active": { + "type": "boolean" + }, + "name": { "type": "string" } } }, - "model.CreateCspRoleRequest": { + "model.CspPolicy": { "type": "object", "properties": { - "cspRoleName": { - "description": "csp의 RoleName. 여러 role이 있기때문에 csp에 정의한 role로 구분하기 위해 사용", - "type": "string" - }, - "cspType": { + "created_at": { "type": "string" }, - "description": { - "type": "string" + "csp_account": { + "$ref": "#/definitions/model.CspAccount" }, - "iamIdentifier": { - "type": "string" + "csp_account_id": { + "type": "integer" }, - "iamRoleId": { + "description": { "type": "string" }, "id": { - "type": "string" + "type": "integer" }, - "idpIdentifier": { + "name": { "type": "string" }, - "path": { + "policy_arn": { "type": "string" }, - "status": { - "type": "string" + "policy_doc": { + "type": "object", + "additionalProperties": true }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Tag" - } - } - } - }, - "model.CreateCspRolesRequest": { - "type": "object", - "required": [ - "cspRoles" - ], - "properties": { - "cspRoles": { - "type": "array", - "items": { - "$ref": "#/definitions/model.CreateCspRoleRequest" - } - } - } - }, - "model.CreateMenuMappingRequest": { - "type": "object", - "required": [ - "menuIds", - "roleId" - ], - "properties": { - "menuIds": { - "type": "array", - "items": { - "type": "string" - } + "policy_type": { + "description": "inline, managed, custom", + "allOf": [ + { + "$ref": "#/definitions/model.PolicyType" + } + ] }, - "roleId": { + "updated_at": { "type": "string" } } }, - "model.CreateRoleRequest": { + "model.CspPolicyFilter": { "type": "object", - "required": [ - "name" - ], "properties": { - "cspRoles": { - "type": "array", - "items": { - "$ref": "#/definitions/model.CreateCspRoleRequest" - } - }, - "description": { - "type": "string" - }, - "menuIds": { - "type": "array", - "items": { - "type": "string" - } + "csp_account_id": { + "type": "integer" }, "name": { "type": "string" }, - "parentId": { - "type": "integer" - }, - "roleTypes": { - "description": "RoleTypes []constants.IAMRoleType `json:\"roleTypes\" validate:\"required,dive,oneof=platform workspace csp\"`", - "type": "array", - "items": { - "$ref": "#/definitions/constants.IAMRoleType" - } + "policy_type": { + "$ref": "#/definitions/model.PolicyType" } } }, @@ -7344,6 +9620,19 @@ "created_at": { "type": "string" }, + "csp_account": { + "$ref": "#/definitions/model.CspAccount" + }, + "csp_account_id": { + "description": "CSP 계정 및 IDP 설정 참조 (신규 추가)", + "type": "integer" + }, + "csp_idp_config": { + "$ref": "#/definitions/model.CspIdpConfig" + }, + "csp_idp_config_id": { + "type": "integer" + }, "csp_type": { "type": "string" }, @@ -7353,6 +9642,10 @@ "description": { "type": "string" }, + "extended_config": { + "type": "object", + "additionalProperties": true + }, "iam_identifier": { "type": "string" }, @@ -7444,6 +9737,101 @@ } } }, + "model.ImportApiFramework": { + "type": "object", + "required": [ + "name", + "sourceType", + "sourceUrl", + "version" + ], + "properties": { + "name": { + "description": "Framework name (e.g., \"mc-infra-manager\")", + "type": "string" + }, + "repository": { + "description": "Repository URL (e.g., \"https://github.com/...\")", + "type": "string" + }, + "sourceType": { + "description": "Source type: \"swagger\" or \"openapi\"", + "type": "string" + }, + "sourceUrl": { + "description": "URL to fetch the API specification from", + "type": "string" + }, + "version": { + "description": "Framework version (e.g., \"0.9.22\")", + "type": "string" + } + } + }, + "model.ImportApiFrameworkResult": { + "type": "object", + "properties": { + "actionCount": { + "description": "Number of actions imported (on success)", + "type": "integer" + }, + "errorMessage": { + "description": "Error message (on failure)", + "type": "string" + }, + "name": { + "description": "Framework name", + "type": "string" + }, + "success": { + "description": "Whether the import was successful", + "type": "boolean" + }, + "version": { + "description": "Framework version", + "type": "string" + } + } + }, + "model.ImportApiRequest": { + "type": "object", + "required": [ + "frameworks" + ], + "properties": { + "frameworks": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/model.ImportApiFramework" + } + } + } + }, + "model.ImportApiResponse": { + "type": "object", + "properties": { + "failureCount": { + "description": "Number of failed frameworks", + "type": "integer" + }, + "frameworkResults": { + "description": "Detailed results for each framework", + "type": "array", + "items": { + "$ref": "#/definitions/model.ImportApiFrameworkResult" + } + }, + "successCount": { + "description": "Number of successfully imported frameworks", + "type": "integer" + }, + "totalFrameworks": { + "description": "Total number of frameworks in request", + "type": "integer" + } + } + }, "model.MciamPermission": { "type": "object", "properties": { @@ -7585,6 +9973,29 @@ } } }, + "model.PolicyType": { + "type": "string", + "enum": [ + "inline", + "managed", + "custom" + ], + "x-enum-comments": { + "PolicyTypeCustom": "사용자 정의 정책", + "PolicyTypeInline": "인라인 정책 (역할에 직접 포함)", + "PolicyTypeManaged": "관리형 정책 (독립 정책)" + }, + "x-enum-descriptions": [ + "인라인 정책 (역할에 직접 포함)", + "관리형 정책 (독립 정책)", + "사용자 정의 정책" + ], + "x-enum-varnames": [ + "PolicyTypeInline", + "PolicyTypeManaged", + "PolicyTypeCustom" + ] + }, "model.Project": { "type": "object", "properties": { @@ -7653,6 +10064,23 @@ } } }, + "model.RoleFilterRequest": { + "type": "object", + "properties": { + "roleId": { + "type": "string" + }, + "roleName": { + "type": "string" + }, + "roleTypes": { + "type": "array", + "items": { + "$ref": "#/definitions/constants.IAMRoleType" + } + } + } + }, "model.RoleLastUsed": { "type": "object", "properties": { @@ -7818,6 +10246,21 @@ } } }, + "model.SyncPoliciesRequest": { + "type": "object", + "required": [ + "csp_account_id" + ], + "properties": { + "csp_account_id": { + "type": "integer" + }, + "policy_scope": { + "description": "All, AWS, Local", + "type": "string" + } + } + }, "model.Tag": { "type": "object", "properties": { @@ -7829,6 +10272,64 @@ } } }, + "model.UpdateCspAccountRequest": { + "type": "object", + "properties": { + "account_info": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "model.UpdateCspIdpConfigRequest": { + "type": "object", + "properties": { + "config": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "model.UpdateCspPolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "policy_arn": { + "type": "string" + }, + "policy_doc": { + "type": "object", + "additionalProperties": true + } + } + }, "model.User": { "type": "object", "properties": { @@ -7980,6 +10481,24 @@ } } }, + "model.WorkspaceProjectMappingRequest": { + "type": "object", + "required": [ + "projectIds", + "workspaceId" + ], + "properties": { + "projectIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "workspaceId": { + "type": "string" + } + } + }, "model.WorkspaceWithUsersAndRoles": { "type": "object", "properties": { diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 3e08a9b2..e319f4c5 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -162,6 +162,96 @@ definitions: description: 워크스페이스 ID (문자열로 받음) type: string type: object + model.AttachPolicyRequest: + properties: + csp_policy_id: + type: integer + csp_role_id: + type: integer + required: + - csp_policy_id + - csp_role_id + type: object + model.AuthMethodType: + enum: + - OIDC + - SAML + - SECRET_KEY + type: string + x-enum-varnames: + - AuthMethodOIDC + - AuthMethodSAML + - AuthMethodSecretKey + model.CreateCspAccountRequest: + properties: + account_info: + additionalProperties: + type: string + type: object + csp_type: + enum: + - aws + - gcp + - azure + type: string + description: + type: string + name: + type: string + required: + - csp_type + - name + type: object + model.CreateCspIdpConfigRequest: + properties: + auth_method: + allOf: + - $ref: '#/definitions/model.AuthMethodType' + enum: + - OIDC + - SAML + - SECRET_KEY + config: + additionalProperties: + type: string + type: object + csp_account_id: + type: integer + description: + type: string + name: + type: string + required: + - auth_method + - config + - csp_account_id + - name + type: object + model.CreateCspPolicyRequest: + properties: + csp_account_id: + type: integer + description: + type: string + name: + type: string + policy_arn: + type: string + policy_doc: + additionalProperties: true + type: object + policy_type: + allOf: + - $ref: '#/definitions/model.PolicyType' + enum: + - inline + - managed + - custom + required: + - csp_account_id + - name + - policy_type + type: object model.CreateCspRoleRequest: properties: cspRoleName: @@ -209,6 +299,18 @@ definitions: - menuIds - roleId type: object + model.CreateProjectRequest: + properties: + description: + type: string + name: + type: string + workspaceId: + description: optional workspace to assign project to + type: string + required: + - name + type: object model.CreateRoleRequest: properties: cspRoles: @@ -234,18 +336,134 @@ definitions: required: - name type: object + model.CspAccount: + properties: + account_info: + additionalProperties: + type: string + type: object + created_at: + type: string + csp_type: + description: aws, gcp, azure + type: string + description: + type: string + id: + type: integer + is_active: + type: boolean + name: + type: string + updated_at: + type: string + type: object + model.CspAccountFilter: + properties: + csp_type: + type: string + is_active: + type: boolean + name: + type: string + type: object + model.CspIdpConfig: + properties: + auth_method: + allOf: + - $ref: '#/definitions/model.AuthMethodType' + description: OIDC, SAML, SECRET_KEY + config: + additionalProperties: + type: string + type: object + created_at: + type: string + csp_account: + $ref: '#/definitions/model.CspAccount' + csp_account_id: + type: integer + description: + type: string + id: + type: integer + is_active: + type: boolean + name: + type: string + updated_at: + type: string + type: object + model.CspIdpConfigFilter: + properties: + auth_method: + $ref: '#/definitions/model.AuthMethodType' + csp_account_id: + type: integer + is_active: + type: boolean + name: + type: string + type: object + model.CspPolicy: + properties: + created_at: + type: string + csp_account: + $ref: '#/definitions/model.CspAccount' + csp_account_id: + type: integer + description: + type: string + id: + type: integer + name: + type: string + policy_arn: + type: string + policy_doc: + additionalProperties: true + type: object + policy_type: + allOf: + - $ref: '#/definitions/model.PolicyType' + description: inline, managed, custom + updated_at: + type: string + type: object + model.CspPolicyFilter: + properties: + csp_account_id: + type: integer + name: + type: string + policy_type: + $ref: '#/definitions/model.PolicyType' + type: object model.CspRole: properties: create_date: type: string created_at: type: string + csp_account: + $ref: '#/definitions/model.CspAccount' + csp_account_id: + description: CSP 계정 및 IDP 설정 참조 (신규 추가) + type: integer + csp_idp_config: + $ref: '#/definitions/model.CspIdpConfig' + csp_idp_config_id: + type: integer csp_type: type: string deleted_at: type: string description: type: string + extended_config: + additionalProperties: true + type: object iam_identifier: type: string iam_role_id: @@ -306,6 +524,74 @@ definitions: workspaceName: type: string type: object + model.ImportApiFramework: + properties: + name: + description: Framework name (e.g., "mc-infra-manager") + type: string + repository: + description: Repository URL (e.g., "https://github.com/...") + type: string + sourceType: + description: 'Source type: "swagger" or "openapi"' + type: string + sourceUrl: + description: URL to fetch the API specification from + type: string + version: + description: Framework version (e.g., "0.9.22") + type: string + required: + - name + - sourceType + - sourceUrl + - version + type: object + model.ImportApiFrameworkResult: + properties: + actionCount: + description: Number of actions imported (on success) + type: integer + errorMessage: + description: Error message (on failure) + type: string + name: + description: Framework name + type: string + success: + description: Whether the import was successful + type: boolean + version: + description: Framework version + type: string + type: object + model.ImportApiRequest: + properties: + frameworks: + items: + $ref: '#/definitions/model.ImportApiFramework' + minItems: 1 + type: array + required: + - frameworks + type: object + model.ImportApiResponse: + properties: + failureCount: + description: Number of failed frameworks + type: integer + frameworkResults: + description: Detailed results for each framework + items: + $ref: '#/definitions/model.ImportApiFrameworkResult' + type: array + successCount: + description: Number of successfully imported frameworks + type: integer + totalFrameworks: + description: Total number of frameworks in request + type: integer + type: object model.MciamPermission: properties: action: @@ -402,6 +688,24 @@ definitions: resType: type: string type: object + model.PolicyType: + enum: + - inline + - managed + - custom + type: string + x-enum-comments: + PolicyTypeCustom: 사용자 정의 정책 + PolicyTypeInline: 인라인 정책 (역할에 직접 포함) + PolicyTypeManaged: 관리형 정책 (독립 정책) + x-enum-descriptions: + - 인라인 정책 (역할에 직접 포함) + - 관리형 정책 (독립 정책) + - 사용자 정의 정책 + x-enum-varnames: + - PolicyTypeInline + - PolicyTypeManaged + - PolicyTypeCustom model.Project: properties: created_at: @@ -448,6 +752,17 @@ definitions: message: type: string type: object + model.RoleFilterRequest: + properties: + roleId: + type: string + roleName: + type: string + roleTypes: + items: + $ref: '#/definitions/constants.IAMRoleType' + type: array + type: object model.RoleLastUsed: properties: last_used_date: @@ -556,6 +871,16 @@ definitions: username: type: string type: object + model.SyncPoliciesRequest: + properties: + csp_account_id: + type: integer + policy_scope: + description: All, AWS, Local + type: string + required: + - csp_account_id + type: object model.Tag: properties: key: @@ -563,6 +888,44 @@ definitions: value: type: string type: object + model.UpdateCspAccountRequest: + properties: + account_info: + additionalProperties: + type: string + type: object + description: + type: string + is_active: + type: boolean + name: + type: string + type: object + model.UpdateCspIdpConfigRequest: + properties: + config: + additionalProperties: + type: string + type: object + description: + type: string + is_active: + type: boolean + name: + type: string + type: object + model.UpdateCspPolicyRequest: + properties: + description: + type: string + name: + type: string + policy_arn: + type: string + policy_doc: + additionalProperties: true + type: object + type: object model.User: properties: created_at: @@ -666,6 +1029,18 @@ definitions: updated_at: type: string type: object + model.WorkspaceProjectMappingRequest: + properties: + projectIds: + items: + type: string + type: array + workspaceId: + type: string + required: + - projectIds + - workspaceId + type: object model.WorkspaceWithUsersAndRoles: properties: created_at: @@ -763,9 +1138,33 @@ paths: - application/json description: Refresh JWT access token using a valid refresh token. operationId: mciamRefreshToken + parameters: + - description: Refresh token + in: body + name: refresh_token + required: true + schema: + type: string produces: - application/json - responses: {} + responses: + "200": + description: New token information + schema: + additionalProperties: true + type: object + "400": + description: 'error: Bad Request' + schema: + additionalProperties: + type: string + type: object + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object summary: Refresh access token tags: - auth @@ -792,6 +1191,13 @@ paths: - application/json description: Validate the current access token and refresh if expired operationId: mciamValidateToken + parameters: + - description: Refresh token + in: body + name: refresh_token + required: true + schema: + type: string produces: - application/json responses: @@ -800,6 +1206,12 @@ paths: schema: additionalProperties: true type: object + "400": + description: 'error: Bad Request' + schema: + additionalProperties: + type: string + type: object "401": description: 'error: Unauthorized' schema: @@ -811,123 +1223,1188 @@ paths: summary: Validate access token tags: - auth - /api/csp-credentials: + /api/csp-accounts: + post: + consumes: + - application/json + description: Create a new CSP account + operationId: createCspAccount + parameters: + - description: CSP Account Info + in: body + name: account + required: true + schema: + $ref: '#/definitions/model.CreateCspAccountRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.CspAccount' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create CSP account + tags: + - csp-accounts + /api/csp-accounts/id/{accountId}: + delete: + consumes: + - application/json + description: Delete a CSP account by ID + operationId: deleteCspAccount + parameters: + - description: Account ID + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete CSP account + tags: + - csp-accounts get: consumes: - application/json - description: 모든 CSP 인증 정보 목록을 조회합니다 - operationId: mciamListCredentials + description: Retrieve CSP account details by ID + operationId: getCspAccountByID + parameters: + - description: Account ID + in: path + name: accountId + required: true + type: string produces: - application/json - responses: {} + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.CspAccount' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object security: - BearerAuth: [] - summary: CSP 인증 정보 목록 조회 + summary: Get CSP account by ID tags: - - csp-credentials + - csp-accounts + put: + consumes: + - application/json + description: Update CSP account details + operationId: updateCspAccount + parameters: + - description: Account ID + in: path + name: accountId + required: true + type: string + - description: CSP Account Info + in: body + name: account + required: true + schema: + $ref: '#/definitions/model.UpdateCspAccountRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.CspAccount' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Update CSP account + tags: + - csp-accounts + /api/csp-accounts/id/{accountId}/activate: post: consumes: - application/json - description: 새로운 CSP 인증 정보를 생성합니다 - operationId: mciamCreateCredential + description: Activate a CSP account + operationId: activateCspAccount + parameters: + - description: Account ID + in: path + name: accountId + required: true + type: string produces: - application/json - responses: {} + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Activate CSP account + tags: + - csp-accounts + /api/csp-accounts/id/{accountId}/deactivate: + post: + consumes: + - application/json + description: Deactivate a CSP account + operationId: deactivateCspAccount + parameters: + - description: Account ID + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Deactivate CSP account + tags: + - csp-accounts + /api/csp-accounts/id/{accountId}/validate: + post: + consumes: + - application/json + description: Validate CSP account configuration + operationId: validateCspAccount + parameters: + - description: Account ID + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Validate CSP account + tags: + - csp-accounts + /api/csp-accounts/list: + post: + consumes: + - application/json + description: Retrieve a list of CSP accounts with optional filters + operationId: listCspAccounts + parameters: + - description: Filter options + in: body + name: filter + schema: + $ref: '#/definitions/model.CspAccountFilter' + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.CspAccount' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List CSP accounts + tags: + - csp-accounts + /api/csp-credentials: + get: + consumes: + - application/json + description: 모든 CSP 인증 정보 목록을 조회합니다 + operationId: mciamListCredentials + produces: + - application/json + responses: {} + security: + - BearerAuth: [] + summary: CSP 인증 정보 목록 조회 + tags: + - csp-credentials + post: + consumes: + - application/json + description: 새로운 CSP 인증 정보를 생성합니다 + operationId: mciamCreateCredential + produces: + - application/json + responses: {} + security: + - BearerAuth: [] + summary: 새 CSP 인증 정보 생성 + tags: + - csp-credentials + /api/csp-credentials/{id}: + delete: + consumes: + - application/json + description: CSP 인증 정보를 삭제합니다 + operationId: mciamDeleteCredential + parameters: + - description: Credential ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "401": + description: 'error: Unauthorized' + schema: + additionalProperties: + type: string + type: object + "403": + description: 'error: Forbidden' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Credential not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: CSP 인증 정보 삭제 + tags: + - csp-credentials + get: + consumes: + - application/json + description: 특정 CSP 인증 정보를 ID로 조회합니다 + operationId: mciamGetCredentialByID + parameters: + - description: Credential ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "404": + description: 'error: Credential not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: CSP 인증 정보 ID로 조회 + tags: + - csp-credentials + put: + consumes: + - application/json + description: CSP 인증 정보를 업데이트합니다 + operationId: mciamUpdateCredential + parameters: + - description: Credential ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "404": + description: 'error: Credential not found' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: CSP 인증 정보 업데이트 + tags: + - csp-credentials + /api/csp-idp-configs: + post: + consumes: + - application/json + description: Create a new CSP IDP configuration + operationId: createCspIdpConfig + parameters: + - description: CSP IDP Config Info + in: body + name: config + required: true + schema: + $ref: '#/definitions/model.CreateCspIdpConfigRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.CspIdpConfig' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create CSP IDP config + tags: + - csp-idp-configs + /api/csp-idp-configs/id/{configId}: + delete: + consumes: + - application/json + description: Delete a CSP IDP configuration by ID + operationId: deleteCspIdpConfig + parameters: + - description: Config ID + in: path + name: configId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete CSP IDP config + tags: + - csp-idp-configs + get: + consumes: + - application/json + description: Retrieve CSP IDP configuration details by ID + operationId: getCspIdpConfigByID + parameters: + - description: Config ID + in: path + name: configId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.CspIdpConfig' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get CSP IDP config by ID + tags: + - csp-idp-configs + put: + consumes: + - application/json + description: Update CSP IDP configuration details + operationId: updateCspIdpConfig + parameters: + - description: Config ID + in: path + name: configId + required: true + type: string + - description: CSP IDP Config Info + in: body + name: config + required: true + schema: + $ref: '#/definitions/model.UpdateCspIdpConfigRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.CspIdpConfig' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Update CSP IDP config + tags: + - csp-idp-configs + /api/csp-idp-configs/id/{configId}/activate: + post: + consumes: + - application/json + description: Activate a CSP IDP configuration + operationId: activateCspIdpConfig + parameters: + - description: Config ID + in: path + name: configId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Activate CSP IDP config + tags: + - csp-idp-configs + /api/csp-idp-configs/id/{configId}/deactivate: + post: + consumes: + - application/json + description: Deactivate a CSP IDP configuration + operationId: deactivateCspIdpConfig + parameters: + - description: Config ID + in: path + name: configId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Deactivate CSP IDP config + tags: + - csp-idp-configs + /api/csp-idp-configs/id/{configId}/test: + post: + consumes: + - application/json + description: Test connection to CSP using IDP configuration + operationId: testCspIdpConnection + parameters: + - description: Config ID + in: path + name: configId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Test CSP IDP connection + tags: + - csp-idp-configs + /api/csp-idp-configs/list: + post: + consumes: + - application/json + description: Retrieve a list of CSP IDP configurations with optional filters + operationId: listCspIdpConfigs + parameters: + - description: Filter options + in: body + name: filter + schema: + $ref: '#/definitions/model.CspIdpConfigFilter' + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.CspIdpConfig' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List CSP IDP configs + tags: + - csp-idp-configs + /api/csp-policies: + post: + consumes: + - application/json + description: Create a new CSP policy + operationId: createCspPolicy + parameters: + - description: CSP Policy Info + in: body + name: policy + required: true + schema: + $ref: '#/definitions/model.CreateCspPolicyRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/model.CspPolicy' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Create CSP policy + tags: + - csp-policies + /api/csp-policies/attach: + post: + consumes: + - application/json + description: Attach a CSP policy to a CSP role + operationId: attachPolicyToRole + parameters: + - description: Attach Policy Request + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.AttachPolicyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Attach policy to role + tags: + - csp-policies + /api/csp-policies/detach: + post: + consumes: + - application/json + description: Detach a CSP policy from a CSP role + operationId: detachPolicyFromRole + parameters: + - description: Detach Policy Request + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.AttachPolicyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Detach policy from role + tags: + - csp-policies + /api/csp-policies/id/{policyId}: + delete: + consumes: + - application/json + description: Delete a CSP policy by ID + operationId: deleteCspPolicy + parameters: + - description: Policy ID + in: path + name: policyId + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Delete CSP policy + tags: + - csp-policies + get: + consumes: + - application/json + description: Retrieve CSP policy details by ID + operationId: getCspPolicyByID + parameters: + - description: Policy ID + in: path + name: policyId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.CspPolicy' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get CSP policy by ID + tags: + - csp-policies + put: + consumes: + - application/json + description: Update CSP policy details + operationId: updateCspPolicy + parameters: + - description: Policy ID + in: path + name: policyId + required: true + type: string + - description: CSP Policy Info + in: body + name: policy + required: true + schema: + $ref: '#/definitions/model.UpdateCspPolicyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.CspPolicy' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object security: - BearerAuth: [] - summary: 새 CSP 인증 정보 생성 + summary: Update CSP policy tags: - - csp-credentials - /api/csp-credentials/{id}: - delete: + - csp-policies + /api/csp-policies/id/{policyId}/document: + get: consumes: - application/json - description: CSP 인증 정보를 삭제합니다 - operationId: mciamDeleteCredential + description: Get the policy document content + operationId: getPolicyDocument parameters: - - description: Credential ID + - description: Policy ID in: path - name: id + name: policyId required: true type: string produces: - application/json responses: - "204": - description: No Content - "401": - description: 'error: Unauthorized' + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request schema: additionalProperties: type: string type: object - "403": - description: 'error: Forbidden' + "404": + description: Not Found schema: additionalProperties: type: string type: object - "404": - description: 'error: Credential not found' + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: CSP 인증 정보 삭제 + summary: Get policy document tags: - - csp-credentials + - csp-policies + /api/csp-policies/list: + post: + consumes: + - application/json + description: Retrieve a list of CSP policies with optional filters + operationId: listCspPolicies + parameters: + - description: Filter options + in: body + name: filter + schema: + $ref: '#/definitions/model.CspPolicyFilter' + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.CspPolicy' + type: array + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List CSP policies + tags: + - csp-policies + /api/csp-policies/role/{roleId}: get: consumes: - application/json - description: 특정 CSP 인증 정보를 ID로 조회합니다 - operationId: mciamGetCredentialByID + description: Get list of policies attached to a CSP role + operationId: getRolePolicies parameters: - - description: Credential ID + - description: Role ID in: path - name: id + name: roleId required: true type: string produces: - application/json responses: - "404": - description: 'error: Credential not found' + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.CspPolicy' + type: array + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: CSP 인증 정보 ID로 조회 + summary: Get policies attached to role tags: - - csp-credentials - put: + - csp-policies + /api/csp-policies/sync: + post: consumes: - application/json - description: CSP 인증 정보를 업데이트합니다 - operationId: mciamUpdateCredential + description: Synchronize policies from the CSP cloud + operationId: syncCspPolicies parameters: - - description: Credential ID - in: path - name: id + - description: Sync Policies Request + in: body + name: request required: true - type: string + schema: + $ref: '#/definitions/model.SyncPoliciesRequest' produces: - application/json responses: - "404": - description: 'error: Credential not found' + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.CspPolicy' + type: array + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error schema: additionalProperties: type: string type: object security: - BearerAuth: [] - summary: CSP 인증 정보 업데이트 + summary: Sync CSP policies from cloud tags: - - csp-credentials + - csp-policies /api/initial-admin: post: consumes: @@ -1128,6 +2605,44 @@ paths: summary: Get platform actions by permission ID tags: - mcmp-api-permission-action-mappings + /api/mcmp-apis/import: + post: + consumes: + - application/json + description: Fetches API specifications from remote URLs and imports them to + the database. Supports swagger and openapi source types. + operationId: importAPIs + parameters: + - description: Frameworks to import + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.ImportApiRequest' + produces: + - application/json + responses: + "200": + description: Import results + schema: + $ref: '#/definitions/model.ImportApiResponse' + "400": + description: 'error: Invalid request body' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Failed to import APIs' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Import MCMP APIs from Remote Sources + tags: + - McmpAPI /api/mcmp-apis/list: post: consumes: @@ -1961,7 +3476,8 @@ paths: post: consumes: - application/json - description: Create a new project with the specified information. + description: Create a new project with the specified information. Optionally + specify a workspace to assign the project to. operationId: createProject parameters: - description: Project Info @@ -1969,7 +3485,7 @@ paths: name: project required: true schema: - $ref: '#/definitions/model.Project' + $ref: '#/definitions/model.CreateProjectRequest' produces: - application/json responses: @@ -1983,6 +3499,12 @@ paths: additionalProperties: type: string type: object + "404": + description: Not Found + schema: + additionalProperties: + type: string + type: object "500": description: Internal Server Error schema: @@ -2110,23 +3632,19 @@ paths: summary: Update project tags: - projects - /api/projects/{id}/workspaces/{workspaceId}: + /api/projects/assign/workspaces: post: consumes: - application/json description: 프로젝트에 워크스페이스를 연결합니다. operationId: addWorkspaceToProject parameters: - - description: 프로젝트 ID - in: path - name: id - required: true - type: integer - - description: 워크스페이스 ID - in: path - name: workspaceId + - description: Workspace and Project IDs + in: body + name: request required: true - type: integer + schema: + $ref: '#/definitions/model.WorkspaceProjectMappingRequest' produces: - application/json responses: @@ -2155,6 +3673,50 @@ paths: summary: 프로젝트에 워크스페이스 연결 tags: - projects + /api/projects/id/{projectId}/workspaces: + get: + consumes: + - application/json + description: Retrieve list of workspaces that the project is assigned to + operationId: getProjectWorkspaces + parameters: + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Workspace' + type: array + "400": + description: 'error: Invalid project ID' + schema: + additionalProperties: + type: string + type: object + "404": + description: 'error: Project not found' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Internal server error' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Get workspaces assigned to project + tags: + - projects /api/projects/list: post: consumes: @@ -2217,6 +3779,41 @@ paths: summary: Get project by name tags: - projects + /api/projects/unassign/workspaces: + delete: + consumes: + - application/json + description: Remove a workspace from a project + operationId: removeWorkspaceFromProject + parameters: + - description: Workspace and Project IDs + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.WorkspaceProjectMappingRequest' + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: 'error: Invalid request' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Internal server error' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: Remove workspace from project + tags: + - projects /api/resource-types/cloud-resources: post: consumes: @@ -3845,7 +5442,7 @@ paths: consumes: - application/json description: Get a list of all workspace roles - operationId: listWorkspaceRoles + operationId: listRolesOfWorkspaceType produces: - application/json responses: @@ -5070,6 +6667,45 @@ paths: summary: List workspace projects tags: - workspaces + /api/workspaces/roles/list: + post: + consumes: + - application/json + description: Retrieve all workspace-level roles with optional filtering + operationId: listWorkspaceRoles + parameters: + - description: Role filter parameters + in: body + name: request + required: true + schema: + $ref: '#/definitions/model.RoleFilterRequest' + produces: + - application/json + responses: + "200": + description: Successfully retrieved workspace roles + schema: + items: + $ref: '#/definitions/model.RoleMaster' + type: array + "400": + description: 'error: Invalid request format' + schema: + additionalProperties: + type: string + type: object + "500": + description: 'error: Failed to retrieve workspace roles' + schema: + additionalProperties: + type: string + type: object + security: + - BearerAuth: [] + summary: List workspace roles + tags: + - workspaces /api/workspaces/temporary-credentials: post: consumes: @@ -5204,6 +6840,11 @@ paths: - application/json description: Check the health status of the service. operationId: mciamCheckHealth + parameters: + - description: Detail check components (nginx,db,keycloak,all) + in: query + name: detail + type: string produces: - application/json responses: diff --git a/src/go.mod b/src/go.mod index 8c7eec50..18db9811 100644 --- a/src/go.mod +++ b/src/go.mod @@ -1,6 +1,6 @@ module github.com/m-cmp/mc-iam-manager -go 1.23.1 +go 1.25.0 require ( cloud.google.com/go/iam v1.5.2 @@ -10,7 +10,9 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.17.67 github.com/aws/aws-sdk-go-v2/service/iam v1.41.1 github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 + github.com/go-playground/validator/v10 v10.26.0 github.com/golang-jwt/jwt/v5 v5.0.0 + github.com/google/uuid v1.6.0 github.com/joho/godotenv v1.5.1 github.com/labstack/echo/v4 v4.13.3 github.com/lib/pq v1.10.9 @@ -19,6 +21,7 @@ require ( github.com/swaggo/swag v1.16.4 google.golang.org/api v0.232.0 gopkg.in/yaml.v3 v3.0.1 + gorm.io/datatypes v1.2.5 gorm.io/driver/postgres v1.5.11 gorm.io/driver/sqlite v1.5.7 gorm.io/gorm v1.26.1 @@ -42,17 +45,17 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.1 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/spec v0.21.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.26.0 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/go-sql-driver/mysql v1.9.2 // indirect github.com/google/s2a-go v0.1.9 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -75,6 +78,11 @@ require ( github.com/swaggo/files/v2 v2.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect + go.opentelemetry.io/otel v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/trace v1.35.0 // indirect golang.org/x/crypto v0.37.0 // indirect golang.org/x/net v0.39.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect @@ -89,6 +97,5 @@ require ( google.golang.org/grpc v1.72.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gorm.io/datatypes v1.2.5 // indirect gorm.io/driver/mysql v1.5.7 // indirect ) diff --git a/src/go.sum b/src/go.sum index 150778ef..d8bc0a46 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,3 +1,5 @@ +cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA= +cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q= cloud.google.com/go/auth v0.16.1 h1:XrXauHMd30LhQYVRHLGvJiYeczweKQXZxsTbV9TiguU= cloud.google.com/go/auth v0.16.1/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= @@ -49,6 +51,7 @@ github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3G github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -61,6 +64,8 @@ github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9Z github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -74,6 +79,10 @@ github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRj github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -88,8 +97,6 @@ github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrk github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= @@ -124,14 +131,16 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA= +github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -151,6 +160,8 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= @@ -181,8 +192,6 @@ golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= @@ -218,6 +227,8 @@ gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I= gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= +gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g= +gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw= gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= diff --git a/src/handler/admin_handler.go b/src/handler/admin_handler.go index 8db97988..947dd48e 100644 --- a/src/handler/admin_handler.go +++ b/src/handler/admin_handler.go @@ -144,8 +144,14 @@ func (h *AdminHandler) SetupInitialAdmin(c echo.Context) error { } // 기본 workspace 생성 + defaultWsName := os.Getenv("DEFAULT_WORKSPACE_NAME") + if defaultWsName == "" { + defaultWsName = "ws01" // fallback + log.Printf("[INFO] DEFAULT_WORKSPACE_NAME not set, using default: %s", defaultWsName) + } + err = h.workspaceService.CreateWorkspace(&model.Workspace{ - Name: "ws01", + Name: defaultWsName, Description: "Default Workspace", }) if err != nil { diff --git a/src/handler/auth_handler.go b/src/handler/auth_handler.go index e8ef8aa6..f59a0da1 100755 --- a/src/handler/auth_handler.go +++ b/src/handler/auth_handler.go @@ -110,32 +110,6 @@ func (h *AuthHandler) Login(c echo.Context) error { return c.JSON(http.StatusOK, token) } -// Callback godoc -// @Summary OIDC callback -// @Description Process callback after OIDC authentication -// @Param code query string true "Authentication code" -// @Param state query string true "State" -// @Success 200 {object} map[string]interface{} -// @Router /auth/callback [get] -// func (h *AuthHandler) Callback(c echo.Context) error { -// code := c.QueryParam("code") -// state := c.QueryParam("state") - -// if state != "state" { -// return c.JSON(http.StatusBadRequest, map[string]string{ -// "error": "Invalid state value", -// }) -// } - -// token, err := h.config.Exchange(c.Request().Context(), code) -// if err != nil { -// return c.JSON(http.StatusInternalServerError, map[string]string{ -// "error": "Token exchange failed", -// }) -// } - -// return c.JSON(http.StatusOK, token) -// } // Logout godoc // @Summary Logout user diff --git a/src/handler/csp_account_handler.go b/src/handler/csp_account_handler.go new file mode 100644 index 00000000..880520c5 --- /dev/null +++ b/src/handler/csp_account_handler.go @@ -0,0 +1,274 @@ +package handler + +import ( + "fmt" + "net/http" + + "github.com/labstack/echo/v4" + "github.com/m-cmp/mc-iam-manager/model" + "github.com/m-cmp/mc-iam-manager/service" + "github.com/m-cmp/mc-iam-manager/util" + "gorm.io/gorm" +) + +// CspAccountHandler CSP 계정 관리 핸들러 +type CspAccountHandler struct { + cspAccountService *service.CspAccountService +} + +// NewCspAccountHandler 새 CspAccountHandler 인스턴스 생성 +func NewCspAccountHandler(db *gorm.DB) *CspAccountHandler { + return &CspAccountHandler{ + cspAccountService: service.NewCspAccountService(db), + } +} + +// CreateCspAccount godoc +// @Summary Create CSP account +// @Description Create a new CSP account +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param account body model.CreateCspAccountRequest true "CSP Account Info" +// @Success 201 {object} model.CspAccount +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts [post] +// @Id createCspAccount +func (h *CspAccountHandler) CreateCspAccount(c echo.Context) error { + var req model.CreateCspAccountRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + // 필수 필드 검증 + if req.Name == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Name is required"}) + } + if req.CspType == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP type is required"}) + } + if req.CspType != "aws" && req.CspType != "gcp" && req.CspType != "azure" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid CSP type. Must be one of: aws, gcp, azure"}) + } + + account, err := h.cspAccountService.CreateCspAccount(&req) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to create CSP account: %v", err)}) + } + + return c.JSON(http.StatusCreated, account) +} + +// ListCspAccounts godoc +// @Summary List CSP accounts +// @Description Retrieve a list of CSP accounts with optional filters +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param filter body model.CspAccountFilter false "Filter options" +// @Success 200 {array} model.CspAccount +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts/list [post] +// @Id listCspAccounts +func (h *CspAccountHandler) ListCspAccounts(c echo.Context) error { + var filter model.CspAccountFilter + if err := c.Bind(&filter); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + accounts, err := h.cspAccountService.ListCspAccounts(&filter) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to list CSP accounts: %v", err)}) + } + + if accounts == nil { + accounts = []*model.CspAccount{} + } + + return c.JSON(http.StatusOK, accounts) +} + +// GetCspAccountByID godoc +// @Summary Get CSP account by ID +// @Description Retrieve CSP account details by ID +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param accountId path string true "Account ID" +// @Success 200 {object} model.CspAccount +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts/id/{accountId} [get] +// @Id getCspAccountByID +func (h *CspAccountHandler) GetCspAccountByID(c echo.Context) error { + accountID, err := util.StringToUint(c.Param("accountId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid account ID"}) + } + + account, err := h.cspAccountService.GetCspAccountByID(accountID) + if err != nil { + if err.Error() == fmt.Sprintf("CSP account not found with ID: %d", accountID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to get CSP account: %v", err)}) + } + + return c.JSON(http.StatusOK, account) +} + +// UpdateCspAccount godoc +// @Summary Update CSP account +// @Description Update CSP account details +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param accountId path string true "Account ID" +// @Param account body model.UpdateCspAccountRequest true "CSP Account Info" +// @Success 200 {object} model.CspAccount +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts/id/{accountId} [put] +// @Id updateCspAccount +func (h *CspAccountHandler) UpdateCspAccount(c echo.Context) error { + accountID, err := util.StringToUint(c.Param("accountId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid account ID"}) + } + + var req model.UpdateCspAccountRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + account, err := h.cspAccountService.UpdateCspAccount(accountID, &req) + if err != nil { + if err.Error() == fmt.Sprintf("CSP account not found with ID: %d", accountID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to update CSP account: %v", err)}) + } + + return c.JSON(http.StatusOK, account) +} + +// DeleteCspAccount godoc +// @Summary Delete CSP account +// @Description Delete a CSP account by ID +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param accountId path string true "Account ID" +// @Success 204 "No Content" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts/id/{accountId} [delete] +// @Id deleteCspAccount +func (h *CspAccountHandler) DeleteCspAccount(c echo.Context) error { + accountID, err := util.StringToUint(c.Param("accountId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid account ID"}) + } + + if err := h.cspAccountService.DeleteCspAccount(accountID); err != nil { + if err.Error() == fmt.Sprintf("CSP account not found with ID: %d", accountID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to delete CSP account: %v", err)}) + } + + return c.NoContent(http.StatusNoContent) +} + +// ValidateCspAccount godoc +// @Summary Validate CSP account +// @Description Validate CSP account configuration +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param accountId path string true "Account ID" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts/id/{accountId}/validate [post] +// @Id validateCspAccount +func (h *CspAccountHandler) ValidateCspAccount(c echo.Context) error { + accountID, err := util.StringToUint(c.Param("accountId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid account ID"}) + } + + if err := h.cspAccountService.ValidateCspAccount(accountID); err != nil { + if err.Error() == fmt.Sprintf("CSP account not found with ID: %d", accountID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusBadRequest, map[string]string{"error": fmt.Sprintf("Validation failed: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "CSP account is valid"}) +} + +// ActivateCspAccount godoc +// @Summary Activate CSP account +// @Description Activate a CSP account +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param accountId path string true "Account ID" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts/id/{accountId}/activate [post] +// @Id activateCspAccount +func (h *CspAccountHandler) ActivateCspAccount(c echo.Context) error { + accountID, err := util.StringToUint(c.Param("accountId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid account ID"}) + } + + if err := h.cspAccountService.ActivateCspAccount(accountID); err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to activate CSP account: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "CSP account activated successfully"}) +} + +// DeactivateCspAccount godoc +// @Summary Deactivate CSP account +// @Description Deactivate a CSP account +// @Tags csp-accounts +// @Accept json +// @Produce json +// @Param accountId path string true "Account ID" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-accounts/id/{accountId}/deactivate [post] +// @Id deactivateCspAccount +func (h *CspAccountHandler) DeactivateCspAccount(c echo.Context) error { + accountID, err := util.StringToUint(c.Param("accountId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid account ID"}) + } + + if err := h.cspAccountService.DeactivateCspAccount(accountID); err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to deactivate CSP account: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "CSP account deactivated successfully"}) +} diff --git a/src/handler/csp_idp_config_handler.go b/src/handler/csp_idp_config_handler.go new file mode 100644 index 00000000..4b5b5336 --- /dev/null +++ b/src/handler/csp_idp_config_handler.go @@ -0,0 +1,281 @@ +package handler + +import ( + "fmt" + "net/http" + + "github.com/labstack/echo/v4" + "github.com/m-cmp/mc-iam-manager/model" + "github.com/m-cmp/mc-iam-manager/service" + "github.com/m-cmp/mc-iam-manager/util" + "gorm.io/gorm" +) + +// CspIdpConfigHandler CSP IDP 설정 관리 핸들러 +type CspIdpConfigHandler struct { + cspIdpConfigService *service.CspIdpConfigService +} + +// NewCspIdpConfigHandler 새 CspIdpConfigHandler 인스턴스 생성 +func NewCspIdpConfigHandler(db *gorm.DB) *CspIdpConfigHandler { + keycloakService := service.NewKeycloakService() + return &CspIdpConfigHandler{ + cspIdpConfigService: service.NewCspIdpConfigService(db, keycloakService), + } +} + +// CreateCspIdpConfig godoc +// @Summary Create CSP IDP config +// @Description Create a new CSP IDP configuration +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param config body model.CreateCspIdpConfigRequest true "CSP IDP Config Info" +// @Success 201 {object} model.CspIdpConfig +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs [post] +// @Id createCspIdpConfig +func (h *CspIdpConfigHandler) CreateCspIdpConfig(c echo.Context) error { + var req model.CreateCspIdpConfigRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + // 필수 필드 검증 + if req.Name == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Name is required"}) + } + if req.CspAccountID == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP Account ID is required"}) + } + if req.AuthMethod == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Auth method is required"}) + } + if req.AuthMethod != model.AuthMethodOIDC && req.AuthMethod != model.AuthMethodSAML && req.AuthMethod != model.AuthMethodSecretKey { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid auth method. Must be one of: OIDC, SAML, SECRET_KEY"}) + } + if req.Config == nil || len(req.Config) == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Config is required"}) + } + + idpConfig, err := h.cspIdpConfigService.CreateCspIdpConfig(&req) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to create IDP config: %v", err)}) + } + + return c.JSON(http.StatusCreated, idpConfig) +} + +// ListCspIdpConfigs godoc +// @Summary List CSP IDP configs +// @Description Retrieve a list of CSP IDP configurations with optional filters +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param filter body model.CspIdpConfigFilter false "Filter options" +// @Success 200 {array} model.CspIdpConfig +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs/list [post] +// @Id listCspIdpConfigs +func (h *CspIdpConfigHandler) ListCspIdpConfigs(c echo.Context) error { + var filter model.CspIdpConfigFilter + if err := c.Bind(&filter); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + configs, err := h.cspIdpConfigService.ListCspIdpConfigs(&filter) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to list IDP configs: %v", err)}) + } + + if configs == nil { + configs = []*model.CspIdpConfig{} + } + + return c.JSON(http.StatusOK, configs) +} + +// GetCspIdpConfigByID godoc +// @Summary Get CSP IDP config by ID +// @Description Retrieve CSP IDP configuration details by ID +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param configId path string true "Config ID" +// @Success 200 {object} model.CspIdpConfig +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs/id/{configId} [get] +// @Id getCspIdpConfigByID +func (h *CspIdpConfigHandler) GetCspIdpConfigByID(c echo.Context) error { + configID, err := util.StringToUint(c.Param("configId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid config ID"}) + } + + idpConfig, err := h.cspIdpConfigService.GetCspIdpConfigByID(configID) + if err != nil { + if err.Error() == fmt.Sprintf("IDP config not found with ID: %d", configID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to get IDP config: %v", err)}) + } + + return c.JSON(http.StatusOK, idpConfig) +} + +// UpdateCspIdpConfig godoc +// @Summary Update CSP IDP config +// @Description Update CSP IDP configuration details +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param configId path string true "Config ID" +// @Param config body model.UpdateCspIdpConfigRequest true "CSP IDP Config Info" +// @Success 200 {object} model.CspIdpConfig +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs/id/{configId} [put] +// @Id updateCspIdpConfig +func (h *CspIdpConfigHandler) UpdateCspIdpConfig(c echo.Context) error { + configID, err := util.StringToUint(c.Param("configId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid config ID"}) + } + + var req model.UpdateCspIdpConfigRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + idpConfig, err := h.cspIdpConfigService.UpdateCspIdpConfig(configID, &req) + if err != nil { + if err.Error() == fmt.Sprintf("IDP config not found with ID: %d", configID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to update IDP config: %v", err)}) + } + + return c.JSON(http.StatusOK, idpConfig) +} + +// DeleteCspIdpConfig godoc +// @Summary Delete CSP IDP config +// @Description Delete a CSP IDP configuration by ID +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param configId path string true "Config ID" +// @Success 204 "No Content" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs/id/{configId} [delete] +// @Id deleteCspIdpConfig +func (h *CspIdpConfigHandler) DeleteCspIdpConfig(c echo.Context) error { + configID, err := util.StringToUint(c.Param("configId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid config ID"}) + } + + if err := h.cspIdpConfigService.DeleteCspIdpConfig(configID); err != nil { + if err.Error() == fmt.Sprintf("IDP config not found with ID: %d", configID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to delete IDP config: %v", err)}) + } + + return c.NoContent(http.StatusNoContent) +} + +// TestCspIdpConnection godoc +// @Summary Test CSP IDP connection +// @Description Test connection to CSP using IDP configuration +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param configId path string true "Config ID" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs/id/{configId}/test [post] +// @Id testCspIdpConnection +func (h *CspIdpConfigHandler) TestCspIdpConnection(c echo.Context) error { + configID, err := util.StringToUint(c.Param("configId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid config ID"}) + } + + if err := h.cspIdpConfigService.TestConnection(c.Request().Context(), configID); err != nil { + if err.Error() == fmt.Sprintf("IDP config not found with ID: %d", configID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusBadRequest, map[string]string{"error": fmt.Sprintf("Connection test failed: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "Connection test successful"}) +} + +// ActivateCspIdpConfig godoc +// @Summary Activate CSP IDP config +// @Description Activate a CSP IDP configuration +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param configId path string true "Config ID" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs/id/{configId}/activate [post] +// @Id activateCspIdpConfig +func (h *CspIdpConfigHandler) ActivateCspIdpConfig(c echo.Context) error { + configID, err := util.StringToUint(c.Param("configId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid config ID"}) + } + + if err := h.cspIdpConfigService.ActivateIdpConfig(configID); err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to activate IDP config: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "IDP config activated successfully"}) +} + +// DeactivateCspIdpConfig godoc +// @Summary Deactivate CSP IDP config +// @Description Deactivate a CSP IDP configuration +// @Tags csp-idp-configs +// @Accept json +// @Produce json +// @Param configId path string true "Config ID" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-idp-configs/id/{configId}/deactivate [post] +// @Id deactivateCspIdpConfig +func (h *CspIdpConfigHandler) DeactivateCspIdpConfig(c echo.Context) error { + configID, err := util.StringToUint(c.Param("configId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid config ID"}) + } + + if err := h.cspIdpConfigService.DeactivateIdpConfig(configID); err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to deactivate IDP config: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "IDP config deactivated successfully"}) +} diff --git a/src/handler/csp_policy_handler.go b/src/handler/csp_policy_handler.go new file mode 100644 index 00000000..59ec97b6 --- /dev/null +++ b/src/handler/csp_policy_handler.go @@ -0,0 +1,356 @@ +package handler + +import ( + "fmt" + "net/http" + + "github.com/labstack/echo/v4" + "github.com/m-cmp/mc-iam-manager/model" + "github.com/m-cmp/mc-iam-manager/service" + "github.com/m-cmp/mc-iam-manager/util" + "gorm.io/gorm" +) + +// CspPolicyHandler CSP 정책 관리 핸들러 +type CspPolicyHandler struct { + cspPolicyService *service.CspPolicyService +} + +// NewCspPolicyHandler 새 CspPolicyHandler 인스턴스 생성 +func NewCspPolicyHandler(db *gorm.DB) *CspPolicyHandler { + keycloakService := service.NewKeycloakService() + cspIdpConfigService := service.NewCspIdpConfigService(db, keycloakService) + return &CspPolicyHandler{ + cspPolicyService: service.NewCspPolicyService(db, cspIdpConfigService), + } +} + +// CreateCspPolicy godoc +// @Summary Create CSP policy +// @Description Create a new CSP policy +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param policy body model.CreateCspPolicyRequest true "CSP Policy Info" +// @Success 201 {object} model.CspPolicy +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies [post] +// @Id createCspPolicy +func (h *CspPolicyHandler) CreateCspPolicy(c echo.Context) error { + var req model.CreateCspPolicyRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + // 필수 필드 검증 + if req.Name == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Name is required"}) + } + if req.CspAccountID == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP Account ID is required"}) + } + if req.PolicyType == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Policy type is required"}) + } + if req.PolicyType != model.PolicyTypeInline && req.PolicyType != model.PolicyTypeManaged && req.PolicyType != model.PolicyTypeCustom { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid policy type. Must be one of: inline, managed, custom"}) + } + + policy, err := h.cspPolicyService.CreateCspPolicy(&req) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to create policy: %v", err)}) + } + + return c.JSON(http.StatusCreated, policy) +} + +// ListCspPolicies godoc +// @Summary List CSP policies +// @Description Retrieve a list of CSP policies with optional filters +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param filter body model.CspPolicyFilter false "Filter options" +// @Success 200 {array} model.CspPolicy +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/list [post] +// @Id listCspPolicies +func (h *CspPolicyHandler) ListCspPolicies(c echo.Context) error { + var filter model.CspPolicyFilter + if err := c.Bind(&filter); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + policies, err := h.cspPolicyService.ListCspPolicies(&filter) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to list policies: %v", err)}) + } + + if policies == nil { + policies = []*model.CspPolicy{} + } + + return c.JSON(http.StatusOK, policies) +} + +// GetCspPolicyByID godoc +// @Summary Get CSP policy by ID +// @Description Retrieve CSP policy details by ID +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param policyId path string true "Policy ID" +// @Success 200 {object} model.CspPolicy +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/id/{policyId} [get] +// @Id getCspPolicyByID +func (h *CspPolicyHandler) GetCspPolicyByID(c echo.Context) error { + policyID, err := util.StringToUint(c.Param("policyId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid policy ID"}) + } + + policy, err := h.cspPolicyService.GetCspPolicyByID(policyID) + if err != nil { + if err.Error() == fmt.Sprintf("policy not found with ID: %d", policyID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to get policy: %v", err)}) + } + + return c.JSON(http.StatusOK, policy) +} + +// UpdateCspPolicy godoc +// @Summary Update CSP policy +// @Description Update CSP policy details +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param policyId path string true "Policy ID" +// @Param policy body model.UpdateCspPolicyRequest true "CSP Policy Info" +// @Success 200 {object} model.CspPolicy +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/id/{policyId} [put] +// @Id updateCspPolicy +func (h *CspPolicyHandler) UpdateCspPolicy(c echo.Context) error { + policyID, err := util.StringToUint(c.Param("policyId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid policy ID"}) + } + + var req model.UpdateCspPolicyRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + policy, err := h.cspPolicyService.UpdateCspPolicy(policyID, &req) + if err != nil { + if err.Error() == fmt.Sprintf("policy not found with ID: %d", policyID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to update policy: %v", err)}) + } + + return c.JSON(http.StatusOK, policy) +} + +// DeleteCspPolicy godoc +// @Summary Delete CSP policy +// @Description Delete a CSP policy by ID +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param policyId path string true "Policy ID" +// @Success 204 "No Content" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/id/{policyId} [delete] +// @Id deleteCspPolicy +func (h *CspPolicyHandler) DeleteCspPolicy(c echo.Context) error { + policyID, err := util.StringToUint(c.Param("policyId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid policy ID"}) + } + + if err := h.cspPolicyService.DeleteCspPolicy(policyID); err != nil { + if err.Error() == fmt.Sprintf("policy not found with ID: %d", policyID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to delete policy: %v", err)}) + } + + return c.NoContent(http.StatusNoContent) +} + +// SyncCspPolicies godoc +// @Summary Sync CSP policies from cloud +// @Description Synchronize policies from the CSP cloud +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param request body model.SyncPoliciesRequest true "Sync Policies Request" +// @Success 200 {array} model.CspPolicy +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/sync [post] +// @Id syncCspPolicies +func (h *CspPolicyHandler) SyncCspPolicies(c echo.Context) error { + var req model.SyncPoliciesRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + if req.CspAccountID == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP Account ID is required"}) + } + + policies, err := h.cspPolicyService.SyncPoliciesFromCloud(c.Request().Context(), &req) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to sync policies: %v", err)}) + } + + return c.JSON(http.StatusOK, policies) +} + +// AttachPolicyToRole godoc +// @Summary Attach policy to role +// @Description Attach a CSP policy to a CSP role +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param request body model.AttachPolicyRequest true "Attach Policy Request" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/attach [post] +// @Id attachPolicyToRole +func (h *CspPolicyHandler) AttachPolicyToRole(c echo.Context) error { + var req model.AttachPolicyRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + if req.CspRoleID == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP Role ID is required"}) + } + if req.CspPolicyID == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP Policy ID is required"}) + } + + if err := h.cspPolicyService.AttachPolicyToRole(req.CspRoleID, req.CspPolicyID); err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to attach policy: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "Policy attached successfully"}) +} + +// DetachPolicyFromRole godoc +// @Summary Detach policy from role +// @Description Detach a CSP policy from a CSP role +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param request body model.AttachPolicyRequest true "Detach Policy Request" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/detach [post] +// @Id detachPolicyFromRole +func (h *CspPolicyHandler) DetachPolicyFromRole(c echo.Context) error { + var req model.AttachPolicyRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request format"}) + } + + if req.CspRoleID == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP Role ID is required"}) + } + if req.CspPolicyID == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "CSP Policy ID is required"}) + } + + if err := h.cspPolicyService.DetachPolicyFromRole(req.CspRoleID, req.CspPolicyID); err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to detach policy: %v", err)}) + } + + return c.JSON(http.StatusOK, map[string]string{"message": "Policy detached successfully"}) +} + +// GetRolePolicies godoc +// @Summary Get policies attached to role +// @Description Get list of policies attached to a CSP role +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param roleId path string true "Role ID" +// @Success 200 {array} model.CspPolicy +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/role/{roleId} [get] +// @Id getRolePolicies +func (h *CspPolicyHandler) GetRolePolicies(c echo.Context) error { + roleID, err := util.StringToUint(c.Param("roleId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid role ID"}) + } + + policies, err := h.cspPolicyService.GetPoliciesByRoleID(roleID) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to get policies: %v", err)}) + } + + if policies == nil { + policies = []*model.CspPolicy{} + } + + return c.JSON(http.StatusOK, policies) +} + +// GetPolicyDocument godoc +// @Summary Get policy document +// @Description Get the policy document content +// @Tags csp-policies +// @Accept json +// @Produce json +// @Param policyId path string true "Policy ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Security BearerAuth +// @Router /api/csp-policies/id/{policyId}/document [get] +// @Id getPolicyDocument +func (h *CspPolicyHandler) GetPolicyDocument(c echo.Context) error { + policyID, err := util.StringToUint(c.Param("policyId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid policy ID"}) + } + + document, err := h.cspPolicyService.GetPolicyDocument(c.Request().Context(), policyID) + if err != nil { + if err.Error() == fmt.Sprintf("policy not found with ID: %d", policyID) { + return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("Failed to get policy document: %v", err)}) + } + + return c.JSON(http.StatusOK, document) +} diff --git a/src/handler/mcmpapi_handler.go b/src/handler/mcmpapi_handler.go index 55555897..652f1e76 100644 --- a/src/handler/mcmpapi_handler.go +++ b/src/handler/mcmpapi_handler.go @@ -49,6 +49,53 @@ func (h *McmpApiHandler) SyncMcmpAPIs(c echo.Context) error { return c.JSON(http.StatusOK, map[string]string{"message": "Successfully triggered MCMP API sync"}) } +// ImportAPIs godoc +// @Summary Import MCMP APIs from Remote Sources +// @Description Fetches API specifications from remote URLs and imports them to the database. Supports swagger and openapi source types. Optionally accepts baseUrl and authentication info to populate the mcmp_api_services table. +// @Tags McmpAPI +// @Accept json +// @Produce json +// @Param request body model.ImportApiRequest true "Frameworks to import (with optional baseUrl, authType, authUser, authPass)" +// @Success 200 {object} model.ImportApiResponse "Import results" +// @Failure 400 {object} map[string]string "error: Invalid request body" +// @Failure 500 {object} map[string]string "error: Failed to import APIs" +// @Router /api/mcmp-apis/import [post] +// @Security BearerAuth +// @Id importAPIs +func (h *McmpApiHandler) ImportAPIs(c echo.Context) error { + var req model.ImportApiRequest + if err := c.Bind(&req); err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request body: " + err.Error()}) + } + + // Validate request + if len(req.Frameworks) == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "At least one framework is required"}) + } + + for i, fw := range req.Frameworks { + if fw.Name == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": fmt.Sprintf("Framework at index %d: name is required", i)}) + } + if fw.Version == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": fmt.Sprintf("Framework '%s': version is required", fw.Name)}) + } + if fw.SourceType == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": fmt.Sprintf("Framework '%s': sourceType is required (swagger or openapi)", fw.Name)}) + } + if fw.SourceURL == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": fmt.Sprintf("Framework '%s': sourceUrl is required", fw.Name)}) + } + } + + response, err := h.service.ImportAPIs(&req) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to import APIs: " + err.Error()}) + } + + return c.JSON(http.StatusOK, response) +} + // Add other handler methods if needed, e.g., to get API definitions via API // SetActiveVersion godoc @@ -348,120 +395,3 @@ func (h *McmpApiHandler) UpdateFrameworkService(c echo.Context) error { return c.JSON(http.StatusOK, map[string]string{"message": fmt.Sprintf("Service '%s' updated successfully", serviceName)}) } -// ListMCMPAPIs godoc -// @Summary MCMP API 목록 조회 -// @Description 모든 MCMP API 목록을 조회합니다 -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Success 200 {array} model.MCMPAPI -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Security BearerAuth -// @Router /api/mcmp-apis [get] - -// GetMCMPAPIByID godoc -// @Summary MCMP API ID로 조회 -// @Description 특정 MCMP API를 ID로 조회합니다 -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Param id path string true "API ID" -// @Success 200 {object} model.MCMPAPI -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Failure 404 {object} map[string]string "error: API not found" -// @Security BearerAuth -// @Router /api/mcmp-apis/{id} [get] - -// CreateMCMPAPI godoc -// @Summary 새 MCMP API 생성 -// @Description 새로운 MCMP API를 생성합니다 -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Param api body model.MCMPAPI true "API Info" -// @Success 201 {object} model.MCMPAPI -// @Failure 400 {object} map[string]string "error: Invalid request" -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Security BearerAuth -// @Router /api/mcmp-apis [post] - -// UpdateMCMPAPI godoc -// @Summary MCMP API 업데이트 -// @Description MCMP API 정보를 업데이트합니다 -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Param id path string true "API ID" -// @Param api body model.MCMPAPI true "API Info" -// @Success 200 {object} model.MCMPAPI -// @Failure 400 {object} map[string]string "error: Invalid request" -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Failure 404 {object} map[string]string "error: API not found" -// @Security BearerAuth -// @Router /api/mcmp-apis/{id} [put] - -// DeleteMCMPAPI godoc -// @Summary MCMP API 삭제 -// @Description MCMP API를 삭제합니다 -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Param id path string true "API ID" -// @Success 204 "No Content" -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Failure 404 {object} map[string]string "error: API not found" -// @Security BearerAuth -// @Router /api/mcmp-apis/{id} [delete] - -// @Summary List services and actions -// @Description Get a list of all MCMP services and their actions -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Success 200 {array} model.McmpService -// @Failure 500 {object} map[string]string -// @Security BearerAuth -// @Router /api/mcmp-apis/list [post] - -// @Summary Set active version -// @Description Set the active version for a service -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Param serviceName path string true "Service Name" -// @Param version path string true "Version" -// @Success 200 {object} map[string]string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Security BearerAuth -// @Router /api/mcmp-apis/name/{serviceName}/versions/{version}/activate [put] - -// @Summary Make MCMP API call -// @Description Make a call to MCMP API -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Param request body model.McmpApiCallRequest true "API Call Request" -// @Success 200 {object} map[string]interface{} -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Security BearerAuth -// @Router /api/mcmp-apis/call [post] - -// @Summary Update service -// @Description Update MCMP service information -// @Tags mcmp-apis -// @Accept json -// @Produce json -// @Param serviceName path string true "Service Name" -// @Param service body model.McmpService true "Service Info" -// @Success 200 {object} model.McmpService -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Security BearerAuth -// @Router /api/mcmp-apis/name/{serviceName} [put] diff --git a/src/handler/mcmpapi_permission_action_mapping_handler.go b/src/handler/mcmpapi_permission_action_mapping_handler.go index 6d59d09e..d4fac0ff 100644 --- a/src/handler/mcmpapi_permission_action_mapping_handler.go +++ b/src/handler/mcmpapi_permission_action_mapping_handler.go @@ -227,62 +227,3 @@ func (h *McmpApiPermissionActionMappingHandler) UpdateMapping(c echo.Context) er return c.JSON(http.StatusOK, map[string]string{"message": "mapping updated successfully"}) } -// ListMappings godoc ListPlatformActions -// @Summary MCMP API 권한-액션 매핑 목록 조회 -// @Description 모든 MCMP API 권한-액션 매핑 목록을 조회합니다 -// @Tags mcmp-api-permission-action-mappings -// @Accept json -// @Produce json -// @Success 200 {array} mcmpapi.MCMPAPIPermissionActionMapping -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Security BearerAuth -// @Router /api/mcmp-api-permission-action-mappings [get] -// @Id listMappings - -// GetMappingByID godoc -// @Summary MCMP API 권한-액션 매핑 ID로 조회 -// @Description 특정 MCMP API 권한-액션 매핑을 ID로 조회합니다 -// @Tags mcmp-api-permission-action-mappings -// @Accept json -// @Produce json -// @Param id path string true "Mapping ID" -// @Success 200 {object} mcmpapi.MCMPAPIPermissionActionMapping -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Failure 404 {object} map[string]string "error: Mapping not found" -// @Security BearerAuth -// @Router /api/mcmp-api-permission-action-mappings/{id} [get] -// @Id getMappingByID - -// UpdateMapping godoc UpdateMapping -// @Summary MCMP API 권한-액션 매핑 업데이트 -// @Description MCMP API 권한-액션 매핑 정보를 업데이트합니다 -// @Tags mcmp-api-permission-action-mappings -// @Accept json -// @Produce json -// @Param id path string true "Mapping ID" -// @Param mapping body mcmpapi.MCMPAPIPermissionActionMapping true "Mapping Info" -// @Success 200 {object} mcmpapi.MCMPAPIPermissionActionMapping -// @Failure 400 {object} map[string]string "error: Invalid request" -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Failure 404 {object} map[string]string "error: Mapping not found" -// @Security BearerAuth -// @Router /api/mcmp-api-permission-action-mappings/{id} [put] -// @Id updateMapping - -// DeleteMapping godoc -// @Summary MCMP API 권한-액션 매핑 삭제 -// @Description MCMP API 권한-액션 매핑을 삭제합니다 -// @Tags mcmp-api-permission-action-mappings -// @Accept json -// @Produce json -// @Param id path string true "Mapping ID" -// @Success 204 "No Content" -// @Failure 401 {object} map[string]string "error: Unauthorized" -// @Failure 403 {object} map[string]string "error: Forbidden" -// @Failure 404 {object} map[string]string "error: Mapping not found" -// @Security BearerAuth -// @Router /api/mcmp-api-permission-action-mappings/{id} [delete] -// @Id deleteMapping diff --git a/src/handler/project_handler.go b/src/handler/project_handler.go index 54d6d9f6..29108b27 100644 --- a/src/handler/project_handler.go +++ b/src/handler/project_handler.go @@ -41,28 +41,45 @@ func NewProjectHandler(db *gorm.DB) *ProjectHandler { // CreateProject godoc // @Summary Create new project -// @Description Create a new project with the specified information. +// @Description Create a new project with the specified information. Optionally specify a workspace to assign the project to. // @Tags projects // @Accept json // @Produce json -// @Param project body model.Project true "Project Info" +// @Param project body model.CreateProjectRequest true "Project Info" // @Success 201 {object} model.Project // @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string // @Failure 500 {object} map[string]string // @Security BearerAuth // @Router /api/projects [post] // @Id createProject func (h *ProjectHandler) CreateProject(c echo.Context) error { - var project model.Project - if err := c.Bind(&project); err != nil { + var req model.CreateProjectRequest + if err := c.Bind(&req); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{"error": "잘못된 요청 형식입니다"}) } - project.ID = 0 // Ensure ID is not set by client - // project.NsId will be set by the service after calling the external API - // Call the service Create method, passing the context - if err := h.projectService.Create(c.Request().Context(), &project); err != nil { - return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("프로젝트 생성 실패 (DB 저장 오류): %v", err)}) + project := &model.Project{ + Name: req.Name, + Description: req.Description, + } + + // Parse optional workspaceId + var workspaceID uint + if req.WorkspaceID != "" { + workspaceIDInt, err := util.StringToUint(req.WorkspaceID) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "잘못된 워크스페이스 ID 형식입니다"}) + } + workspaceID = workspaceIDInt + } + + // Call the service Create method with optional workspaceID + if err := h.projectService.Create(c.Request().Context(), project, workspaceID); err != nil { + if err.Error() == "workspace not found" { + return c.JSON(http.StatusNotFound, map[string]string{"error": "워크스페이스를 찾을 수 없습니다"}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("프로젝트 생성 실패: %v", err)}) } log.Printf("Successfully created project '%s' (ID: %d, NsId: %s)", project.Name, project.ID, project.NsId) @@ -231,6 +248,44 @@ func (h *ProjectHandler) DeleteProject(c echo.Context) error { return c.NoContent(http.StatusNoContent) } +// GetProjectWorkspaces godoc +// @Summary Get workspaces assigned to project +// @Description Retrieve list of workspaces that the project is assigned to +// @Tags projects +// @Accept json +// @Produce json +// @Param projectId path string true "Project ID" +// @Success 200 {array} model.Workspace +// @Failure 400 {object} map[string]string "error: Invalid project ID" +// @Failure 404 {object} map[string]string "error: Project not found" +// @Failure 500 {object} map[string]string "error: Internal server error" +// @Security BearerAuth +// @Router /api/projects/id/{projectId}/workspaces [get] +// @Id getProjectWorkspaces +func (h *ProjectHandler) GetProjectWorkspaces(c echo.Context) error { + projectIDInt, err := util.StringToUint(c.Param("projectId")) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid project ID"}) + } + + workspaces, err := h.projectService.GetProjectWorkspaces(projectIDInt) + if err != nil { + if err.Error() == "project not found" { + return c.JSON(http.StatusNotFound, map[string]string{"error": "Project not found"}) + } + return c.JSON(http.StatusInternalServerError, map[string]string{ + "error": fmt.Sprintf("Failed to retrieve workspace list: %v", err), + }) + } + + // 빈 배열 처리 + if workspaces == nil { + workspaces = []*model.Workspace{} + } + + return c.JSON(http.StatusOK, workspaces) +} + // SyncProjects godoc // @Summary mc-infra-manager와 프로젝트 동기화 // @Description mc-infra-manager의 네임스페이스 목록을 조회하여 로컬 DB에 없는 프로젝트를 추가합니다. @@ -258,14 +313,13 @@ func (h *ProjectHandler) SyncProjects(c echo.Context) error { // @Tags projects // @Accept json // @Produce json -// @Param id path int true "프로젝트 ID" -// @Param workspaceId path int true "워크스페이스 ID" +// @Param request body model.WorkspaceProjectMappingRequest true "Workspace and Project IDs" // @Success 204 "No Content" // @Failure 400 {object} map[string]string "error: 잘못된 ID 형식" // @Failure 404 {object} map[string]string "error: 프로젝트 또는 워크스페이스를 찾을 수 없습니다" // @Failure 500 {object} map[string]string "error: 서버 내부 오류" // @Security BearerAuth -// @Router /api/projects/{id}/workspaces/{workspaceId} [post] +// @Router /api/projects/assign/workspaces [post] // @Id addWorkspaceToProject func (h *ProjectHandler) AddWorkspaceToProject(c echo.Context) error { var req model.WorkspaceProjectMappingRequest @@ -309,7 +363,12 @@ func (h *ProjectHandler) AddWorkspaceToProject(c echo.Context) error { // @Tags projects // @Accept json // @Produce json -// @Param id path string true "Project ID" +// @Param request body model.WorkspaceProjectMappingRequest true "Workspace and Project IDs" +// @Success 204 "No Content" +// @Failure 400 {object} map[string]string "error: Invalid request" +// @Failure 500 {object} map[string]string "error: Internal server error" +// @Security BearerAuth +// @Router /api/projects/unassign/workspaces [delete] // @Id removeWorkspaceFromProject func (h *ProjectHandler) RemoveWorkspaceFromProject(c echo.Context) error { var req model.WorkspaceProjectMappingRequest diff --git a/src/handler/role_handler.go b/src/handler/role_handler.go index 136fde05..c0c1aeab 100644 --- a/src/handler/role_handler.go +++ b/src/handler/role_handler.go @@ -715,7 +715,7 @@ func (h *RoleHandler) ListPlatformRoles(c echo.Context) error { // @Failure 500 {object} map[string]string // @Security BearerAuth // @Router /api/roles/workspace-roles/list [post] -// @Id listWorkspaceRoles +// @Id listRolesOfWorkspaceType func (h *RoleHandler) ListWorkspaceRoles(c echo.Context) error { var req model.RoleFilterRequest if err := c.Bind(&req); err != nil { @@ -1465,10 +1465,36 @@ func (h *RoleHandler) AssignPlatformRole(c echo.Context) error { return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("플랫폼 역할 할당 실패: %v", err)}) } - // keycloak 역할 할당 - err := h.keycloakService.AssignRealmRoleToUser(c.Request().Context(), user.KcId, req.RoleName) - //err = h.keycloakService.AssignRealmRoleToUser(c.Request().Context(), user.KcId, req.RoleName) + // Keycloak role 존재 여부 확인 및 생성 + roleExists, err := h.keycloakService.CheckRealmRoleExists(c.Request().Context(), req.RoleName) if err != nil { + log.Printf("Failed to check realm role existence: %v", err) + // DB 롤백을 위해 역할 제거 + if rollbackErr := h.roleService.RemovePlatformRole(userID, roleID); rollbackErr != nil { + log.Printf("Failed to rollback platform role assignment: %v", rollbackErr) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("키클로크 역할 확인 실패: %v", err)}) + } + + // Keycloak role이 없으면 생성하고 생성 완료까지 대기 + if !roleExists { + if err := h.keycloakService.CreateRealmRoleAndWait(c.Request().Context(), req.RoleName); err != nil { + log.Printf("Failed to create realm role: %v", err) + // DB 롤백을 위해 역할 제거 + if rollbackErr := h.roleService.RemovePlatformRole(userID, roleID); rollbackErr != nil { + log.Printf("Failed to rollback platform role assignment: %v", rollbackErr) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("키클로크 역할 생성 실패: %v", err)}) + } + } + + // Keycloak에 역할 할당 + if err := h.keycloakService.AssignRealmRoleToUser(c.Request().Context(), user.KcId, req.RoleName); err != nil { + log.Printf("Failed to assign realm role: %v", err) + // DB 롤백을 위해 역할 제거 + if rollbackErr := h.roleService.RemovePlatformRole(userID, roleID); rollbackErr != nil { + log.Printf("Failed to rollback platform role assignment: %v", rollbackErr) + } return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("키클로크 역할 할당 실패: %v", err)}) } } @@ -1541,11 +1567,39 @@ func (h *RoleHandler) RemovePlatformRole(c echo.Context) error { return c.JSON(http.StatusBadRequest, map[string]string{"error": "역할 ID 또는 역할명이 필요합니다"}) } - // 역할 제거 + // 사용자 정보 조회 (Keycloak ID 필요) + user, err := h.userService.GetUserByID(c.Request().Context(), userID) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("사용자 조회 실패: %v", err)}) + } + if user == nil { + return c.JSON(http.StatusNotFound, map[string]string{"error": "해당 사용자를 찾을 수 없습니다"}) + } + + // 역할 정보 조회 (RoleName 필요) - Platform 역할로 조회 + role, err := h.roleService.GetRoleByID(roleID, constants.RoleTypePlatform) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("역할 조회 실패: %v", err)}) + } + if role == nil { + return c.JSON(http.StatusNotFound, map[string]string{"error": "해당 역할을 찾을 수 없습니다"}) + } + + // DB에서 역할 제거 if err := h.roleService.RemovePlatformRole(userID, roleID); err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("플랫폼 역할 제거 실패: %v", err)}) } + // Keycloak에서 역할 제거 + if err := h.keycloakService.RemoveRealmRoleFromUser(c.Request().Context(), user.KcId, role.Name); err != nil { + log.Printf("Failed to remove realm role from user: %v", err) + // DB 롤백을 위해 역할 재할당 + if rollbackErr := h.roleService.AssignPlatformRole(userID, roleID); rollbackErr != nil { + log.Printf("Failed to rollback platform role removal: %v", rollbackErr) + } + return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("키클로크 역할 제거 실패: %v", err)}) + } + return c.JSON(http.StatusOK, map[string]string{"message": "플랫폼 역할이 성공적으로 제거되었습니다"}) } diff --git a/src/handler/workspace_handler.go b/src/handler/workspace_handler.go index 803973fc..17f5fce1 100644 --- a/src/handler/workspace_handler.go +++ b/src/handler/workspace_handler.go @@ -550,7 +550,19 @@ func (h *WorkspaceHandler) ListWorkspaceUsersAndRoles(c echo.Context) error { return c.JSON(http.StatusOK, workspaceUsersRoles) } -// GetWorkspaceRoles 워크스페이스의 역할 목록 조회 +// ListWorkspaceRoles godoc +// @Summary List workspace roles +// @Description Retrieve all workspace-level roles with optional filtering +// @Tags workspaces +// @Accept json +// @Produce json +// @Param request body model.RoleFilterRequest true "Role filter parameters" +// @Success 200 {array} model.RoleMaster "Successfully retrieved workspace roles" +// @Failure 400 {object} map[string]string "error: Invalid request format" +// @Failure 500 {object} map[string]string "error: Failed to retrieve workspace roles" +// @Security BearerAuth +// @Router /api/workspaces/roles/list [post] +// @Id listWorkspaceRoles func (h *WorkspaceHandler) ListWorkspaceRoles(c echo.Context) error { var req model.RoleFilterRequest if err := c.Bind(&req); err != nil { @@ -569,35 +581,6 @@ func (h *WorkspaceHandler) ListWorkspaceRoles(c echo.Context) error { return c.JSON(http.StatusOK, roles) } -// ListWorkspaceUsers godoc -// @Summary Get workspace users -// @Description Get users in a workspace -// @Tags workspaces -// @Accept json -// @Produce json -// @Param id path string true "Workspace ID" -// @Success 200 {array} model.User -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Security BearerAuth -// @Router /api/workspaces/{id}/users [get] -// @Id ListWorkspaceUsers -// func (h *WorkspaceHandler) ListWorkspaceUsers(c echo.Context) error { -// var req model.WorkspaceFilterRequest -// if err := c.Bind(&req); err != nil { -// return c.JSON(http.StatusBadRequest, map[string]string{"error": "잘못된 요청 형식입니다"}) -// } - -// workspaceUsers, err := h.workspaceService.ListWorkspaces(&req) -// if err != nil { -// if err.Error() == "workspace not found" { -// return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()}) -// } -// return c.JSON(http.StatusInternalServerError, map[string]string{"error": fmt.Sprintf("사용자 목록 조회 실패: %v", err)}) -// } - -// return c.JSON(http.StatusOK, workspaceUsers) -// } // AddUserToWorkspace godoc // @Summary Add user to workspace diff --git a/src/main.go b/src/main.go index c669323f..315d2a3a 100755 --- a/src/main.go +++ b/src/main.go @@ -82,11 +82,16 @@ func main() { &model.ResourceType{}, &model.UserPlatformRole{}, &model.UserWorkspaceRole{}, + &model.CspAccount{}, + &model.CspIdpConfig{}, &model.CspRole{}, + &model.CspPolicy{}, + &model.CspRolePolicyMapping{}, &model.RoleMasterCspRoleMapping{}, &model.TempCredential{}, &mcmpapi.McmpApiService{}, &mcmpapi.McmpApiAction{}, + &mcmpapi.McmpApiServiceMeta{}, &model.MciamPermission{}, &model.MciamRoleMciamPermission{}, ); err != nil { @@ -115,6 +120,11 @@ func main() { permissionHandler := handler.NewMciamPermissionHandler(db) roleHandler := handler.NewRoleHandler(db) + // CSP 관리 핸들러 초기화 + cspAccountHandler := handler.NewCspAccountHandler(db) + cspIdpConfigHandler := handler.NewCspIdpConfigHandler(db) + cspPolicyHandler := handler.NewCspPolicyHandler(db) + // Echo 인스턴스 생성 e := echo.New() @@ -210,12 +220,15 @@ func main() { workspaces.POST("/users/list", workspaceHandler.ListWorkspaceUsers) // workspace의 사용자 목록 조회 workspaces.POST("/users-roles/list", workspaceHandler.ListWorkspaceUsersAndRoles, middleware.PlatformRoleMiddleware(middleware.Write)) // workspace와 사용자 및 role 조회 + workspaces.POST("/roles/list", workspaceHandler.ListWorkspaceRoles) // workspace 역할 목록 조회 workspaces.POST("/projects/list", workspaceHandler.ListWorkspaceProjects) workspaces.GET("/id/:workspaceId/projects/list", workspaceHandler.GetWorkspaceProjectsByWorkspaceId) workspaces.POST("/id/:workspaceId/users/list", workspaceHandler.ListUsersAndRolesByWorkspaces) // TODO ListAllWorkspaceUsersAndRoles으로 대체 또는 통합 가능하지 않나? workspaces.GET("/id/:workspaceId/users/id/:userId", roleHandler.GetUserWorkspaceRoles, middleware.PlatformRoleMiddleware(middleware.Write)) // 특정 사용자에게 할당된 워크스페이스 역할 조회 ( 관리자가 사용자의 workspace role 조회) --> get을 post로 바꿀까? + workspaces.POST("/id/:id/users", workspaceHandler.AddUserToWorkspace, middleware.PlatformRoleMiddleware(middleware.Write)) // workspace에 사용자 추가 + workspaces.DELETE("/id/:id/users/:userId", workspaceHandler.RemoveUserFromWorkspace, middleware.PlatformRoleMiddleware(middleware.Write)) // workspace에서 사용자 제거 workspaces.POST("/assign/projects", workspaceHandler.AddProjectToWorkspace, middleware.PlatformAdminMiddleware) workspaces.DELETE("/unassign/projects", workspaceHandler.RemoveProjectFromWorkspace, middleware.PlatformAdminMiddleware) @@ -231,6 +244,8 @@ func main() { projects.PUT("/id/:projectId", projectHandler.UpdateProject, middleware.PlatformRoleMiddleware(middleware.Manage)) projects.DELETE("/id/:projectId", projectHandler.DeleteProject, middleware.PlatformRoleMiddleware(middleware.Manage)) + projects.GET("/id/:projectId/workspaces", projectHandler.GetProjectWorkspaces) // Get workspaces assigned to project + projects.POST("/assign/workspaces", projectHandler.AddWorkspaceToProject, middleware.PlatformAdminMiddleware) projects.DELETE("/unassign/workspaces", projectHandler.RemoveWorkspaceFromProject, middleware.PlatformAdminMiddleware) } @@ -371,6 +386,7 @@ func main() { mcmpApis.POST("/call", mcmpApiHandler.McmpApiCall, middleware.PlatformRoleMiddleware(middleware.Manage)) mcmpApis.GET("/test/mc-infra-manager/getallns", mcmpApiHandler.TestCallGetAllNs, middleware.PlatformRoleMiddleware(middleware.Manage)) mcmpApis.PUT("/name/:serviceName", mcmpApiHandler.UpdateFrameworkService, middleware.PlatformRoleMiddleware(middleware.Manage)) + mcmpApis.POST("/import", mcmpApiHandler.ImportAPIs, middleware.PlatformRoleMiddleware(middleware.Manage)) } // MCMP API 권한-액션 매핑 라우트 @@ -386,6 +402,47 @@ func main() { mcmpApiPermissionActionMappings.DELETE("/permissions/:permissionId/actions/:actionId", mcmpApiPermissionActionMappingHandler.DeleteMapping, middleware.PlatformRoleMiddleware(middleware.Manage)) } + // CSP 계정 관리 라우트 + cspAccounts := api.Group("/csp-accounts", middleware.PlatformRoleMiddleware(middleware.Read)) + { + cspAccounts.POST("/list", cspAccountHandler.ListCspAccounts) + cspAccounts.POST("", cspAccountHandler.CreateCspAccount, middleware.PlatformAdminMiddleware) + cspAccounts.GET("/id/:accountId", cspAccountHandler.GetCspAccountByID) + cspAccounts.PUT("/id/:accountId", cspAccountHandler.UpdateCspAccount, middleware.PlatformAdminMiddleware) + cspAccounts.DELETE("/id/:accountId", cspAccountHandler.DeleteCspAccount, middleware.PlatformAdminMiddleware) + cspAccounts.POST("/id/:accountId/validate", cspAccountHandler.ValidateCspAccount, middleware.PlatformAdminMiddleware) + cspAccounts.POST("/id/:accountId/activate", cspAccountHandler.ActivateCspAccount, middleware.PlatformAdminMiddleware) + cspAccounts.POST("/id/:accountId/deactivate", cspAccountHandler.DeactivateCspAccount, middleware.PlatformAdminMiddleware) + } + + // CSP IDP 설정 관리 라우트 + cspIdpConfigs := api.Group("/csp-idp-configs", middleware.PlatformRoleMiddleware(middleware.Read)) + { + cspIdpConfigs.POST("/list", cspIdpConfigHandler.ListCspIdpConfigs) + cspIdpConfigs.POST("", cspIdpConfigHandler.CreateCspIdpConfig, middleware.PlatformAdminMiddleware) + cspIdpConfigs.GET("/id/:configId", cspIdpConfigHandler.GetCspIdpConfigByID) + cspIdpConfigs.PUT("/id/:configId", cspIdpConfigHandler.UpdateCspIdpConfig, middleware.PlatformAdminMiddleware) + cspIdpConfigs.DELETE("/id/:configId", cspIdpConfigHandler.DeleteCspIdpConfig, middleware.PlatformAdminMiddleware) + cspIdpConfigs.POST("/id/:configId/test", cspIdpConfigHandler.TestCspIdpConnection, middleware.PlatformAdminMiddleware) + cspIdpConfigs.POST("/id/:configId/activate", cspIdpConfigHandler.ActivateCspIdpConfig, middleware.PlatformAdminMiddleware) + cspIdpConfigs.POST("/id/:configId/deactivate", cspIdpConfigHandler.DeactivateCspIdpConfig, middleware.PlatformAdminMiddleware) + } + + // CSP 정책 관리 라우트 + cspPolicies := api.Group("/csp-policies", middleware.PlatformRoleMiddleware(middleware.Read)) + { + cspPolicies.POST("/list", cspPolicyHandler.ListCspPolicies) + cspPolicies.POST("", cspPolicyHandler.CreateCspPolicy, middleware.PlatformAdminMiddleware) + cspPolicies.GET("/id/:policyId", cspPolicyHandler.GetCspPolicyByID) + cspPolicies.PUT("/id/:policyId", cspPolicyHandler.UpdateCspPolicy, middleware.PlatformAdminMiddleware) + cspPolicies.DELETE("/id/:policyId", cspPolicyHandler.DeleteCspPolicy, middleware.PlatformAdminMiddleware) + cspPolicies.GET("/id/:policyId/document", cspPolicyHandler.GetPolicyDocument) + cspPolicies.POST("/sync", cspPolicyHandler.SyncCspPolicies, middleware.PlatformAdminMiddleware) + cspPolicies.POST("/attach", cspPolicyHandler.AttachPolicyToRole, middleware.PlatformAdminMiddleware) + cspPolicies.POST("/detach", cspPolicyHandler.DetachPolicyFromRole, middleware.PlatformAdminMiddleware) + cspPolicies.GET("/role/:roleId", cspPolicyHandler.GetRolePolicies) + } + // Swagger 문서 라우트 e.GET("/swagger/*", echoSwagger.WrapHandler) diff --git a/src/model/csp_account.go b/src/model/csp_account.go new file mode 100644 index 00000000..e33566f0 --- /dev/null +++ b/src/model/csp_account.go @@ -0,0 +1,110 @@ +package model + +import ( + "time" +) + +// CspAccount CSP 계정 정보 모델 +// AWS Account ID, GCP Project ID, Azure Subscription ID 등 CSP별 계정 정보를 관리 +type CspAccount struct { + ID uint `gorm:"primaryKey" json:"id"` + Name string `gorm:"size:255;not null" json:"name"` + CspType string `gorm:"size:50;not null" json:"csp_type"` // aws, gcp, azure + AccountInfo map[string]string `gorm:"type:jsonb;serializer:json" json:"account_info"` + IsActive bool `gorm:"default:true" json:"is_active"` + Description string `gorm:"size:500" json:"description"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// TableName CspAccount 테이블 이름 반환 +func (CspAccount) TableName() string { + return "mcmp_csp_accounts" +} + +// CspAccountInfo CSP별 계정 정보 구조 +// AWS AccountInfo 예시: +// +// { +// "account_id": "050864702683", +// "alias": "my-aws-account", +// "region": "ap-northeast-2" +// } +// +// GCP AccountInfo 예시: +// +// { +// "project_id": "my-gcp-project", +// "project_number": "123456789" +// } +// +// Azure AccountInfo 예시: +// +// { +// "subscription_id": "xxx-xxx-xxx", +// "tenant_id": "yyy-yyy-yyy", +// "directory_id": "zzz-zzz-zzz" +// } + +// GetAccountID AWS Account ID 반환 +func (c *CspAccount) GetAccountID() string { + if c.AccountInfo == nil { + return "" + } + return c.AccountInfo["account_id"] +} + +// GetProjectID GCP Project ID 반환 +func (c *CspAccount) GetProjectID() string { + if c.AccountInfo == nil { + return "" + } + return c.AccountInfo["project_id"] +} + +// GetSubscriptionID Azure Subscription ID 반환 +func (c *CspAccount) GetSubscriptionID() string { + if c.AccountInfo == nil { + return "" + } + return c.AccountInfo["subscription_id"] +} + +// GetTenantID Azure Tenant ID 반환 +func (c *CspAccount) GetTenantID() string { + if c.AccountInfo == nil { + return "" + } + return c.AccountInfo["tenant_id"] +} + +// GetRegion 리전 정보 반환 +func (c *CspAccount) GetRegion() string { + if c.AccountInfo == nil { + return "" + } + return c.AccountInfo["region"] +} + +// CspAccountFilter CSP 계정 조회 필터 +type CspAccountFilter struct { + CspType string `json:"csp_type,omitempty"` + IsActive *bool `json:"is_active,omitempty"` + Name string `json:"name,omitempty"` +} + +// CreateCspAccountRequest CSP 계정 생성 요청 +type CreateCspAccountRequest struct { + Name string `json:"name" binding:"required"` + CspType string `json:"csp_type" binding:"required,oneof=aws gcp azure"` + AccountInfo map[string]string `json:"account_info"` + Description string `json:"description"` +} + +// UpdateCspAccountRequest CSP 계정 수정 요청 +type UpdateCspAccountRequest struct { + Name string `json:"name"` + AccountInfo map[string]string `json:"account_info"` + IsActive *bool `json:"is_active"` + Description string `json:"description"` +} diff --git a/src/model/csp_idp_config.go b/src/model/csp_idp_config.go new file mode 100644 index 00000000..e32f0618 --- /dev/null +++ b/src/model/csp_idp_config.go @@ -0,0 +1,274 @@ +package model + +import ( + "time" +) + +// AuthMethodType IDP 인증 방식 타입 +type AuthMethodType string + +const ( + AuthMethodOIDC AuthMethodType = "OIDC" + AuthMethodSAML AuthMethodType = "SAML" + AuthMethodSecretKey AuthMethodType = "SECRET_KEY" +) + +// CspIdpConfig CSP IDP 연동 설정 모델 +// OIDC, SAML, Secret Key 등 CSP별 IDP 연동 정보를 관리 +type CspIdpConfig struct { + ID uint `gorm:"primaryKey" json:"id"` + Name string `gorm:"size:255;not null" json:"name"` + CspAccountID uint `gorm:"not null" json:"csp_account_id"` + CspAccount *CspAccount `gorm:"foreignKey:CspAccountID" json:"csp_account,omitempty"` + AuthMethod AuthMethodType `gorm:"size:50;not null" json:"auth_method"` // OIDC, SAML, SECRET_KEY + Config map[string]string `gorm:"type:jsonb;serializer:json" json:"config"` + IsActive bool `gorm:"default:true" json:"is_active"` + Description string `gorm:"size:500" json:"description"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// TableName CspIdpConfig 테이블 이름 반환 +func (CspIdpConfig) TableName() string { + return "mcmp_csp_idp_configs" +} + +// CspIdpConfigInfo 인증 방식별 설정 정보 구조 +// OIDC Config 예시: +// +// { +// "oidc_provider_arn": "arn:aws:iam::050864702683:oidc-provider/keycloak.example.com", +// "audience": "mciam-client", +// "sts_endpoint": "https://sts.amazonaws.com" +// } +// +// SAML Config 예시: +// +// AWS SAML: +// +// { +// "saml_provider_arn": "arn:aws:iam::050864702683:saml-provider/keycloak", +// "sso_service_location": "https://devkc.onecloudcon.com/realms/saml-demo/protocol/saml", +// "issuer_url": "https://devkc.onecloudcon.com/realms/saml-demo", +// "signin_url": "https://signin.aws.amazon.com/saml/acs/SAMLSPD9IMTW2LM46J042K", +// "metadata_url": "https://signin.aws.amazon.com/static/saml/SAMLSPD9IMTW2LM46J042K/saml-metadata.xml", +// "valid_until": "2125-02-20" +// } +// +// GCP SAML: +// +// { +// "saml_provider_resource_name": "projects/123456789/locations/global/workloadIdentityPools/mciam-pool/providers/keycloak-saml", +// "sso_service_location": "https://devkc.onecloudcon.com/realms/gcp-demo/protocol/saml", +// "issuer_url": "https://devkc.onecloudcon.com/realms/gcp-demo", +// "audience": "//iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/mciam-pool/providers/keycloak-saml", +// "metadata_url": "https://devkc.onecloudcon.com/realms/gcp-demo/protocol/saml/descriptor" +// } +// +// Azure SAML: +// +// { +// "application_id": "12345678-1234-1234-1234-123456789012", +// "tenant_id": "87654321-4321-4321-4321-210987654321", +// "sso_service_location": "https://devkc.onecloudcon.com/realms/azure-demo/protocol/saml", +// "issuer_url": "https://devkc.onecloudcon.com/realms/azure-demo", +// "reply_url": "https://login.microsoftonline.com/login/saml2", +// "metadata_url": "https://login.microsoftonline.com/TENANT_ID/federationmetadata/2007-06/federationmetadata.xml", +// "federated_credential_id": "credential-12345" +// } +// +// SECRET_KEY Config 예시: +// +// { +// "access_key_id": "AKIAIOSFODNN7EXAMPLE", +// "secret_access_key": "encrypted_value", +// "encrypted": "true" +// } + +// GetOidcProviderArn OIDC Provider ARN 반환 +func (c *CspIdpConfig) GetOidcProviderArn() string { + if c.Config == nil { + return "" + } + return c.Config["oidc_provider_arn"] +} + +// GetAudience OIDC Audience 반환 +func (c *CspIdpConfig) GetAudience() string { + if c.Config == nil { + return "" + } + return c.Config["audience"] +} + +// GetStsEndpoint STS Endpoint 반환 +func (c *CspIdpConfig) GetStsEndpoint() string { + if c.Config == nil { + return "" + } + return c.Config["sts_endpoint"] +} + +// GetSamlProviderArn SAML Provider ARN 반환 (AWS) +func (c *CspIdpConfig) GetSamlProviderArn() string { + if c.Config == nil { + return "" + } + return c.Config["saml_provider_arn"] +} + +// ========== Common SAML Fields (All CSPs) ========== + +// GetSsoServiceLocation SSO Service Location 반환 (SAML) +func (c *CspIdpConfig) GetSsoServiceLocation() string { + if c.Config == nil { + return "" + } + // Prefer sso_service_location, fallback to assertion_endpoint for backward compatibility + if loc := c.Config["sso_service_location"]; loc != "" { + return loc + } + return c.Config["assertion_endpoint"] +} + +// GetIssuerUrl Issuer URL 반환 (SAML) +func (c *CspIdpConfig) GetIssuerUrl() string { + if c.Config == nil { + return "" + } + return c.Config["issuer_url"] +} + +// GetMetadataUrl SAML Metadata Document URL 반환 +func (c *CspIdpConfig) GetMetadataUrl() string { + if c.Config == nil { + return "" + } + return c.Config["metadata_url"] +} + +// ========== AWS-Specific SAML Fields ========== + +// GetSigninUrl AWS SAML Sign-in URL (ACS endpoint) 반환 +func (c *CspIdpConfig) GetSigninUrl() string { + if c.Config == nil { + return "" + } + return c.Config["signin_url"] +} + +// GetValidUntil SAML Assertion Valid Until Date 반환 (AWS) +func (c *CspIdpConfig) GetValidUntil() string { + if c.Config == nil { + return "" + } + return c.Config["valid_until"] +} + +// ========== GCP-Specific SAML Fields ========== + +// GetSamlProviderResourceName GCP SAML Provider Resource Name 반환 +func (c *CspIdpConfig) GetSamlProviderResourceName() string { + if c.Config == nil { + return "" + } + return c.Config["saml_provider_resource_name"] +} + +// ========== Azure-Specific SAML Fields ========== + +// GetApplicationId Azure AD Application ID 반환 +func (c *CspIdpConfig) GetApplicationId() string { + if c.Config == nil { + return "" + } + return c.Config["application_id"] +} + +// GetTenantId Azure AD Tenant ID 반환 +func (c *CspIdpConfig) GetTenantId() string { + if c.Config == nil { + return "" + } + return c.Config["tenant_id"] +} + +// GetReplyUrl Azure AD Reply URL 반환 +func (c *CspIdpConfig) GetReplyUrl() string { + if c.Config == nil { + return "" + } + return c.Config["reply_url"] +} + +// GetFederatedCredentialId Azure Federated Credential ID 반환 +func (c *CspIdpConfig) GetFederatedCredentialId() string { + if c.Config == nil { + return "" + } + return c.Config["federated_credential_id"] +} + +// GetAccessKeyID Secret Key Access Key ID 반환 +func (c *CspIdpConfig) GetAccessKeyID() string { + if c.Config == nil { + return "" + } + return c.Config["access_key_id"] +} + +// GetSecretAccessKey Secret Key Secret Access Key 반환 (암호화된 값) +func (c *CspIdpConfig) GetSecretAccessKey() string { + if c.Config == nil { + return "" + } + return c.Config["secret_access_key"] +} + +// IsEncrypted Secret Key 암호화 여부 확인 +func (c *CspIdpConfig) IsEncrypted() bool { + if c.Config == nil { + return false + } + return c.Config["encrypted"] == "true" +} + +// IsOIDC OIDC 인증 방식인지 확인 +func (c *CspIdpConfig) IsOIDC() bool { + return c.AuthMethod == AuthMethodOIDC +} + +// IsSAML SAML 인증 방식인지 확인 +func (c *CspIdpConfig) IsSAML() bool { + return c.AuthMethod == AuthMethodSAML +} + +// IsSecretKey Secret Key 인증 방식인지 확인 +func (c *CspIdpConfig) IsSecretKey() bool { + return c.AuthMethod == AuthMethodSecretKey +} + +// CspIdpConfigFilter CSP IDP 설정 조회 필터 +type CspIdpConfigFilter struct { + CspAccountID *uint `json:"csp_account_id,omitempty"` + AuthMethod AuthMethodType `json:"auth_method,omitempty"` + IsActive *bool `json:"is_active,omitempty"` + Name string `json:"name,omitempty"` +} + +// CreateCspIdpConfigRequest CSP IDP 설정 생성 요청 +type CreateCspIdpConfigRequest struct { + Name string `json:"name" binding:"required"` + CspAccountID uint `json:"csp_account_id" binding:"required"` + AuthMethod AuthMethodType `json:"auth_method" binding:"required,oneof=OIDC SAML SECRET_KEY"` + Config map[string]string `json:"config" binding:"required"` + Description string `json:"description"` +} + +// UpdateCspIdpConfigRequest CSP IDP 설정 수정 요청 +type UpdateCspIdpConfigRequest struct { + Name string `json:"name"` + Config map[string]string `json:"config"` + IsActive *bool `json:"is_active"` + Description string `json:"description"` +} diff --git a/src/model/csp_policy.go b/src/model/csp_policy.go new file mode 100644 index 00000000..835065d5 --- /dev/null +++ b/src/model/csp_policy.go @@ -0,0 +1,152 @@ +package model + +import ( + "time" +) + +// PolicyType 정책 타입 +type PolicyType string + +const ( + PolicyTypeInline PolicyType = "inline" // 인라인 정책 (역할에 직접 포함) + PolicyTypeManaged PolicyType = "managed" // 관리형 정책 (독립 정책) + PolicyTypeCustom PolicyType = "custom" // 사용자 정의 정책 +) + +// CspPolicy CSP 정책 모델 +// AWS IAM Policy, GCP IAM Role, Azure Role Definition 등을 관리 +type CspPolicy struct { + ID uint `gorm:"primaryKey" json:"id"` + Name string `gorm:"size:255;not null" json:"name"` + CspAccountID uint `gorm:"not null" json:"csp_account_id"` + CspAccount *CspAccount `gorm:"foreignKey:CspAccountID" json:"csp_account,omitempty"` + PolicyType PolicyType `gorm:"size:50;not null" json:"policy_type"` // inline, managed, custom + PolicyArn string `gorm:"size:500" json:"policy_arn,omitempty"` + PolicyDoc map[string]interface{} `gorm:"type:jsonb;serializer:json" json:"policy_doc,omitempty"` + Description string `gorm:"size:500" json:"description"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// TableName CspPolicy 테이블 이름 반환 +func (CspPolicy) TableName() string { + return "mcmp_csp_policies" +} + +// CspRolePolicyMapping CSP 역할-정책 매핑 모델 +type CspRolePolicyMapping struct { + CspRoleID uint `gorm:"primaryKey" json:"csp_role_id"` + CspPolicyID uint `gorm:"primaryKey" json:"csp_policy_id"` + CspRole *CspRole `gorm:"foreignKey:CspRoleID" json:"csp_role,omitempty"` + CspPolicy *CspPolicy `gorm:"foreignKey:CspPolicyID" json:"csp_policy,omitempty"` + CreatedAt time.Time `json:"created_at"` +} + +// TableName CspRolePolicyMapping 테이블 이름 반환 +func (CspRolePolicyMapping) TableName() string { + return "mcmp_csp_role_policy_mappings" +} + +// PolicyDocument AWS IAM Policy Document 구조 +// PolicyDoc 예시 (AWS): +// +// { +// "Version": "2012-10-17", +// "Statement": [ +// { +// "Effect": "Allow", +// "Action": ["s3:GetObject", "s3:PutObject"], +// "Resource": ["arn:aws:s3:::my-bucket/*"] +// } +// ] +// } +// +// PolicyDoc 예시 (GCP): +// +// { +// "included_permissions": ["storage.objects.get", "storage.objects.create"], +// "stage": "GA" +// } +// +// PolicyDoc 예시 (Azure): +// +// { +// "actions": ["Microsoft.Storage/storageAccounts/read"], +// "not_actions": [], +// "data_actions": [], +// "not_data_actions": [] +// } + +// IsInline 인라인 정책인지 확인 +func (p *CspPolicy) IsInline() bool { + return p.PolicyType == PolicyTypeInline +} + +// IsManaged 관리형 정책인지 확인 +func (p *CspPolicy) IsManaged() bool { + return p.PolicyType == PolicyTypeManaged +} + +// IsCustom 사용자 정의 정책인지 확인 +func (p *CspPolicy) IsCustom() bool { + return p.PolicyType == PolicyTypeCustom +} + +// GetPolicyVersion 정책 버전 반환 (AWS) +func (p *CspPolicy) GetPolicyVersion() string { + if p.PolicyDoc == nil { + return "" + } + if version, ok := p.PolicyDoc["Version"].(string); ok { + return version + } + return "" +} + +// GetStatements 정책 Statement 반환 (AWS) +func (p *CspPolicy) GetStatements() []interface{} { + if p.PolicyDoc == nil { + return nil + } + if statements, ok := p.PolicyDoc["Statement"].([]interface{}); ok { + return statements + } + return nil +} + +// CspPolicyFilter CSP 정책 조회 필터 +type CspPolicyFilter struct { + CspAccountID *uint `json:"csp_account_id,omitempty"` + PolicyType PolicyType `json:"policy_type,omitempty"` + Name string `json:"name,omitempty"` +} + +// CreateCspPolicyRequest CSP 정책 생성 요청 +type CreateCspPolicyRequest struct { + Name string `json:"name" binding:"required"` + CspAccountID uint `json:"csp_account_id" binding:"required"` + PolicyType PolicyType `json:"policy_type" binding:"required,oneof=inline managed custom"` + PolicyArn string `json:"policy_arn"` + PolicyDoc map[string]interface{} `json:"policy_doc"` + Description string `json:"description"` +} + +// UpdateCspPolicyRequest CSP 정책 수정 요청 +type UpdateCspPolicyRequest struct { + Name string `json:"name"` + PolicyArn string `json:"policy_arn"` + PolicyDoc map[string]interface{} `json:"policy_doc"` + Description string `json:"description"` +} + +// AttachPolicyRequest 정책 연결 요청 +type AttachPolicyRequest struct { + CspRoleID uint `json:"csp_role_id" binding:"required"` + CspPolicyID uint `json:"csp_policy_id" binding:"required"` +} + +// SyncPoliciesRequest 정책 동기화 요청 +type SyncPoliciesRequest struct { + CspAccountID uint `json:"csp_account_id" binding:"required"` + PolicyScope string `json:"policy_scope"` // All, AWS, Local +} diff --git a/src/model/csp_role.go b/src/model/csp_role.go index 70a2d95f..66fa6d35 100644 --- a/src/model/csp_role.go +++ b/src/model/csp_role.go @@ -17,7 +17,9 @@ type Tag struct { } // CspRole CSP 역할 모델 -// 대상 CSP와 연결하기 위한 연결정보(AWS에 OIDC로 연결되는 경우 제대로 동작. TODO: SAML을 추가했을 때 Table형태나 다른Table을 추가하게 될 수 있음) +// 대상 CSP와 연결하기 위한 연결정보 +// CspAccount: CSP 계정 정보 참조 +// CspIdpConfig: IDP 연동 설정 참조 (OIDC, SAML, SECRET_KEY) type CspRole struct { ID uint `gorm:"primaryKey" json:"id"` Name string `gorm:"size:255;not null" json:"name"` @@ -34,9 +36,17 @@ type CspRole struct { PermissionsBoundary string `gorm:"size:255" json:"permissions_boundary"` RoleLastUsed *RoleLastUsed `gorm:"type:jsonb;serializer:json" json:"role_last_used"` Tags []Tag `gorm:"-" json:"tags"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - DeletedAt *time.Time `json:"deleted_at" gorm:"index"` + + // CSP 계정 및 IDP 설정 참조 (신규 추가) + CspAccountID *uint `gorm:"column:csp_account_id" json:"csp_account_id"` + CspAccount *CspAccount `gorm:"foreignKey:CspAccountID" json:"csp_account,omitempty"` + CspIdpConfigID *uint `gorm:"column:csp_idp_config_id" json:"csp_idp_config_id"` + CspIdpConfig *CspIdpConfig `gorm:"foreignKey:CspIdpConfigID" json:"csp_idp_config,omitempty"` + ExtendedConfig map[string]interface{} `gorm:"type:jsonb;serializer:json" json:"extended_config,omitempty"` + + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt *time.Time `json:"deleted_at" gorm:"index"` } func (CspRole) TableName() string { // Renamed receiver diff --git a/src/model/mcmpapi/mcmpapi_service_meta.go b/src/model/mcmpapi/mcmpapi_service_meta.go new file mode 100644 index 00000000..8dfba816 --- /dev/null +++ b/src/model/mcmpapi/mcmpapi_service_meta.go @@ -0,0 +1,18 @@ +package mcmpapi + +import "time" + +// McmpApiServiceMeta stores version metadata for each service from _meta section +type McmpApiServiceMeta struct { + ServiceName string `gorm:"primaryKey;column:service_name;type:varchar(100)"` + Version string `gorm:"column:version;type:varchar(50)"` + Repository string `gorm:"column:repository;type:varchar(255)"` + GeneratedAt time.Time `gorm:"column:generated_at"` + SyncedAt time.Time `gorm:"column:synced_at;autoUpdateTime"` + CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"` +} + +// TableName returns the table name for GORM +func (McmpApiServiceMeta) TableName() string { + return "mcmp_api_service_meta" +} diff --git a/src/model/request.go b/src/model/request.go index 392b889a..ec3d64b1 100644 --- a/src/model/request.go +++ b/src/model/request.go @@ -27,6 +27,7 @@ type ProjectFilterRequest struct { type CreateProjectRequest struct { Name string `json:"name" validate:"required"` Description string `json:"description"` + WorkspaceID string `json:"workspaceId,omitempty"` // optional workspace to assign project to } // McmpApiRequestParams defines the structure for parameters needed in an API call. @@ -227,3 +228,38 @@ type FilterRoleMasterMappingRequest struct { CspType string `json:"cspType,omitempty"` AuthMethod string `json:"authMethod,omitempty"` } + +// ImportApiFramework represents a single framework to import +type ImportApiFramework struct { + Name string `json:"name" validate:"required"` // Framework name (e.g., "mc-infra-manager") + Version string `json:"version" validate:"required"` // Framework version (e.g., "0.9.22") + Repository string `json:"repository,omitempty"` // Repository URL (e.g., "https://github.com/...") + SourceType string `json:"sourceType" validate:"required"` // Source type: "swagger" or "openapi" + SourceURL string `json:"sourceUrl" validate:"required"` // URL to fetch the API specification from + BaseURL string `json:"baseUrl,omitempty"` // Base URL for the service (e.g., "http://localhost:1323/tumblebug") + AuthType string `json:"authType,omitempty"` // Authentication type: "none", "basic", "bearer" + AuthUser string `json:"authUser,omitempty"` // Username for basic auth + AuthPass string `json:"authPass,omitempty"` // Password for basic auth or token for bearer auth +} + +// ImportApiRequest represents the request body for importing APIs from remote sources +type ImportApiRequest struct { + Frameworks []ImportApiFramework `json:"frameworks" validate:"required,min=1"` +} + +// ImportApiFrameworkResult represents the result of importing a single framework +type ImportApiFrameworkResult struct { + Name string `json:"name"` // Framework name + Version string `json:"version"` // Framework version + Success bool `json:"success"` // Whether the import was successful + ActionCount int `json:"actionCount,omitempty"` // Number of actions imported (on success) + ErrorMessage string `json:"errorMessage,omitempty"` // Error message (on failure) +} + +// ImportApiResponse represents the response body for importing APIs +type ImportApiResponse struct { + TotalFrameworks int `json:"totalFrameworks"` // Total number of frameworks in request + SuccessCount int `json:"successCount"` // Number of successfully imported frameworks + FailureCount int `json:"failureCount"` // Number of failed frameworks + FrameworkResults []ImportApiFrameworkResult `json:"frameworkResults"` // Detailed results for each framework +} diff --git a/src/repository/csp_account_repository.go b/src/repository/csp_account_repository.go new file mode 100644 index 00000000..82719723 --- /dev/null +++ b/src/repository/csp_account_repository.go @@ -0,0 +1,150 @@ +package repository + +import ( + "fmt" + + "github.com/m-cmp/mc-iam-manager/model" + "gorm.io/gorm" +) + +// CspAccountRepository CSP 계정 레포지토리 +type CspAccountRepository struct { + db *gorm.DB +} + +// NewCspAccountRepository 새 CspAccountRepository 인스턴스 생성 +func NewCspAccountRepository(db *gorm.DB) *CspAccountRepository { + return &CspAccountRepository{db: db} +} + +// Create CSP 계정 생성 +func (r *CspAccountRepository) Create(account *model.CspAccount) error { + if err := r.db.Create(account).Error; err != nil { + return fmt.Errorf("failed to create CSP account: %w", err) + } + return nil +} + +// GetByID ID로 CSP 계정 조회 +func (r *CspAccountRepository) GetByID(id uint) (*model.CspAccount, error) { + var account model.CspAccount + if err := r.db.First(&account, id).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP account by ID: %w", err) + } + return &account, nil +} + +// GetByName 이름으로 CSP 계정 조회 +func (r *CspAccountRepository) GetByName(name string) (*model.CspAccount, error) { + var account model.CspAccount + if err := r.db.Where("name = ?", name).First(&account).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP account by name: %w", err) + } + return &account, nil +} + +// GetByNameAndCspType 이름과 CSP 타입으로 CSP 계정 조회 +func (r *CspAccountRepository) GetByNameAndCspType(name string, cspType string) (*model.CspAccount, error) { + var account model.CspAccount + if err := r.db.Where("name = ? AND csp_type = ?", name, cspType).First(&account).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + return &account, nil +} + +// List CSP 계정 목록 조회 +func (r *CspAccountRepository) List(filter *model.CspAccountFilter) ([]*model.CspAccount, error) { + var accounts []*model.CspAccount + query := r.db.Model(&model.CspAccount{}) + + if filter != nil { + if filter.CspType != "" { + query = query.Where("csp_type = ?", filter.CspType) + } + if filter.IsActive != nil { + query = query.Where("is_active = ?", *filter.IsActive) + } + if filter.Name != "" { + query = query.Where("name LIKE ?", "%"+filter.Name+"%") + } + } + + if err := query.Order("created_at DESC").Find(&accounts).Error; err != nil { + return nil, fmt.Errorf("failed to list CSP accounts: %w", err) + } + return accounts, nil +} + +// Update CSP 계정 수정 +func (r *CspAccountRepository) Update(account *model.CspAccount) error { + if err := r.db.Save(account).Error; err != nil { + return fmt.Errorf("failed to update CSP account: %w", err) + } + return nil +} + +// Delete CSP 계정 삭제 +func (r *CspAccountRepository) Delete(id uint) error { + result := r.db.Delete(&model.CspAccount{}, id) + if result.Error != nil { + return fmt.Errorf("failed to delete CSP account: %w", result.Error) + } + if result.RowsAffected == 0 { + return fmt.Errorf("CSP account not found") + } + return nil +} + +// ExistsByID ID로 CSP 계정 존재 여부 확인 +func (r *CspAccountRepository) ExistsByID(id uint) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspAccount{}).Where("id = ?", id).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP account existence: %w", err) + } + return count > 0, nil +} + +// ExistsByName 이름으로 CSP 계정 존재 여부 확인 +func (r *CspAccountRepository) ExistsByName(name string) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspAccount{}).Where("name = ?", name).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP account existence: %w", err) + } + return count > 0, nil +} + +// ExistsByNameAndCspType 이름과 CSP 타입으로 CSP 계정 존재 여부 확인 +func (r *CspAccountRepository) ExistsByNameAndCspType(name string, cspType string) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspAccount{}).Where("name = ? AND csp_type = ?", name, cspType).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP account existence: %w", err) + } + return count > 0, nil +} + +// GetActiveAccounts 활성 CSP 계정 목록 조회 +func (r *CspAccountRepository) GetActiveAccounts() ([]*model.CspAccount, error) { + var accounts []*model.CspAccount + if err := r.db.Where("is_active = ?", true).Find(&accounts).Error; err != nil { + return nil, fmt.Errorf("failed to get active CSP accounts: %w", err) + } + return accounts, nil +} + +// GetByCspType CSP 타입으로 계정 목록 조회 +func (r *CspAccountRepository) GetByCspType(cspType string) ([]*model.CspAccount, error) { + var accounts []*model.CspAccount + if err := r.db.Where("csp_type = ?", cspType).Find(&accounts).Error; err != nil { + return nil, fmt.Errorf("failed to get CSP accounts by type: %w", err) + } + return accounts, nil +} diff --git a/src/repository/csp_idp_config_repository.go b/src/repository/csp_idp_config_repository.go new file mode 100644 index 00000000..40ea243c --- /dev/null +++ b/src/repository/csp_idp_config_repository.go @@ -0,0 +1,180 @@ +package repository + +import ( + "fmt" + + "github.com/m-cmp/mc-iam-manager/model" + "gorm.io/gorm" +) + +// CspIdpConfigRepository CSP IDP 설정 레포지토리 +type CspIdpConfigRepository struct { + db *gorm.DB +} + +// NewCspIdpConfigRepository 새 CspIdpConfigRepository 인스턴스 생성 +func NewCspIdpConfigRepository(db *gorm.DB) *CspIdpConfigRepository { + return &CspIdpConfigRepository{db: db} +} + +// Create CSP IDP 설정 생성 +func (r *CspIdpConfigRepository) Create(config *model.CspIdpConfig) error { + if err := r.db.Create(config).Error; err != nil { + return fmt.Errorf("failed to create CSP IDP config: %w", err) + } + return nil +} + +// GetByID ID로 CSP IDP 설정 조회 +func (r *CspIdpConfigRepository) GetByID(id uint) (*model.CspIdpConfig, error) { + var config model.CspIdpConfig + if err := r.db.Preload("CspAccount").First(&config, id).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP IDP config by ID: %w", err) + } + return &config, nil +} + +// GetByName 이름으로 CSP IDP 설정 조회 +func (r *CspIdpConfigRepository) GetByName(name string) (*model.CspIdpConfig, error) { + var config model.CspIdpConfig + if err := r.db.Preload("CspAccount").Where("name = ?", name).First(&config).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP IDP config by name: %w", err) + } + return &config, nil +} + +// GetByNameAndAccountID 이름과 계정 ID로 CSP IDP 설정 조회 +func (r *CspIdpConfigRepository) GetByNameAndAccountID(name string, accountID uint) (*model.CspIdpConfig, error) { + var config model.CspIdpConfig + if err := r.db.Preload("CspAccount").Where("name = ? AND csp_account_id = ?", name, accountID).First(&config).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP IDP config: %w", err) + } + return &config, nil +} + +// List CSP IDP 설정 목록 조회 +func (r *CspIdpConfigRepository) List(filter *model.CspIdpConfigFilter) ([]*model.CspIdpConfig, error) { + var configs []*model.CspIdpConfig + query := r.db.Model(&model.CspIdpConfig{}).Preload("CspAccount") + + if filter != nil { + if filter.CspAccountID != nil { + query = query.Where("csp_account_id = ?", *filter.CspAccountID) + } + if filter.AuthMethod != "" { + query = query.Where("auth_method = ?", filter.AuthMethod) + } + if filter.IsActive != nil { + query = query.Where("is_active = ?", *filter.IsActive) + } + if filter.Name != "" { + query = query.Where("name LIKE ?", "%"+filter.Name+"%") + } + } + + if err := query.Order("created_at DESC").Find(&configs).Error; err != nil { + return nil, fmt.Errorf("failed to list CSP IDP configs: %w", err) + } + return configs, nil +} + +// Update CSP IDP 설정 수정 +func (r *CspIdpConfigRepository) Update(config *model.CspIdpConfig) error { + if err := r.db.Save(config).Error; err != nil { + return fmt.Errorf("failed to update CSP IDP config: %w", err) + } + return nil +} + +// Delete CSP IDP 설정 삭제 +func (r *CspIdpConfigRepository) Delete(id uint) error { + result := r.db.Delete(&model.CspIdpConfig{}, id) + if result.Error != nil { + return fmt.Errorf("failed to delete CSP IDP config: %w", result.Error) + } + if result.RowsAffected == 0 { + return fmt.Errorf("CSP IDP config not found") + } + return nil +} + +// ExistsByID ID로 CSP IDP 설정 존재 여부 확인 +func (r *CspIdpConfigRepository) ExistsByID(id uint) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspIdpConfig{}).Where("id = ?", id).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP IDP config existence: %w", err) + } + return count > 0, nil +} + +// ExistsByName 이름으로 CSP IDP 설정 존재 여부 확인 +func (r *CspIdpConfigRepository) ExistsByName(name string) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspIdpConfig{}).Where("name = ?", name).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP IDP config existence: %w", err) + } + return count > 0, nil +} + +// ExistsByNameAndAccountID 이름과 계정 ID로 CSP IDP 설정 존재 여부 확인 +func (r *CspIdpConfigRepository) ExistsByNameAndAccountID(name string, accountID uint) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspIdpConfig{}).Where("name = ? AND csp_account_id = ?", name, accountID).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP IDP config existence: %w", err) + } + return count > 0, nil +} + +// GetByAccountID 계정 ID로 CSP IDP 설정 목록 조회 +func (r *CspIdpConfigRepository) GetByAccountID(accountID uint) ([]*model.CspIdpConfig, error) { + var configs []*model.CspIdpConfig + if err := r.db.Preload("CspAccount").Where("csp_account_id = ?", accountID).Find(&configs).Error; err != nil { + return nil, fmt.Errorf("failed to get CSP IDP configs by account ID: %w", err) + } + return configs, nil +} + +// GetActiveConfigs 활성 CSP IDP 설정 목록 조회 +func (r *CspIdpConfigRepository) GetActiveConfigs() ([]*model.CspIdpConfig, error) { + var configs []*model.CspIdpConfig + if err := r.db.Preload("CspAccount").Where("is_active = ?", true).Find(&configs).Error; err != nil { + return nil, fmt.Errorf("failed to get active CSP IDP configs: %w", err) + } + return configs, nil +} + +// GetActiveByAccountID 특정 계정의 활성 CSP IDP 설정 목록 조회 +func (r *CspIdpConfigRepository) GetActiveByAccountID(accountID uint) ([]*model.CspIdpConfig, error) { + var configs []*model.CspIdpConfig + if err := r.db.Preload("CspAccount").Where("csp_account_id = ? AND is_active = ?", accountID, true).Find(&configs).Error; err != nil { + return nil, fmt.Errorf("failed to get active CSP IDP configs by account ID: %w", err) + } + return configs, nil +} + +// GetByAuthMethod 인증 방식으로 CSP IDP 설정 목록 조회 +func (r *CspIdpConfigRepository) GetByAuthMethod(authMethod model.AuthMethodType) ([]*model.CspIdpConfig, error) { + var configs []*model.CspIdpConfig + if err := r.db.Preload("CspAccount").Where("auth_method = ?", authMethod).Find(&configs).Error; err != nil { + return nil, fmt.Errorf("failed to get CSP IDP configs by auth method: %w", err) + } + return configs, nil +} + +// CountByAccountID 특정 계정의 CSP IDP 설정 개수 조회 +func (r *CspIdpConfigRepository) CountByAccountID(accountID uint) (int64, error) { + var count int64 + if err := r.db.Model(&model.CspIdpConfig{}).Where("csp_account_id = ?", accountID).Count(&count).Error; err != nil { + return 0, fmt.Errorf("failed to count CSP IDP configs: %w", err) + } + return count, nil +} diff --git a/src/repository/csp_policy_repository.go b/src/repository/csp_policy_repository.go new file mode 100644 index 00000000..f74dfa66 --- /dev/null +++ b/src/repository/csp_policy_repository.go @@ -0,0 +1,262 @@ +package repository + +import ( + "fmt" + + "github.com/m-cmp/mc-iam-manager/model" + "gorm.io/gorm" +) + +// CspPolicyRepository CSP 정책 레포지토리 +type CspPolicyRepository struct { + db *gorm.DB +} + +// NewCspPolicyRepository 새 CspPolicyRepository 인스턴스 생성 +func NewCspPolicyRepository(db *gorm.DB) *CspPolicyRepository { + return &CspPolicyRepository{db: db} +} + +// Create CSP 정책 생성 +func (r *CspPolicyRepository) Create(policy *model.CspPolicy) error { + if err := r.db.Create(policy).Error; err != nil { + return fmt.Errorf("failed to create CSP policy: %w", err) + } + return nil +} + +// GetByID ID로 CSP 정책 조회 +func (r *CspPolicyRepository) GetByID(id uint) (*model.CspPolicy, error) { + var policy model.CspPolicy + if err := r.db.Preload("CspAccount").First(&policy, id).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP policy by ID: %w", err) + } + return &policy, nil +} + +// GetByName 이름으로 CSP 정책 조회 +func (r *CspPolicyRepository) GetByName(name string) (*model.CspPolicy, error) { + var policy model.CspPolicy + if err := r.db.Preload("CspAccount").Where("name = ?", name).First(&policy).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP policy by name: %w", err) + } + return &policy, nil +} + +// GetByArn ARN으로 CSP 정책 조회 +func (r *CspPolicyRepository) GetByArn(arn string) (*model.CspPolicy, error) { + var policy model.CspPolicy + if err := r.db.Preload("CspAccount").Where("policy_arn = ?", arn).First(&policy).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP policy by ARN: %w", err) + } + return &policy, nil +} + +// GetByNameAndAccountID 이름과 계정 ID로 CSP 정책 조회 +func (r *CspPolicyRepository) GetByNameAndAccountID(name string, accountID uint) (*model.CspPolicy, error) { + var policy model.CspPolicy + if err := r.db.Preload("CspAccount").Where("name = ? AND csp_account_id = ?", name, accountID).First(&policy).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get CSP policy: %w", err) + } + return &policy, nil +} + +// List CSP 정책 목록 조회 +func (r *CspPolicyRepository) List(filter *model.CspPolicyFilter) ([]*model.CspPolicy, error) { + var policies []*model.CspPolicy + query := r.db.Model(&model.CspPolicy{}).Preload("CspAccount") + + if filter != nil { + if filter.CspAccountID != nil { + query = query.Where("csp_account_id = ?", *filter.CspAccountID) + } + if filter.PolicyType != "" { + query = query.Where("policy_type = ?", filter.PolicyType) + } + if filter.Name != "" { + query = query.Where("name LIKE ?", "%"+filter.Name+"%") + } + } + + if err := query.Order("created_at DESC").Find(&policies).Error; err != nil { + return nil, fmt.Errorf("failed to list CSP policies: %w", err) + } + return policies, nil +} + +// Update CSP 정책 수정 +func (r *CspPolicyRepository) Update(policy *model.CspPolicy) error { + if err := r.db.Save(policy).Error; err != nil { + return fmt.Errorf("failed to update CSP policy: %w", err) + } + return nil +} + +// Delete CSP 정책 삭제 +func (r *CspPolicyRepository) Delete(id uint) error { + // 트랜잭션으로 매핑 테이블도 함께 삭제 + return r.db.Transaction(func(tx *gorm.DB) error { + // 매핑 관계 삭제 + if err := tx.Where("csp_policy_id = ?", id).Delete(&model.CspRolePolicyMapping{}).Error; err != nil { + return fmt.Errorf("failed to delete policy mappings: %w", err) + } + + // 정책 삭제 + result := tx.Delete(&model.CspPolicy{}, id) + if result.Error != nil { + return fmt.Errorf("failed to delete CSP policy: %w", result.Error) + } + if result.RowsAffected == 0 { + return fmt.Errorf("CSP policy not found") + } + return nil + }) +} + +// ExistsByID ID로 CSP 정책 존재 여부 확인 +func (r *CspPolicyRepository) ExistsByID(id uint) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspPolicy{}).Where("id = ?", id).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP policy existence: %w", err) + } + return count > 0, nil +} + +// ExistsByName 이름으로 CSP 정책 존재 여부 확인 +func (r *CspPolicyRepository) ExistsByName(name string) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspPolicy{}).Where("name = ?", name).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP policy existence: %w", err) + } + return count > 0, nil +} + +// ExistsByArn ARN으로 CSP 정책 존재 여부 확인 +func (r *CspPolicyRepository) ExistsByArn(arn string) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspPolicy{}).Where("policy_arn = ?", arn).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP policy existence: %w", err) + } + return count > 0, nil +} + +// ExistsByNameAndAccountID 이름과 계정 ID로 CSP 정책 존재 여부 확인 +func (r *CspPolicyRepository) ExistsByNameAndAccountID(name string, accountID uint) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspPolicy{}).Where("name = ? AND csp_account_id = ?", name, accountID).Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check CSP policy existence: %w", err) + } + return count > 0, nil +} + +// GetByAccountID 계정 ID로 CSP 정책 목록 조회 +func (r *CspPolicyRepository) GetByAccountID(accountID uint) ([]*model.CspPolicy, error) { + var policies []*model.CspPolicy + if err := r.db.Preload("CspAccount").Where("csp_account_id = ?", accountID).Find(&policies).Error; err != nil { + return nil, fmt.Errorf("failed to get CSP policies by account ID: %w", err) + } + return policies, nil +} + +// GetByPolicyType 정책 타입으로 CSP 정책 목록 조회 +func (r *CspPolicyRepository) GetByPolicyType(policyType model.PolicyType) ([]*model.CspPolicy, error) { + var policies []*model.CspPolicy + if err := r.db.Preload("CspAccount").Where("policy_type = ?", policyType).Find(&policies).Error; err != nil { + return nil, fmt.Errorf("failed to get CSP policies by type: %w", err) + } + return policies, nil +} + +// AttachPolicyToRole 역할에 정책 연결 +func (r *CspPolicyRepository) AttachPolicyToRole(roleID, policyID uint) error { + mapping := model.CspRolePolicyMapping{ + CspRoleID: roleID, + CspPolicyID: policyID, + } + if err := r.db.Create(&mapping).Error; err != nil { + return fmt.Errorf("failed to attach policy to role: %w", err) + } + return nil +} + +// DetachPolicyFromRole 역할에서 정책 분리 +func (r *CspPolicyRepository) DetachPolicyFromRole(roleID, policyID uint) error { + result := r.db.Where("csp_role_id = ? AND csp_policy_id = ?", roleID, policyID).Delete(&model.CspRolePolicyMapping{}) + if result.Error != nil { + return fmt.Errorf("failed to detach policy from role: %w", result.Error) + } + if result.RowsAffected == 0 { + return fmt.Errorf("policy mapping not found") + } + return nil +} + +// GetPoliciesByRoleID 역할에 연결된 정책 목록 조회 +func (r *CspPolicyRepository) GetPoliciesByRoleID(roleID uint) ([]*model.CspPolicy, error) { + var policies []*model.CspPolicy + err := r.db. + Joins("JOIN mcmp_csp_role_policy_mappings ON mcmp_csp_role_policy_mappings.csp_policy_id = mcmp_csp_policies.id"). + Where("mcmp_csp_role_policy_mappings.csp_role_id = ?", roleID). + Preload("CspAccount"). + Find(&policies).Error + if err != nil { + return nil, fmt.Errorf("failed to get policies by role ID: %w", err) + } + return policies, nil +} + +// GetRolesByPolicyID 정책이 연결된 역할 목록 조회 +func (r *CspPolicyRepository) GetRolesByPolicyID(policyID uint) ([]*model.CspRole, error) { + var roles []*model.CspRole + err := r.db. + Joins("JOIN mcmp_csp_role_policy_mappings ON mcmp_csp_role_policy_mappings.csp_role_id = mcmp_role_csp_roles.id"). + Where("mcmp_csp_role_policy_mappings.csp_policy_id = ?", policyID). + Find(&roles).Error + if err != nil { + return nil, fmt.Errorf("failed to get roles by policy ID: %w", err) + } + return roles, nil +} + +// IsPolicyAttachedToRole 역할에 정책이 연결되어 있는지 확인 +func (r *CspPolicyRepository) IsPolicyAttachedToRole(roleID, policyID uint) (bool, error) { + var count int64 + if err := r.db.Model(&model.CspRolePolicyMapping{}). + Where("csp_role_id = ? AND csp_policy_id = ?", roleID, policyID). + Count(&count).Error; err != nil { + return false, fmt.Errorf("failed to check policy attachment: %w", err) + } + return count > 0, nil +} + +// CountByAccountID 특정 계정의 CSP 정책 개수 조회 +func (r *CspPolicyRepository) CountByAccountID(accountID uint) (int64, error) { + var count int64 + if err := r.db.Model(&model.CspPolicy{}).Where("csp_account_id = ?", accountID).Count(&count).Error; err != nil { + return 0, fmt.Errorf("failed to count CSP policies: %w", err) + } + return count, nil +} + +// GetManagedPoliciesByAccountID 특정 계정의 관리형 정책 목록 조회 +func (r *CspPolicyRepository) GetManagedPoliciesByAccountID(accountID uint) ([]*model.CspPolicy, error) { + var policies []*model.CspPolicy + if err := r.db.Preload("CspAccount"). + Where("csp_account_id = ? AND policy_type = ?", accountID, model.PolicyTypeManaged). + Find(&policies).Error; err != nil { + return nil, fmt.Errorf("failed to get managed policies: %w", err) + } + return policies, nil +} diff --git a/src/repository/mcmpapi_repository.go b/src/repository/mcmpapi_repository.go index c7d74352..f3c2b929 100644 --- a/src/repository/mcmpapi_repository.go +++ b/src/repository/mcmpapi_repository.go @@ -19,6 +19,11 @@ type McmpApiRepository interface { UpdateService(serviceName string, updates map[string]interface{}) error GetService(serviceName string) (*mcmpapi.McmpApiService, error) GetServiceAction(serviceName, actionName string) (*mcmpapi.McmpApiAction, error) + // New methods for upsert logic and version tracking + DeleteActionsByServiceName(tx *gorm.DB, serviceName string) error + GetServiceMeta(serviceName string) (*mcmpapi.McmpApiServiceMeta, error) + UpsertServiceMeta(tx *gorm.DB, meta *mcmpapi.McmpApiServiceMeta) error + UpsertService(tx *gorm.DB, service *mcmpapi.McmpApiService) error } // mcmpApiRepository implements the McmpApiRepository interface. @@ -337,3 +342,62 @@ func (r *mcmpApiRepository) GetActiveService(serviceName string) (*mcmpapi.McmpA return &service, nil } + +// DeleteActionsByServiceName deletes all actions for a service within a transaction. +func (r *mcmpApiRepository) DeleteActionsByServiceName(tx *gorm.DB, serviceName string) error { + query := tx.Where("service_name = ?", serviceName).Delete(&mcmpapi.McmpApiAction{}) + if err := query.Error; err != nil { + sql := query.Statement.SQL.String() + args := query.Statement.Vars + log.Printf("DeleteActionsByServiceName SQL Query (ERROR): %s", sql) + log.Printf("DeleteActionsByServiceName SQL Args (ERROR): %v", args) + return fmt.Errorf("failed to delete actions for service %s: %w", serviceName, err) + } + log.Printf("Deleted %d actions for service %s", query.RowsAffected, serviceName) + return nil +} + +// GetServiceMeta retrieves version metadata for a service. +func (r *mcmpApiRepository) GetServiceMeta(serviceName string) (*mcmpapi.McmpApiServiceMeta, error) { + var meta mcmpapi.McmpApiServiceMeta + query := r.db.Where("service_name = ?", serviceName).First(&meta) + if err := query.Error; err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + sql := query.Statement.SQL.String() + args := query.Statement.Vars + log.Printf("GetServiceMeta SQL Query (ERROR): %s", sql) + log.Printf("GetServiceMeta SQL Args (ERROR): %v", args) + } + return nil, err + } + return &meta, nil +} + +// UpsertServiceMeta creates or updates version metadata within a transaction. +func (r *mcmpApiRepository) UpsertServiceMeta(tx *gorm.DB, meta *mcmpapi.McmpApiServiceMeta) error { + // Use Save which does upsert based on primary key + query := tx.Save(meta) + if err := query.Error; err != nil { + sql := query.Statement.SQL.String() + args := query.Statement.Vars + log.Printf("UpsertServiceMeta SQL Query (ERROR): %s", sql) + log.Printf("UpsertServiceMeta SQL Args (ERROR): %v", args) + return fmt.Errorf("failed to upsert meta for service %s: %w", meta.ServiceName, err) + } + return nil +} + +// UpsertService creates or updates a service record within a transaction. +func (r *mcmpApiRepository) UpsertService(tx *gorm.DB, service *mcmpapi.McmpApiService) error { + // Use Save which does upsert based on primary key (Name) + query := tx.Save(service) + if err := query.Error; err != nil { + sql := query.Statement.SQL.String() + args := query.Statement.Vars + log.Printf("UpsertService SQL Query (ERROR): %s", sql) + log.Printf("UpsertService SQL Args (ERROR): %v", args) + return fmt.Errorf("failed to upsert service %s: %w", service.Name, err) + } + log.Printf("Upserted service: %s (version: %s, baseURL: %s)", service.Name, service.Version, service.BaseURL) + return nil +} diff --git a/src/repository/workspace_repository.go b/src/repository/workspace_repository.go index 7a183da0..44446a77 100644 --- a/src/repository/workspace_repository.go +++ b/src/repository/workspace_repository.go @@ -182,24 +182,23 @@ func (r *WorkspaceRepository) FindWorkspaceProjectsByWorkspaceID(id uint) (*mode // AddProjectAssociation add project association to workspace func (r *WorkspaceRepository) AddProjectAssociation(workspaceID, projectID uint) error { + // Remove all existing workspace associations for this project (1:N relationship enforcement) + // This ensures a project can only belong to one workspace at a time + result := r.db.Where("project_id = ?", projectID). + Delete(&model.WorkspaceProject{}) + if result.Error != nil { + return result.Error + } + + // Add new workspace association workspaceProject := &model.WorkspaceProject{ WorkspaceID: workspaceID, ProjectID: projectID, } - // If project was stored in default workspace, remove it from default workspace - if workspaceID != 1 { - result := r.db.Where("workspace_id = ? AND project_id = ?", 1, projectID). - Delete(&model.WorkspaceProject{}) - if result.Error != nil { - return result.Error - } - } - // Save directly to mcmp_workspace_projects table err := r.db.Save(workspaceProject).Error if err != nil { - return err } return nil @@ -207,9 +206,8 @@ func (r *WorkspaceRepository) AddProjectAssociation(workspaceID, projectID uint) // RemoveProjectAssociation remove project association from workspace func (r *WorkspaceRepository) RemoveProjectAssociation(workspaceID, projectID uint) error { - // Cannot remove from default workspace, and when removing connection from other workspaces, assign to default workspace - // Delete directly from mcmp_workspace_projects table + // 기본 workspace 포함 모든 workspace에서 제거 가능 result := r.db.Where("workspace_id = ? AND project_id = ?", workspaceID, projectID). Delete(&model.WorkspaceProject{}) @@ -217,24 +215,8 @@ func (r *WorkspaceRepository) RemoveProjectAssociation(workspaceID, projectID ui return result.Error } - workspaceProject := &model.WorkspaceProject{ - WorkspaceID: 1, // Default workspace ID - ProjectID: projectID, - } - - err := r.db.Save(workspaceProject).Error - if err != nil { - - return err - } - - // mcmp_workspace_projects 테이블에서 직접 삭제 - // result := r.db.Where("workspace_id = ? AND project_id = ?", workspaceID, projectID). - // Delete(&model.WorkspaceProject{}) - - // if result.Error != nil { - // return result.Error - // } + // 기본 workspace로 재할당하지 않음 + // 프로젝트가 미할당 상태가 될 수 있음 // Do not treat as error even if no records were deleted (relationship may not have existed) return nil diff --git a/src/service/csp_account_service.go b/src/service/csp_account_service.go new file mode 100644 index 00000000..23da0a8f --- /dev/null +++ b/src/service/csp_account_service.go @@ -0,0 +1,257 @@ +package service + +import ( + "fmt" + "log" + + "github.com/m-cmp/mc-iam-manager/model" + "github.com/m-cmp/mc-iam-manager/repository" + "gorm.io/gorm" +) + +// CspAccountService CSP 계정 서비스 +type CspAccountService struct { + db *gorm.DB + cspAccountRepo *repository.CspAccountRepository + cspIdpConfigRepo *repository.CspIdpConfigRepository + cspPolicyRepo *repository.CspPolicyRepository +} + +// NewCspAccountService 새 CspAccountService 인스턴스 생성 +func NewCspAccountService(db *gorm.DB) *CspAccountService { + return &CspAccountService{ + db: db, + cspAccountRepo: repository.NewCspAccountRepository(db), + cspIdpConfigRepo: repository.NewCspIdpConfigRepository(db), + cspPolicyRepo: repository.NewCspPolicyRepository(db), + } +} + +// CreateCspAccount CSP 계정 생성 +func (s *CspAccountService) CreateCspAccount(req *model.CreateCspAccountRequest) (*model.CspAccount, error) { + // 이름 중복 확인 + exists, err := s.cspAccountRepo.ExistsByNameAndCspType(req.Name, req.CspType) + if err != nil { + return nil, fmt.Errorf("failed to check CSP account existence: %w", err) + } + if exists { + return nil, fmt.Errorf("CSP account with name '%s' and type '%s' already exists", req.Name, req.CspType) + } + + // CSP 계정 생성 + account := &model.CspAccount{ + Name: req.Name, + CspType: req.CspType, + AccountInfo: req.AccountInfo, + IsActive: true, + Description: req.Description, + } + + if err := s.cspAccountRepo.Create(account); err != nil { + return nil, fmt.Errorf("failed to create CSP account: %w", err) + } + + log.Printf("Created CSP account: %s (type: %s)", account.Name, account.CspType) + return account, nil +} + +// GetCspAccountByID ID로 CSP 계정 조회 +func (s *CspAccountService) GetCspAccountByID(id uint) (*model.CspAccount, error) { + account, err := s.cspAccountRepo.GetByID(id) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return nil, fmt.Errorf("CSP account not found with ID: %d", id) + } + return account, nil +} + +// GetCspAccountByName 이름으로 CSP 계정 조회 +func (s *CspAccountService) GetCspAccountByName(name string) (*model.CspAccount, error) { + account, err := s.cspAccountRepo.GetByName(name) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + return account, nil +} + +// ListCspAccounts CSP 계정 목록 조회 +func (s *CspAccountService) ListCspAccounts(filter *model.CspAccountFilter) ([]*model.CspAccount, error) { + accounts, err := s.cspAccountRepo.List(filter) + if err != nil { + return nil, fmt.Errorf("failed to list CSP accounts: %w", err) + } + return accounts, nil +} + +// UpdateCspAccount CSP 계정 수정 +func (s *CspAccountService) UpdateCspAccount(id uint, req *model.UpdateCspAccountRequest) (*model.CspAccount, error) { + // 기존 계정 조회 + account, err := s.cspAccountRepo.GetByID(id) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return nil, fmt.Errorf("CSP account not found with ID: %d", id) + } + + // 필드 업데이트 + if req.Name != "" { + // 이름 변경 시 중복 확인 + if req.Name != account.Name { + exists, err := s.cspAccountRepo.ExistsByNameAndCspType(req.Name, account.CspType) + if err != nil { + return nil, fmt.Errorf("failed to check CSP account existence: %w", err) + } + if exists { + return nil, fmt.Errorf("CSP account with name '%s' already exists", req.Name) + } + } + account.Name = req.Name + } + if req.AccountInfo != nil { + account.AccountInfo = req.AccountInfo + } + if req.IsActive != nil { + account.IsActive = *req.IsActive + } + if req.Description != "" { + account.Description = req.Description + } + + if err := s.cspAccountRepo.Update(account); err != nil { + return nil, fmt.Errorf("failed to update CSP account: %w", err) + } + + log.Printf("Updated CSP account: %s (ID: %d)", account.Name, account.ID) + return account, nil +} + +// DeleteCspAccount CSP 계정 삭제 +func (s *CspAccountService) DeleteCspAccount(id uint) error { + // 계정 존재 확인 + exists, err := s.cspAccountRepo.ExistsByID(id) + if err != nil { + return fmt.Errorf("failed to check CSP account existence: %w", err) + } + if !exists { + return fmt.Errorf("CSP account not found with ID: %d", id) + } + + // 연관된 IDP 설정 확인 + idpCount, err := s.cspIdpConfigRepo.CountByAccountID(id) + if err != nil { + return fmt.Errorf("failed to count IDP configs: %w", err) + } + if idpCount > 0 { + return fmt.Errorf("cannot delete CSP account: %d IDP configs are associated", idpCount) + } + + // 연관된 정책 확인 + policyCount, err := s.cspPolicyRepo.CountByAccountID(id) + if err != nil { + return fmt.Errorf("failed to count policies: %w", err) + } + if policyCount > 0 { + return fmt.Errorf("cannot delete CSP account: %d policies are associated", policyCount) + } + + if err := s.cspAccountRepo.Delete(id); err != nil { + return fmt.Errorf("failed to delete CSP account: %w", err) + } + + log.Printf("Deleted CSP account with ID: %d", id) + return nil +} + +// ValidateCspAccount CSP 계정 유효성 검증 +func (s *CspAccountService) ValidateCspAccount(id uint) error { + account, err := s.cspAccountRepo.GetByID(id) + if err != nil { + return fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return fmt.Errorf("CSP account not found with ID: %d", id) + } + + // CSP 타입별 필수 필드 검증 + switch account.CspType { + case "aws": + if account.GetAccountID() == "" { + return fmt.Errorf("AWS account_id is required") + } + case "gcp": + if account.GetProjectID() == "" { + return fmt.Errorf("GCP project_id is required") + } + case "azure": + if account.GetSubscriptionID() == "" { + return fmt.Errorf("Azure subscription_id is required") + } + if account.GetTenantID() == "" { + return fmt.Errorf("Azure tenant_id is required") + } + default: + return fmt.Errorf("unsupported CSP type: %s", account.CspType) + } + + log.Printf("Validated CSP account: %s (ID: %d)", account.Name, account.ID) + return nil +} + +// GetActiveCspAccounts 활성 CSP 계정 목록 조회 +func (s *CspAccountService) GetActiveCspAccounts() ([]*model.CspAccount, error) { + accounts, err := s.cspAccountRepo.GetActiveAccounts() + if err != nil { + return nil, fmt.Errorf("failed to get active CSP accounts: %w", err) + } + return accounts, nil +} + +// GetCspAccountsByCspType CSP 타입별 계정 목록 조회 +func (s *CspAccountService) GetCspAccountsByCspType(cspType string) ([]*model.CspAccount, error) { + accounts, err := s.cspAccountRepo.GetByCspType(cspType) + if err != nil { + return nil, fmt.Errorf("failed to get CSP accounts by type: %w", err) + } + return accounts, nil +} + +// ActivateCspAccount CSP 계정 활성화 +func (s *CspAccountService) ActivateCspAccount(id uint) error { + account, err := s.cspAccountRepo.GetByID(id) + if err != nil { + return fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return fmt.Errorf("CSP account not found with ID: %d", id) + } + + account.IsActive = true + if err := s.cspAccountRepo.Update(account); err != nil { + return fmt.Errorf("failed to activate CSP account: %w", err) + } + + log.Printf("Activated CSP account: %s (ID: %d)", account.Name, account.ID) + return nil +} + +// DeactivateCspAccount CSP 계정 비활성화 +func (s *CspAccountService) DeactivateCspAccount(id uint) error { + account, err := s.cspAccountRepo.GetByID(id) + if err != nil { + return fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return fmt.Errorf("CSP account not found with ID: %d", id) + } + + account.IsActive = false + if err := s.cspAccountRepo.Update(account); err != nil { + return fmt.Errorf("failed to deactivate CSP account: %w", err) + } + + log.Printf("Deactivated CSP account: %s (ID: %d)", account.Name, account.ID) + return nil +} diff --git a/src/service/csp_idp_config_service.go b/src/service/csp_idp_config_service.go new file mode 100644 index 00000000..5ac36925 --- /dev/null +++ b/src/service/csp_idp_config_service.go @@ -0,0 +1,505 @@ +package service + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/m-cmp/mc-iam-manager/model" + "github.com/m-cmp/mc-iam-manager/repository" + "gorm.io/gorm" +) + +// CspIdpConfigService CSP IDP 설정 서비스 +type CspIdpConfigService struct { + db *gorm.DB + cspIdpConfigRepo *repository.CspIdpConfigRepository + cspAccountRepo *repository.CspAccountRepository + keycloakService KeycloakService +} + +// NewCspIdpConfigService 새 CspIdpConfigService 인스턴스 생성 +func NewCspIdpConfigService(db *gorm.DB, keycloakService KeycloakService) *CspIdpConfigService { + return &CspIdpConfigService{ + db: db, + cspIdpConfigRepo: repository.NewCspIdpConfigRepository(db), + cspAccountRepo: repository.NewCspAccountRepository(db), + keycloakService: keycloakService, + } +} + +// CreateCspIdpConfig CSP IDP 설정 생성 +func (s *CspIdpConfigService) CreateCspIdpConfig(req *model.CreateCspIdpConfigRequest) (*model.CspIdpConfig, error) { + // CSP 계정 존재 확인 + account, err := s.cspAccountRepo.GetByID(req.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return nil, fmt.Errorf("CSP account not found with ID: %d", req.CspAccountID) + } + + // 이름 중복 확인 + exists, err := s.cspIdpConfigRepo.ExistsByNameAndAccountID(req.Name, req.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to check IDP config existence: %w", err) + } + if exists { + return nil, fmt.Errorf("IDP config with name '%s' already exists for this account", req.Name) + } + + // IDP 설정 생성 + idpConfig := &model.CspIdpConfig{ + Name: req.Name, + CspAccountID: req.CspAccountID, + AuthMethod: req.AuthMethod, + Config: req.Config, + IsActive: true, + Description: req.Description, + } + + if err := s.cspIdpConfigRepo.Create(idpConfig); err != nil { + return nil, fmt.Errorf("failed to create IDP config: %w", err) + } + + log.Printf("Created CSP IDP config: %s (method: %s)", idpConfig.Name, idpConfig.AuthMethod) + return idpConfig, nil +} + +// GetCspIdpConfigByID ID로 CSP IDP 설정 조회 +func (s *CspIdpConfigService) GetCspIdpConfigByID(id uint) (*model.CspIdpConfig, error) { + idpConfig, err := s.cspIdpConfigRepo.GetByID(id) + if err != nil { + return nil, fmt.Errorf("failed to get IDP config: %w", err) + } + if idpConfig == nil { + return nil, fmt.Errorf("IDP config not found with ID: %d", id) + } + return idpConfig, nil +} + +// ListCspIdpConfigs CSP IDP 설정 목록 조회 +func (s *CspIdpConfigService) ListCspIdpConfigs(filter *model.CspIdpConfigFilter) ([]*model.CspIdpConfig, error) { + configs, err := s.cspIdpConfigRepo.List(filter) + if err != nil { + return nil, fmt.Errorf("failed to list IDP configs: %w", err) + } + return configs, nil +} + +// UpdateCspIdpConfig CSP IDP 설정 수정 +func (s *CspIdpConfigService) UpdateCspIdpConfig(id uint, req *model.UpdateCspIdpConfigRequest) (*model.CspIdpConfig, error) { + // 기존 설정 조회 + idpConfig, err := s.cspIdpConfigRepo.GetByID(id) + if err != nil { + return nil, fmt.Errorf("failed to get IDP config: %w", err) + } + if idpConfig == nil { + return nil, fmt.Errorf("IDP config not found with ID: %d", id) + } + + // 필드 업데이트 + if req.Name != "" { + // 이름 변경 시 중복 확인 + if req.Name != idpConfig.Name { + exists, err := s.cspIdpConfigRepo.ExistsByNameAndAccountID(req.Name, idpConfig.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to check IDP config existence: %w", err) + } + if exists { + return nil, fmt.Errorf("IDP config with name '%s' already exists", req.Name) + } + } + idpConfig.Name = req.Name + } + if req.Config != nil { + idpConfig.Config = req.Config + } + if req.IsActive != nil { + idpConfig.IsActive = *req.IsActive + } + if req.Description != "" { + idpConfig.Description = req.Description + } + + if err := s.cspIdpConfigRepo.Update(idpConfig); err != nil { + return nil, fmt.Errorf("failed to update IDP config: %w", err) + } + + log.Printf("Updated CSP IDP config: %s (ID: %d)", idpConfig.Name, idpConfig.ID) + return idpConfig, nil +} + +// DeleteCspIdpConfig CSP IDP 설정 삭제 +func (s *CspIdpConfigService) DeleteCspIdpConfig(id uint) error { + // 설정 존재 확인 + exists, err := s.cspIdpConfigRepo.ExistsByID(id) + if err != nil { + return fmt.Errorf("failed to check IDP config existence: %w", err) + } + if !exists { + return fmt.Errorf("IDP config not found with ID: %d", id) + } + + // TODO: 연관된 CspRole 확인 (CspRole.CspIdpConfigID 참조) + + if err := s.cspIdpConfigRepo.Delete(id); err != nil { + return fmt.Errorf("failed to delete IDP config: %w", err) + } + + log.Printf("Deleted CSP IDP config with ID: %d", id) + return nil +} + +// TestConnection IDP 연결 테스트 +func (s *CspIdpConfigService) TestConnection(ctx context.Context, id uint) error { + idpConfig, err := s.cspIdpConfigRepo.GetByID(id) + if err != nil { + return fmt.Errorf("failed to get IDP config: %w", err) + } + if idpConfig == nil { + return fmt.Errorf("IDP config not found with ID: %d", id) + } + + // CSP 계정 정보 조회 + account, err := s.cspAccountRepo.GetByID(idpConfig.CspAccountID) + if err != nil { + return fmt.Errorf("failed to get CSP account: %w", err) + } + + // 인증 방식에 따른 연결 테스트 + switch idpConfig.AuthMethod { + case model.AuthMethodOIDC: + return s.testOidcConnection(ctx, idpConfig, account) + case model.AuthMethodSAML: + return s.testSamlConnection(ctx, idpConfig, account) + case model.AuthMethodSecretKey: + return s.testSecretKeyConnection(ctx, idpConfig, account) + default: + return fmt.Errorf("unsupported auth method: %s", idpConfig.AuthMethod) + } +} + +// testOidcConnection OIDC 연결 테스트 +func (s *CspIdpConfigService) testOidcConnection(ctx context.Context, idpConfig *model.CspIdpConfig, account *model.CspAccount) error { + switch account.CspType { + case "aws": + return s.testAwsOidcConnection(ctx, idpConfig, account) + case "gcp": + // TODO: GCP Workload Identity Federation 테스트 + return fmt.Errorf("GCP OIDC connection test not implemented yet") + case "azure": + // TODO: Azure AD Workload Identity 테스트 + return fmt.Errorf("Azure OIDC connection test not implemented yet") + default: + return fmt.Errorf("unsupported CSP type: %s", account.CspType) + } +} + +// testAwsOidcConnection AWS OIDC 연결 테스트 +func (s *CspIdpConfigService) testAwsOidcConnection(ctx context.Context, idpConfig *model.CspIdpConfig, account *model.CspAccount) error { + // Keycloak에서 OIDC 토큰 획득 + token, err := s.keycloakService.GetClientCredentialsToken(ctx) + if err != nil { + return fmt.Errorf("failed to get Keycloak token: %w", err) + } + + // AWS STS 클라이언트 생성 + region := account.GetRegion() + if region == "" { + region = "ap-northeast-2" + } + + cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) + if err != nil { + return fmt.Errorf("failed to load AWS config: %w", err) + } + + stsClient := sts.NewFromConfig(cfg) + + // Role ARN 구성 (환경 변수 또는 IDP Config에서) + roleArn := idpConfig.Config["role_arn"] + if roleArn == "" { + roleArn = os.Getenv("IDENTITY_ROLE_ARN_AWS") + } + if roleArn == "" { + return fmt.Errorf("role_arn is not configured") + } + + // AssumeRoleWithWebIdentity 테스트 + input := &sts.AssumeRoleWithWebIdentityInput{ + RoleArn: aws.String(roleArn), + RoleSessionName: aws.String("mciam-connection-test"), + WebIdentityToken: aws.String(token.AccessToken), + DurationSeconds: aws.Int32(900), // 최소 15분 + } + + result, err := stsClient.AssumeRoleWithWebIdentity(ctx, input) + if err != nil { + return fmt.Errorf("AWS OIDC connection test failed: %w", err) + } + + log.Printf("AWS OIDC connection test successful. AssumedRoleUser: %s", *result.AssumedRoleUser.Arn) + return nil +} + +// testSamlConnection SAML 연결 테스트 +func (s *CspIdpConfigService) testSamlConnection(ctx context.Context, idpConfig *model.CspIdpConfig, account *model.CspAccount) error { + // TODO: SAML 연결 테스트 구현 + return fmt.Errorf("SAML connection test not implemented yet") +} + +// testSecretKeyConnection Secret Key 연결 테스트 +func (s *CspIdpConfigService) testSecretKeyConnection(ctx context.Context, idpConfig *model.CspIdpConfig, account *model.CspAccount) error { + switch account.CspType { + case "aws": + return s.testAwsSecretKeyConnection(ctx, idpConfig, account) + case "gcp": + // TODO: GCP 서비스 계정 키 테스트 + return fmt.Errorf("GCP Secret Key connection test not implemented yet") + case "azure": + // TODO: Azure 서비스 프린시펄 테스트 + return fmt.Errorf("Azure Secret Key connection test not implemented yet") + default: + return fmt.Errorf("unsupported CSP type: %s", account.CspType) + } +} + +// testAwsSecretKeyConnection AWS Secret Key 연결 테스트 +func (s *CspIdpConfigService) testAwsSecretKeyConnection(ctx context.Context, idpConfig *model.CspIdpConfig, account *model.CspAccount) error { + accessKeyID := idpConfig.GetAccessKeyID() + secretAccessKey := idpConfig.GetSecretAccessKey() + + if accessKeyID == "" || secretAccessKey == "" { + return fmt.Errorf("access_key_id or secret_access_key is not configured") + } + + // 암호화된 경우 복호화 필요 + if idpConfig.IsEncrypted() { + // TODO: 복호화 로직 구현 + return fmt.Errorf("encrypted secret key decryption not implemented yet") + } + + // AWS 설정 생성 + region := account.GetRegion() + if region == "" { + region = "ap-northeast-2" + } + + cfg, err := config.LoadDefaultConfig(ctx, + config.WithRegion(region), + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider( + accessKeyID, + secretAccessKey, + "", + )), + ) + if err != nil { + return fmt.Errorf("failed to load AWS config: %w", err) + } + + // STS GetCallerIdentity로 자격 증명 테스트 + stsClient := sts.NewFromConfig(cfg) + result, err := stsClient.GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{}) + if err != nil { + return fmt.Errorf("AWS Secret Key connection test failed: %w", err) + } + + log.Printf("AWS Secret Key connection test successful. Account: %s, Arn: %s", *result.Account, *result.Arn) + return nil +} + +// GetActiveIdpConfigsByAccountID 특정 계정의 활성 IDP 설정 목록 조회 +func (s *CspIdpConfigService) GetActiveIdpConfigsByAccountID(accountID uint) ([]*model.CspIdpConfig, error) { + configs, err := s.cspIdpConfigRepo.GetActiveByAccountID(accountID) + if err != nil { + return nil, fmt.Errorf("failed to get active IDP configs: %w", err) + } + return configs, nil +} + +// GetIdpConfigsByAuthMethod 인증 방식별 IDP 설정 목록 조회 +func (s *CspIdpConfigService) GetIdpConfigsByAuthMethod(authMethod model.AuthMethodType) ([]*model.CspIdpConfig, error) { + configs, err := s.cspIdpConfigRepo.GetByAuthMethod(authMethod) + if err != nil { + return nil, fmt.Errorf("failed to get IDP configs by auth method: %w", err) + } + return configs, nil +} + +// ActivateIdpConfig IDP 설정 활성화 +func (s *CspIdpConfigService) ActivateIdpConfig(id uint) error { + idpConfig, err := s.cspIdpConfigRepo.GetByID(id) + if err != nil { + return fmt.Errorf("failed to get IDP config: %w", err) + } + if idpConfig == nil { + return fmt.Errorf("IDP config not found with ID: %d", id) + } + + idpConfig.IsActive = true + if err := s.cspIdpConfigRepo.Update(idpConfig); err != nil { + return fmt.Errorf("failed to activate IDP config: %w", err) + } + + log.Printf("Activated CSP IDP config: %s (ID: %d)", idpConfig.Name, idpConfig.ID) + return nil +} + +// DeactivateIdpConfig IDP 설정 비활성화 +func (s *CspIdpConfigService) DeactivateIdpConfig(id uint) error { + idpConfig, err := s.cspIdpConfigRepo.GetByID(id) + if err != nil { + return fmt.Errorf("failed to get IDP config: %w", err) + } + if idpConfig == nil { + return fmt.Errorf("IDP config not found with ID: %d", id) + } + + idpConfig.IsActive = false + if err := s.cspIdpConfigRepo.Update(idpConfig); err != nil { + return fmt.Errorf("failed to deactivate IDP config: %w", err) + } + + log.Printf("Deactivated CSP IDP config: %s (ID: %d)", idpConfig.Name, idpConfig.ID) + return nil +} + +// AssumeRoleWithIdpConfig IDP 설정을 사용하여 임시 자격 증명 획득 +func (s *CspIdpConfigService) AssumeRoleWithIdpConfig(ctx context.Context, idpConfigID uint, roleArn string, sessionName string, durationSeconds int32) (*model.TempCredential, error) { + idpConfig, err := s.cspIdpConfigRepo.GetByID(idpConfigID) + if err != nil { + return nil, fmt.Errorf("failed to get IDP config: %w", err) + } + if idpConfig == nil { + return nil, fmt.Errorf("IDP config not found with ID: %d", idpConfigID) + } + + if !idpConfig.IsActive { + return nil, fmt.Errorf("IDP config is not active") + } + + account, err := s.cspAccountRepo.GetByID(idpConfig.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + + if account.CspType != "aws" { + return nil, fmt.Errorf("only AWS is supported for AssumeRole currently") + } + + region := account.GetRegion() + if region == "" { + region = "ap-northeast-2" + } + + switch idpConfig.AuthMethod { + case model.AuthMethodOIDC: + return s.assumeRoleWithOidc(ctx, idpConfig, roleArn, sessionName, durationSeconds, region) + case model.AuthMethodSecretKey: + return s.assumeRoleWithSecretKey(ctx, idpConfig, roleArn, sessionName, durationSeconds, region) + default: + return nil, fmt.Errorf("unsupported auth method for AssumeRole: %s", idpConfig.AuthMethod) + } +} + +// assumeRoleWithOidc OIDC를 사용하여 역할 인수 +func (s *CspIdpConfigService) assumeRoleWithOidc(ctx context.Context, idpConfig *model.CspIdpConfig, roleArn string, sessionName string, durationSeconds int32, region string) (*model.TempCredential, error) { + // Keycloak에서 OIDC 토큰 획득 + token, err := s.keycloakService.GetClientCredentialsToken(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get Keycloak token: %w", err) + } + + cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) + if err != nil { + return nil, fmt.Errorf("failed to load AWS config: %w", err) + } + + stsClient := sts.NewFromConfig(cfg) + + if durationSeconds < 900 { + durationSeconds = 3600 // 기본 1시간 + } + + input := &sts.AssumeRoleWithWebIdentityInput{ + RoleArn: aws.String(roleArn), + RoleSessionName: aws.String(sessionName), + WebIdentityToken: aws.String(token.AccessToken), + DurationSeconds: aws.Int32(durationSeconds), + } + + result, err := stsClient.AssumeRoleWithWebIdentity(ctx, input) + if err != nil { + return nil, fmt.Errorf("failed to assume role with OIDC: %w", err) + } + + return &model.TempCredential{ + Provider: "aws", + AuthType: "oidc", + AccessKeyId: *result.Credentials.AccessKeyId, + SecretAccessKey: *result.Credentials.SecretAccessKey, + SessionToken: *result.Credentials.SessionToken, + Region: region, + IssuedAt: time.Now(), + ExpiresAt: *result.Credentials.Expiration, + IsActive: true, + }, nil +} + +// assumeRoleWithSecretKey Secret Key를 사용하여 역할 인수 +func (s *CspIdpConfigService) assumeRoleWithSecretKey(ctx context.Context, idpConfig *model.CspIdpConfig, roleArn string, sessionName string, durationSeconds int32, region string) (*model.TempCredential, error) { + accessKeyID := idpConfig.GetAccessKeyID() + secretAccessKey := idpConfig.GetSecretAccessKey() + + if accessKeyID == "" || secretAccessKey == "" { + return nil, fmt.Errorf("access_key_id or secret_access_key is not configured") + } + + cfg, err := config.LoadDefaultConfig(ctx, + config.WithRegion(region), + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider( + accessKeyID, + secretAccessKey, + "", + )), + ) + if err != nil { + return nil, fmt.Errorf("failed to load AWS config: %w", err) + } + + stsClient := sts.NewFromConfig(cfg) + + if durationSeconds < 900 { + durationSeconds = 3600 // 기본 1시간 + } + + input := &sts.AssumeRoleInput{ + RoleArn: aws.String(roleArn), + RoleSessionName: aws.String(sessionName), + DurationSeconds: aws.Int32(durationSeconds), + } + + result, err := stsClient.AssumeRole(ctx, input) + if err != nil { + return nil, fmt.Errorf("failed to assume role with secret key: %w", err) + } + + return &model.TempCredential{ + Provider: "aws", + AuthType: "secret_key", + AccessKeyId: *result.Credentials.AccessKeyId, + SecretAccessKey: *result.Credentials.SecretAccessKey, + SessionToken: *result.Credentials.SessionToken, + Region: region, + IssuedAt: time.Now(), + ExpiresAt: *result.Credentials.Expiration, + IsActive: true, + }, nil +} diff --git a/src/service/csp_policy_service.go b/src/service/csp_policy_service.go new file mode 100644 index 00000000..038265a1 --- /dev/null +++ b/src/service/csp_policy_service.go @@ -0,0 +1,470 @@ +package service + +import ( + "context" + "fmt" + "log" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/iam" + iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" + "github.com/m-cmp/mc-iam-manager/model" + "github.com/m-cmp/mc-iam-manager/repository" + "gorm.io/gorm" +) + +// CspPolicyService CSP 정책 서비스 +type CspPolicyService struct { + db *gorm.DB + cspPolicyRepo *repository.CspPolicyRepository + cspAccountRepo *repository.CspAccountRepository + cspRoleRepo *repository.CspRoleRepository + cspIdpConfigService *CspIdpConfigService +} + +// NewCspPolicyService 새 CspPolicyService 인스턴스 생성 +func NewCspPolicyService(db *gorm.DB, cspIdpConfigService *CspIdpConfigService) *CspPolicyService { + return &CspPolicyService{ + db: db, + cspPolicyRepo: repository.NewCspPolicyRepository(db), + cspAccountRepo: repository.NewCspAccountRepository(db), + cspRoleRepo: repository.NewCspRoleRepository(db), + cspIdpConfigService: cspIdpConfigService, + } +} + +// CreateCspPolicy CSP 정책 생성 +func (s *CspPolicyService) CreateCspPolicy(req *model.CreateCspPolicyRequest) (*model.CspPolicy, error) { + // CSP 계정 존재 확인 + account, err := s.cspAccountRepo.GetByID(req.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return nil, fmt.Errorf("CSP account not found with ID: %d", req.CspAccountID) + } + + // 이름 중복 확인 + exists, err := s.cspPolicyRepo.ExistsByNameAndAccountID(req.Name, req.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to check policy existence: %w", err) + } + if exists { + return nil, fmt.Errorf("policy with name '%s' already exists for this account", req.Name) + } + + // 정책 생성 + policy := &model.CspPolicy{ + Name: req.Name, + CspAccountID: req.CspAccountID, + PolicyType: req.PolicyType, + PolicyArn: req.PolicyArn, + PolicyDoc: req.PolicyDoc, + Description: req.Description, + } + + if err := s.cspPolicyRepo.Create(policy); err != nil { + return nil, fmt.Errorf("failed to create policy: %w", err) + } + + log.Printf("Created CSP policy: %s (type: %s)", policy.Name, policy.PolicyType) + return policy, nil +} + +// GetCspPolicyByID ID로 CSP 정책 조회 +func (s *CspPolicyService) GetCspPolicyByID(id uint) (*model.CspPolicy, error) { + policy, err := s.cspPolicyRepo.GetByID(id) + if err != nil { + return nil, fmt.Errorf("failed to get policy: %w", err) + } + if policy == nil { + return nil, fmt.Errorf("policy not found with ID: %d", id) + } + return policy, nil +} + +// ListCspPolicies CSP 정책 목록 조회 +func (s *CspPolicyService) ListCspPolicies(filter *model.CspPolicyFilter) ([]*model.CspPolicy, error) { + policies, err := s.cspPolicyRepo.List(filter) + if err != nil { + return nil, fmt.Errorf("failed to list policies: %w", err) + } + return policies, nil +} + +// UpdateCspPolicy CSP 정책 수정 +func (s *CspPolicyService) UpdateCspPolicy(id uint, req *model.UpdateCspPolicyRequest) (*model.CspPolicy, error) { + // 기존 정책 조회 + policy, err := s.cspPolicyRepo.GetByID(id) + if err != nil { + return nil, fmt.Errorf("failed to get policy: %w", err) + } + if policy == nil { + return nil, fmt.Errorf("policy not found with ID: %d", id) + } + + // 필드 업데이트 + if req.Name != "" { + // 이름 변경 시 중복 확인 + if req.Name != policy.Name { + exists, err := s.cspPolicyRepo.ExistsByNameAndAccountID(req.Name, policy.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to check policy existence: %w", err) + } + if exists { + return nil, fmt.Errorf("policy with name '%s' already exists", req.Name) + } + } + policy.Name = req.Name + } + if req.PolicyArn != "" { + policy.PolicyArn = req.PolicyArn + } + if req.PolicyDoc != nil { + policy.PolicyDoc = req.PolicyDoc + } + if req.Description != "" { + policy.Description = req.Description + } + + if err := s.cspPolicyRepo.Update(policy); err != nil { + return nil, fmt.Errorf("failed to update policy: %w", err) + } + + log.Printf("Updated CSP policy: %s (ID: %d)", policy.Name, policy.ID) + return policy, nil +} + +// DeleteCspPolicy CSP 정책 삭제 +func (s *CspPolicyService) DeleteCspPolicy(id uint) error { + // 정책 존재 확인 + exists, err := s.cspPolicyRepo.ExistsByID(id) + if err != nil { + return fmt.Errorf("failed to check policy existence: %w", err) + } + if !exists { + return fmt.Errorf("policy not found with ID: %d", id) + } + + // 연결된 역할 확인 + roles, err := s.cspPolicyRepo.GetRolesByPolicyID(id) + if err != nil { + return fmt.Errorf("failed to get roles by policy: %w", err) + } + if len(roles) > 0 { + return fmt.Errorf("cannot delete policy: %d roles are attached", len(roles)) + } + + if err := s.cspPolicyRepo.Delete(id); err != nil { + return fmt.Errorf("failed to delete policy: %w", err) + } + + log.Printf("Deleted CSP policy with ID: %d", id) + return nil +} + +// AttachPolicyToRole 역할에 정책 연결 +func (s *CspPolicyService) AttachPolicyToRole(roleID, policyID uint) error { + // 역할 존재 확인 + roleExists, err := s.cspRoleRepo.ExistsCspRoleByID(roleID) + if err != nil { + return fmt.Errorf("failed to check role existence: %w", err) + } + if !roleExists { + return fmt.Errorf("CSP role not found with ID: %d", roleID) + } + + // 정책 존재 확인 + policyExists, err := s.cspPolicyRepo.ExistsByID(policyID) + if err != nil { + return fmt.Errorf("failed to check policy existence: %w", err) + } + if !policyExists { + return fmt.Errorf("CSP policy not found with ID: %d", policyID) + } + + // 이미 연결되어 있는지 확인 + attached, err := s.cspPolicyRepo.IsPolicyAttachedToRole(roleID, policyID) + if err != nil { + return fmt.Errorf("failed to check policy attachment: %w", err) + } + if attached { + return fmt.Errorf("policy is already attached to the role") + } + + if err := s.cspPolicyRepo.AttachPolicyToRole(roleID, policyID); err != nil { + return fmt.Errorf("failed to attach policy to role: %w", err) + } + + log.Printf("Attached policy %d to role %d", policyID, roleID) + return nil +} + +// DetachPolicyFromRole 역할에서 정책 분리 +func (s *CspPolicyService) DetachPolicyFromRole(roleID, policyID uint) error { + // 연결 여부 확인 + attached, err := s.cspPolicyRepo.IsPolicyAttachedToRole(roleID, policyID) + if err != nil { + return fmt.Errorf("failed to check policy attachment: %w", err) + } + if !attached { + return fmt.Errorf("policy is not attached to the role") + } + + if err := s.cspPolicyRepo.DetachPolicyFromRole(roleID, policyID); err != nil { + return fmt.Errorf("failed to detach policy from role: %w", err) + } + + log.Printf("Detached policy %d from role %d", policyID, roleID) + return nil +} + +// GetPoliciesByRoleID 역할에 연결된 정책 목록 조회 +func (s *CspPolicyService) GetPoliciesByRoleID(roleID uint) ([]*model.CspPolicy, error) { + policies, err := s.cspPolicyRepo.GetPoliciesByRoleID(roleID) + if err != nil { + return nil, fmt.Errorf("failed to get policies by role: %w", err) + } + return policies, nil +} + +// SyncPoliciesFromCloud CSP에서 정책 동기화 +func (s *CspPolicyService) SyncPoliciesFromCloud(ctx context.Context, req *model.SyncPoliciesRequest) ([]*model.CspPolicy, error) { + // CSP 계정 조회 + account, err := s.cspAccountRepo.GetByID(req.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + if account == nil { + return nil, fmt.Errorf("CSP account not found with ID: %d", req.CspAccountID) + } + + switch account.CspType { + case "aws": + return s.syncAwsPolicies(ctx, account, req.PolicyScope) + case "gcp": + return nil, fmt.Errorf("GCP policy sync not implemented yet") + case "azure": + return nil, fmt.Errorf("Azure policy sync not implemented yet") + default: + return nil, fmt.Errorf("unsupported CSP type: %s", account.CspType) + } +} + +// syncAwsPolicies AWS에서 정책 동기화 +func (s *CspPolicyService) syncAwsPolicies(ctx context.Context, account *model.CspAccount, scope string) ([]*model.CspPolicy, error) { + // IDP 설정을 통해 임시 자격 증명 획득 + idpConfigs, err := s.cspIdpConfigService.GetActiveIdpConfigsByAccountID(account.ID) + if err != nil { + return nil, fmt.Errorf("failed to get IDP configs: %w", err) + } + if len(idpConfigs) == 0 { + return nil, fmt.Errorf("no active IDP config found for account") + } + + // 첫 번째 활성 IDP 설정 사용 + idpConfig := idpConfigs[0] + + // 임시 자격 증명 획득 + tempCred, err := s.cspIdpConfigService.AssumeRoleWithIdpConfig(ctx, idpConfig.ID, + idpConfig.Config["role_arn"], + "mciam-policy-sync", + 3600) + if err != nil { + return nil, fmt.Errorf("failed to assume role: %w", err) + } + + // AWS IAM 클라이언트 생성 + cfg, err := config.LoadDefaultConfig(ctx, + config.WithRegion(tempCred.Region), + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider( + tempCred.AccessKeyId, + tempCred.SecretAccessKey, + tempCred.SessionToken, + )), + ) + if err != nil { + return nil, fmt.Errorf("failed to load AWS config: %w", err) + } + + iamClient := iam.NewFromConfig(cfg) + + // 정책 목록 조회 + var policyScope iamtypes.PolicyScopeType + switch scope { + case "All": + policyScope = iamtypes.PolicyScopeTypeAll + case "AWS": + policyScope = iamtypes.PolicyScopeTypeAws + case "Local": + policyScope = iamtypes.PolicyScopeTypeLocal + default: + policyScope = iamtypes.PolicyScopeTypeLocal + } + + input := &iam.ListPoliciesInput{ + Scope: policyScope, + } + + var syncedPolicies []*model.CspPolicy + paginator := iam.NewListPoliciesPaginator(iamClient, input) + + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + return nil, fmt.Errorf("failed to list AWS policies: %w", err) + } + + for _, awsPolicy := range page.Policies { + // 기존 정책 확인 + existingPolicy, _ := s.cspPolicyRepo.GetByArn(*awsPolicy.Arn) + if existingPolicy != nil { + // 업데이트 + existingPolicy.Name = *awsPolicy.PolicyName + if awsPolicy.Description != nil { + existingPolicy.Description = *awsPolicy.Description + } + if err := s.cspPolicyRepo.Update(existingPolicy); err != nil { + log.Printf("Failed to update policy %s: %v", *awsPolicy.PolicyName, err) + continue + } + syncedPolicies = append(syncedPolicies, existingPolicy) + } else { + // 새로 생성 + newPolicy := &model.CspPolicy{ + Name: *awsPolicy.PolicyName, + CspAccountID: account.ID, + PolicyType: model.PolicyTypeManaged, + PolicyArn: *awsPolicy.Arn, + } + if awsPolicy.Description != nil { + newPolicy.Description = *awsPolicy.Description + } + if err := s.cspPolicyRepo.Create(newPolicy); err != nil { + log.Printf("Failed to create policy %s: %v", *awsPolicy.PolicyName, err) + continue + } + syncedPolicies = append(syncedPolicies, newPolicy) + } + } + } + + log.Printf("Synced %d policies from AWS", len(syncedPolicies)) + return syncedPolicies, nil +} + +// GetPolicyDocument CSP에서 정책 문서 조회 +func (s *CspPolicyService) GetPolicyDocument(ctx context.Context, policyID uint) (map[string]interface{}, error) { + policy, err := s.cspPolicyRepo.GetByID(policyID) + if err != nil { + return nil, fmt.Errorf("failed to get policy: %w", err) + } + if policy == nil { + return nil, fmt.Errorf("policy not found with ID: %d", policyID) + } + + // 이미 PolicyDoc가 있으면 반환 + if policy.PolicyDoc != nil { + return policy.PolicyDoc, nil + } + + // 관리형 정책이고 ARN이 있으면 CSP에서 조회 + if policy.PolicyType == model.PolicyTypeManaged && policy.PolicyArn != "" { + account, err := s.cspAccountRepo.GetByID(policy.CspAccountID) + if err != nil { + return nil, fmt.Errorf("failed to get CSP account: %w", err) + } + + if account.CspType == "aws" { + return s.getAwsPolicyDocument(ctx, account, policy.PolicyArn) + } + } + + return nil, fmt.Errorf("policy document not available") +} + +// getAwsPolicyDocument AWS에서 정책 문서 조회 +func (s *CspPolicyService) getAwsPolicyDocument(ctx context.Context, account *model.CspAccount, policyArn string) (map[string]interface{}, error) { + // IDP 설정을 통해 임시 자격 증명 획득 + idpConfigs, err := s.cspIdpConfigService.GetActiveIdpConfigsByAccountID(account.ID) + if err != nil { + return nil, fmt.Errorf("failed to get IDP configs: %w", err) + } + if len(idpConfigs) == 0 { + return nil, fmt.Errorf("no active IDP config found for account") + } + + idpConfig := idpConfigs[0] + tempCred, err := s.cspIdpConfigService.AssumeRoleWithIdpConfig(ctx, idpConfig.ID, + idpConfig.Config["role_arn"], + "mciam-policy-get", + 900) + if err != nil { + return nil, fmt.Errorf("failed to assume role: %w", err) + } + + // AWS IAM 클라이언트 생성 + cfg, err := config.LoadDefaultConfig(ctx, + config.WithRegion(tempCred.Region), + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider( + tempCred.AccessKeyId, + tempCred.SecretAccessKey, + tempCred.SessionToken, + )), + ) + if err != nil { + return nil, fmt.Errorf("failed to load AWS config: %w", err) + } + + iamClient := iam.NewFromConfig(cfg) + + // 정책 정보 조회 + getPolicyInput := &iam.GetPolicyInput{ + PolicyArn: aws.String(policyArn), + } + policyResult, err := iamClient.GetPolicy(ctx, getPolicyInput) + if err != nil { + return nil, fmt.Errorf("failed to get policy: %w", err) + } + + // 정책 버전 문서 조회 + getPolicyVersionInput := &iam.GetPolicyVersionInput{ + PolicyArn: aws.String(policyArn), + VersionId: policyResult.Policy.DefaultVersionId, + } + versionResult, err := iamClient.GetPolicyVersion(ctx, getPolicyVersionInput) + if err != nil { + return nil, fmt.Errorf("failed to get policy version: %w", err) + } + + // URL 디코딩 및 JSON 파싱 + if versionResult.PolicyVersion.Document != nil { + // AWS는 URL 인코딩된 JSON을 반환 + // 여기서는 간단히 string으로 반환 (실제로는 파싱 필요) + return map[string]interface{}{ + "document": *versionResult.PolicyVersion.Document, + }, nil + } + + return nil, fmt.Errorf("policy document not found") +} + +// GetManagedPoliciesByAccountID 특정 계정의 관리형 정책 목록 조회 +func (s *CspPolicyService) GetManagedPoliciesByAccountID(accountID uint) ([]*model.CspPolicy, error) { + policies, err := s.cspPolicyRepo.GetManagedPoliciesByAccountID(accountID) + if err != nil { + return nil, fmt.Errorf("failed to get managed policies: %w", err) + } + return policies, nil +} + +// GetPoliciesByAccountID 특정 계정의 모든 정책 목록 조회 +func (s *CspPolicyService) GetPoliciesByAccountID(accountID uint) ([]*model.CspPolicy, error) { + policies, err := s.cspPolicyRepo.GetByAccountID(accountID) + if err != nil { + return nil, fmt.Errorf("failed to get policies by account: %w", err) + } + return policies, nil +} diff --git a/src/service/keycloak_service.go b/src/service/keycloak_service.go index c2148126..d042abfb 100644 --- a/src/service/keycloak_service.go +++ b/src/service/keycloak_service.go @@ -62,6 +62,14 @@ type KeycloakService interface { GetImpersonationTokenByServiceAccount(ctx context.Context) (*gocloak.JWT, error) // AssignRealmRoleToUser assigns a realm role to a user AssignRealmRoleToUser(ctx context.Context, kcUserId, roleName string) error + // CheckRealmRoleExists checks if a realm role exists + CheckRealmRoleExists(ctx context.Context, roleName string) (bool, error) + // CreateRealmRole creates a realm role + CreateRealmRole(ctx context.Context, roleName string) error + // CreateRealmRoleAndWait creates a realm role and waits for it to be available + CreateRealmRoleAndWait(ctx context.Context, roleName string) error + // RemoveRealmRoleFromUser removes a realm role from a user + RemoveRealmRoleFromUser(ctx context.Context, kcUserId, roleName string) error // IssueWorkspaceTicket 워크스페이스 티켓을 발행합니다. IssueWorkspaceTicket(ctx context.Context, kcUserId string, workspaceID uint) (string, map[string]interface{}, error) // 기본 Role 정의 @@ -811,7 +819,7 @@ func (s *keycloakService) SetupInitialKeycloakAdmin(ctx context.Context, adminTo // 3. platformAdmin 역할 할당. patformAdmin 역할이 없으면 생성 log.Printf("[DEBUG] Setting platformAdmin role") platformAdminRoleName := "platformAdmin" - platformAdminRole := gocloak.Role{} + var platformAdminRole gocloak.Role realmRole, err := config.KC.Client.GetRealmRole(ctx, adminToken.AccessToken, config.KC.Realm, platformAdminRoleName) if err != nil { log.Printf("failed to get platformAdmin role: %v", err) @@ -839,7 +847,7 @@ func (s *keycloakService) SetupInitialKeycloakAdmin(ctx context.Context, adminTo } else { platformAdminRole = *realmRole } - log.Printf("platformAdminRole: %s", platformAdminRole) + log.Printf("platformAdminRole: %+v", platformAdminRole) // platformAdminRole, err := config.KC.Client.GetRealmRole(ctx, adminToken.AccessToken, config.KC.Realm, "platformAdmin") // if err != nil { // log.Printf("failed to get platformAdmin role: %v", err) @@ -1139,7 +1147,7 @@ func (s *keycloakService) GetImpersonationTokenByAdminToken(ctx context.Context, return "", fmt.Errorf("failed to decode impersonation response: %w", err) } - log.Printf("[DEBUG] Impersonation resp.StatusCode : ", resp.StatusCode) //if result.Token == "" { + log.Printf("[DEBUG] Impersonation resp.StatusCode : %d", resp.StatusCode) //if result.Token == "" { // resp.Body를 다시 읽기 위해 전체 바이트로 읽음 respBody, _ := ioutil.ReadAll(resp.Body) log.Printf("[DEBUG] Impersonation response body: %s", string(respBody)) @@ -1336,3 +1344,128 @@ func (s *keycloakService) GetClientCredentialsToken(ctx context.Context) (*goclo //log.Printf("[DEBUG] client credentials token: %s", token) return token, nil } + +// CheckRealmRoleExists checks if a realm role exists +func (s *keycloakService) CheckRealmRoleExists(ctx context.Context, roleName string) (bool, error) { + if config.KC == nil || config.KC.Client == nil { + return false, fmt.Errorf("keycloak configuration not initialized") + } + + token, err := config.KC.GetAdminToken(ctx) + if err != nil { + return false, fmt.Errorf("failed to get admin token: %w", err) + } + + _, err = config.KC.Client.GetRealmRole(ctx, token.AccessToken, config.KC.Realm, roleName) + if err != nil { + // Role not found + return false, nil + } + return true, nil +} + +// CreateRealmRole creates a realm role +func (s *keycloakService) CreateRealmRole(ctx context.Context, roleName string) error { + if config.KC == nil || config.KC.Client == nil { + return fmt.Errorf("keycloak configuration not initialized") + } + + token, err := config.KC.GetAdminToken(ctx) + if err != nil { + return fmt.Errorf("failed to get admin token: %w", err) + } + + newRole := gocloak.Role{ + Name: &roleName, + Description: gocloak.StringP("Platform role"), + } + + result, err := config.KC.Client.CreateRealmRole(ctx, token.AccessToken, config.KC.Realm, newRole) + if err != nil { + return fmt.Errorf("failed to create realm role %s: %w", roleName, err) + } + + log.Printf("Successfully created realm role: %s, result: %s", roleName, result) + return nil +} + +// RemoveRealmRoleFromUser removes a realm role from a user +func (s *keycloakService) RemoveRealmRoleFromUser(ctx context.Context, kcUserId, roleName string) error { + if config.KC == nil || config.KC.Client == nil { + return fmt.Errorf("keycloak configuration not initialized") + } + + token, err := config.KC.GetAdminToken(ctx) + if err != nil { + return fmt.Errorf("failed to get admin token: %w", err) + } + + // Get the role by name + roles, err := config.KC.Client.GetRealmRoles(ctx, token.AccessToken, config.KC.Realm, gocloak.GetRoleParams{ + Search: &roleName, + }) + if err != nil { + return fmt.Errorf("failed to get realm role %s: %w", roleName, err) + } + if len(roles) == 0 { + log.Printf("Realm role %s not found, skipping removal", roleName) + return nil + } + if len(roles) > 1 { + log.Printf("Warning: Found multiple roles matching '%s'. Using the first one.", roleName) + } + + // Remove the role from the user + err = config.KC.Client.DeleteRealmRoleFromUser(ctx, token.AccessToken, config.KC.Realm, kcUserId, []gocloak.Role{*roles[0]}) + if err != nil { + return fmt.Errorf("failed to remove realm role %s from user %s: %w", roleName, kcUserId, err) + } + + log.Printf("Successfully removed realm role %s from user %s", roleName, kcUserId) + return nil +} + +// CreateRealmRoleAndWait creates a realm role and waits for it to be available +func (s *keycloakService) CreateRealmRoleAndWait(ctx context.Context, roleName string) error { + if config.KC == nil || config.KC.Client == nil { + return fmt.Errorf("keycloak configuration not initialized") + } + + token, err := config.KC.GetAdminToken(ctx) + if err != nil { + return fmt.Errorf("failed to get admin token: %w", err) + } + + newRole := gocloak.Role{ + Name: &roleName, + Description: gocloak.StringP("Platform role"), + } + + result, err := config.KC.Client.CreateRealmRole(ctx, token.AccessToken, config.KC.Realm, newRole) + if err != nil { + return fmt.Errorf("failed to create realm role %s: %w", roleName, err) + } + + log.Printf("Realm role creation initiated: %s, result: %s", roleName, result) + + // 1초마다 최대 20번 시도하여 role 생성 확인 + maxRetries := 20 + for i := 0; i < maxRetries; i++ { + time.Sleep(1 * time.Second) + + exists, err := s.CheckRealmRoleExists(ctx, roleName) + if err != nil { + log.Printf("Failed to check realm role existence (attempt %d/%d): %v", i+1, maxRetries, err) + continue + } + + if exists { + log.Printf("Realm role %s successfully created and available (attempt %d/%d)", roleName, i+1, maxRetries) + return nil + } + + log.Printf("Realm role %s not yet available, waiting... (attempt %d/%d)", roleName, i+1, maxRetries) + } + + return fmt.Errorf("realm role %s was not available after %d attempts", roleName, maxRetries) +} diff --git a/src/service/mcmpapi_service.go b/src/service/mcmpapi_service.go index 427333e8..65e1dc40 100644 --- a/src/service/mcmpapi_service.go +++ b/src/service/mcmpapi_service.go @@ -1,31 +1,31 @@ package service import ( - "bytes" // For request body + "bytes" "context" - "encoding/base64" // For Basic Auth encoding + "encoding/base64" "encoding/json" "errors" "fmt" "io" "log" "net/http" - "net/http/httputil" // For dumping request - "net/url" // For query parameter mapping + "net/http/httputil" + "net/url" "os" - "path/filepath" // Ensure filepath is imported - "strings" // Ensure strings is imported - - // "encoding/json" // Removed unused import + "strings" + "time" "github.com/m-cmp/mc-iam-manager/model" - "github.com/m-cmp/mc-iam-manager/model/mcmpapi" // Updated import path + "github.com/m-cmp/mc-iam-manager/model/mcmpapi" + "github.com/m-cmp/mc-iam-manager/pkg/apiparser" "github.com/m-cmp/mc-iam-manager/repository" "gopkg.in/yaml.v3" - "gorm.io/gorm" // Needed if passing db directly, but better via repo + "gorm.io/gorm" ) -const apiYamlEnvVar = "MCADMINCLI_APIYAML" // Re-add constant definition +// Local path to service-actions.yaml file (relative to working directory) +const localServiceActionsPath = "asset/mcmpapi/service-actions.yaml" // McmpApiService defines the interface for mcmp API operations type McmpApiService interface { @@ -38,6 +38,7 @@ type McmpApiService interface { UpdateService(serviceName string, updates map[string]interface{}) error McmpApiCall(ctx context.Context, req *model.McmpApiCallRequest) (int, []byte, string, string, error) SyncMcmpAPIsFromYAML() error + ImportAPIs(req *model.ImportApiRequest) (*model.ImportApiResponse, error) } // mcmpApiService implements the McmpApiService interface. @@ -79,112 +80,50 @@ func (s *mcmpApiService) CreateAction(tx *gorm.DB, action *mcmpapi.McmpApiAction return s.repo.CreateAction(tx, action) } -// SyncMcmpAPIsFromYAML loads API definitions from the YAML URL specified by env var -// and saves them to the database via the repository. +// SyncMcmpAPIsFromYAML loads API definitions from local service-actions.yaml file +// and saves them to the database via the repository with upsert logic. func (s *mcmpApiService) SyncMcmpAPIsFromYAML() error { - // 테이블이 없으면 생성 - var count int64 - if err := s.db.Table("mcmp_api_services").Count(&count).Error; err != nil { - // 테이블이 없으면 생성 - if err := s.db.AutoMigrate(&mcmpapi.McmpApiService{}, &mcmpapi.McmpApiAction{}); err != nil { - return fmt.Errorf("failed to create mcmp API tables: %w", err) - } - log.Printf("Created mcmp API tables") - } - - yamlSource := os.Getenv(apiYamlEnvVar) - if yamlSource == "" { - err := fmt.Errorf("environment variable %s is not set", apiYamlEnvVar) - log.Printf("Error syncing mcmp APIs: %v", err) - return err + // Ensure tables exist + if err := s.ensureTables(); err != nil { + return fmt.Errorf("failed to ensure tables: %w", err) } - localYamlPath := filepath.Join("asset", "mcmpapi", "mcmp_api.yaml") - - // Check if yamlSource is a URL - if strings.HasPrefix(yamlSource, "http://") || strings.HasPrefix(yamlSource, "https://") { - log.Printf("Starting mcmp API sync: Downloading from URL %s to %s", yamlSource, localYamlPath) - - // Ensure directory exists - if err := os.MkdirAll(filepath.Dir(localYamlPath), 0755); err != nil { - err = fmt.Errorf("failed to create directory for local YAML file %s: %w", localYamlPath, err) - log.Printf("Error syncing mcmp APIs: %v", err) - return err - } - - // Download the file - resp, err := http.Get(yamlSource) - if err != nil { - err = fmt.Errorf("failed to fetch mcmp API YAML from %s: %w", yamlSource, err) - log.Printf("Error syncing mcmp APIs: %v", err) - return err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - err = fmt.Errorf("failed to fetch mcmp API YAML: status code %d", resp.StatusCode) - log.Printf("Error syncing mcmp APIs: %v", err) - return err - } - - // Create the local file - outFile, err := os.Create(localYamlPath) - if err != nil { - err = fmt.Errorf("failed to create local YAML file %s: %w", localYamlPath, err) - log.Printf("Error syncing mcmp APIs: %v", err) - return err - } - defer outFile.Close() - - // Write the body to the file - _, err = io.Copy(outFile, resp.Body) - if err != nil { - err = fmt.Errorf("failed to write downloaded content to %s: %w", localYamlPath, err) - log.Printf("Error syncing mcmp APIs: %v", err) - return err - } - log.Printf("Successfully downloaded YAML to %s", localYamlPath) - } else { - // Assume yamlSource is a local file path relative to project root - log.Printf("Starting mcmp API sync: Using local file path %s", yamlSource) - localYamlPath = yamlSource - } - - // Read the local YAML file - log.Printf("Reading mcmp API definitions from %s", localYamlPath) - yamlData, err := os.ReadFile(localYamlPath) + // Read from local file only (no URL download) + log.Printf("Reading MCMP API definitions from local file: %s", localServiceActionsPath) + yamlData, err := os.ReadFile(localServiceActionsPath) if err != nil { - err = fmt.Errorf("failed to read local mcmp API YAML file %s: %w", localYamlPath, err) - log.Printf("Error syncing mcmp APIs: %v", err) - return err + return fmt.Errorf("failed to read service-actions.yaml from %s: %w", localServiceActionsPath, err) } - var defs mcmpapi.McmpApiDefinitions - err = yaml.Unmarshal(yamlData, &defs) - if err != nil { - err = fmt.Errorf("failed to unmarshal mcmp API YAML: %w", err) - log.Printf("Error syncing mcmp APIs: %v", err) - return err + // Parse the YAML structure with serviceActions containing _meta + var rawData map[string]interface{} + if err := yaml.Unmarshal(yamlData, &rawData); err != nil { + return fmt.Errorf("failed to unmarshal YAML: %w", err) } - // Save to Database - err = s.saveDefinitionsToDB(&defs) - if err != nil { - log.Printf("Error saving mcmp API definitions to database: %v", err) - return fmt.Errorf("failed to save mcmp API definitions to DB: %w", err) + serviceActionsRaw, ok := rawData["serviceActions"].(map[string]interface{}) + if !ok { + return fmt.Errorf("invalid YAML format: missing or invalid serviceActions") } - log.Println("Successfully synced mcmp API definitions to database.") - return nil + return s.syncServicesAndActions(serviceActionsRaw) } -// saveDefinitionsToDB handles the transaction and logic for saving definitions. -func (s *mcmpApiService) saveDefinitionsToDB(defs *mcmpapi.McmpApiDefinitions) error { - if defs == nil || len(defs.Services) == 0 { - log.Println("No service definitions provided to save.") - return nil // Nothing to save +// ensureTables creates MCMP API tables if they don't exist +func (s *mcmpApiService) ensureTables() error { + var count int64 + if err := s.db.Table("mcmp_api_services").Count(&count).Error; err != nil { + // Table doesn't exist, create it + if err := s.db.AutoMigrate(&mcmpapi.McmpApiService{}, &mcmpapi.McmpApiAction{}, &mcmpapi.McmpApiServiceMeta{}); err != nil { + return fmt.Errorf("failed to create mcmp API tables: %w", err) + } + log.Printf("Created mcmp API tables") } + return nil +} +// syncServicesAndActions processes service actions from parsed YAML and syncs to database +func (s *mcmpApiService) syncServicesAndActions(serviceActionsRaw map[string]interface{}) error { tx := s.db.Begin() if tx.Error != nil { return fmt.Errorf("failed to begin transaction: %w", tx.Error) @@ -192,74 +131,150 @@ func (s *mcmpApiService) saveDefinitionsToDB(defs *mcmpapi.McmpApiDefinitions) e defer func() { if r := recover(); r != nil { tx.Rollback() - panic(r) // Re-panic after rollback + panic(r) } }() - for name, serviceDef := range defs.Services { - // Check if service with the same name and version already exists (using non-transactional DB read is okay here) - _, err := s.repo.GetServiceByNameAndVersion(name, serviceDef.Version) - - if errors.Is(err, gorm.ErrRecordNotFound) { - // Service with this name and version does not exist, create it within the transaction - log.Printf("Adding new service definition: %s (Version: %s)", name, serviceDef.Version) - dbService := mcmpapi.McmpApiService{ - Name: name, - Version: serviceDef.Version, - BaseURL: serviceDef.BaseURL, - AuthType: serviceDef.Auth.Type, - AuthUser: serviceDef.Auth.Username, - AuthPass: serviceDef.Auth.Password, // Consider encryption - // IsActive defaults to false or needs explicit handling if required + for serviceName, actionsRaw := range serviceActionsRaw { + actionsMap, ok := actionsRaw.(map[string]interface{}) + if !ok { + log.Printf("Warning: invalid actions format for service %s, skipping", serviceName) + continue + } + + // Extract _meta + meta, err := s.extractMeta(serviceName, actionsMap) + if err != nil { + log.Printf("Warning: failed to extract meta for %s: %v", serviceName, err) + } + + // Check if update is needed + shouldUpdate, err := s.shouldUpdateService(serviceName, meta) + if err != nil { + log.Printf("Error checking service %s: %v", serviceName, err) + } + + if shouldUpdate { + // Upsert service meta + if meta != nil { + if err := s.repo.UpsertServiceMeta(tx, meta); err != nil { + tx.Rollback() + return fmt.Errorf("failed to upsert meta for %s: %w", serviceName, err) + } } - if createErr := s.repo.CreateService(tx, &dbService); createErr != nil { + + // Delete existing actions for this service (full replace) + if err := s.repo.DeleteActionsByServiceName(tx, serviceName); err != nil { tx.Rollback() - return fmt.Errorf("error creating service %s (Version: %s): %w", name, serviceDef.Version, createErr) + return fmt.Errorf("failed to delete actions for %s: %w", serviceName, err) } - // Add Actions ONLY for the newly created service version - if actions, ok := defs.ServiceActions[name]; ok { - log.Printf("Adding actions for new service: %s (Version: %s)", name, serviceDef.Version) - for actionName, actionDef := range actions { - dbAction := mcmpapi.McmpApiAction{ - ServiceName: name, // Link to the service name - ActionName: actionName, - Method: actionDef.Method, - ResourcePath: actionDef.ResourcePath, - Description: actionDef.Description, - // Version linking might be needed here if actions are version-specific - } - if createActionErr := s.repo.CreateAction(tx, &dbAction); createActionErr != nil { - tx.Rollback() - return fmt.Errorf("error creating action %s for service %s: %w", actionName, name, createActionErr) - } + // Create new actions + actionCount := 0 + for actionName, actionRaw := range actionsMap { + if actionName == "_meta" { + continue // Skip meta entry + } + + actionDef, ok := actionRaw.(map[string]interface{}) + if !ok { + log.Printf("Warning: invalid action format for %s/%s, skipping", serviceName, actionName) + continue + } + + action := &mcmpapi.McmpApiAction{ + ServiceName: serviceName, + ActionName: actionName, + Method: s.getString(actionDef, "method"), + ResourcePath: s.getString(actionDef, "resourcePath"), + Description: s.getString(actionDef, "description"), + } + + if err := s.repo.CreateAction(tx, action); err != nil { + tx.Rollback() + return fmt.Errorf("failed to create action %s for %s: %w", actionName, serviceName, err) } + actionCount++ } - } else if err != nil { - // Other DB error during check - tx.Rollback() - return fmt.Errorf("error checking existing service %s (Version: %s): %w", name, serviceDef.Version, err) + + version := "" + if meta != nil { + version = meta.Version + } + log.Printf("Updated service: %s (version: %s, actions: %d)", serviceName, version, actionCount) } else { - // Service with this name and version already exists, skip. - log.Printf("Skipping existing service definition: %s (Version: %s)", name, serviceDef.Version) + log.Printf("Skipping service %s - no changes detected", serviceName) } } if err := tx.Commit().Error; err != nil { - // Rollback might have already happened, but doesn't hurt to call again if needed - // tx.Rollback() return fmt.Errorf("failed to commit transaction: %w", err) } - return nil // Commit successful + log.Println("Successfully synced mcmp API definitions to database.") + return nil } -// Implement other methods like GetMcmpService, GetMcmpAction if needed, -// likely by calling corresponding repository methods. -// Example: -// func (s *mcmpApiService) GetMcmpService(name string) (*mcmpapi.McmpApiService, error) { // Renamed -// return s.repo.GetService(name) // Assumes repo method exists -// } +// extractMeta extracts _meta information from service actions map +func (s *mcmpApiService) extractMeta(serviceName string, actionsMap map[string]interface{}) (*mcmpapi.McmpApiServiceMeta, error) { + metaRaw, ok := actionsMap["_meta"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("no _meta found for service %s", serviceName) + } + + generatedAtStr := s.getString(metaRaw, "generatedAt") + var generatedAt time.Time + if generatedAtStr != "" { + parsed, err := time.Parse(time.RFC3339, generatedAtStr) + if err != nil { + log.Printf("Warning: failed to parse generatedAt for %s: %v", serviceName, err) + } else { + generatedAt = parsed + } + } + + return &mcmpapi.McmpApiServiceMeta{ + ServiceName: serviceName, + Version: s.getString(metaRaw, "version"), + Repository: s.getString(metaRaw, "repository"), + GeneratedAt: generatedAt, + }, nil +} + +// shouldUpdateService checks if a service needs to be updated based on version metadata +func (s *mcmpApiService) shouldUpdateService(serviceName string, newMeta *mcmpapi.McmpApiServiceMeta) (bool, error) { + if newMeta == nil { + return true, nil // No meta, always update + } + + existingMeta, err := s.repo.GetServiceMeta(serviceName) + if errors.Is(err, gorm.ErrRecordNotFound) { + return true, nil // New service + } + if err != nil { + return false, err + } + + // Compare version and generatedAt + if existingMeta.Version != newMeta.Version { + log.Printf("Service %s version changed: %s -> %s", serviceName, existingMeta.Version, newMeta.Version) + return true, nil + } + if !existingMeta.GeneratedAt.Equal(newMeta.GeneratedAt) { + log.Printf("Service %s generatedAt changed: %v -> %v", serviceName, existingMeta.GeneratedAt, newMeta.GeneratedAt) + return true, nil + } + + return false, nil // No changes +} + +// getString safely extracts a string value from a map +func (s *mcmpApiService) getString(m map[string]interface{}, key string) string { + if v, ok := m[key].(string); ok { + return v + } + return "" +} // SetActiveVersion sets the specified version of a service as active. func (s *mcmpApiService) SetActiveVersion(serviceName, version string) error { @@ -446,4 +461,184 @@ func (s *mcmpApiService) McmpApiCall(ctx context.Context, req *model.McmpApiCall return statusCode, respBody, serviceVersion, calledURL, err } -// Removed ServiceApiCall function implementation +// ImportAPIs fetches API specifications from remote URLs and imports them to the database +func (s *mcmpApiService) ImportAPIs(req *model.ImportApiRequest) (*model.ImportApiResponse, error) { + // Ensure tables exist + if err := s.ensureTables(); err != nil { + return nil, fmt.Errorf("failed to ensure tables: %w", err) + } + + processor := apiparser.NewProcessor(30) // 30 second timeout + + response := &model.ImportApiResponse{ + TotalFrameworks: len(req.Frameworks), + FrameworkResults: make([]model.ImportApiFrameworkResult, 0, len(req.Frameworks)), + } + + for _, fw := range req.Frameworks { + result := model.ImportApiFrameworkResult{ + Name: fw.Name, + Version: fw.Version, + } + + // Process the framework + fwResult := processor.ProcessFramework(fw.Name, fw.Version, fw.Repository, fw.SourceType, fw.SourceURL) + + if fwResult.Error != nil { + result.Success = false + result.ErrorMessage = fwResult.Error.Error() + response.FailureCount++ + log.Printf("Failed to import framework %s: %v", fw.Name, fwResult.Error) + } else { + // Sync to database - use the new method if service info is provided + var err error + if fw.BaseURL != "" { + // Use the new method that saves service info + err = s.syncFrameworkWithServiceInfo(fw.Name, fw.Version, fw.Repository, fw.BaseURL, fw.AuthType, fw.AuthUser, fw.AuthPass, fwResult.Actions) + } else { + // Use the old method (meta + actions only) + err = s.syncFrameworkToDatabase(fw.Name, fw.Version, fw.Repository, fwResult.Actions) + log.Printf("Warning: Framework '%s' imported without service info (baseUrl not provided)", fw.Name) + } + + if err != nil { + result.Success = false + result.ErrorMessage = fmt.Sprintf("failed to save to database: %v", err) + response.FailureCount++ + log.Printf("Failed to save framework %s to database: %v", fw.Name, err) + } else { + result.Success = true + result.ActionCount = fwResult.ActionCount + response.SuccessCount++ + log.Printf("Successfully imported framework %s (version: %s, actions: %d)", fw.Name, fw.Version, fwResult.ActionCount) + } + } + + response.FrameworkResults = append(response.FrameworkResults, result) + } + + return response, nil +} + +// syncFrameworkToDatabase saves a single framework's actions to the database +func (s *mcmpApiService) syncFrameworkToDatabase(serviceName, version, repository string, actions map[string]apiparser.ServiceAction) error { + tx := s.db.Begin() + if tx.Error != nil { + return fmt.Errorf("failed to begin transaction: %w", tx.Error) + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + panic(r) + } + }() + + // Upsert service meta + meta := &mcmpapi.McmpApiServiceMeta{ + ServiceName: serviceName, + Version: version, + Repository: repository, + GeneratedAt: time.Now(), + } + if err := s.repo.UpsertServiceMeta(tx, meta); err != nil { + tx.Rollback() + return fmt.Errorf("failed to upsert meta: %w", err) + } + + // Delete existing actions for this service (full replace) + if err := s.repo.DeleteActionsByServiceName(tx, serviceName); err != nil { + tx.Rollback() + return fmt.Errorf("failed to delete existing actions: %w", err) + } + + // Create new actions + for actionName, actionDef := range actions { + action := &mcmpapi.McmpApiAction{ + ServiceName: serviceName, + ActionName: actionName, + Method: actionDef.Method, + ResourcePath: actionDef.ResourcePath, + Description: actionDef.Description, + } + + if err := s.repo.CreateAction(tx, action); err != nil { + tx.Rollback() + return fmt.Errorf("failed to create action %s: %w", actionName, err) + } + } + + if err := tx.Commit().Error; err != nil { + return fmt.Errorf("failed to commit transaction: %w", err) + } + + return nil +} + +// syncFrameworkWithServiceInfo saves a framework's actions and service info to the database +func (s *mcmpApiService) syncFrameworkWithServiceInfo(serviceName, version, repository, baseURL, authType, authUser, authPass string, actions map[string]apiparser.ServiceAction) error { + tx := s.db.Begin() + if tx.Error != nil { + return fmt.Errorf("failed to begin transaction: %w", tx.Error) + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + panic(r) + } + }() + + // Upsert service meta + meta := &mcmpapi.McmpApiServiceMeta{ + ServiceName: serviceName, + Version: version, + Repository: repository, + GeneratedAt: time.Now(), + } + if err := s.repo.UpsertServiceMeta(tx, meta); err != nil { + tx.Rollback() + return fmt.Errorf("failed to upsert meta: %w", err) + } + + // Upsert service (with BaseURL and Auth info) + service := &mcmpapi.McmpApiService{ + Name: serviceName, + Version: version, + BaseURL: baseURL, + AuthType: authType, + AuthUser: authUser, + AuthPass: authPass, + IsActive: true, + } + if err := s.repo.UpsertService(tx, service); err != nil { + tx.Rollback() + return fmt.Errorf("failed to upsert service: %w", err) + } + + // Delete existing actions for this service (full replace) + if err := s.repo.DeleteActionsByServiceName(tx, serviceName); err != nil { + tx.Rollback() + return fmt.Errorf("failed to delete existing actions: %w", err) + } + + // Create new actions + for actionName, actionDef := range actions { + action := &mcmpapi.McmpApiAction{ + ServiceName: serviceName, + ActionName: actionName, + Method: actionDef.Method, + ResourcePath: actionDef.ResourcePath, + Description: actionDef.Description, + } + + if err := s.repo.CreateAction(tx, action); err != nil { + tx.Rollback() + return fmt.Errorf("failed to create action %s: %w", actionName, err) + } + } + + if err := tx.Commit().Error; err != nil { + return fmt.Errorf("failed to commit transaction: %w", err) + } + + return nil +} diff --git a/src/service/project_service.go b/src/service/project_service.go index bda1fb78..7ac39c26 100644 --- a/src/service/project_service.go +++ b/src/service/project_service.go @@ -6,9 +6,10 @@ import ( "errors" // "errors" // Remove unused import - "fmt" // Add fmt import for errors - "log" // Add log import - "os" // Import os package to read environment variables + "fmt" // Add fmt import for errors + "log" // Add log import + "os" // Import os package to read environment variables + "strings" // Add strings import for string operations // "net/http" // Remove unused import @@ -45,7 +46,8 @@ func NewProjectService(db *gorm.DB) *ProjectService { } // Create 프로젝트 생성 (mc-infra-manager 호출 및 DB 저장) -func (s *ProjectService) Create(ctx context.Context, project *model.Project) error { +// workspaceID is optional: if 0, assigns to default workspace; otherwise assigns to specified workspace +func (s *ProjectService) Create(ctx context.Context, project *model.Project, workspaceID ...uint) error { // 이름 중복 체크 existingProject, err := s.projectRepo.FindProjectByProjectName(project.Name) if err == nil && existingProject != nil { @@ -55,6 +57,51 @@ func (s *ProjectService) Create(ctx context.Context, project *model.Project) err return err } + // Step 0: Determine target workspace (specified or default) and validate BEFORE calling mc-infra-manager + var targetWorkspace *model.Workspace + var targetWorkspaceID uint + + if len(workspaceID) > 0 && workspaceID[0] != 0 { + // Workspace specified, verify it exists + targetWorkspaceID = workspaceID[0] + targetWorkspace, err = s.workspaceRepo.FindWorkspaceByID(targetWorkspaceID) + if err != nil || targetWorkspace == nil { + log.Printf("Error finding specified workspace %d: %v", targetWorkspaceID, err) + return fmt.Errorf("workspace not found") + } + log.Printf("Validated specified workspace: %s (ID: %d)", targetWorkspace.Name, targetWorkspace.ID) + } else { + // No workspace specified, use default + defaultWsName := os.Getenv("DEFAULT_WORKSPACE_NAME") + if defaultWsName == "" { + defaultWsName = "default" + log.Printf("DEFAULT_WORKSPACE_NAME not set in environment, using default value: %s", defaultWsName) + } + log.Printf("Using default workspace name: %s", defaultWsName) + targetWorkspace, err = s.workspaceRepo.FindWorkspaceByName(defaultWsName) + if err != nil { + if err.Error() == "workspace not found" { + // Default workspace doesn't exist, create it + log.Printf("Default workspace '%s' not found. Creating it...", defaultWsName) + newWorkspace := &model.Workspace{ + Name: defaultWsName, + Description: "Default workspace for automatically synced projects", + } + if err := s.workspaceRepo.CreateWorkspace(newWorkspace); err != nil { + log.Printf("Error creating default workspace '%s': %v", defaultWsName, err) + return fmt.Errorf("failed to create default workspace: %w", err) + } + log.Printf("Successfully created default workspace '%s'", defaultWsName) + targetWorkspace = newWorkspace + } else { + log.Printf("Error finding default workspace '%s': %v. Cannot assign projects.", defaultWsName, err) + return fmt.Errorf("failed to find or create default workspace: %w", err) + } + } + targetWorkspaceID = targetWorkspace.ID + } + log.Printf("Workspace validation complete. Will assign project to workspace: %s (ID: %d)", targetWorkspace.Name, targetWorkspaceID) + log.Printf("Attempting to create namespace in mc-infra-manager for project: %s", project.Name) // Check if mcmpApiService is properly initialized @@ -68,38 +115,31 @@ func (s *ProjectService) Create(ctx context.Context, project *model.Project) err "name": project.Name, "description": project.Description, } - // bodyBytes, err := json.Marshal(nsRequestBody) // Don't marshal here - // if err != nil { - // log.Printf("Error marshalling request body for PostNs: %v", err) - // return fmt.Errorf("failed to marshal request body for PostNs: %w", err) - // } callReq := &model.McmpApiCallRequest{ ServiceName: "mc-infra-manager", - ActionName: "Postns", // Corrected action name based on previous analysis + ActionName: "Postns", RequestParams: model.McmpApiRequestParams{ - Body: nsRequestBody, // Pass the original map directly + Body: nsRequestBody, }, } log.Printf("About to call mcmpApiService.McmpApiCall with service: %+v", s.mcmpApiService) - statusCode, respBody, serviceVersion, calledURL, err := s.mcmpApiService.McmpApiCall(ctx, callReq) // Get new return values + statusCode, respBody, serviceVersion, calledURL, err := s.mcmpApiService.McmpApiCall(ctx, callReq) if err != nil { - // Include version and URL in the error message log.Printf("Error calling %s(v%s) %s (URL: %s): %v (status code: %d)", callReq.ServiceName, serviceVersion, callReq.ActionName, calledURL, err, statusCode) return fmt.Errorf("failed to call %s(v%s) %s (URL: %s): %w (status code: %d)", callReq.ServiceName, serviceVersion, callReq.ActionName, calledURL, err, statusCode) } if statusCode < 200 || statusCode >= 300 { - // Include version and URL in the error message log.Printf("%s(v%s) %s call failed (URL: %s): status code %d, response: %s", callReq.ServiceName, serviceVersion, callReq.ActionName, calledURL, statusCode, string(respBody)) var errorResp map[string]interface{} - errMsg := fmt.Sprintf("%s(v%s) %s call failed with status code %d (URL: %s)", callReq.ServiceName, serviceVersion, callReq.ActionName, statusCode, calledURL) // Base error message + errMsg := fmt.Sprintf("%s(v%s) %s call failed with status code %d (URL: %s)", callReq.ServiceName, serviceVersion, callReq.ActionName, statusCode, calledURL) if json.Unmarshal(respBody, &errorResp) == nil { if msg, ok := errorResp["message"].(string); ok { - errMsg = fmt.Sprintf("%s(v%s) error: %s (URL: %s, Status: %d)", callReq.ServiceName, serviceVersion, msg, calledURL, statusCode) // More specific message if possible + errMsg = fmt.Sprintf("%s(v%s) error: %s (URL: %s, Status: %d)", callReq.ServiceName, serviceVersion, msg, calledURL, statusCode) } } - return errors.New(errMsg) // Return as a simple error for now, or wrap if needed + return errors.New(errMsg) } // Extract NsId from response @@ -124,44 +164,17 @@ func (s *ProjectService) Create(ctx context.Context, project *model.Project) err // 2. Create project in local DB if err := s.projectRepo.CreateProject(project); err != nil { - return err // Return DB creation error + return err } - // 3. Assign to default workspace - defaultWsName := os.Getenv("DEFAULT_WORKSPACE_NAME") - if defaultWsName == "" { - defaultWsName = "default" - log.Printf("DEFAULT_WORKSPACE_NAME not set in environment, using default value: %s", defaultWsName) + // 3. Assign project to target workspace (already validated above) + if err := s.projectRepo.AddProjectWorkspaceAssociation(project.ID, targetWorkspaceID); err != nil { + log.Printf("Error assigning project %d to workspace %d: %v", project.ID, targetWorkspaceID, err) + return nil // Project created but assignment failed } - log.Printf("Using workspace name: %s", defaultWsName) - defaultWs, err := s.workspaceRepo.FindWorkspaceByName(defaultWsName) - if err != nil { - if err.Error() == "workspace not found" { - // Default workspace doesn't exist, create it - log.Printf("Default workspace '%s' not found. Creating it...", defaultWsName) - newWorkspace := &model.Workspace{ - Name: defaultWsName, - Description: "Default workspace for automatically synced projects", - } - if err := s.workspaceRepo.CreateWorkspace(newWorkspace); err != nil { - log.Printf("Error creating default workspace '%s': %v", defaultWsName, err) - return fmt.Errorf("failed to create default workspace: %w", err) - } - log.Printf("Successfully created default workspace '%s'", defaultWsName) - defaultWs = newWorkspace - } else { - log.Printf("Error finding default workspace '%s': %v. Cannot assign projects.", defaultWsName, err) - return fmt.Errorf("failed to find or create default workspace: %w", err) - } - } - if err := s.projectRepo.AddProjectWorkspaceAssociation(project.ID, defaultWs.ID); err != nil { - log.Printf("Error assigning project %d to default workspace %d: %v", project.ID, defaultWs.ID, err) - // Log a warning, but the project creation was successful. - return nil // Or return fmt.Errorf("failed to assign project to default workspace: %w", err) - } - log.Printf("Successfully assigned project %d to default workspace %d", project.ID, defaultWs.ID) + log.Printf("Successfully assigned project %d to workspace %d (%s)", project.ID, targetWorkspaceID, targetWorkspace.Name) - return nil // Project created and assigned (or assignment failed but logged) + return nil } // List 모든 프로젝트 조회 @@ -169,6 +182,18 @@ func (s *ProjectService) ListProjects(req *model.ProjectFilterRequest) ([]*model return s.projectRepo.FindProjects(req) } +// GetProjectWorkspaces 프로젝트에 할당된 workspace 목록 조회 +func (s *ProjectService) GetProjectWorkspaces(projectID uint) ([]*model.Workspace, error) { + // 프로젝트 존재 여부 확인 + _, err := s.projectRepo.FindProjectByProjectID(projectID) + if err != nil { + return nil, err + } + + // 할당된 workspace 목록 조회 + return s.projectRepo.FindAssignedWorkspaces(projectID) +} + // GetByID ID로 프로젝트 조회 func (s *ProjectService) GetProjectByID(id uint) (*model.Project, error) { return s.projectRepo.FindProjectByProjectID(id) @@ -191,10 +216,54 @@ func (s *ProjectService) UpdateProject(id uint, updates map[string]interface{}) // Delete 프로젝트 삭제 func (s *ProjectService) DeleteProject(id uint) error { - _, err := s.projectRepo.FindProjectByProjectID(id) + // 1. 프로젝트 존재 여부 확인 + project, err := s.projectRepo.FindProjectByProjectID(id) if err != nil { return err } + + // 2. 워크스페이스 할당 확인 + workspaces, err := s.projectRepo.FindAssignedWorkspaces(id) + if err != nil { + return fmt.Errorf("워크스페이스 할당 확인 실패: %v", err) + } + + // 3. 할당된 워크스페이스가 있으면 삭제 불가 + if len(workspaces) > 0 { + workspaceNames := make([]string, len(workspaces)) + for i, ws := range workspaces { + workspaceNames[i] = ws.Name + } + return fmt.Errorf("프로젝트가 워크스페이스에 할당되어 있습니다: %s. 먼저 모든 워크스페이스에서 할당을 해제하세요", + strings.Join(workspaceNames, ", ")) + } + + // 4. mc-infra-manager namespace 삭제 + if project.NsId != "" { + ctx := context.Background() + callReq := &model.McmpApiCallRequest{ + ServiceName: "mc-infra-manager", + ActionName: "DeleteNs", + RequestParams: model.McmpApiRequestParams{ + PathParams: map[string]string{ + "nsId": project.NsId, + }, + }, + } + + statusCode, respBody, _, _, err := s.mcmpApiService.McmpApiCall(ctx, callReq) + if err != nil { + log.Printf("Warning: failed to delete namespace %s from mc-infra-manager: %v", project.NsId, err) + // 계속 진행 (DB 정리는 수행) + } else if statusCode < 200 || statusCode >= 300 { + log.Printf("Warning: mc-infra-manager DeleteNs failed (status %d): %s", statusCode, string(respBody)) + // 계속 진행 (DB 정리는 수행) + } else { + log.Printf("Successfully deleted namespace %s from mc-infra-manager", project.NsId) + } + } + + // 5. DB에서 프로젝트 삭제 return s.projectRepo.DeleteProject(id) } diff --git a/src/service/workspace_service.go b/src/service/workspace_service.go index 78f63f24..c600f835 100644 --- a/src/service/workspace_service.go +++ b/src/service/workspace_service.go @@ -4,7 +4,7 @@ import ( "context" "errors" "fmt" - "os" + "strings" "github.com/m-cmp/mc-iam-manager/constants" "github.com/m-cmp/mc-iam-manager/model" @@ -73,17 +73,23 @@ func (s *WorkspaceService) UpdateWorkspace(workspace *model.Workspace) error { // Delete 워크스페이스 삭제 func (s *WorkspaceService) DeleteWorkspace(workspaceID uint) error { - // Check if workspace exists - workspace, err := s.workspaceRepo.FindWorkspaceProjectsByWorkspaceID(workspaceID) // 실제 존재하는 workspace인지 확인 + // 1. 워크스페이스 존재 확인 + workspace, err := s.workspaceRepo.FindWorkspaceProjectsByWorkspaceID(workspaceID) if err != nil { return err } - // 워크스페이스에 연결된 프로젝트가 있는지 확인 + // 2. 할당된 프로젝트 확인 if len(workspace.Projects) > 0 { - return errors.New("워크스페이스에 연결된 프로젝트가 있습니다") + projectNames := make([]string, len(workspace.Projects)) + for i, p := range workspace.Projects { + projectNames[i] = p.Name + } + return fmt.Errorf("워크스페이스에 연결된 프로젝트가 있습니다: %s. 먼저 모든 프로젝트를 제거하세요", + strings.Join(projectNames, ", ")) } + // 3. 삭제 실행 return s.workspaceRepo.DeleteWorkspace(workspaceID) } @@ -181,50 +187,11 @@ func (s *WorkspaceService) AddProjectToWorkspace(workspaceID, projectID uint) er // RemoveProjectFromWorkspace 워크스페이스에서 프로젝트 제거 func (s *WorkspaceService) RemoveProjectFromWorkspace(workspaceID, projectID uint) error { - // 프로젝트가 다른 워크스페이스에 할당되어 있는지 확인 - assignedWorkspaces, err := s.projectRepo.FindAssignedWorkspaces(projectID) - if err != nil { - return fmt.Errorf("워크스페이스 할당 정보를 가져오는데 실패했습니다: %v", err) - } - - // 현재 워크스페이스에서만 할당되어 있는 경우에만 기본 워크스페이스에 할당 - if len(assignedWorkspaces) == 1 && assignedWorkspaces[0].ID == workspaceID { - // 기본 워크스페이스 조회 - defaultWsName := os.Getenv("DEFAULT_WORKSPACE_NAME") - if defaultWsName == "" { - defaultWsName = "default" - } - defaultWs, err := s.workspaceRepo.FindWorkspaceByName(defaultWsName) - if err != nil { - if err.Error() == "workspace not found" { - // 기본 워크스페이스가 없으면 생성 - newWorkspace := &model.Workspace{ - Name: defaultWsName, - Description: "Default workspace for automatically synced projects", - } - if err := s.workspaceRepo.CreateWorkspace(newWorkspace); err != nil { - return fmt.Errorf("기본 워크스페이스 생성에 실패했습니다: %v", err) - } - defaultWs = newWorkspace - } else { - return fmt.Errorf("기본 워크스페이스를 찾는데 실패했습니다: %v", err) - } - } - - // 기존 워크스페이스에서 제거 - if err := s.workspaceRepo.RemoveProjectAssociation(workspaceID, projectID); err != nil { - return fmt.Errorf("워크스페이스 연결 제거에 실패했습니다: %v", err) - } - - // 기본 워크스페이스에 할당 - if err := s.workspaceRepo.AddProjectAssociation(defaultWs.ID, projectID); err != nil { - return fmt.Errorf("기본 워크스페이스 할당에 실패했습니다: %v", err) - } - } else { - // 다른 워크스페이스에도 할당되어 있는 경우 단순히 현재 워크스페이스에서만 제거 - if err := s.workspaceRepo.RemoveProjectAssociation(workspaceID, projectID); err != nil { - return fmt.Errorf("워크스페이스 연결 제거에 실패했습니다: %v", err) - } + // 워크스페이스에서 프로젝트 제거 + // 기본 workspace 포함 모든 workspace에서 제거 가능 + // 프로젝트는 미할당 상태가 될 수 있음 + if err := s.workspaceRepo.RemoveProjectAssociation(workspaceID, projectID); err != nil { + return fmt.Errorf("워크스페이스 연결 제거에 실패했습니다: %v", err) } return nil