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
15 changes: 15 additions & 0 deletions crowdin_api/api_resources/application/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,18 @@ class UserPermissions(Enum):
class ProjectPermissions(Enum):
OWN = "own"
RESTRICTED = "restricted"


class ListApplicationConsentsOrderBy(Enum):
ID = "id"
CREATED_AT = "createdAt"


class ApplicationConsentStatus(Enum):
GRANTED = "granted"
DENIED = "denied"


class ApplicationConsentPatchPath(Enum):
STATUS = "/status"
SCOPES = "/scopes"
86 changes: 85 additions & 1 deletion crowdin_api/api_resources/application/resource.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from typing import Optional, Iterable
from typing import Iterable, Optional

from crowdin_api.parser import dumps
from crowdin_api.api_resources.application.types import (
AddApplicationConsentRequest,
ApplicationConsentPatchRequest,
ApplicationPermissions,
ApplicationInstallationPatchRequest,
)
from crowdin_api.api_resources.abstract.resources import BaseResource
from crowdin_api.sorting import Sorting


class ApplicationResource(BaseResource):
Expand Down Expand Up @@ -102,6 +106,86 @@ def edit_applicatoin_installation(
request_data=data,
)

def get_application_consents_path(self, consent_id: Optional[int] = None):
if consent_id is not None:
return f"applications/consents/{consent_id}"
return "applications/consents"

def list_application_consents(
self,
identifier: Optional[str] = None,
order_by: Optional[Sorting] = None,
limit: Optional[int] = None,
offset: Optional[int] = None,
):
"""
List Application Consents

Available for Crowdin.com only (not supported in Crowdin Enterprise).

Link to documentation:
https://developer.crowdin.com/api/v2/#operation/api.applications.consents.getMany
"""
params = {
"identifier": identifier,
"orderBy": order_by,
}
params.update(self.get_page_params(limit=limit, offset=offset))

return self._get_entire_data(
method="get",
path=self.get_application_consents_path(),
params=params,
)

def add_application_consent(self, request_data: AddApplicationConsentRequest):
"""
Add Application Consent

Available for Crowdin.com only (not supported in Crowdin Enterprise).

Link to documentation:
https://developer.crowdin.com/api/v2/#operation/api.applications.consents.post
"""
return self.requester.request(
method="post",
path=self.get_application_consents_path(),
request_data=request_data,
)

def edit_application_consent(
self,
consent_id: int,
request_data: Iterable[ApplicationConsentPatchRequest],
):
"""
Edit Application Consent

Available for Crowdin.com only (not supported in Crowdin Enterprise).

Link to documentation:
https://developer.crowdin.com/api/v2/#operation/api.applications.consents.patch
"""
return self.requester.request(
method="patch",
path=self.get_application_consents_path(consent_id=consent_id),
request_data=request_data,
)

def delete_application_consent(self, consent_id: int):
"""
Delete Application Consent

Available for Crowdin.com only (not supported in Crowdin Enterprise).

Link to documentation:
https://developer.crowdin.com/api/v2/#operation/api.applications.consents.delete
"""
return self.requester.request(
method="delete",
path=self.get_application_consents_path(consent_id=consent_id),
)

