Coverage for /home/runner/work/viur-core/viur-core/viur/src/viur/core/decorators.py: 47%
43 statements
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-16 22:16 +0000
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-16 22:16 +0000
1import typing as t
2from viur.core.module import Method
4__all__ = [
5 "access",
6 "exposed",
7 "force_post",
8 "force_ssl",
9 "internal_exposed",
10 "skey",
11]
14def exposed(func: t.Callable) -> Method:
15 """
16 Decorator, which marks a function as exposed.
18 Only exposed functions are callable by http-requests.
19 Can optionally receive a dict of language->translated name to make that function
20 available under different names
21 """
22 if isinstance(func, dict): 22 ↛ 23line 22 didn't jump to line 23 because the condition on line 22 was never true
23 seo_language_map = func
25 # We received said dictionary:
26 def expose_with_translations(func: t.Callable) -> Method:
27 func = Method.ensure(func)
28 func.exposed = True
29 func.seo_language_map = seo_language_map
30 return func
32 return expose_with_translations
34 func = Method.ensure(func)
35 func.exposed = True
36 return func
39def internal_exposed(func: t.Callable) -> Method:
40 """
41 Decorator, which marks a function as internal exposed.
42 """
43 func = Method.ensure(func)
44 func.exposed = False
45 return func
48def force_ssl(func: t.Callable) -> Method:
49 """
50 Decorator, which enforces usage of an encrypted channel for a given resource.
51 Has no effect on development-servers.
52 """
53 func = Method.ensure(func)
54 func.ssl = True
55 return func
58def force_post(func: t.Callable) -> Method:
59 """
60 Decorator, which enforces usage of a http post request.
61 """
62 func = Method.ensure(func)
63 func.methods = ("POST",)
64 return func
67def access(
68 *access: str | list[str] | tuple[str] | set[str] | t.Callable,
69 offer_login: bool | str = False,
70 message: str | None = None,
71) -> t.Callable:
72 """
73 Decorator, which performs an authentication and authorization check primarily based on the current user's access,
74 which is defined via the `UserSkel.access`-bone. Additionally, a callable for individual access checking can be
75 provided.
77 In case no user is logged in, the decorator enforces to raise an HTTP error 401 - Unauthorized in case no user is
78 logged in, otherwise it returns an HTTP error 403 - Forbidden when the specified access parameters prohibit to call
79 the decorated method.
81 :params access: Access configuration, either names of access rights or a callable for verification.
82 :params offer_login: Offers a way to login; Either set it to True, to automatically redirect to /user/login,
83 or set it to any other URL.
84 :params message: A custom message to be printed when access is denied or unauthorized.
86 To check on authenticated users with the access "root" or ("admin" and "file-edit") or "maintainer" use the
87 decorator like this:
89 .. code-block:: python
90 from viur.core.decorators import access
91 @access("root", ["admin", "file-edit"], ["maintainer"])
92 def my_method(self):
93 return "You're allowed!"
95 Furthermore, instead of a list/tuple/set/str, a callable can be provided which performs custom access checking,
96 and directly is checked on True for access grant.
97 """
98 access_config = locals()
100 def decorator(func):
101 meth = Method.ensure(func)
102 meth.access = access_config
103 return meth
105 return decorator
108def skey(
109 func: t.Callable = None,
110 *,
111 allow_empty: bool | list[str] | tuple[str] | t.Callable = False,
112 forward_payload: str | None = None,
113 message: str = None,
114 name: str = "skey",
115 validate: t.Callable | None = None,
116 **extra_kwargs: dict,
117) -> Method:
118 """
119 Decorator, which configures an exposed method for requiring a CSRF-security-key.
120 The decorator enforces a raise of HTTP error 406 - Precondition failed in case the security-key is not provided
121 or became invalid.
123 :param allow_empty: Allows to call the method without a security-key when no other parameters where provided.
124 This can also be a tuple or list of keys which are being ignored, or a callable taking args and kwargs, and
125 programmatically decide whether security-key is required or not.
126 :param forward_payload: Forwards the extracted payload of the security-key to the method under the key specified
127 here as a value in kwargs.
128 :param message: Allows to specify a custom error message in case a HTTP 406 is raised.
129 :param name: Defaults to "skey", but allows also for another name passed to the method.
130 :param validate: Allows to specify a Callable used to further evaluate the payload of the security-key.
131 Security-keys can be equipped with further data, see the securitykey-module for details.
132 :param extra_kwargs: Any provided extra_kwargs are being passed to securitykey.validate as kwargs.
133 """
134 skey_config = locals()
136 def decorator(func):
137 meth = Method.ensure(func)
138 meth.skey = skey_config
139 return meth
141 if func is None: 141 ↛ 144line 141 didn't jump to line 144 because the condition on line 141 was always true
142 return decorator
144 return decorator(func)