Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,33 +1,49 @@
# (C) 2022 GoodData Corporation
from __future__ import annotations

from typing import Any
from typing import List, Optional, Type

import attr

from gooddata_metadata_client.model.json_api_organization_in import JsonApiOrganizationIn
from gooddata_metadata_client.model.json_api_organization_in_attributes import JsonApiOrganizationInAttributes
from gooddata_metadata_client.model.json_api_organization_in_document import JsonApiOrganizationInDocument
from gooddata_sdk.catalog.entity import CatalogNameEntity


class CatalogOrganization(CatalogNameEntity):
def __init__(self, organization_id: str, name: str, hostname: str) -> None:
super(CatalogOrganization, self).__init__(organization_id, name)
self.hostname = hostname

@classmethod
def from_api(cls, entity: dict[str, Any]) -> CatalogOrganization:
ea = entity["attributes"]
return cls(organization_id=entity["id"], name=ea["name"], hostname=ea["hostname"])

def to_api(self) -> JsonApiOrganizationInDocument:
return JsonApiOrganizationInDocument(
data=JsonApiOrganizationIn(
id=self.id,
attributes=JsonApiOrganizationInAttributes(name=self.name, hostname=self.hostname),
)
)

def __eq__(self, other: object) -> bool:
if not isinstance(other, CatalogOrganization):
return False
return self.id == other.id and self.name == other.name and self.hostname == other.hostname
from gooddata_sdk.catalog.base import Base


@attr.s(auto_attribs=True, kw_only=True)
class CatalogOrganizationDocument(Base):
data: CatalogOrganization

@staticmethod
def client_class() -> Type[JsonApiOrganizationInDocument]:
return JsonApiOrganizationInDocument

def to_api(self, oauth_client_secret: Optional[str] = None) -> JsonApiOrganizationInDocument:
dictionary = self._get_snake_dict()
if oauth_client_secret is not None:
dictionary["data"]["attributes"]["oauth_client_secret"] = oauth_client_secret
return self.client_class().from_dict(dictionary, camel_case=False)


@attr.s(auto_attribs=True, kw_only=True)
class CatalogOrganization(Base):
id: str
attributes: CatalogOrganizationAttributes

@staticmethod
def client_class() -> Type[JsonApiOrganizationIn]:
return JsonApiOrganizationIn


@attr.s(auto_attribs=True, kw_only=True)
class CatalogOrganizationAttributes(Base):
name: Optional[str] = None
hostname: Optional[str] = None
allowed_origins: Optional[List[str]] = None
oauth_issuer_location: Optional[str] = None
oauth_client_id: Optional[str] = None

@staticmethod
def client_class() -> Type[JsonApiOrganizationInAttributes]:
return JsonApiOrganizationInAttributes
26 changes: 26 additions & 0 deletions gooddata-sdk/gooddata_sdk/catalog/organization/service.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
# (C) 2022 GoodData Corporation
from __future__ import annotations

from typing import Optional

from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase
from gooddata_sdk.catalog.organization.entity_model.organization import CatalogOrganizationDocument
from gooddata_sdk.client import GoodDataApiClient


class CatalogOrganizationService(CatalogServiceBase):
def __init__(self, api_client: GoodDataApiClient) -> None:
super(CatalogOrganizationService, self).__init__(api_client)

def update_oidc_parameters(
Comment thread
hkad98 marked this conversation as resolved.
self,
oauth_issuer_location: Optional[str] = None,
oauth_client_id: Optional[str] = None,
oauth_client_secret: Optional[str] = None,
) -> None:
parameters = [oauth_issuer_location, oauth_client_id, oauth_client_secret]
if not all(p is not None for p in parameters) and any(p is not None for p in parameters):
raise ValueError("All parameters have to be set to None or all parameters has to be string.")
organization = self.get_organization()
organization.attributes.oauth_issuer_location = oauth_issuer_location
organization.attributes.oauth_client_id = oauth_client_id
organization_document = CatalogOrganizationDocument(data=organization)
self._entities_api.update_entity_organizations(
organization.id, organization_document.to_api(oauth_client_secret=oauth_client_secret)
)