def get_application_data(self, applicationIdentifier: str, path: str):
"""
Get Application Data.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from unittest import mock

import pytest
from crowdin_api.api_resources.enums import PatchOperation
from crowdin_api.api_resources.application.resource import ApplicationResource
from crowdin_api.api_resources.application.enums import (
ApplicationConsentPatchPath,
ApplicationConsentStatus,
ListApplicationConsentsOrderBy,
UserPermissions,
ProjectPermissions,
)
from crowdin_api.requester import APIRequester
from crowdin_api.sorting import Sorting, SortingOrder, SortingRule


class TestApplicationResource:
Expand Down Expand Up @@ -158,6 +164,137 @@ def test_edit_application_installation(
request_data=data,
)

@pytest.mark.parametrize(
"in_params, path",
(
({}, "applications/consents"),
({"consent_id": 12}, "applications/consents/12"),
),
)
def test_get_application_consents_path(self, in_params, path, base_absolut_url):
resource = self.get_resource(base_absolut_url)
assert resource.get_application_consents_path(**in_params) == path

@pytest.mark.parametrize(
"in_params, request_params",
(
(
{},
{
"identifier": None,
"orderBy": None,
"limit": 25,
"offset": 0,
},
),
(
{
"identifier": "example-application",
"order_by": Sorting(
[
SortingRule(
ListApplicationConsentsOrderBy.CREATED_AT,
SortingOrder.DESC,
)
]
),
"limit": 10,
"offset": 2,
},
{
"identifier": "example-application",
"orderBy": Sorting(
[
SortingRule(
ListApplicationConsentsOrderBy.CREATED_AT,
SortingOrder.DESC,
)
]
),
"limit": 10,
"offset": 2,
},
),
),
)
@mock.patch("crowdin_api.requester.APIRequester.request")
def test_list_application_consents(
self, m_request, in_params, request_params, base_absolut_url
):
m_request.return_value = "response"

resource = self.get_resource(base_absolut_url)
assert resource.list_application_consents(**in_params) == "response"
m_request.assert_called_once_with(
method="get",
path=resource.get_application_consents_path(),
params=request_params,
)

@pytest.mark.parametrize(
"request_data",
(
{
"identifier": "example-application",
"installedBy": 12,
"status": ApplicationConsentStatus.GRANTED,
"scopes": ["project", "tm"],
},
{
"identifier": "example-application",
"installedBy": 12,
"status": ApplicationConsentStatus.DENIED,
"scopes": None,
},
),
)
@mock.patch("crowdin_api.requester.APIRequester.request")
def test_add_application_consent(self, m_request, request_data, base_absolut_url):
m_request.return_value = "response"

resource = self.get_resource(base_absolut_url)
assert resource.add_application_consent(request_data) == "response"
m_request.assert_called_once_with(
method="post",
path=resource.get_application_consents_path(),
request_data=request_data,
)

@mock.patch("crowdin_api.requester.APIRequester.request")
def test_edit_application_consent(self, m_request, base_absolut_url):
m_request.return_value = "response"
request_data = [
{
"op": PatchOperation.REPLACE,
"path": ApplicationConsentPatchPath.STATUS,
"value": ApplicationConsentStatus.DENIED,
},
{
"op": PatchOperation.REPLACE,
"path": ApplicationConsentPatchPath.SCOPES,
"value": ["project"],
},
]

resource = self.get_resource(base_absolut_url)
assert resource.edit_application_consent(12, request_data) == "response"
m_request.assert_called_once_with(
method="patch",
path=resource.get_application_consents_path(consent_id=12),
request_data=request_data,
)

@mock.patch("crowdin_api.requester.APIRequester.request")
def test_delete_application_consent(self, m_request, base_absolut_url):
m_request.return_value = "response"

resource = self.get_resource(base_absolut_url)
assert resource.delete_application_consent(12) == "response"
m_request.assert_called_once_with(
method="delete",
path=resource.get_application_consents_path(consent_id=12),
)

@mock.patch("crowdin_api.requester.APIRequester.request")
def test_get_application_data(self, m_request, base_absolut_url):
m_request.return_value = "response"
Expand Down
19 changes: 18 additions & 1 deletion crowdin_api/api_resources/application/types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from typing import Iterable
from typing import Any, Iterable, Optional

from crowdin_api.api_resources.enums import PatchOperation
from crowdin_api.typing import TypedDict
from crowdin_api.api_resources.application.enums import (
ApplicationConsentPatchPath,
ApplicationConsentStatus,
UserPermissions,
ProjectPermissions,
)
Expand All @@ -25,3 +29,16 @@ class ApplicationInstallationPatchRequest(TypedDict):
op: str
path: str
value: str


class AddApplicationConsentRequest(TypedDict):
identifier: str
installedBy: int
status: ApplicationConsentStatus
scopes: Optional[Iterable[str]]


class ApplicationConsentPatchRequest(TypedDict):
op: PatchOperation
path: ApplicationConsentPatchPath
value: Any
Loading