Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update workspace group #340

Merged
merged 1 commit into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions src/spaceone/identity/interface/grpc/workspace_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,6 @@ def delete(self, request, context):
workspace_group_svc.delete(params)
return self.empty()

def add_workspaces(self, request, context):
params, metadata = self.parse_request(request, context)
workspace_group_svc = WorkspaceGroupService(metadata)
response: dict = workspace_group_svc.add_workspaces(params)
return self.dict_to_message(response)

def remove_workspaces(self, request, context):
params, metadata = self.parse_request(request, context)
workspace_group_svc = WorkspaceGroupService(metadata)
response: dict = workspace_group_svc.remove_workspaces(params)
return self.dict_to_message(response)

def find_users(self, request, context):
params, metadata = self.parse_request(request, context)
workspace_group_svc = WorkspaceGroupService(metadata)
response: dict = workspace_group_svc.find_users(params)
return self.dict_to_message(response)

def add_users(self, request, context):
params, metadata = self.parse_request(request, context)
workspace_group_svc = WorkspaceGroupService(metadata)
Expand Down
3 changes: 2 additions & 1 deletion src/spaceone/identity/manager/role_binding_manager.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import logging
from typing import Tuple
from mongoengine import QuerySet

from mongoengine import QuerySet
from spaceone.core.manager import BaseManager

from spaceone.identity.model.role_binding.database import RoleBinding

_LOGGER = logging.getLogger(__name__)
Expand Down
55 changes: 46 additions & 9 deletions src/spaceone/identity/manager/workspace_group_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import logging
from typing import Tuple
from typing import Dict, List, Tuple

from mongoengine import QuerySet
from spaceone.core.error import ERROR_INVALID_PARAMETER, ERROR_NOT_FOUND
from spaceone.core.manager import BaseManager

from spaceone.identity.manager.role_binding_manager import RoleBindingManager
Expand Down Expand Up @@ -51,19 +52,21 @@ def delete_workspace_group_by_vo(self, workspace_group_vo: WorkspaceGroup) -> No

if rb_vos.count() > 0:
_LOGGER.debug(
f"[delete_workspace_group_by_vo] Delete role bindings count with {workspace_group_vo.workspaces}: {rb_vos.count()}"
f"[delete_workspace_group_by_vo] Delete role bindings count with {workspace_group_vo.users}: {rb_vos.count()}"
)
rb_vos.delete()
for rb_vo in rb_vos:
_LOGGER.debug(
f"[delete_workspace_group_by_vo] Delete role binding info: {rb_vo.to_dict()}"
)
rb_vo.delete()

workspace_group_vo.delete()

