Coverage for api/constants/restricted_features.py: 94%
30 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 06:14 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 06:14 +0000
1import typing
2from dataclasses import dataclass
4from rest_framework.request import Request
7ANONYMOUS: typing.Literal["anonymous"] = "anonymous"
8AUTHENTICATED: typing.Literal["authenticated"] = "authenticated"
9PRIVILEGED: typing.Literal["privileged"] = "privileged"
11AccessLevel = typing.Literal[ANONYMOUS, AUTHENTICATED, PRIVILEGED]
12ACCESS_LEVELS = typing.get_args(AccessLevel)
15_RESTRICTED_FEATURES = {}
17T = typing.TypeVar("T")
20@dataclass
21class RestrictedFeature(typing.Generic[T]):
22 """
23 Feature with gradient levels of access granted to applications upon approved request to Openverse maintainers.
25 Maintainers review requests for increased access to restricted features on a per-case basis.
27 Distinct from ``rate_limit_model`` which only affects access rates rather than level of access to certain features.
28 """
30 slug: str
31 anonymous: T
32 authenticated: T
33 privileged: T
35 def __post_init__(self):
36 _RESTRICTED_FEATURES[self.slug] = self
38 def request_level(self, request: None | Request) -> tuple[AccessLevel, T]:
39 """Retrieve the level of any request in relation to the privilege."""
40 if request is None or request.auth is None:
41 return ANONYMOUS, self.anonymous
43 if self.slug in request.auth.application.privileges: 43 ↛ 44line 43 didn't jump to line 44 because the condition on line 43 was never true
44 return PRIVILEGED, self.privileged
46 return AUTHENTICATED, self.authenticated
48 @classmethod
49 @property
50 def choices(cls):
51 return ((slug,) * 2 for slug in _RESTRICTED_FEATURES)
54MAX_PAGE_SIZE: RestrictedFeature[int] = RestrictedFeature(
55 "max_page_size",
56 anonymous=20,
57 authenticated=50,
58 # Max out privileged page size at the maximum authenticated
59 # pagination depth, otherwise privileged page size limit can
60 # contradict pagination depth limit.
61 privileged=240,
62)
64MAX_RESULT_COUNT: RestrictedFeature[int] = RestrictedFeature(
65 "max_result_count",
66 # 12 pages of 20 results
67 # Both anon and authed are limited to the same depth
68 # authed users can request bigger pages, but still only the same
69 # overall number of results available
70 anonymous=12 * MAX_PAGE_SIZE.anonymous,
71 authenticated=12 * MAX_PAGE_SIZE.anonymous,
72 # 20 pages of maxed out page sizes for privileged apps
73 privileged=20 * MAX_PAGE_SIZE.privileged,
74)