Skip to content

Commit

Permalink
Merge pull request #211 from ImMin5/master
Browse files Browse the repository at this point in the history
Add api for user add and remove at ProjectGroup
  • Loading branch information
ImMin5 authored Mar 14, 2024
2 parents 415651d + 08f0cbc commit 688f684
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 26 deletions.
40 changes: 26 additions & 14 deletions src/spaceone/identity/interface/grpc/project_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,54 @@ class ProjectGroup(BaseAPI, project_group_pb2_grpc.ProjectGroupServicer):

def create(self, request, context):
params, metadata = self.parse_request(request, context)
project_svc = ProjectGroupService(metadata)
response: dict = project_svc.create(params)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.create(params)
return self.dict_to_message(response)

def update(self, request, context):
params, metadata = self.parse_request(request, context)
project_svc = ProjectGroupService(metadata)
response: dict = project_svc.update(params)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.update(params)
return self.dict_to_message(response)

def change_parent_group(self, request, context):
params, metadata = self.parse_request(request, context)
project_svc = ProjectGroupService(metadata)
response: dict = project_svc.change_parent_group(params)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.change_parent_group(params)
return self.dict_to_message(response)

def delete(self, request, context):
params, metadata = self.parse_request(request, context)
project_svc = ProjectGroupService(metadata)
project_svc.delete(params)
project_group_svc = ProjectGroupService(metadata)
project_group_svc.delete(params)
return self.empty()

def add_users(self, request, context):
params, metadata = self.parse_request(request, context)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.add_users(params)
return self.dict_to_message(response)

def remove_users(self, request, context):
params, metadata = self.parse_request(request, context)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.remove_users(params)
return self.dict_to_message(response)

def get(self, request, context):
params, metadata = self.parse_request(request, context)
project_svc = ProjectGroupService(metadata)
response: dict = project_svc.get(params)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.get(params)
return self.dict_to_message(response)

def list(self, request, context):
params, metadata = self.parse_request(request, context)
project_svc = ProjectGroupService(metadata)
response: dict = project_svc.list(params)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.list(params)
return self.dict_to_message(response)

def stat(self, request, context):
params, metadata = self.parse_request(request, context)
project_svc = ProjectGroupService(metadata)
response: dict = project_svc.stat(params)
project_group_svc = ProjectGroupService(metadata)
response: dict = project_group_svc.stat(params)
return self.dict_to_message(response)
4 changes: 3 additions & 1 deletion src/spaceone/identity/manager/job_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ def change_canceled_status(job_vo: Job) -> None:
job_vo.update({"status": "CANCELED", "finished_at": datetime.utcnow()})