# TODO: When add_users and remove_users, are user_id and role_type required?
def get_workspace_group(
self,
workspace_group_id: str,
domain_id: str,
user_id: str = None,
role_type: str = None,
) -> WorkspaceGroup:
conditions = {
"workspace_group_id": workspace_group_id,
Expand All @@ -73,10 +76,6 @@ def get_workspace_group(
if user_id:
conditions["users__user_id"] = user_id

# TODO: Check if this is correct
# if role_type:
# conditions["users__role_type"] = role_type

return self.workspace_group_model.get(**conditions)

def filter_workspace_groups(self, **conditions) -> QuerySet:
Expand All @@ -94,3 +93,41 @@ def check_user_id_in_users(user_id: str, workspace_group_vo: WorkspaceGroup):
workspace_group_user_id == user_id
for workspace_group_user_id in workspace_group_vo["users"]
)

def get_old_users_and_new_users(
self, users: List[Dict[str, str]], workspace_group_id: str, domain_id: str
) -> Tuple[List[str], List[str]]:
workspace_group_vo = self.get_workspace_group(workspace_group_id, domain_id)

old_users = list(
set(
[user_info["user_id"] for user_info in workspace_group_vo.users]
if workspace_group_vo.users
else []
)
)
new_users = list(set([user_info["user_id"] for user_info in users]))

return old_users, new_users

@staticmethod
def check_new_users_already_in_workspace_group(
old_users: List[str], new_users: List[str]
) -> None:
if set(old_users) & set(new_users):
_LOGGER.error(
f"Users {new_users} is already in workspace group or not registered."
)
raise ERROR_INVALID_PARAMETER(
key="users",
reason=f"User {new_users} is already in the workspace group or not registered.",
)

@staticmethod
def check_user_ids_exist_in_workspace_group(
old_user_ids: List[str], user_ids: List[str]
) -> None:
for user_id in user_ids:
if user_id not in old_user_ids:
_LOGGER.error(f"User ID {user_id} is not in workspace group.")
raise ERROR_NOT_FOUND(key="user_id", value=user_id)
27 changes: 20 additions & 7 deletions src/spaceone/identity/model/workspace_group/database.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
from mongoengine import DateTimeField, DictField, ListField, StringField
from mongoengine import (
DateTimeField,
DictField,
EmbeddedDocument,
EmbeddedDocumentField,
ListField,
StringField,
)
from spaceone.core.model.mongo_model import MongoModel


class WorkspaceGroupUser(EmbeddedDocument):
user_id = StringField(max_length=40, required=True)
role_id = StringField(max_length=40, required=True)
role_type = StringField(
max_length=20, choices=("WORKSPACE_OWNER", "WORKSPACE_MEMBER")
)


class WorkspaceGroup(MongoModel):
workspace_group_id = StringField(max_length=40, generate_id="wg", unique=True)
name = StringField(max_length=255, unique_with="domain_id")
workspaces = ListField(StringField(max_length=40), default=None, null=True)
users = ListField(DictField(default=None), default=None, null=True)
users = ListField(
EmbeddedDocumentField(WorkspaceGroupUser), default=None, null=True
)
tags = DictField(default=None)
created_by = StringField(max_length=255)
updated_by = StringField(max_length=255)
Expand All @@ -17,7 +33,6 @@ class WorkspaceGroup(MongoModel):
meta = {
"updatable_fields": [
"name",
"workspaces",
"users",
"tags",
"updated_by",
Expand All @@ -27,9 +42,7 @@ class WorkspaceGroup(MongoModel):
"workspace_group_id",
"name",
],
"change_query_keys": {
"workspace_id": "workspaces",
},
"change_query_keys": {},
"ordering": ["name"],
"indexes": [
"workspace_group_id",
Expand Down
16 changes: 0 additions & 16 deletions src/spaceone/identity/model/workspace_group/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
"WorkspaceGroupCreateRequest",
"WorkspaceGroupUpdateRequest",
"WorkspaceGroupDeleteRequest",
"WorkspaceGroupAddWorkspacesRequest",
"WorkspaceGroupRemoveWorkspacesRequest",
"WorkspaceGroupAddUsersRequest",
"WorkspaceGroupRemoveUsersRequest",
"WorkspaceGroupUpdateRoleRequest",
Expand Down Expand Up @@ -41,20 +39,6 @@ class WorkspaceGroupDeleteRequest(BaseModel):
domain_id: str


class WorkspaceGroupAddWorkspacesRequest(BaseModel):
workspace_group_id: str
workspaces: List[str]
workspace_id: Union[str, None] = None
domain_id: str


class WorkspaceGroupRemoveWorkspacesRequest(BaseModel):
workspace_group_id: str
workspaces: List[str]
workspace_id: Union[str, None] = None
domain_id: str


class WorkspaceGroupAddUsersRequest(BaseModel):
workspace_group_id: str
users: List[Dict[str, str]]
Expand Down
13 changes: 10 additions & 3 deletions src/spaceone/identity/model/workspace_group/response.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
from datetime import datetime
from typing import Dict, List, Union
from typing import List, Union

from pydantic.main import BaseModel
from spaceone.core import utils

__all__ = ["WorkspaceGroupResponse", "WorkspaceGroupsResponse"]


class WorkspaceGroupUser(BaseModel):
user_id: str
role_id: str
role_type: str
user_name: Union[str, None] = None
state: Union[str, None] = None


class WorkspaceGroupResponse(BaseModel):
workspace_group_id: Union[str, None] = None
name: Union[str, None] = None
workspaces: Union[list, None] = None
users: Union[List[Dict[str, str]], None] = None
users: Union[List[WorkspaceGroupUser], None] = None
tags: Union[dict, None] = None
created_by: Union[str, None] = None
updated_by: Union[str, None] = None
Expand Down
45 changes: 25 additions & 20 deletions src/spaceone/identity/service/role_binding_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from spaceone.identity.manager.role_manager import RoleManager
from spaceone.identity.manager.user_manager import UserManager
from spaceone.identity.manager.workspace_manager import WorkspaceManager
from spaceone.identity.model import RoleBinding
from spaceone.identity.model.role_binding.request import *
from spaceone.identity.model.role_binding.response import *

Expand Down Expand Up @@ -269,26 +270,7 @@ def delete(self, params: RoleBindingDeleteRequest) -> None:
user_vo = self.user_mgr.get_user(rb_vo.user_id, rb_vo.domain_id)

self.user_mgr.update_user_by_vo(user_role_info, user_vo)
self.role_binding_manager.delete_role_binding_by_vo(rb_vo)

workspace_vo = self.workspace_mgr.get_workspace(
params.workspace_id, params.domain_id
)

user_rb_ids = self.role_binding_manager.stat_role_bindings(
query={
"distinct": "user_id",
"filter": [
{"k": "workspace_id", "v": params.workspace_id, "o": "eq"},
{"k": "domain_id", "v": params.domain_id, "o": "eq"},
],
}
).get("results", [])
user_rb_total_count = len(user_rb_ids)

self.workspace_mgr.update_workspace_by_vo(
{"user_count": user_rb_total_count}, workspace_vo
)
self.delete_role_binding_by_vo(rb_vo, params.domain_id, params.workspace_id)

@transaction(
permission="identity:RoleBinding.read",
Expand Down Expand Up @@ -474,3 +456,26 @@ def _get_latest_role_type(before: str, after: str) -> str:
return "USER"

return after

def delete_role_binding_by_vo(
self, rb_vo: RoleBinding, domain_id: str, workspace_id: str = None
):
self.role_binding_manager.delete_role_binding_by_vo(rb_vo)

if workspace_id:
workspace_vo = self.workspace_mgr.get_workspace(workspace_id, domain_id)

user_rb_ids = self.role_binding_manager.stat_role_bindings(
query={
"distinct": "user_id",
"filter": [
{"k": "workspace_id", "v": workspace_id, "o": "eq"},
{"k": "domain_id", "v": domain_id, "o": "eq"},
],
}
).get("results", [])
user_rb_total_count = len(user_rb_ids)

self.workspace_mgr.update_workspace_by_vo(
{"user_count": user_rb_total_count}, workspace_vo
)
14 changes: 7 additions & 7 deletions src/spaceone/identity/service/token_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ def grant(self, params: TokenGrantRequest) -> Union[GrantTokenResponse, dict]:

# todo: remove
if (
domain_id == SystemManager.get_root_domain_id()
and params.scope == "WORKSPACE"
domain_id == SystemManager.get_root_domain_id()
and params.scope == "WORKSPACE"
):
public_jwk = self.domain_secret_mgr.get_domain_public_key(domain_id)
domain_id = params.domain_id
Expand Down Expand Up @@ -317,7 +317,7 @@ def _verify_token(grant_type: str, token: str, public_jwk: dict) -> dict:
return token_info

def _get_user_role_info(
self, user_vo: User, workspace_id: str = None
self, user_vo: User, workspace_id: str = None
) -> Tuple[str, Union[str, None]]:
if user_vo.role_type == "DOMAIN_ADMIN":
rb_vos = self.rb_mgr.filter_role_bindings(
Expand Down Expand Up @@ -357,13 +357,13 @@ def _get_app_role_info(app_vo: App) -> Tuple[str, str]:
key="identity:role-permissions-page-access:{domain_id}:{role_id}", expire=600
)
def _get_role_permissions_and_page_access(
self, role_id: str, domain_id: str
self, role_id: str, domain_id: str
) -> Tuple[List[str], List[str]]:
role_vo = self.role_mgr.get_role(role_id=role_id, domain_id=domain_id)
return role_vo.permissions, role_vo.page_access

def _get_user_projects_in_project_group(
self, domain_id: str, workspace_id: str, user_id: str
self, domain_id: str, workspace_id: str, user_id: str
) -> List[str]:
user_projects = []
project_groups = self.project_group_mgr.filter_project_groups(
Expand All @@ -384,7 +384,7 @@ def _get_user_projects_in_project_group(
return user_projects

def _get_user_projects(
self, user_id: str, workspace_id: str, domain_id: str
self, user_id: str, workspace_id: str, domain_id: str
) -> List[str]:
user_projects = []

Expand Down Expand Up @@ -419,7 +419,7 @@ def _check_user_required_actions(required_actions: list, user_id: str) -> None:
expire=600,
)
def _get_combined_role_permissions_and_page_access(
self, role_type: str, user_id: str, domain_id: str
self, role_type: str, user_id: str, domain_id: str
) -> Tuple[List[str], List[str]]:
role_bindings = self.rb_mgr.filter_role_bindings(
role_type=role_type,
Expand Down
Loading
Loading