From 5f3c154bea08e54724cc8c4da1ea65e3920d1b9f Mon Sep 17 00:00:00 2001 From: Nikita Turchaninov Date: Fri, 8 Dec 2023 12:07:21 +0300 Subject: [PATCH 1/2] Bump to 1.1.0 --- HISTORY.md | 5 +++++ cybsi/__version__.py | 2 +- pyproject.toml | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 359e9b9..f263966 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,11 @@ Release History =============== +1.1.0 (2023-12-08) +------------------ + +- Add api-key limits + 1.0.8 (2023-12-06) ------------------ diff --git a/cybsi/__version__.py b/cybsi/__version__.py index ccef35c..cd049a0 100644 --- a/cybsi/__version__.py +++ b/cybsi/__version__.py @@ -1,4 +1,4 @@ -__version__ = "1.0.8" +__version__ = "1.1.0" __title__ = "cybsi-cloud-sdk" __description__ = "Cybsi Cloud development kit" __license__ = "Apache License 2.0" diff --git a/pyproject.toml b/pyproject.toml index c9420ee..0a8c79f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cybsi-cloud-sdk" -version = "1.0.8" +version = "1.1.0" description = "Cybsi Cloud development kit" authors = ["Cybsi Cloud developers"] license = "Apache License 2.0" @@ -36,7 +36,7 @@ extend_skip = ["__init__.py"] [tool.tbump] [tool.tbump.version] -current = "1.0.8" +current = "1.1.0" regex = ''' ^ From 8eb734ea2337ece76c493fdb4a1007e19c5b2b67 Mon Sep 17 00:00:00 2001 From: Nikita Turchaninov Date: Thu, 7 Dec 2023 15:56:35 +0300 Subject: [PATCH 2/2] Add api-key request limits --- cybsi/cloud/auth/__init__.py | 6 ++ cybsi/cloud/auth/api_key.py | 10 +++ cybsi/cloud/auth/limits.py | 71 ++++++++++++++++++++++ cybsi/cloud/error.py | 4 ++ examples/get_collection_objects_chained.py | 3 +- 5 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 cybsi/cloud/auth/limits.py diff --git a/cybsi/cloud/auth/__init__.py b/cybsi/cloud/auth/__init__.py index 3bf45c8..c944d26 100644 --- a/cybsi/cloud/auth/__init__.py +++ b/cybsi/cloud/auth/__init__.py @@ -8,6 +8,12 @@ APIKeyForm, APIKeyView, ) +from .limits import ( + RequestLimitForm, + RequestLimitTargetView, + RequestLimitView, + LimitPeriod, +) from .permission import ( ResourceAction, ResourcePermissionView, diff --git a/cybsi/cloud/auth/api_key.py b/cybsi/cloud/auth/api_key.py index 1da14fe..b8e1e2f 100644 --- a/cybsi/cloud/auth/api_key.py +++ b/cybsi/cloud/auth/api_key.py @@ -18,6 +18,7 @@ rfc3339_timestamp, ) from ..pagination import Cursor, Page +from .limits import RequestLimitForm, RequestLimitView from .permission import ResourcePermissionForm, ResourcePermissionView from .token import TokenView @@ -196,12 +197,14 @@ class APIKeyForm(JsonObjectForm): expires_at: Expiration date. The API-Key is automatically disabled after the expiration date. description: API-Key description. + request_limits: List of API-Key request limits. """ def __init__( self, permissions: Iterable[ResourcePermissionForm], *, + request_limits: Optional[Iterable[RequestLimitForm]] = None, expires_at: Optional[datetime] = None, description: Optional[str] = None, ): @@ -210,6 +213,8 @@ def __init__( self._data["expiresAt"] = rfc3339_timestamp(expires_at) if description is not None: self._data["description"] = description + if request_limits is not None: + self._data["requestLimits"] = [limit.json() for limit in request_limits] self._data["permissions"] = [perm.json() for perm in permissions] @@ -268,3 +273,8 @@ def revoked(self) -> bool: def permissions(self) -> List[ResourcePermissionView]: """List of permissions.""" return [ResourcePermissionView(perm) for perm in self._get("permissions")] + + @property + def request_limits(self) -> List[RequestLimitView]: + """List of request limits.""" + return [RequestLimitView(limit) for limit in self._get("requestLimits")] diff --git a/cybsi/cloud/auth/limits.py b/cybsi/cloud/auth/limits.py new file mode 100644 index 0000000..b9204aa --- /dev/null +++ b/cybsi/cloud/auth/limits.py @@ -0,0 +1,71 @@ +from enum_tools import document_enum + +from ..enum import CybsiAPIEnum +from ..internal import JsonObjectForm, JsonObjectView +from .permission import ResourceAction +from .resource import ResourceRefView + + +@document_enum +class LimitPeriod(CybsiAPIEnum): + """Limit time window.""" + + Day = "Day" + """Time window with period of one day.""" + + +class RequestLimitTargetView(JsonObjectView): + """Request limit target.""" + + @property + def resource(self) -> ResourceRefView: + """Resource.""" + return ResourceRefView(self._get("resource")) + + @property + def action(self) -> ResourceAction: + """Limited action.""" + return ResourceAction(self._get("action")) + + +class RequestLimitView(JsonObjectView): + """Request limit.""" + + @property + def target(self) -> RequestLimitTargetView: + """Limit target.""" + return RequestLimitTargetView(self._get("target")) + + @property + def limit(self) -> int: + """Maximum requests count within time window.""" + return self._get("limit") + + @property + def period(self) -> LimitPeriod: + """Time window for limit.""" + return LimitPeriod(self._get("period")) + + +class RequestLimitForm(JsonObjectForm): + """Request limit form. + + Args: + resource_id: resource identifier. + action: limited action. + limit_period: time window for limit. + limit: maximum requests count within time window. + """ + + def __init__( + self, + *, + resource_id: int, + action: ResourceAction, + limit_period: LimitPeriod, + limit: int, + ): + super().__init__() + self._data["target"] = {"resource": {"id": resource_id}, "action": action.value} + self._data["limit"] = limit + self._data["period"] = limit_period.value diff --git a/cybsi/cloud/error.py b/cybsi/cloud/error.py index 882ba4b..8b4a974 100644 --- a/cybsi/cloud/error.py +++ b/cybsi/cloud/error.py @@ -199,6 +199,10 @@ class SemanticErrorCodes(CybsiAPIEnum): """schemaID parameter can't be changed.""" SchemaNotFound = "SchemaNotFound" """The specified schema is not found""" + InvalidRequestLimit = "InvalidRequestLimit" + """The specified request limit cannot be set.""" + LimitSetConflict = "LimitSetConflict" + """The limit set has conflicts.""" # Objects InvalidKeyFormat = "InvalidKeyFormat" diff --git a/examples/get_collection_objects_chained.py b/examples/get_collection_objects_chained.py index 75d06b1..f3b488c 100644 --- a/examples/get_collection_objects_chained.py +++ b/examples/get_collection_objects_chained.py @@ -10,8 +10,7 @@ # Retrieve collection schema, it describes all attributes # of objects you can encounter in the collection. - schema_view = client.iocean.collections.view_schema( - collection_id=collection_id) + schema_view = client.iocean.collections.view_schema(collection_id=collection_id) print(schema_view.schema) # Retrieve first page of collection objects.