def update_name(self, name: str) -> None:
organization = self.get_organization()
organization.attributes.name = name
organization_document = CatalogOrganizationDocument(data=organization)
self._entities_api.update_entity_organizations(organization.id, organization_document.to_api())
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
from gooddata_metadata_client.model.declarative_users import DeclarativeUsers
from gooddata_sdk.catalog.base import Base
from gooddata_sdk.catalog.identifier import CatalogUserGroupIdentifier
from gooddata_sdk.utils import create_directory, get_sorted_yaml_files, read_layout_from_file, write_layout_to_file
from gooddata_sdk.utils import create_directory, read_layout_from_file, write_layout_to_file

LAYOUT_USERS_DIR = "users"
LAYOUT_USERS_FILE = "users.yaml"


@attr.s(auto_attribs=True, kw_only=True)
Expand All @@ -26,17 +27,19 @@ def client_class() -> Type[DeclarativeUsers]:
@classmethod
def load_from_disk(cls, layout_organization_folder: Path) -> CatalogDeclarativeUsers:
users_directory = layout_organization_folder / LAYOUT_USERS_DIR
user_files = get_sorted_yaml_files(users_directory)
users_file = users_directory / LAYOUT_USERS_FILE
data = read_layout_from_file(users_file)
users = []
for user_file in user_files:
users.append(CatalogDeclarativeUser.load_from_disk(user_file))
for record in data:
users.append(CatalogDeclarativeUser.from_dict(record, camel_case=True))
return cls(users=users)

def store_to_disk(self, layout_organization_folder: Path) -> None:
users_directory = layout_organization_folder / LAYOUT_USERS_DIR
users_file = users_directory / LAYOUT_USERS_FILE
create_directory(users_directory)
for user in self.users:
user.store_to_disk(users_directory)
users = [user.to_dict(camel_case=True) for user in self.users]
write_layout_to_file(users_file, users)


@attr.s(auto_attribs=True, kw_only=True)
Expand All @@ -48,13 +51,3 @@ class CatalogDeclarativeUser(Base):
@staticmethod
def client_class() -> Type[DeclarativeUser]:
return DeclarativeUser

def store_to_disk(self, users_directory: Path) -> None:
user_path = users_directory / f"{self.id}.yaml"
user_data = self.to_dict(camel_case=True)
write_layout_to_file(user_path, user_data)

@classmethod
def load_from_disk(cls, users_directory: Path) -> CatalogDeclarativeUser:
data = read_layout_from_file(users_directory)
return cls.from_dict(data, camel_case=True)
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
from gooddata_metadata_client.model.declarative_user_groups import DeclarativeUserGroups
from gooddata_sdk.catalog.base import Base
from gooddata_sdk.catalog.identifier import CatalogUserGroupIdentifier
from gooddata_sdk.utils import create_directory, get_sorted_yaml_files, read_layout_from_file, write_layout_to_file
from gooddata_sdk.utils import create_directory, read_layout_from_file, write_layout_to_file

LAYOUT_USER_GROUPS_DIR = "user_groups"
LAYOUT_USER_GROUPS_FILE = "user_groups.yaml"


@attr.s(auto_attribs=True, kw_only=True)
Expand All @@ -26,17 +27,19 @@ def client_class() -> Type[DeclarativeUserGroups]:
@classmethod
def load_from_disk(cls, layout_organization_folder: Path) -> CatalogDeclarativeUserGroups:
user_groups_directory = layout_organization_folder / LAYOUT_USER_GROUPS_DIR
user_group_files = get_sorted_yaml_files(user_groups_directory)
user_groups_file = user_groups_directory / LAYOUT_USER_GROUPS_FILE
data = read_layout_from_file(user_groups_file)
user_groups = []
for user_group_file in user_group_files:
user_groups.append(CatalogDeclarativeUserGroup.load_from_disk(user_group_file))
for record in data:
user_groups.append(CatalogDeclarativeUserGroup.from_dict(record, camel_case=True))
return cls(user_groups=user_groups)

def store_to_disk(self, layout_organization_folder: Path) -> None:
user_groups_directory = layout_organization_folder / LAYOUT_USER_GROUPS_DIR
user_groups_file = user_groups_directory / LAYOUT_USER_GROUPS_FILE
create_directory(user_groups_directory)
for user_group in self.user_groups:
user_group.store_to_disk(user_groups_directory)
user_groups = [user_group.to_dict(camel_case=True) for user_group in self.user_groups]
write_layout_to_file(user_groups_file, user_groups)


@attr.s(auto_attribs=True, kw_only=True)
Expand All @@ -47,13 +50,3 @@ class CatalogDeclarativeUserGroup(Base):
@staticmethod
def client_class() -> Type[DeclarativeUserGroup]:
return DeclarativeUserGroup

def store_to_disk(self, user_groups_directory: Path) -> None:
user_group_path = user_groups_directory / f"{self.id}.yaml"
user_data = self.to_dict(camel_case=True)
write_layout_to_file(user_group_path, user_data)

@classmethod
def load_from_disk(cls, user_groups_directory: Path) -> CatalogDeclarativeUserGroup:
data = read_layout_from_file(user_groups_directory)
return cls.from_dict(data, camel_case=True)
37 changes: 24 additions & 13 deletions gooddata-sdk/gooddata_sdk/catalog/user/entity_model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@ def client_class() -> Type[JsonApiUserInDocument]:

@classmethod
def create_user(
cls, user_id: str, authentication_id: Optional[str] = None, user_groups: Optional[List[str]] = None
cls, user_id: str, authentication_id: Optional[str] = None, user_group_ids: Optional[List[str]] = None
) -> CatalogUserDocument:
attributes = CatalogUserAttributes(authentication_id=authentication_id)
relationships = None
if user_groups is not None:
relationships = CatalogUserRelationships(
user_groups=CatalogUserGroupsData(data=[CatalogUserGroup(id=user_group) for user_group in user_groups])
)
relationships = CatalogUserRelationships.create_user_relationships(user_group_ids=user_group_ids)
user = CatalogUser(id=user_id, attributes=attributes, relationships=relationships)
return cls(data=user)

def update_user(self, authentication_id: Optional[str] = None, user_group_ids: Optional[List[str]] = None) -> None:
attributes = CatalogUserAttributes(authentication_id=authentication_id)
relationships = CatalogUserRelationships.create_user_relationships(user_group_ids=user_group_ids)
self.data.attributes = attributes
self.data.relationships = relationships


@attr.s(auto_attribs=True, kw_only=True)
class CatalogUser(Base):
Expand All @@ -44,8 +46,8 @@ def client_class() -> Type[JsonApiUserIn]:
return JsonApiUserIn

@property
def get_user_groups(self) -> Optional[List[str]]:
return self.relationships.get_user_groups if self.relationships is not None else None
def get_user_groups(self) -> List[str]:
return self.relationships.get_user_groups if self.relationships is not None else []


@attr.s(auto_attribs=True, kw_only=True)
Expand All @@ -58,14 +60,23 @@ class CatalogUserRelationships(Base):
user_groups: Optional[CatalogUserGroupsData] = None

@property
def get_user_groups(self) -> Optional[List[str]]:
return self.user_groups.get_user_groups if self.user_groups is not None else None
def get_user_groups(self) -> List[str]:
return self.user_groups.get_user_groups if self.user_groups is not None else []

@classmethod
def create_user_relationships(cls, user_group_ids: Optional[List[str]]) -> CatalogUserRelationships:
user_groups = None
if user_group_ids is not None:
user_groups = CatalogUserGroupsData(
data=[CatalogUserGroup(id=user_group_id) for user_group_id in user_group_ids]
)
return cls(user_groups=user_groups)


@attr.s(auto_attribs=True, kw_only=True)
class CatalogUserGroupsData(Base):
data: List[CatalogUserGroup]
data: Optional[List[CatalogUserGroup]] = None

@property
def get_user_groups(self) -> Optional[List[str]]:
return [user_group.id for user_group in self.data]
def get_user_groups(self) -> List[str]:
return [user_group.id for user_group in self.data] if self.data is not None else []
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@ def client_class() -> Type[JsonApiUserGroupInDocument]:
def create_user_group(
cls, user_group_id: str, user_group_parents_id: Optional[List[str]] = None
) -> CatalogUserGroupDocument:
relationships = None
if user_group_parents_id is not None:
relationships = CatalogUserGroupRelationships(
parents=CatalogUserGroupParents(
data=[CatalogUserGroup(id=user_group_parent_id) for user_group_parent_id in user_group_parents_id]
)
)
relationships = CatalogUserGroupRelationships.create_user_group_relationships(user_group_parents_id)
return cls(data=CatalogUserGroup(id=user_group_id, relationships=relationships))

