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

feat: adds permissions find, find_one, and update #145

Merged
merged 4 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
20 changes: 7 additions & 13 deletions src/posit/connect/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,12 @@
from . import urls

from .config import Config
from .permissions import Permissions
from .resources import Resources, Resource


class ContentItem(Resource):
"""A piece of content.

Parameters
----------
Resource : _type_
_description_

Returns
-------
_type_
_description_
"""
"""A piece of content."""

@property
def guid(self) -> str:
Expand Down Expand Up @@ -199,6 +189,10 @@ def app_role(self) -> str:
def id(self) -> str:
return self.get("id") # type: ignore

@property
def permissions(self) -> Permissions:
return Permissions(self.config, self.session, content_guid=self.guid)

@overload
def update(
self,
Expand Down Expand Up @@ -297,7 +291,7 @@ def update(self, *args, **kwargs) -> None:
super().update(**response.json())


class Content(Resources[ContentItem]):
class Content(Resources):
def __init__(self, config: Config, session: Session) -> None:
self.url = urls.append_path(config.url, "v1/content")
self.config = config
Expand Down
107 changes: 107 additions & 0 deletions src/posit/connect/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from __future__ import annotations

from typing import List, overload

from requests.sessions import Session as Session

from . import urls

from .config import Config
from .resources import Resource, Resources


class Permission(Resource):
@property
def guid(self) -> str:
"""The globally unique identifier.

An alias for the field 'id'.

The conventional name for this field is 'guid'. As of v2024.03.0, the API uses the field name 'id'.

Returns
-------
str
"""
# Alias 'id' to 'guid'.
# The conventional name for this field across applications is 'guid'.
return self.get("id", self.get("guid")) # type: ignore
tdstein marked this conversation as resolved.
Show resolved Hide resolved

@property
def content_guid(self) -> str:
return self.get("content_guid") # type: ignore

@property
def principal_guid(self) -> str:
return self.get("principal_guid") # type: ignore

@property
def principal_type(self) -> str:
return self.get("principal_type") # type: ignore

@property
def role(self) -> str:
return self.get("role") # type: ignore

@overload
def update(self, role: str) -> None:
"""Update a permission.

Parameters
----------
role : str
The principal role.
"""
...

@overload
def update(self, *args, **kwargs) -> None:
"""Update a permission."""
...

def update(self, *args, **kwargs) -> None:
"""Update a permission."""
body = dict(*args, **kwargs)
path = f"v1/content/{self.content_guid}/permissions/{self.guid}"
url = urls.append_path(self.config.url, path)
response = self.session.put(
url,
json={
"principal_guid": self.principal_guid,
"principal_type": self.principal_type,
"role": self.role,
# shorthand to overwrite the above fields with method arguments
**body,
},
)
super().update(**response.json())


class Permissions(Resources):
def __init__(self, config: Config, session: Session, *, content_guid: str) -> None:
super().__init__(config, session)
self.content_guid = content_guid

def find(self, *args, **kwargs) -> List[Permission]:
"""Find permissions.

Returns
-------
List[Permission]
"""
body = dict(*args, **kwargs)
path = f"v1/content/{self.content_guid}/permissions"
url = urls.append_path(self.config.url, path)
response = self.session.get(url, json=body)
results = response.json()
return [Permission(self.config, self.session, **result) for result in results]

def find_one(self, *args, **kwargs) -> Permission | None:
"""Find a permission.

Returns
-------
Permission | None
"""
permissions = self.find(*args, **kwargs)
return next(iter(permissions), None)
32 changes: 4 additions & 28 deletions src/posit/connect/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,7 @@ def __setattr__(self, name: str, value: Any) -> None:
raise AttributeError("cannot set attributes: use update() instead")


class Resources(ABC, Generic[T]):
@abstractmethod
def create(self, *args, **kwargs) -> T:
raise NotImplementedError()

@abstractmethod
def delete(self, *args, **kwargs) -> None:
raise NotImplementedError()

@abstractmethod
def find(self, *args, **kwargs) -> List[T]:
raise NotImplementedError()

@abstractmethod
def find_one(self, *args, **kwargs) -> Optional[T]:
raise NotImplementedError()

@abstractmethod
def get(self, *args, **kwargs) -> T:
raise NotImplementedError()

@abstractmethod
def update(self, *args, **kwargs) -> T:
raise NotImplementedError()

@abstractmethod
def count(self, *args, **kwargs) -> int:
raise NotImplementedError()
Comment on lines -47 to -74
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can cherry-pick this out if needed. I'm realizing that not all API endpoints can support every one of these methods.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine by me to leave it here (and I'm always happy about deleting code 😂 )

class Resources(ABC):
def __init__(self, config: Config, session: requests.Session) -> None:
self.config = config
self.session = session
14 changes: 9 additions & 5 deletions src/posit/connect/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def update(self, *args, **kwargs) -> None:
super().update(**response.json())


class Users(Resources[User]):
class Users(Resources):
def __init__(self, config: Config, session: requests.Session) -> None:
self.url = urls.append_path(config.url, "v1/users")
self.config = config
Expand All @@ -160,10 +160,12 @@ def __init__(self, config: Config, session: requests.Session) -> None:
@overload
def find(
self, prefix: str = ..., user_role: str = ..., account_status: str = ...
) -> List[User]: ...
) -> List[User]:
...

@overload
def find(self, *args, **kwargs) -> List[User]: ...
def find(self, *args, **kwargs) -> List[User]:
...

def find(self, *args, **kwargs):
params = dict(*args, **kwargs)
Expand All @@ -181,10 +183,12 @@ def find(self, *args, **kwargs):
@overload
def find_one(
self, prefix: str = ..., user_role: str = ..., account_status: str = ...
) -> User | None: ...
) -> User | None:
...

@overload
def find_one(self, *args, **kwargs) -> User | None: ...
def find_one(self, *args, **kwargs) -> User | None:
...

def find_one(self, *args, **kwargs) -> User | None:
params = dict(*args, **kwargs)
Expand Down
Loading
Loading