Skip to content

Commit 6ca7ae8

Browse files
committed
feat(gooddata-sdk): [AUTO] Add CustomUserApplicationSetting CRUD endpoints for per-user app settings
1 parent 1c4dfe4 commit 6ca7ae8

4 files changed

Lines changed: 275 additions & 0 deletions

File tree

packages/gooddata-sdk/src/gooddata_sdk/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@
181181
CatalogDeclarativeUserGroupPermission,
182182
CatalogDeclarativeUserGroups,
183183
)
184+
from gooddata_sdk.catalog.user.entity_model.custom_user_application_setting import (
185+
CatalogCustomUserApplicationSetting,
186+
CatalogCustomUserApplicationSettingAttributes,
187+
)
184188
from gooddata_sdk.catalog.user.entity_model.user import CatalogUser
185189
from gooddata_sdk.catalog.user.entity_model.user_group import CatalogUserGroup
186190
from gooddata_sdk.catalog.user.management_model.management import (
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# (C) 2026 GoodData Corporation
2+
from __future__ import annotations
3+
4+
from typing import Any
5+
6+
import attrs
7+
from gooddata_api_client.model.json_api_custom_user_application_setting_in import (
8+
JsonApiCustomUserApplicationSettingIn,
9+
)
10+
from gooddata_api_client.model.json_api_custom_user_application_setting_in_attributes import (
11+
JsonApiCustomUserApplicationSettingInAttributes,
12+
)
13+
from gooddata_api_client.model.json_api_custom_user_application_setting_in_document import (
14+
JsonApiCustomUserApplicationSettingInDocument,
15+
)
16+
from gooddata_api_client.model.json_api_custom_user_application_setting_post_optional_id import (
17+
JsonApiCustomUserApplicationSettingPostOptionalId,
18+
)
19+
from gooddata_api_client.model.json_api_custom_user_application_setting_post_optional_id_document import (
20+
JsonApiCustomUserApplicationSettingPostOptionalIdDocument,
21+
)
22+
23+
from gooddata_sdk.catalog.base import Base
24+
25+
26+
@attrs.define(kw_only=True)
27+
class CatalogCustomUserApplicationSettingAttributes(Base):
28+
"""Attributes of a custom user application setting."""
29+
30+
application_name: str
31+
content: dict[str, Any]
32+
workspace_id: str | None = None
33+
34+
@staticmethod
35+
def client_class() -> type[JsonApiCustomUserApplicationSettingInAttributes]:
36+
return JsonApiCustomUserApplicationSettingInAttributes
37+
38+
39+
@attrs.define(kw_only=True)
40+
class CatalogCustomUserApplicationSetting(Base):
41+
"""Entity representing a per-user application setting."""
42+
43+
id: str
44+
attributes: CatalogCustomUserApplicationSettingAttributes
45+
46+
@staticmethod
47+
def client_class() -> type[JsonApiCustomUserApplicationSettingIn]:
48+
return JsonApiCustomUserApplicationSettingIn
49+
50+
@classmethod
51+
def init(
52+
cls,
53+
setting_id: str,
54+
application_name: str,
55+
content: dict[str, Any],
56+
*,
57+
workspace_id: str | None = None,
58+
) -> CatalogCustomUserApplicationSetting:
59+
"""Convenience factory to create a setting entity without constructing attributes manually."""
60+
return cls(
61+
id=setting_id,
62+
attributes=CatalogCustomUserApplicationSettingAttributes(
63+
application_name=application_name,
64+
content=content,
65+
workspace_id=workspace_id,
66+
),
67+
)
68+
69+
@classmethod
70+
def from_api(cls, entity: dict[str, Any]) -> CatalogCustomUserApplicationSetting:
71+
ea = entity.get("attributes", {})
72+
return cls(
73+
id=entity["id"],
74+
attributes=CatalogCustomUserApplicationSettingAttributes(
75+
application_name=ea["applicationName"],
76+
content=ea["content"],
77+
workspace_id=ea.get("workspaceId"),
78+
),
79+
)
80+
81+
def as_post_document(self) -> JsonApiCustomUserApplicationSettingPostOptionalIdDocument:
82+
"""Serialize to the document form used by the POST (create) endpoint."""
83+
kwargs: dict[str, Any] = {}
84+
if self.attributes.workspace_id is not None:
85+
kwargs["workspace_id"] = self.attributes.workspace_id
86+
api_attrs = JsonApiCustomUserApplicationSettingInAttributes(
87+
application_name=self.attributes.application_name,
88+
content=self.attributes.content,
89+
_check_type=False,
90+
**kwargs,
91+
)
92+
data = JsonApiCustomUserApplicationSettingPostOptionalId(
93+
attributes=api_attrs,
94+
id=self.id,
95+
_check_type=False,
96+
)
97+
return JsonApiCustomUserApplicationSettingPostOptionalIdDocument(data=data, _check_type=False)
98+
99+
def as_patch_document(self) -> JsonApiCustomUserApplicationSettingInDocument:
100+
"""Serialize to the document form used by the PATCH (update) endpoint."""
101+
kwargs: dict[str, Any] = {}
102+
if self.attributes.workspace_id is not None:
103+
kwargs["workspace_id"] = self.attributes.workspace_id
104+
api_attrs = JsonApiCustomUserApplicationSettingInAttributes(
105+
application_name=self.attributes.application_name,
106+
content=self.attributes.content,
107+
_check_type=False,
108+
**kwargs,
109+
)
110+
data = JsonApiCustomUserApplicationSettingIn(
111+
attributes=api_attrs,
112+
id=self.id,
113+
_check_type=False,
114+
)
115+
return JsonApiCustomUserApplicationSettingInDocument(data=data, _check_type=False)

packages/gooddata-sdk/src/gooddata_sdk/catalog/user/service.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
from gooddata_sdk.catalog.user.declarative_model.user_and_user_groups import CatalogDeclarativeUsersUserGroups
1414
from gooddata_sdk.catalog.user.declarative_model.user_group import CatalogDeclarativeUserGroups
1515
from gooddata_sdk.catalog.user.entity_model.api_token import CatalogApiToken
16+
from gooddata_sdk.catalog.user.entity_model.custom_user_application_setting import (
17+
CatalogCustomUserApplicationSetting,
18+
)
1619
from gooddata_sdk.catalog.user.entity_model.user import CatalogUser, CatalogUserDocument
1720
from gooddata_sdk.catalog.user.entity_model.user_group import CatalogUserGroup, CatalogUserGroupDocument
1821
from gooddata_sdk.catalog.user.management_model.management import (
@@ -458,3 +461,98 @@ def get_user_api_token(self, user_id: str, api_token_id: str) -> CatalogApiToken
458461

459462
def delete_user_api_token(self, user_id: str, api_token_id: str) -> None:
460463
self._entities_api.delete_entity_api_tokens(user_id, api_token_id)
464+
465+
# Custom user application settings
466+
467+
def list_custom_user_application_settings(self, user_id: str) -> list[CatalogCustomUserApplicationSetting]:
468+
"""List all custom application settings for a user.
469+
470+
Args:
471+
user_id (str):
472+
User identification string.
473+
474+
Returns:
475+
list[CatalogCustomUserApplicationSetting]:
476+
List of custom user application setting entities.
477+
"""
478+
get_settings = functools.partial(
479+
self._entities_api.get_all_entities_custom_user_application_settings,
480+
user_id,
481+
_check_return_type=False,
482+
)
483+
settings = load_all_entities(get_settings)
484+
return [CatalogCustomUserApplicationSetting.from_api(v) for v in settings.data]
485+
486+
def get_custom_user_application_setting(self, user_id: str, setting_id: str) -> CatalogCustomUserApplicationSetting:
487+
"""Get a single custom application setting for a user.
488+
489+
Args:
490+
user_id (str):
491+
User identification string.
492+
setting_id (str):
493+
Setting identification string.
494+
495+
Returns:
496+
CatalogCustomUserApplicationSetting:
497+
Custom user application setting entity.
498+
"""
499+
result = self._entities_api.get_entity_custom_user_application_settings(
500+
user_id, setting_id, _check_return_type=False
501+
)
502+
return CatalogCustomUserApplicationSetting.from_api(result.data)
503+
504+
def create_custom_user_application_setting(
505+
self, user_id: str, setting: CatalogCustomUserApplicationSetting
506+
) -> CatalogCustomUserApplicationSetting:
507+
"""Create a custom application setting for a user.
508+
509+
Args:
510+
user_id (str):
511+
User identification string.
512+
setting (CatalogCustomUserApplicationSetting):
513+
Setting entity to create.
514+
515+
Returns:
516+
CatalogCustomUserApplicationSetting:
517+
The newly created custom user application setting entity.
518+
"""
519+
document = setting.as_post_document()
520+
result = self._entities_api.create_entity_custom_user_application_settings(
521+
user_id, document, _check_return_type=False
522+
)
523+
return CatalogCustomUserApplicationSetting.from_api(result.data)
524+
525+
def update_custom_user_application_setting(
526+
self, user_id: str, setting: CatalogCustomUserApplicationSetting
527+
) -> CatalogCustomUserApplicationSetting:
528+
"""Update (patch) a custom application setting for a user.
529+
530+
Args:
531+
user_id (str):
532+
User identification string.
533+
setting (CatalogCustomUserApplicationSetting):
534+
Setting entity with updated values.
535+
536+
Returns:
537+
CatalogCustomUserApplicationSetting:
538+
The updated custom user application setting entity.
539+
"""
540+
document = setting.as_patch_document()
541+
result = self._entities_api.update_entity_custom_user_application_settings(
542+
user_id, setting.id, document, _check_return_type=False
543+
)
544+
return CatalogCustomUserApplicationSetting.from_api(result.data)
545+
546+
def delete_custom_user_application_setting(self, user_id: str, setting_id: str) -> None:
547+
"""Delete a custom application setting for a user.
548+
549+
Args:
550+
user_id (str):
551+
User identification string.
552+
setting_id (str):
553+
Setting identification string.
554+
555+
Returns:
556+
None
557+
"""
558+
self._entities_api.delete_entity_custom_user_application_settings(user_id, setting_id)

packages/gooddata-sdk/tests/catalog/test_catalog_user_service.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import pytest
2828
from gooddata_sdk import (
2929
CatalogAssigneeIdentifier,
30+
CatalogCustomUserApplicationSetting,
3031
CatalogDeclarativeUser,
3132
CatalogDeclarativeUserGroup,
3233
CatalogDeclarativeUserGroups,
@@ -776,6 +777,63 @@ def test_api_tokens(test_config):
776777
safe_delete(sdk.catalog_user.delete_user_api_token, test_config["demo_user"], token_id)
777778

778779

780+
# Custom user application settings
781+
782+
783+
@gd_vcr.use_cassette(str(_fixtures_dir / "test_custom_user_application_settings.yaml"))
784+
def test_custom_user_application_settings(test_config):
785+
sdk = GoodDataSdk.create(host_=test_config["host"], token_=test_config["token"])
786+
user_id = test_config["demo_user"]
787+
setting_id = "test-setting-1"
788+
application_name = "my-app"
789+
content = {"theme": "dark", "language": "en"}
790+
updated_content = {"theme": "light", "language": "fr"}
791+
792+
initial_settings = sdk.catalog_user.list_custom_user_application_settings(user_id)
793+
initial_count = len(initial_settings)
794+
795+
try:
796+
# Create
797+
setting = CatalogCustomUserApplicationSetting.init(
798+
setting_id=setting_id,
799+
application_name=application_name,
800+
content=content,
801+
)
802+
created = sdk.catalog_user.create_custom_user_application_setting(user_id, setting)
803+
assert created.id == setting_id
804+
assert created.attributes.application_name == application_name
805+
assert created.attributes.content == content
806+
assert created.attributes.workspace_id is None
807+
808+
# Get
809+
fetched = sdk.catalog_user.get_custom_user_application_setting(user_id, setting_id)
810+
assert fetched.id == setting_id
811+
assert fetched.attributes.application_name == application_name
812+
assert fetched.attributes.content == content
813+
814+
# List
815+
all_settings = sdk.catalog_user.list_custom_user_application_settings(user_id)
816+
assert len(all_settings) == initial_count + 1
817+
assert any(s.id == setting_id for s in all_settings)
818+
819+
# Update
820+
updated_setting = CatalogCustomUserApplicationSetting.init(
821+
setting_id=setting_id,
822+
application_name=application_name,
823+
content=updated_content,
824+
)
825+
updated = sdk.catalog_user.update_custom_user_application_setting(user_id, updated_setting)
826+
assert updated.id == setting_id
827+
assert updated.attributes.content == updated_content
828+
829+
# Verify update
830+
re_fetched = sdk.catalog_user.get_custom_user_application_setting(user_id, setting_id)
831+
assert re_fetched.attributes.content == updated_content
832+
833+
finally:
834+
safe_delete(sdk.catalog_user.delete_custom_user_application_setting, user_id, setting_id)
835+
836+
779837
# Help functions
780838

781839

0 commit comments

Comments
 (0)