def update_user_group(self, user_group_parents_id: Optional[List[str]] = None) -> None:
relationships = CatalogUserGroupRelationships.create_user_group_relationships(user_group_parents_id)
self.data.relationships = relationships


@attr.s(auto_attribs=True, kw_only=True)
class CatalogUserGroup(Base):
Expand All @@ -41,12 +39,35 @@ class CatalogUserGroup(Base):
def client_class() -> Type[JsonApiUserGroupIn]:
return JsonApiUserGroupIn

@property
def get_parents(self) -> List[str]:
return self.relationships.get_parents if self.relationships is not None else []


@attr.s(auto_attribs=True, kw_only=True)
class CatalogUserGroupRelationships(Base):
parents: Optional[CatalogUserGroupParents] = None

@classmethod
def create_user_group_relationships(
cls, user_group_parents_id: Optional[List[str]]
) -> CatalogUserGroupRelationships:
parents = None
if user_group_parents_id is not None:
parents = CatalogUserGroupParents(
data=[CatalogUserGroup(id=user_group_parent_id) for user_group_parent_id in user_group_parents_id]
)
return cls(parents=parents)

@property
def get_parents(self) -> List[str]:
return self.parents.get_parents if self.parents is not None else []


@attr.s(auto_attribs=True, kw_only=True)
class CatalogUserGroupParents(Base):
data: Optional[List[CatalogUserGroup]] = None

@property
def get_parents(self) -> List[str]:
return [user_group.id for user_group in self.data] if self.data is not None else []
33 changes: 25 additions & 8 deletions gooddata-sdk/gooddata_sdk/catalog/user/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pathlib import Path
from typing import List, Optional

from gooddata_metadata_client.exceptions import NotFoundException
from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase
from gooddata_sdk.catalog.user.declarative_model.user import CatalogDeclarativeUsers
from gooddata_sdk.catalog.user.declarative_model.user_group import CatalogDeclarativeUserGroups
Expand Down Expand Up @@ -38,11 +39,17 @@ def get_user(self, user_id: str) -> CatalogUser:
)
return CatalogUser.from_dict(user_dict, camel_case=False)

def create_user(
def create_or_update_user(
self, user_id: str, authentication_id: Optional[str] = None, user_groups: Optional[list[str]] = None
) -> None:
user_document = CatalogUserDocument.create_user(user_id, authentication_id, user_groups)
self._entities_api.create_entity_users(json_api_user_in_document=user_document.to_api())
try:
user = self.get_user(user_id=user_id)
user_document = CatalogUserDocument(data=user)
user_document.update_user(authentication_id=authentication_id, user_group_ids=user_groups)
self._entities_api.update_entity_users(id=user_id, json_api_user_in_document=user_document.to_api())
except NotFoundException:
user_document = CatalogUserDocument.create_user(user_id, authentication_id, user_groups)
self._entities_api.create_entity_users(json_api_user_in_document=user_document.to_api())

def delete_user(self, user_id: str) -> None:
self._entities_api.delete_entity_users(id=user_id)
Expand All @@ -53,11 +60,21 @@ def get_user_group(self, user_group_id: str) -> CatalogUserGroup:
)
return CatalogUserGroup.from_dict(user_group, camel_case=False)

def create_user_group(self, user_group_id: str, user_group_parents_id: Optional[List[str]] = None) -> None:
user_group_document = CatalogUserGroupDocument.create_user_group(
user_group_id=user_group_id, user_group_parents_id=user_group_parents_id
)
self._entities_api.create_entity_user_groups(user_group_document.to_api())
def create_or_update_user_group(
self, user_group_id: str, user_group_parents_id: Optional[List[str]] = None
) -> None:
try:
user_group = self.get_user_group(user_group_id=user_group_id)
user_group_document = CatalogUserGroupDocument(data=user_group)
user_group_document.update_user_group(user_group_parents_id=user_group_parents_id)
self._entities_api.update_entity_user_groups(
id=user_group_id, json_api_user_group_in_document=user_group_document.to_api()
)
except NotFoundException:
user_group_document = CatalogUserGroupDocument.create_user_group(
user_group_id=user_group_id, user_group_parents_id=user_group_parents_id
)
self._entities_api.create_entity_user_groups(user_group_document.to_api())

def delete_user_group(self, user_group_id: str) -> None:
self._entities_api.delete_entity_user_groups(id=user_group_id)
Expand Down
Loading