diff --git a/Dockerfile b/Dockerfile index 1843bb9..35a89e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM cloudforet/python-core:1.12 +FROM cloudforet/python-core:2.0 ARG PACKAGE_VERSION ENV PYTHONUNBUFFERED 1 ENV SPACEONE_PORT 50051 @@ -9,7 +9,8 @@ ENV PACKAGE_VERSION=$PACKAGE_VERSION COPY pkg/pip_requirements.txt pip_requirements.txt -RUN pip install --upgrade -r pip_requirements.txt +RUN pip install --upgrade pip && \ + pip install --upgrade -r pip_requirements.txt COPY src ${SRC_DIR} WORKDIR ${SRC_DIR} @@ -21,4 +22,4 @@ RUN pip install --upgrade spaceone-api EXPOSE ${SPACEONE_PORT} ENTRYPOINT ["spaceone"] -CMD ["grpc", "spaceone.dashboard", "-m", "/opt"] +CMD ["run", "grpc-server", "spaceone.dashboard", "-m", "/opt"] diff --git a/deploy/helm/Chart.yaml b/deploy/helm/Chart.yaml index c5da2e0..a8340b5 100644 --- a/deploy/helm/Chart.yaml +++ b/deploy/helm/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.3.10 +version: 1.3.11 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/deploy/helm/config/config.yaml b/deploy/helm/config/config.yaml index d9eef9a..98f3f9f 100644 --- a/deploy/helm/config/config.yaml +++ b/deploy/helm/config/config.yaml @@ -17,7 +17,6 @@ GLOBAL: backend: spaceone.core.cache.redis_cache.RedisCache host: redis port: 6379 - db: 1 encoding: utf-8 socket_timeout: 10 socket_connect_timeout: 10 @@ -30,14 +29,4 @@ GLOBAL: handlers: file: type: file - filename: /var/log/spaceone/dashboard.log - - HANDLERS: - authentication: - - backend: spaceone.core.handler.authentication_handler.AuthenticationGRPCHandler - uri: grpc+ssl://identity.dev.spaceone.dev:443/v1/Domain/get_public_key - authorization: - - backend: spaceone.core.handler.authorization_handler.AuthorizationGRPCHandler - uri: grpc+ssl://identity.dev.spaceone.dev:443/v1/Authorization/verify - mutation: - - backend: spaceone.core.handler.mutation_handler.SpaceONEMutationHandler \ No newline at end of file + filename: /var/log/spaceone/dashboard.log \ No newline at end of file diff --git a/deploy/helm/templates/deployment-rest.yaml b/deploy/helm/templates/deployment-rest.yaml index 78d243b..9272b22 100644 --- a/deploy/helm/templates/deployment-rest.yaml +++ b/deploy/helm/templates/deployment-rest.yaml @@ -43,7 +43,7 @@ spec: resources: {{- toYaml .Values.resources.rest | nindent 12 }} {{- end }} - command: ['spaceone', 'rest', 'spaceone.{{ regexReplaceAll "-" .Values.name "_" }}', '-p', '8000'] + command: ['spaceone', 'run', 'rest-server', 'spaceone.{{ regexReplaceAll "-" .Values.name "_" }}', '-p', '8000'] ports: - containerPort: 8000 volumeMounts: diff --git a/deploy/helm/templates/deployment-scheduler.yaml b/deploy/helm/templates/deployment-scheduler.yaml index 9ae9bf3..e212adc 100644 --- a/deploy/helm/templates/deployment-scheduler.yaml +++ b/deploy/helm/templates/deployment-scheduler.yaml @@ -43,7 +43,7 @@ spec: resources: {{- toYaml .Values.resources.scheduler | nindent 12 }} {{- end }} - command: ['spaceone', 'scheduler', 'spaceone.{{ regexReplaceAll "-" .Values.name "_" }}'] + command: ['spaceone', 'run', 'scheduler', 'spaceone.{{ regexReplaceAll "-" .Values.name "_" }}'] volumeMounts: - name: default-conf mountPath: /opt/spaceone/{{ .Values.name }}/config/config.yaml @@ -85,7 +85,7 @@ spec: {{- end }} volumes: - - name: default-conf + - name: default-conf configMap: name: {{ .Values.name }}-conf - name: database-conf diff --git a/deploy/helm/templates/deployment-worker.yaml b/deploy/helm/templates/deployment-worker.yaml index bb30a1d..157239e 100644 --- a/deploy/helm/templates/deployment-worker.yaml +++ b/deploy/helm/templates/deployment-worker.yaml @@ -43,7 +43,7 @@ spec: resources: {{- toYaml .Values.resources.worker | nindent 12 }} {{- end }} - command: ['spaceone', 'scheduler', 'spaceone.{{ regexReplaceAll "-" .Values.name "_" }}', '-m', '/opt'] + command: ['spaceone', 'run', 'scheduler', 'spaceone.{{ regexReplaceAll "-" .Values.name "_" }}', '-m', '/opt'] volumeMounts: - name: default-conf mountPath: /opt/spaceone/{{ .Values.name }}/config/config.yaml diff --git a/src/spaceone/dashboard/conf/global_conf.py b/src/spaceone/dashboard/conf/global_conf.py index 99ddc69..e08a6d2 100644 --- a/src/spaceone/dashboard/conf/global_conf.py +++ b/src/spaceone/dashboard/conf/global_conf.py @@ -42,7 +42,7 @@ # Connector Settings CONNECTORS = { "SpaceConnector": { - "backend": "spaceone.core.connector.space_connector.SpaceConnector", + "backend": "spaceone.core.connector.space_connector:SpaceConnector", "endpoints": { "identity": "grpc://identity:50051", }, diff --git a/src/spaceone/dashboard/info/__init__.py b/src/spaceone/dashboard/info/__init__.py index 1fc25d9..0b8c7f2 100644 --- a/src/spaceone/dashboard/info/__init__.py +++ b/src/spaceone/dashboard/info/__init__.py @@ -1,2 +1,3 @@ -from spaceone.dashboard.info.domain_dashboard_info import * -from spaceone.dashboard.info.domain_dashboard_version_info import * +from spaceone.dashboard.info.dashboard_info import * +from spaceone.dashboard.info.dashboard_version_info import * +from spaceone.dashboard.info.common_info import * diff --git a/src/spaceone/dashboard/info/common_info.py b/src/spaceone/dashboard/info/common_info.py new file mode 100644 index 0000000..a47f60d --- /dev/null +++ b/src/spaceone/dashboard/info/common_info.py @@ -0,0 +1,12 @@ +from google.protobuf.empty_pb2 import Empty +from spaceone.core.pygrpc.message_type import * + +__all__ = ["EmptyInfo", "StatisticsInfo"] + + +def EmptyInfo(): + return Empty() + + +def StatisticsInfo(result): + return change_struct_type(result) diff --git a/src/spaceone/dashboard/info/dashboard_info.py b/src/spaceone/dashboard/info/dashboard_info.py index c528fc7..45e7ff9 100644 --- a/src/spaceone/dashboard/info/dashboard_info.py +++ b/src/spaceone/dashboard/info/dashboard_info.py @@ -1,47 +1,46 @@ import functools -from spaceone.api.dashboard.v1 import domain_dashboard_pb2 +from spaceone.api.dashboard.v1 import dashboard_pb2 from spaceone.core.pygrpc.message_type import * from spaceone.core import utils from spaceone.dashboard.model.dashboard_model import Dashboard -__all__ = ["DomainDashboardInfo", "DomainDashboardsInfo"] +__all__ = ["DashboardInfo", "DashboardsInfo"] -def DomainDashboardInfo(domain_dashboard_vo: Dashboard, minimal=False): +def DashboardInfo(dashboard_vo: Dashboard, minimal=False): info = { - "domain_dashboard_id": domain_dashboard_vo.domain_dashboard_id, - "name": domain_dashboard_vo.name, - "viewers": domain_dashboard_vo.viewers, - "version": domain_dashboard_vo.version, - "labels": change_list_value_type(domain_dashboard_vo.labels), - "user_id": domain_dashboard_vo.user_id, - "domain_id": domain_dashboard_vo.domain_id, + "dashboard_id": dashboard_vo.dashboard_id, + "name": dashboard_vo.name, + "dashboard_type": dashboard_vo.dashboard_type, + "version": dashboard_vo.version, + "labels": change_list_value_type(dashboard_vo.labels), + "resource_group": dashboard_vo.resource_group, + "user_id": dashboard_vo.user_id, + "project_id": dashboard_vo.project_id, + "workspace_id": dashboard_vo.workspace_id, + "domain_id": dashboard_vo.domain_id, } if not minimal: info.update( { - "layouts": change_list_value_type(domain_dashboard_vo.layouts) - if domain_dashboard_vo.layouts + "layouts": change_list_value_type(dashboard_vo.layouts) + if dashboard_vo.layouts else None, - "variables": change_struct_type(domain_dashboard_vo.variables), - "settings": change_struct_type(domain_dashboard_vo.settings), - "variables_schema": change_struct_type( - domain_dashboard_vo.variables_schema - ), - "tags": change_struct_type(domain_dashboard_vo.tags), - "created_at": utils.datetime_to_iso8601(domain_dashboard_vo.created_at), - "updated_at": utils.datetime_to_iso8601(domain_dashboard_vo.updated_at), + "variables": change_struct_type(dashboard_vo.variables), + "settings": change_struct_type(dashboard_vo.settings), + "variables_schema": change_struct_type(dashboard_vo.variables_schema), + "tags": change_struct_type(dashboard_vo.tags), + "created_at": utils.datetime_to_iso8601(dashboard_vo.created_at), + "updated_at": utils.datetime_to_iso8601(dashboard_vo.updated_at), } ) - return domain_dashboard_pb2.DomainDashboardInfo(**info) + return dashboard_pb2.DashboardInfo(**info) -def DomainDashboardsInfo(domain_dashboard_vos, total_count, **kwargs): - return domain_dashboard_pb2.DomainDashboardsInfo( - results=list( - map(functools.partial(DomainDashboardInfo, **kwargs), domain_dashboard_vos) - ), +def DashboardsInfo(dashboard_vos, total_count, **kwargs): + return dashboard_pb2.DashboardsInfo( + results=list(map(functools.partial(DashboardInfo, **kwargs), dashboard_vos)), total_count=total_count, ) diff --git a/src/spaceone/dashboard/info/dashboard_version_info.py b/src/spaceone/dashboard/info/dashboard_version_info.py index e0170b5..45c25eb 100644 --- a/src/spaceone/dashboard/info/dashboard_version_info.py +++ b/src/spaceone/dashboard/info/dashboard_version_info.py @@ -1,24 +1,24 @@ import functools -from spaceone.api.dashboard.v1 import domain_dashboard_pb2 +from spaceone.api.dashboard.v1 import dashboard_pb2 from spaceone.core.pygrpc.message_type import * from spaceone.core import utils from spaceone.dashboard.model import DashboardVersion -__all__ = ["DomainDashboardVersionInfo", "DomainDashboardVersionsInfo"] +__all__ = ["DashboardVersionInfo", "DashboardVersionsInfo"] -def DomainDashboardVersionInfo( - domain_dashboard_version_vo: DashboardVersion, minimal=False, latest_version=None +def DashboardVersionInfo( + dashboard_version_vo: DashboardVersion, minimal=False, latest_version=None ): info = { - "domain_dashboard_id": domain_dashboard_version_vo.domain_dashboard_id, - "version": domain_dashboard_version_vo.version, - "created_at": utils.datetime_to_iso8601(domain_dashboard_version_vo.created_at), - "domain_id": domain_dashboard_version_vo.domain_id, + "dashboard_id": dashboard_version_vo.dashboard_id, + "version": dashboard_version_vo.version, + "created_at": utils.datetime_to_iso8601(dashboard_version_vo.created_at), + "domain_id": dashboard_version_vo.domain_id, } if latest_version: - if latest_version == domain_dashboard_version_vo.version: + if latest_version == dashboard_version_vo.version: info.update({"latest": True}) else: info.update({"latest": False}) @@ -26,26 +26,26 @@ def DomainDashboardVersionInfo( if not minimal: info.update( { - "layouts": change_list_value_type(domain_dashboard_version_vo.layouts) - if domain_dashboard_version_vo.layouts + "layouts": change_list_value_type(dashboard_version_vo.layouts) + if dashboard_version_vo.layouts else None, - "variables": change_struct_type(domain_dashboard_version_vo.variables), - "settings": change_struct_type(domain_dashboard_version_vo.settings), + "variables": change_struct_type(dashboard_version_vo.variables), + "settings": change_struct_type(dashboard_version_vo.settings), "variables_schema": change_struct_type( - domain_dashboard_version_vo.variables_schema + dashboard_version_vo.variables_schema ), } ) - return domain_dashboard_pb2.DomainDashboardVersionInfo(**info) + return dashboard_pb2.DashboardVersionInfo(**info) -def DomainDashboardVersionsInfo(domain_dashboard_version_vos, total_count, **kwargs): - return domain_dashboard_pb2.DomainDashboardVersionsInfo( +def DashboardVersionsInfo(dashboard_version_vos, total_count, **kwargs): + return dashboard_pb2.DashboardVersionsInfo( results=list( map( - functools.partial(DomainDashboardVersionInfo, **kwargs), - domain_dashboard_version_vos, + functools.partial(DashboardVersionInfo, **kwargs), + dashboard_version_vos, ) ), total_count=total_count, diff --git a/src/spaceone/dashboard/manager/__init__.py b/src/spaceone/dashboard/manager/__init__.py index 1624fe4..0ad11a9 100644 --- a/src/spaceone/dashboard/manager/__init__.py +++ b/src/spaceone/dashboard/manager/__init__.py @@ -1,2 +1,3 @@ from spaceone.dashboard.manager.dashboard_manager import DashboardManager from spaceone.dashboard.manager.dashboard_version_manager import DashboardVersionManager +from spaceone.dashboard.manager.identity_manager import IdentityManager diff --git a/src/spaceone/dashboard/manager/dashboard_manager.py b/src/spaceone/dashboard/manager/dashboard_manager.py index 4a9e93a..56a62c3 100644 --- a/src/spaceone/dashboard/manager/dashboard_manager.py +++ b/src/spaceone/dashboard/manager/dashboard_manager.py @@ -8,69 +8,80 @@ class DashboardManager(BaseManager): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.domain_dashboard_model: Dashboard = self.locator.get_model("Dashboard") + self.dashboard_model: Dashboard = self.locator.get_model("Dashboard") - def create_domain_dashboard(self, params): - def _rollback(domain_dashboard_vo): + def create_dashboard(self, params: dict) -> Dashboard: + def _rollback(vo: Dashboard) -> None: _LOGGER.info( - f"[create_domain_dashboard._rollback] " - f"Delete domain_dashboard_vo : {domain_dashboard_vo.name} " - f"({domain_dashboard_vo.domain_dashboard_id})" + f"[create_dashboard._rollback] " + f"Delete vo : {vo.name} " + f"({vo.dashboard_id})" ) - domain_dashboard_vo.delete() + vo.delete() - domain_dashboard_vo: Dashboard = self.domain_dashboard_model.create(params) - self.transaction.add_rollback(_rollback, domain_dashboard_vo) + dashboard_vo: Dashboard = self.dashboard_model.create(params) + self.transaction.add_rollback(_rollback, dashboard_vo) - return domain_dashboard_vo + return dashboard_vo - def update_domain_dashboard(self, params): - domain_dashboard_vo: Dashboard = self.get_domain_dashboard( - params["domain_dashboard_id"], params["domain_id"] + def update_dashboard(self, params: dict) -> Dashboard: + dashboard_vo: Dashboard = self.get_dashboard( + params["dashboard_id"], params["domain_id"] ) - return self.update_domain_dashboard_by_vo(params, domain_dashboard_vo) + return self.update_dashboard_by_vo(params, dashboard_vo) - def update_domain_dashboard_by_vo(self, params, domain_dashboard_vo): - def _rollback(old_data): + def update_dashboard_by_vo( + self, params: dict, dashboard_vo: Dashboard + ) -> Dashboard: + def _rollback(old_data: dict) -> None: _LOGGER.info( - f"[update_domain_dashboard_by_vo._rollback] Revert Data : " - f'{old_data["domain_dashboard_id"]}' + f"[update_dashboard_by_vo._rollback] Revert Data : " + f'{old_data["dashboard_id"]}' ) - domain_dashboard_vo.update(old_data) + dashboard_vo.update(old_data) - self.transaction.add_rollback(_rollback, domain_dashboard_vo.to_dict()) - return domain_dashboard_vo.update(params) + self.transaction.add_rollback(_rollback, dashboard_vo.to_dict()) + return dashboard_vo.update(params) - def delete_domain_dashboard(self, domain_dashboard_id, domain_id): - domain_dashboard_vo: Dashboard = self.get_domain_dashboard( - domain_dashboard_id, domain_id - ) - domain_dashboard_vo.delete() + def delete_dashboard(self, dashboard_id: str, domain_id: str) -> None: + dashboard_vo: Dashboard = self.get_dashboard(dashboard_id, domain_id) + dashboard_vo.delete() - def get_domain_dashboard(self, domain_dashboard_id, domain_id, only=None): - return self.domain_dashboard_model.get( - domain_dashboard_id=domain_dashboard_id, domain_id=domain_id, only=only - ) + def get_dashboard( + self, + dashboard_id: str, + domain_id: str, + workspace_id: str = None, + user_projects=None, + ) -> Dashboard: + conditions = {"dashboard_id": dashboard_id, "domain_id": domain_id} + + if workspace_id: + conditions["workspace_id"] = workspace_id + + if user_projects: + conditions["project_id"] = user_projects + + return self.dashboard_model.get(**conditions) - def list_domain_dashboards(self, query=None): + def list_dashboards(self, query=None): if query is None: query = {} - return self.domain_dashboard_model.query(**query) + return self.dashboard_model.query(**query) - def stat_domain_dashboards(self, query): - return self.domain_dashboard_model.stat(**query) + def stat_dashboards(self, query: dict) -> dict: + return self.dashboard_model.stat(**query) - def increase_version(self, domain_dashboard_vo): + def increase_version(self, dashboard_vo: Dashboard) -> None: def _rollback(vo: Dashboard): _LOGGER.info( - f"[increase_version._rollback] Decrease Version : " - f"{vo.domain_dashboard_id}" + f"[increase_version._rollback] Decrease Version : " f"{vo.dashboard_id}" ) vo.decrement("version") - domain_dashboard_vo.increment("version") - self.transaction.add_rollback(_rollback, domain_dashboard_vo) + dashboard_vo.increment("version") + self.transaction.add_rollback(_rollback, dashboard_vo) @staticmethod - def delete_by_domain_dashboard_vo(domain_dashboard_vo): - domain_dashboard_vo.delete() + def delete_by_dashboard_vo(dashboard_vo: Dashboard) -> None: + dashboard_vo.delete() diff --git a/src/spaceone/dashboard/manager/dashboard_version_manager.py b/src/spaceone/dashboard/manager/dashboard_version_manager.py index aa3fc95..8da9cf2 100644 --- a/src/spaceone/dashboard/manager/dashboard_version_manager.py +++ b/src/spaceone/dashboard/manager/dashboard_version_manager.py @@ -1,6 +1,7 @@ import logging from spaceone.core.manager import BaseManager from spaceone.dashboard.model import DashboardVersion +from spaceone.dashboard.model import Dashboard _LOGGER = logging.getLogger(__name__) @@ -8,66 +9,64 @@ class DashboardVersionManager(BaseManager): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.domain_dashboard_version_model: DashboardVersion = self.locator.get_model( + self.dashboard_version_model: DashboardVersion = self.locator.get_model( "DashboardVersion" ) - def create_version_by_domain_dashboard_vo(self, domain_dashboard_vo, params): - def _rollback(version_vo): + def create_version_by_dashboard_vo( + self, dashboard_vo: Dashboard, params: dict + ) -> DashboardVersion: + def _rollback(vo: DashboardVersion) -> None: _LOGGER.info( - f"[create_domain_dashboard_version._rollback] " - f"Delete domain_dashboard_version_vo : {version_vo.version} " - f"({version_vo.domain_dashboard_id})" + f"[create_dashboard_version._rollback] " + f"Delete dashboard_version_vo : {vo.version} " + f"({vo.dashboard_id})" ) - version_vo.delete() + vo.delete() new_params = { - "domain_dashboard_id": domain_dashboard_vo.domain_dashboard_id, - "version": domain_dashboard_vo.version, + "dashboard_id": dashboard_vo.dashboard_id, + "version": dashboard_vo.version, "layouts": params.get("layouts") if params.get("layouts") - else domain_dashboard_vo.layouts, + else dashboard_vo.layouts, "variables": params.get("variables") if params.get("variables") - else domain_dashboard_vo.variables, + else dashboard_vo.variables, "settings": params.get("settings") if params.get("settings") - else domain_dashboard_vo.settings, + else dashboard_vo.settings, "variables_schema": params.get("variables_schema") if params.get("variables_schema") - else domain_dashboard_vo.variables_schema, - "domain_id": domain_dashboard_vo.domain_id, + else dashboard_vo.variables_schema, + "domain_id": dashboard_vo.domain_id, } - version_vo: DashboardVersion = self.domain_dashboard_version_model.create( - new_params - ) + version_vo: DashboardVersion = self.dashboard_version_model.create(new_params) self.transaction.add_rollback(_rollback, version_vo) return version_vo - def delete_version(self, domain_dashboard_id, version, domain_id): + def delete_version(self, dashboard_id: str, version: int, domain_id: str) -> None: version_vo: DashboardVersion = self.get_version( - domain_dashboard_id, version, domain_id + dashboard_id, version, domain_id ) version_vo.delete() - def delete_versions_by_domain_dashboard_version_vos( - self, domain_dashboard_version_vos - ): + @staticmethod + def delete_versions_by_dashboard_version_vos(domain_dashboard_version_vos): domain_dashboard_version_vos.delete() - def get_version(self, domain_dashboard_id, version, domain_id, only=None): - return self.domain_dashboard_version_model.get( - domain_dashboard_id=domain_dashboard_id, + def get_version(self, dashboard_id, version, domain_id): + return self.dashboard_version_model.get( + dashboard_id=dashboard_id, version=version, domain_id=domain_id, - only=only, ) - def list_versions(self, query=None): + def list_versions(self, query: dict = None) -> dict: if query is None: query = {} - return self.domain_dashboard_version_model.query(**query) + return self.dashboard_version_model.query(**query) - def filter_versions(self, **conditions): - return self.domain_dashboard_version_model.filter(**conditions) + def filter_versions(self, **conditions) -> dict: + return self.dashboard_version_model.filter(**conditions) diff --git a/src/spaceone/dashboard/manager/identity_manager.py b/src/spaceone/dashboard/manager/identity_manager.py new file mode 100644 index 0000000..00b5a9f --- /dev/null +++ b/src/spaceone/dashboard/manager/identity_manager.py @@ -0,0 +1,19 @@ +from spaceone.core.manager import BaseManager +from spaceone.core.connector.space_connector import SpaceConnector + + +class IdentityManager(BaseManager): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.identity_conn: SpaceConnector = self.locator.get_connector( + "SpaceConnector", service="identity" + ) + + def check_workspace(self, workspace_id: str, domain_id: str) -> None: + return self.identity_conn.dispatch( + "Workspace.check", + {"workspace_id": workspace_id, "domain_id": domain_id}, + ) + + def get_project(self, project_id: str) -> dict: + return self.identity_conn.dispatch("Project.get", {"project_id": project_id}) diff --git a/src/spaceone/dashboard/model/dashboard_model.py b/src/spaceone/dashboard/model/dashboard_model.py index 96852c4..49a32fa 100644 --- a/src/spaceone/dashboard/model/dashboard_model.py +++ b/src/spaceone/dashboard/model/dashboard_model.py @@ -5,11 +5,9 @@ class Dashboard(MongoModel): - domain_dashboard_id = StringField( - max_length=40, generate_id="domain-dash", unique=True - ) + dashboard_id = StringField(max_length=40, generate_id="dash", unique=True) name = StringField(max_length=100) - viewers = StringField(max_length=255, choices=("PUBLIC", "PRIVATE")) + dashboard_type = StringField(max_length=40, choices=("PUBLIC", "PRIVATE")) version = IntField(default=1) layouts = ListField(default=[]) variables = DictField(default={}) @@ -17,7 +15,12 @@ class Dashboard(MongoModel): variables_schema = DictField(default={}) labels = ListField(StringField()) tags = DictField(default={}) + resource_group = StringField( + max_length=40, choices=("DOMAIN", "WORKSPACE", "PROJECT") + ) user_id = StringField(max_length=40) + project_id = StringField(max_length=40) + workspace_id = StringField(max_length=40) domain_id = StringField(max_length=40) created_at = DateTimeField(auto_now_add=True) updated_at = DateTimeField(auto_now=True) @@ -33,37 +36,49 @@ class Dashboard(MongoModel): "tags", ], "minimal_fields": [ - "domain_dashboard_id", + "dashboard_id", "name", - "viewers", + "dashboard_type", "version", + "resource_group", "user_id", + "project_id", + "workspace_id", "domain_id", ], "ordering": ["name"], - "indexes": ["name", "viewers", "labels", "user_id", "domain_id"], + "indexes": [ + "name", + "dashboard_type", + "labels", + "resource_group", + "user_id", + "project_id", + "workspace_id", + "domain_id", + ], } @classmethod def create(cls, data): - domain_dashboard_vos = cls.filter( - name=data["name"], user_id=data["user_id"], domain_id=data["domain_id"] + dashboard_vos = cls.filter( + name=data["name"], user_id=data.get("user_id"), domain_id=data["domain_id"] ) - print(domain_dashboard_vos) - if domain_dashboard_vos.count() > 0: + + if dashboard_vos.count() > 0: raise ERROR_NOT_UNIQUE(key="name", value=data["name"]) return super().create(data) def update(self, data): if "name" in data: - domain_dashboard_vos = self.filter( + dashboard_vos = self.filter( name=data["name"], user_id=self.user_id, domain_id=self.domain_id, - domain_dashboard_id__ne=self.domain_dashboard_id, + dashboard_id__ne=self.dashboard_id, ) - if domain_dashboard_vos.count() > 0: + if dashboard_vos.count() > 0: raise ERROR_NOT_UNIQUE(key="name", value=data["name"]) else: return super().update(data) diff --git a/src/spaceone/dashboard/model/dashboard_version_model.py b/src/spaceone/dashboard/model/dashboard_version_model.py index 45a7bc2..e059db6 100644 --- a/src/spaceone/dashboard/model/dashboard_version_model.py +++ b/src/spaceone/dashboard/model/dashboard_version_model.py @@ -4,7 +4,7 @@ class DashboardVersion(MongoModel): - domain_dashboard_id = StringField(max_length=40) + dashboard_id = StringField(max_length=40) version = IntField() layouts = ListField(default=[]) variables = DictField(default={}) @@ -16,11 +16,11 @@ class DashboardVersion(MongoModel): meta = { "updatable_fields": [], "minimal_fields": [ - "domain_dashboard_id", + "dashboard_id", "version", "domain_id", "created_at", ], "ordering": ["-version"], - "indexes": ["domain_dashboard_id", "version", "domain_id", "created_at"], + "indexes": ["dashboard_id", "version", "domain_id", "created_at"], } diff --git a/src/spaceone/dashboard/service/dashboard_service.py b/src/spaceone/dashboard/service/dashboard_service.py index 9768d13..7431525 100644 --- a/src/spaceone/dashboard/service/dashboard_service.py +++ b/src/spaceone/dashboard/service/dashboard_service.py @@ -2,7 +2,11 @@ import logging from spaceone.core.service import * -from spaceone.dashboard.manager import DashboardManager, DashboardVersionManager +from spaceone.dashboard.manager import ( + DashboardManager, + DashboardVersionManager, + IdentityManager, +) from spaceone.dashboard.model import Dashboard, DashboardVersion from spaceone.dashboard.error import * @@ -22,12 +26,13 @@ def __init__(self, *args, **kwargs): self.version_mgr: DashboardVersionManager = self.locator.get_manager( "DashboardVersionManager" ) + self.identity_mgr: IdentityManager = self.locator.get_manager("IdentityManager") @transaction( permission="dashboard:Dashboard.write", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) - @check_required(["name", "dashboard_type", "user_id", "domain_id"]) + @check_required(["name", "dashboard_type", "domain_id"]) def create(self, params: dict) -> Dashboard: """Register domain_dashboard @@ -42,21 +47,36 @@ def create(self, params: dict) -> Dashboard: 'labels': 'list', 'tags': 'dict', 'resource_group': 'str', # required - 'user_id': 'str', # injected from auth - 'project_id': 'str', # injected from auth + 'project_id': 'str', 'workspace_id': 'str', # injected from auth - 'domain_id': 'str' # injected from auth + 'domain_id': 'str' # injected from auth (required) } Returns: dashboard_vo (object) """ - dashboard_vo = self.dashboard_mgr.create_domain_dashboard(params) + resource_group = params["resource_group"] + project_id = params.get("project_id") + workspace_id = params.get("workspace_id") + domain_id = params["domain_id"] + + # Check permission by resource group + if resource_group == "PROJECT": + project_info = self.identity_mgr.get_project(project_id) + params["workspace_id"] = project_info["workspace_id"] + elif resource_group == "WORKSPACE": + self.identity_mgr.check_workspace(workspace_id, domain_id) + params["project_id"] = "*" + else: + params["workspace_id"] = "*" + params["project_id"] = "*" + + dashboard_vo = self.dashboard_mgr.create_dashboard(params) version_keys = ["layouts", "variables", "variables_schema"] if any(set(version_keys) & set(params.keys())): - self.version_mgr.create_version_by_domain_dashboard_vo(dashboard_vo, params) + self.version_mgr.create_version_by_dashboard_vo(dashboard_vo, params) return dashboard_vo @@ -70,7 +90,7 @@ def update(self, params): Args: params (dict): { - 'dashboard_id': 'str', + 'dashboard_id': 'str', # required 'name': 'str', 'layouts': 'list', 'variables': 'dict', @@ -78,7 +98,9 @@ def update(self, params): 'variables_schema': 'list', 'labels': 'list', 'tags': 'dict', - 'domain_id': 'str' + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list' # injected from auth } Returns: @@ -87,18 +109,18 @@ def update(self, params): dashboard_id = params["dashboard_id"] domain_id = params["domain_id"] + workspace_id = params.get("workspace_id") + user_projects = params.get("user_projects") + user_id = self.transaction.get_meta("authorization.user_id") - dashboard_vo: Dashboard = self.dashboard_mgr.get_domain_dashboard( - dashboard_id, domain_id + dashboard_vo: Dashboard = self.dashboard_mgr.get_dashboard( + dashboard_id, domain_id, workspace_id, user_projects ) if "name" not in params: params["name"] = dashboard_vo.name - if ( - dashboard_vo.viewers == "PRIVATE" - and dashboard_vo.user_id != self.transaction.get_meta("user_id") - ): + if dashboard_vo.dashboard_type == "PRIVATE" and dashboard_vo.user_id != user_id: raise ERROR_PERMISSION_DENIED() if "settings" in params: @@ -109,9 +131,9 @@ def update(self, params): version_change_keys = ["layouts", "variables", "variables_schema"] if self._has_version_key_in_params(dashboard_vo, params, version_change_keys): self.dashboard_mgr.increase_version(dashboard_vo) - self.version_mgr.create_version_by_domain_dashboard_vo(dashboard_vo, params) + self.version_mgr.create_version_by_dashboard_vo(dashboard_vo, params) - return self.dashboard_mgr.update_domain_dashboard_by_vo(params, dashboard_vo) + return self.dashboard_mgr.update_dashboard_by_vo(params, dashboard_vo) @transaction( permission="dashboard:Dashboard.write", @@ -123,46 +145,53 @@ def delete(self, params): Args: params (dict): { - 'dashboard_id': 'str', - 'domain_id': 'str' + 'dashboard_id': 'str', # required + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list' # injected from auth } Returns: None """ + dashboard_id = params["dashboard_id"] + workspace_id = params.get("workspace_id") + domain_id = params["domain_id"] + user_projects = params.get("user_projects") + user_id = self.transaction.get_meta("authorization.user_id") - dashboard_vo: Dashboard = self.dashboard_mgr.get_domain_dashboard( - params["dashboard_id"], params["domain_id"] + dashboard_vo: Dashboard = self.dashboard_mgr.get_dashboard( + dashboard_id, domain_id, workspace_id, user_projects ) - if ( - dashboard_vo.viewers == "PRIVATE" - and dashboard_vo.user_id != self.transaction.get_meta("user_id") - ): + if dashboard_vo.dashboard_type == "PRIVATE" and dashboard_vo.user_id != user_id: raise ERROR_PERMISSION_DENIED() if domain_dashboard_version_vos := self.version_mgr.filter_versions( - dashboard_id=dashboard_vo.dashboard_id + dashboard_id=dashboard_vo.dashboard_id, domain_id=domain_id ): - self.version_mgr.delete_versions_by_domain_dashboard_version_vos( + self.version_mgr.delete_versions_by_dashboard_version_vos( domain_dashboard_version_vos ) - self.dashboard_mgr.delete_by_domain_dashboard_vo(dashboard_vo) + self.dashboard_mgr.delete_by_dashboard_vo(dashboard_vo) @transaction( permission="dashboard:Dashboard.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") + @change_value_by_rule("APPEND", "user_projects", "*") @check_required(["dashboard_id", "domain_id"]) def get(self, params): """Get domain_dashboard Args: params (dict): { - 'dashboard_id': 'str', - 'domain_id': 'str', - 'only': 'list + 'dashboard_id': 'str', # required + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list', # injected from auth } Returns: @@ -170,15 +199,15 @@ def get(self, params): """ dashboard_id = params["dashboard_id"] domain_id = params["domain_id"] + workspace_id = params.get("workspace_id") + user_projects = params.get("user_projects") + user_id = self.transaction.get_meta("authorization.user_id") - dashboard_vo = self.dashboard_mgr.get_domain_dashboard( - dashboard_id, domain_id, params.get("only") + dashboard_vo = self.dashboard_mgr.get_dashboard( + dashboard_id, domain_id, workspace_id, user_projects ) - if ( - dashboard_vo.viewers == "PRIVATE" - and dashboard_vo.user_id != self.transaction.get_meta("user_id") - ): + if dashboard_vo.dashboard_type == "PRIVATE" and dashboard_vo.user_id != user_id: raise ERROR_PERMISSION_DENIED() return dashboard_vo @@ -193,9 +222,11 @@ def delete_version(self, params): Args: params (dict): { - 'dashboard_id': 'str', - 'version': 'int', - 'domain_id': 'str', + 'dashboard_id': 'str', # required + 'version': 'int', # required + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list', # injected from auth } Returns: @@ -205,13 +236,15 @@ def delete_version(self, params): dashboard_id = params["dashboard_id"] version = params["version"] domain_id = params["domain_id"] + workspace_id = params.get("workspace_id") + user_projects = params.get("user_projects") + user_id = self.transaction.get_meta("authorization.user_id") - dashboard_vo = self.dashboard_mgr.get_domain_dashboard(dashboard_id, domain_id) + dashboard_vo = self.dashboard_mgr.get_dashboard( + dashboard_id, domain_id, workspace_id, user_projects + ) - if ( - dashboard_vo.viewers == "PRIVATE" - and dashboard_vo.user_id != self.transaction.get_meta("user_id") - ): + if dashboard_vo.dashboard_type == "PRIVATE" and dashboard_vo.user_id != user_id: raise ERROR_PERMISSION_DENIED() current_version = dashboard_vo.version @@ -230,9 +263,11 @@ def revert_version(self, params): Args: params (dict): { - 'dashboard_id': 'str', - 'version': 'int', - 'domain_id': 'str', + 'dashboard_id': 'str', # required + 'version': 'int', # required + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list', # injected from auth } Returns: @@ -242,15 +277,15 @@ def revert_version(self, params): dashboard_id = params["dashboard_id"] version = params["version"] domain_id = params["domain_id"] + workspace_id = params.get("workspace_id") + user_projects = params.get("user_projects") + user_id = self.transaction.get_meta("authorization.user_id") - dashboard_vo: Dashboard = self.dashboard_mgr.get_domain_dashboard( - dashboard_id, domain_id + dashboard_vo: Dashboard = self.dashboard_mgr.get_dashboard( + dashboard_id, domain_id, workspace_id, user_projects ) - if ( - dashboard_vo.viewers == "PRIVATE" - and dashboard_vo.user_id != self.transaction.get_meta("user_id") - ): + if dashboard_vo.dashboard_type == "PRIVATE" and dashboard_vo.user_id != user_id: raise ERROR_PERMISSION_DENIED() version_vo: DashboardVersion = self.version_mgr.get_version( @@ -262,24 +297,28 @@ def revert_version(self, params): params["variables_schema"] = version_vo.variables_schema self.dashboard_mgr.increase_version(dashboard_vo) - self.version_mgr.create_version_by_domain_dashboard_vo(dashboard_vo, params) + self.version_mgr.create_version_by_dashboard_vo(dashboard_vo, params) - return self.dashboard_mgr.update_domain_dashboard_by_vo(params, dashboard_vo) + return self.dashboard_mgr.update_dashboard_by_vo(params, dashboard_vo) @transaction( permission="dashboard:Dashboard.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") + @change_value_by_rule("APPEND", "user_projects", "*") @check_required(["dashboard_id", "version", "domain_id"]) def get_version(self, params): """Get version of domain dashboard Args: params (dict): { - 'dashboard_id': 'str', - 'version': 'int', - 'domain_id': 'str', - 'only': 'list + 'dashboard_id': 'str', # required + 'version': 'int', # required + 'user_id': 'str', # injected from auth + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list', # injected from auth } Returns: @@ -289,25 +328,25 @@ def get_version(self, params): dashboard_id = params["dashboard_id"] version = params["version"] domain_id = params["domain_id"] + workspace_id = params.get("workspace_id") + user_projects = params.get("user_projects") + user_id = self.transaction.get_meta("authorization.user_id") - dashboard_vo: Dashboard = self.dashboard_mgr.get_domain_dashboard( - dashboard_id, domain_id + dashboard_vo: Dashboard = self.dashboard_mgr.get_dashboard( + dashboard_id, domain_id, workspace_id, user_projects ) - if ( - dashboard_vo.viewers == "PRIVATE" - and dashboard_vo.user_id != self.transaction.get_meta("user_id") - ): + if dashboard_vo.dashboard_type == "PRIVATE" and dashboard_vo.user_id != user_id: raise ERROR_PERMISSION_DENIED() - return self.version_mgr.get_version( - dashboard_id, version, domain_id, params.get("only") - ) + return self.version_mgr.get_version(dashboard_id, version, domain_id) @transaction( permission="dashboard:Dashboard.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") + @change_value_by_rule("APPEND", "user_projects", "*") @check_required(["dashboard_id", "domain_id"]) @append_query_filter(["dashboard_id", "version", "domain_id"]) @append_keyword_filter(["dashboard_id", "version"]) @@ -316,10 +355,12 @@ def list_versions(self, params): Args: params (dict): { - 'dashboard_id': 'str', - 'version': 'int', - 'domain_id': 'str', + 'dashboard_id': 'str', # required 'query': 'dict (spaceone.api.core.v1.Query)' + 'version': 'int', + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list', # injected from auth } Returns: @@ -328,17 +369,19 @@ def list_versions(self, params): """ dashboard_id = params["dashboard_id"] domain_id = params["domain_id"] + workspace_id = params.get("workspace_id") + user_projects = params.get("user_projects") + user_id = self.transaction.get_meta("authorization.user_id") query = params.get("query", {}) domain_dashboard_version_vos, total_count = self.version_mgr.list_versions( query ) - dashboard_vo = self.dashboard_mgr.get_domain_dashboard(dashboard_id, domain_id) + dashboard_vo = self.dashboard_mgr.get_dashboard( + dashboard_id, domain_id, workspace_id, user_projects + ) - if ( - dashboard_vo.viewers == "PRIVATE" - and dashboard_vo.user_id != self.transaction.get_meta("user_id") - ): + if dashboard_vo.dashboard_type == "PRIVATE" and dashboard_vo.user_id != user_id: raise ERROR_PERMISSION_DENIED() return domain_dashboard_version_vos, total_count, dashboard_vo.version @@ -347,20 +390,24 @@ def list_versions(self, params): permission="dashboard:Dashboard.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") + @change_value_by_rule("APPEND", "user_projects", "*") @check_required(["domain_id"]) - @append_query_filter(["dashboard_id", "name", "viewers", "user_id", "domain_id"]) + @append_query_filter(["dashboard_id", "name", "viewers", "domain_id"]) @append_keyword_filter(["dashboard_id", "name"]) def list(self, params): """List public_dashboards Args: params (dict): { + 'query': 'dict (spaceone.api.core.v1.Query)' 'dashboard_id': 'str', 'name': 'str', - 'viewers': 'str', - 'user_id': 'str' - 'domain_id': 'str', - 'query': 'dict (spaceone.api.core.v1.Query)' + 'dashboard_type': 'str', + 'workspace_id': 'str', + 'project_id': 'str', + 'domain_id': 'str', # injected from auth + 'user_projects': 'list', # injected from auth } Returns: @@ -368,23 +415,26 @@ def list(self, params): total_count """ + user_id = self.transaction.get_meta("authorization.user_id") query = params.get("query", {}) query["filter"] = query.get("filter", []) query["filter"].append( { "k": "user_id", - "v": [self.transaction.get_meta("user_id"), None], + "v": [user_id, None], "o": "in", } ) - return self.dashboard_mgr.list_domain_dashboards(query) + return self.dashboard_mgr.list_dashboards(query) @transaction( permission="dashboard:Dashboard.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") + @change_value_by_rule("APPEND", "user_projects", "*") @check_required(["query", "domain_id"]) @append_query_filter(["domain_id"]) @append_keyword_filter(["dashboard_id", "name"]) @@ -392,29 +442,35 @@ def stat(self, params): """ Args: params (dict): { - 'domain_id': 'str', 'query': 'dict (spaceone.api.core.v1.StatisticsQuery)' + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str' # injected from auth (required) + 'user_projects': 'list', # injected from auth } Returns: values (list) : 'list of statistics data' """ + + user_id = self.transaction.get_meta("authorization.user_id") query = params.get("query", {}) query["filter"] = query.get("filter", []) query["filter"].append( { "k": "user_id", - "v": [self.transaction.get_meta("user_id"), None], + "v": [user_id, None], "o": "in", } ) - return self.dashboard_mgr.stat_domain_dashboards(query) + return self.dashboard_mgr.stat_dashboards(query) @staticmethod - def _has_version_key_in_params(dashboard_vo, params, version_change_keys): + def _has_version_key_in_params( + dashboard_vo: Dashboard, params: dict, version_change_keys: list + ) -> bool: layouts = dashboard_vo.layouts variables = dashboard_vo.variables variables_schema = dashboard_vo.variables_schema @@ -432,7 +488,7 @@ def _has_version_key_in_params(dashboard_vo, params, version_change_keys): return False @staticmethod - def _merge_settings(old_settings, new_settings): + def _merge_settings(old_settings: dict, new_settings: dict) -> dict: settings = copy.deepcopy(old_settings) if old_settings: