Skip to content

Commit 39300bd

Browse files
committed
improve code docstring
1 parent a05ac79 commit 39300bd

File tree

7 files changed

+95
-30
lines changed

7 files changed

+95
-30
lines changed

docs/security/authorization/claims-based.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ from ellar.common import Controller, get
1313

1414
@Controller("/articles")
1515
@Authorize()
16-
@AuthenticationRequired()
1716
class ArticleController:
1817
@get("/create")
1918
@CheckPolicies(ClaimsPolicy("article", "create"))
@@ -47,7 +46,6 @@ Claims can have single or multiple values:
4746
```python
4847
@Controller("/content")
4948
@Authorize()
50-
@AuthenticationRequired()
5149
class ContentController:
5250
@get("/premium")
5351
@CheckPolicies(ClaimsPolicy("subscription", "premium")) # Single claim value
@@ -67,7 +65,6 @@ You can combine multiple claims policies using logical operators:
6765
```python
6866
@Controller("/advanced")
6967
@Authorize()
70-
@AuthenticationRequired()
7168
class AdvancedController:
7269
@get("/editor")
7370
@CheckPolicies(
@@ -101,7 +98,6 @@ Here's a comprehensive example showing claims-based authorization in an e-commer
10198
```python
10299
@Controller("/store")
103100
@Authorize()
104-
@AuthenticationRequired()
105101
class StoreController:
106102
@get("/products")
107103
@CheckPolicies(ClaimsPolicy("store", "view_products"))

docs/security/authorization/combining-policies.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ from .custom_policies import AgeRequirementPolicy, TeamMemberPolicy
7777

7878
@Controller("/mixed")
7979
@Authorize()
80-
@AuthenticationRequired()
8180
class MixedPolicyController:
8281
@get("/content")
8382
@CheckPolicies(
@@ -106,7 +105,6 @@ Here are some practical examples of policy combinations:
106105
```python
107106
@Controller("/cms")
108107
@Authorize()
109-
@AuthenticationRequired()
110108
class CMSController:
111109
@get("/articles/{id}/edit")
112110
@CheckPolicies(
@@ -132,7 +130,6 @@ class CMSController:
132130
```python
133131
@Controller("/store")
134132
@Authorize()
135-
@AuthenticationRequired()
136133
class StoreController:
137134
@get("/products/{id}/manage")
138135
@CheckPolicies(

docs/security/authorization/custom-policies.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ from ellar.common import Controller, get
3737

3838
@Controller("/content")
3939
@Authorize()
40-
@AuthenticationRequired()
4140
class ContentController:
4241
@get("/adult")
4342
@CheckPolicies(AgeRequirementPolicy[21]) # Requires age >= 21

docs/security/authorization/policies.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ from ellar.common import Controller, get
2929

3030
@Controller("/content")
3131
@Authorize()
32-
@AuthenticationRequired()
3332
class ContentController:
3433
@get("/adult")
3534
@CheckPolicies(AdultOnlyPolicy)
@@ -67,7 +66,6 @@ class PremiumUserPolicy(Policy):
6766

6867
@Controller("/premium")
6968
@Authorize()
70-
@AuthenticationRequired()
7169
class PremiumController:
7270
@get("/content")
7371
@CheckPolicies(PremiumUserPolicy)

docs/security/authorization/role-based.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ from ellar.common import Controller, get
1313

1414
@Controller("/admin")
1515
@Authorize()
16-
@AuthenticationRequired()
1716
class AdminController:
1817
@get("/dashboard")
1918
@CheckPolicies(RolePolicy("admin"))
@@ -46,7 +45,6 @@ You can require multiple roles in different ways:
4645
```python
4746
@Controller("/organization")
4847
@Authorize()
49-
@AuthenticationRequired()
5048
class OrganizationController:
5149
@get("/finance")
5250
@CheckPolicies(RolePolicy("admin") | RolePolicy("finance")) # Requires either role
@@ -78,7 +76,6 @@ Here's an example showing how to handle access for users with different departme
7876
```python
7977
@Controller("/departments")
8078
@Authorize()
81-
@AuthenticationRequired()
8279
class DepartmentController:
8380
@get("/it")
8481
@CheckPolicies(RolePolicy("it_staff") | RolePolicy("it_manager"))

ellar/auth/decorators.py

Lines changed: 91 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,28 @@
1111

1212
def CheckPolicies(*policies: t.Union[str, PolicyType]) -> t.Callable:
1313
"""
14-
========= CONTROLLER AND ROUTE FUNCTION DECORATOR ==============
15-
Decorates a controller or a route function with specific policy requirements
16-
:param policies:
17-
:return:
14+
Applies policy requirements to a controller or route function.
15+
16+
This decorator allows you to specify one or more policies that must be satisfied
17+
for the user to access the decorated endpoint. Policies can be either string
18+
identifiers or PolicyType objects.
19+
20+
Example:
21+
```python
22+
@Controller()
23+
class UserController:
24+
@CheckPolicies('admin', RequireRole('manager'))
25+
def get_sensitive_data(self):
26+
return {'data': 'sensitive information'}
27+
```
28+
29+
Args:
30+
*policies: Variable number of policy requirements. Can be strings or PolicyType objects.
31+
- String policies are resolved using the policy provider
32+
- PolicyType objects are evaluated directly
33+
34+
Returns:
35+
A decorator function that applies the policy requirements.
1836
"""
1937

2038
def _decorator(target: t.Callable) -> t.Union[t.Callable, t.Any]:
@@ -26,9 +44,25 @@ def _decorator(target: t.Callable) -> t.Union[t.Callable, t.Any]:
2644

2745
def Authorize() -> t.Callable:
2846
"""
29-
========= CONTROLLER AND ROUTE FUNCTION DECORATOR ==============
30-
Decorates a controller class or route function with `AuthorizationInterceptor`
31-
:return:
47+
Enables authorization checks for a controller or route function.
48+
49+
This decorator adds the AuthorizationInterceptor which performs two main checks:
50+
1. Verifies that the user is authenticated
51+
2. Validates any policy requirements specified using @CheckPolicies
52+
53+
Example:
54+
```python
55+
@Controller()
56+
@Authorize() # Enable authorization for all routes in controller
57+
class SecureController:
58+
@get('/')
59+
@CheckPolicies('admin') # Require admin policy
60+
def secure_endpoint(self):
61+
return {'message': 'secure data'}
62+
```
63+
64+
Returns:
65+
A decorator function that enables authorization checks.
3266
"""
3367

3468
return set_meta(constants.ROUTE_INTERCEPTORS, [AuthorizationInterceptor])
@@ -39,13 +73,34 @@ def AuthenticationRequired(
3973
openapi_scope: t.Optional[t.List] = None,
4074
) -> t.Callable:
4175
"""
42-
========= CONTROLLER AND ROUTE FUNCTION DECORATOR ==============
43-
44-
Decorates a controller class or route function with `IsAuthenticatedGuard`
45-
46-
@param authentication_scheme: authentication_scheme - Based on the authentication scheme class name or openapi_name used.
47-
@param openapi_scope: OpenAPi scope
48-
@return: Callable
76+
Requires authentication for accessing a controller or route function.
77+
78+
This decorator adds the AuthenticatedRequiredGuard which ensures that requests
79+
are authenticated before they can access the protected resource.
80+
81+
Example:
82+
```python
83+
@Controller()
84+
class UserController:
85+
@get('/profile')
86+
@AuthenticationRequired('jwt') # Require JWT authentication
87+
def get_profile(self):
88+
return {'user': 'data'}
89+
90+
@get('/public')
91+
@AuthenticationRequired(openapi_scope=['read:public'])
92+
def public_data(self):
93+
return {'public': 'data'}
94+
```
95+
96+
Args:
97+
authentication_scheme: Optional name of the authentication scheme to use.
98+
This should match the scheme name defined in your authentication setup.
99+
openapi_scope: Optional list of OpenAPI security scopes required for the endpoint.
100+
These scopes will be reflected in the OpenAPI documentation.
101+
102+
Returns:
103+
A decorator function that enforces authentication requirements.
49104
"""
50105
if callable(authentication_scheme):
51106
return set_meta(constants.GUARDS_KEY, [AuthenticatedRequiredGuard(None, [])])(
@@ -60,9 +115,28 @@ def AuthenticationRequired(
60115

61116
def SkipAuth() -> t.Callable:
62117
"""
63-
========= CONTROLLER AND ROUTE FUNCTION DECORATOR ==============
64-
Decorates a Class or Route Function with SKIP_AUTH attribute that is checked by `AuthenticationRequiredGuard`
65-
@return: Callable
118+
Marks a controller or route function to skip authentication checks.
119+
120+
This decorator is useful when you have a controller with @AuthenticationRequired
121+
but want to exclude specific routes from the authentication requirement.
122+
123+
Example:
124+
```python
125+
@Controller()
126+
@AuthenticationRequired() # Require auth for all routes
127+
class UserController:
128+
@get('/private')
129+
def private_data(self): # This requires auth
130+
return {'private': 'data'}
131+
132+
@get('/public')
133+
@SkipAuth() # This endpoint skips auth
134+
def public_data(self):
135+
return {'public': 'data'}
136+
```
137+
138+
Returns:
139+
A decorator function that marks the endpoint to skip authentication.
66140
"""
67141

68142
return set_meta(

ellar/auth/guards/auth_required.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010

1111
class AuthenticatedRequiredGuard(GuardCanActivate):
12+
"""
13+
This guard will check if the user is authenticated and also allow you to define the authentication scheme and openapi scope.
14+
"""
15+
1216
status_code = starlette.status.HTTP_401_UNAUTHORIZED
1317

1418
def __init__(

0 commit comments

Comments
 (0)