@staticmethod
def change_error_status(job_vo: Job, error: ERROR_BASE = None) -> None:
def change_error_status(
job_vo: Job, error: Union[ERROR_BASE, Exception] = None
) -> None:
if not isinstance(error, ERROR_BASE):
error = ERROR_UNKNOWN(message=str(error))
_LOGGER.debug(
Expand Down
5 changes: 5 additions & 0 deletions src/spaceone/identity/model/project_group/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class ProjectGroup(MongoModel):
project_group_id = StringField(max_length=40, generate_id="pg", unique=True)
name = StringField(max_length=40)
tags = DictField(default=None)
users = ListField(StringField(max_length=255), default=None)
parent_group_id = StringField(max_length=40, null=True, default=None)
workspace_id = StringField(max_length=40)
domain_id = StringField(max_length=40)
Expand All @@ -15,6 +16,7 @@ class ProjectGroup(MongoModel):
"updatable_fields": [
"name",
"tags",
"users",
"parent_group_id",
],
"minimal_fields": [
Expand All @@ -23,6 +25,9 @@ class ProjectGroup(MongoModel):
"parent_group_id",
"workspace_id",
],
"change_query_keys": {
"user_id": "users",
},
"ordering": ["name"],
"indexes": [
"parent_group_id",
Expand Down
18 changes: 17 additions & 1 deletion src/spaceone/identity/model/project_group/request.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from typing import Union, Literal
from typing import Union, Literal, List
from pydantic import BaseModel

__all__ = [
"ProjectGroupCreateRequest",
"ProjectGroupUpdateRequest",
"ProjectChangeParentGroupRequest",
"ProjectGroupDeleteRequest",
"ProjectGroupAddUsersRequest",
"ProjectGroupRemoveUsersRequest",
"ProjectGroupGetRequest",
"ProjectGroupSearchQueryRequest",
"ProjectGroupStatQueryRequest",
Expand Down Expand Up @@ -41,6 +43,20 @@ class ProjectGroupDeleteRequest(BaseModel):
domain_id: str


class ProjectGroupAddUsersRequest(BaseModel):
project_group_id: str
users: List[str]
workspace_id: str
domain_id: str


class ProjectGroupRemoveUsersRequest(BaseModel):
project_group_id: str
users: List[str]
workspace_id: str
domain_id: str


class ProjectGroupGetRequest(BaseModel):
project_group_id: str
workspace_id: Union[str, None] = None
Expand Down
1 change: 1 addition & 0 deletions src/spaceone/identity/model/project_group/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ProjectGroupResponse(BaseModel):
project_group_id: Union[str, None] = None
name: Union[str, None] = None
tags: Union[dict, None] = None
users: Union[List[str], None] = None
parent_group_id: Union[str, None] = None
workspace_id: Union[str, None] = None
domain_id: Union[str, None] = None
Expand Down
101 changes: 91 additions & 10 deletions src/spaceone/identity/service/job_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@
AccountCollectorPluginManager,
)
from spaceone.identity.manager.job_manager import JobManager
from spaceone.identity.manager.project_manager import ProjectManager
from spaceone.identity.manager.provider_manager import ProviderManager
from spaceone.identity.manager.secret_manager import SecretManager
from spaceone.identity.manager.schema_manager import SchemaManager
from spaceone.identity.manager.service_account_manager import ServiceAccountManager
from spaceone.identity.manager.secret_manager import SecretManager
from spaceone.identity.manager.trusted_account_manager import TrustedAccountManager
from spaceone.identity.manager.workspace_manager import WorkspaceManager
from spaceone.identity.model.project.database import Project
from spaceone.identity.model.provider.database import Provider
from spaceone.identity.model.service_account.database import ServiceAccount
from spaceone.identity.model.trusted_account.database import TrustedAccount
from spaceone.identity.model.job.database import Job
from spaceone.identity.model.job.request import *
Expand All @@ -36,6 +41,9 @@ def __init__(self, *args, **kwargs):
self.trusted_account_mgr = TrustedAccountManager()
self.provider_mgr = ProviderManager()
self.account_collector_plugin_mgr = AccountCollectorPluginManager()
self.workspace_mgr = WorkspaceManager()
self.service_account_mgr = ServiceAccountManager()
self.project_mgr = ProjectManager()

@transaction(exclude=["authentication", "authorization", "mutation"])
def create_jobs_by_trusted_account(self, params):
Expand Down Expand Up @@ -226,9 +234,11 @@ def sync_service_accounts(self, params: dict) -> None:
response = self.account_collector_plugin_mgr.sync(
endpoint, options, secret_data, domain_id, schema_id
)
for account_data in response.get("results", []):
self._check_service_account_data(account_data, job_vo, sync_options)
self._create_service_account(account_data, job_vo, sync_options)
for result in response.get("results", []):
# self._check_service_account_data(result, job_vo, sync_options)
# self._sync_accounts(
# provider, result, job_vo, sync_options, workspace_id
# )

if self._is_job_failed(job_id, domain_id, job_vo.workspace_id):
self.job_mgr.change_canceled_status(job_vo)
Expand Down Expand Up @@ -283,7 +293,7 @@ def created_service_account_job(
schema_mgr = SchemaManager()
# Check secret_data by schema
schema_mgr.validate_secret_data_by_schema_id(
schema_id, domain_id, trusted_secret_data, "SECRET"
schema_id, domain_id, trusted_secret_data, "TRUSTED_SECRET"
)
except Exception as e:
trusted_secret_data = {}
Expand Down Expand Up @@ -327,7 +337,7 @@ def _get_all_schedule_enabled_trusted_accounts(self, current_hour: int) -> list:
query = {
"filter": [
{"k": "schedule.state", "v": "ENABLED", "o": "eq"},
{"k": "schedule.hour", "v": current_hour, "o": "contain"},
{"k": "schedule.hour", "v": [current_hour], "o": "in"},
]
}
(
Expand Down Expand Up @@ -405,8 +415,79 @@ def _check_service_account_data(
# todo : complete this method
pass

def _create_service_account(
self, account_data: dict, job_vo: Job, sync_options: dict
def _sync_accounts(
self,
domain_id,
provider: str,
result: dict,
job_vo: Job,
sync_options: dict,
workspace_id: str = None,
) -> None:
# todo : complete this method
pass
locations = result.get("locations", [])
trusted_account_id = job_vo.trusted_account_id

if locations:
if len(locations) == 1:
project_vo = self._create_project(domain_id, workspace_id, locations[0])
self._create_service_account(
result, project_vo, trusted_account_id, provider, locations[0]
)
elif len(locations) == 2:
pass
else:
pass

def _create_project(
self,
domain_id: str,
workspace_id: str,
name: str,
project_type: str = "PRIVATE",
) -> Project:
params = {
"name": name,
"domain_id": domain_id,
"workspace_id": workspace_id,
"project_type": project_type,
}
project_vos = self.project_mgr.filter_projects(**params)
if project_vos:
project_vo = project_vos[0]
else:
project_vo = self.project_mgr.create_project(params)
return project_vo

def _create_service_account(
self,
result: dict,
project_vo: Project,
trusted_account_id: str,
provider: str,
name: str,
) -> ServiceAccount:
secret_data = result.get("secret_data", {})
data = result.get("data", {})
schema_id = result.get("secret_schema_id")
tags = result.get("tags", {})

if secret_data and schema_id is None:
raise ERROR_INVALID_PARAMETER(key="secret_schema_id")

params = {
"name": name,
"data": data,
"secret_data": secret_data,
"project_id": project_vo.project_id,
"workspace_id": project_vo.workspace_id,
"domain_id": project_vo.domain_id,
"provider": provider,
"trusted_account_id": trusted_account_id,
"tags": tags,
}

if schema_id:
params["schema_id"] = schema_id

service_account_vo = self.service_account_mgr.create_service_account(params)
return service_account_vo
78 changes: 78 additions & 0 deletions src/spaceone/identity/service/project_group_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from spaceone.identity.error.error_project_group import *
from spaceone.identity.manager.project_group_manager import ProjectGroupManager
from spaceone.identity.manager.workspace_user_manager import WorkspaceUserManager
from spaceone.identity.model.project_group.request import *
from spaceone.identity.model.project_group.response import *

Expand Down Expand Up @@ -161,6 +162,83 @@ def delete(self, params: ProjectGroupDeleteRequest) -> None:

self.project_group_mgr.delete_project_group_by_vo(project_group_vo)

@transaction(
permission="identity:ProjectGroup.write", role_types=["WORKSPACE_OWNER"]
)
@convert_model
def add_users(
self, params: ProjectGroupAddUsersRequest
) -> Union[ProjectGroupResponse, dict]:
"""Add users to project group
Args:
params (ProjectGroupAddUsersRequest): {
'project_group_id': 'str', # required
'user_ids': 'list', # required
'domain_id': 'str', # injected from auth (required)
'workspace_id': 'str' # injected from auth (required)
}
Returns:
ProjectGroupResponse:
"""

project_group_vo = self.project_group_mgr.get_project_group(
params.project_group_id,
params.domain_id,
params.workspace_id,
)

if len(params.users) > 0:
workspace_user_mgr = WorkspaceUserManager()
workspace_user_mgr.check_workspace_users(
params.users, params.workspace_id, params.domain_id
)

users = project_group_vo.users or []
users.extend(params.users)
params.users = list(set(users))

project_group_vo = self.project_group_mgr.update_project_group_by_vo(
params.dict(exclude_unset=True), project_group_vo
)

return ProjectGroupResponse(**project_group_vo.to_dict())

@transaction(
permission="identity:ProjectGroup.write", role_types=["WORKSPACE_OWNER"]
)
@convert_model
def remove_users(
self, params: ProjectGroupRemoveUsersRequest
) -> ProjectGroupResponse:
"""Remove users from project group
Args:
params: (ProjectGroupRemoveUsersRequest): {
'project_group_id': 'str', # required
'users': 'list', # required
'workspace_id': 'str', # injected from auth (required)
'domain_id': 'str' # injected from auth (required)
}
"""

project_group_vo = self.project_group_mgr.get_project_group(
params.project_group_id, params.domain_id, params.workspace_id
)
if len(params.users) > 0:
workspace_user_mgr = WorkspaceUserManager()
workspace_user_mgr.check_workspace_users(
params.users, params.workspace_id, params.domain_id
)

users = project_group_vo.users or []
params.users = list(set(users) - set(params.users))
project_group_vo = self.project_group_mgr.update_project_group_by_vo(
params.dict(exclude_unset=True), project_group_vo
)

return ProjectGroupResponse(**project_group_vo.to_dict())

@transaction(
permission="identity:ProjectGroup.read",
role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"],
Expand Down

0 comments on commit 688f684

Please sign in to comment.