Skip to content

Commit ceb3bcf

Browse files
authored
Merge pull request #93 from eadwinCode/guards_to_use_guard
Guards to UseGuards
2 parents f86562a + 2844f8f commit ceb3bcf

File tree

14 files changed

+63
-49
lines changed

14 files changed

+63
-49
lines changed

docs/basics/execution-context.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ Next, we apply the `RoleGuard` to `CarController`
267267
```python
268268
# project_name/apps/cars/controllers.py
269269
import typing
270-
from ellar.common import Body, Controller, post, set_metadata, Guards, ControllerBase
270+
from ellar.common import Body, Controller, post, set_metadata, UseGuards, ControllerBase
271271
from .schemas import CreateCarSerializer
272272
from .guards import RoleGuard
273273

@@ -276,7 +276,7 @@ def roles(*_roles: str) -> typing.Callable:
276276

277277

278278
@Controller('/car')
279-
@Guards(RoleGuard)
279+
@UseGuards(RoleGuard)
280280
class CarController(ControllerBase):
281281
@post()
282282
@roles('admin', 'is_staff')

docs/basics/testing.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ class TestCarController:
152152
```
153153
We this, anywhere `CarRepository` is needed, a `MockCarRepository()` instance will be applied.
154154

155-
In same way, we can override `Guards` used in controllers during testing. For example, lets assume `CarController` has a guard `JWTGuard`
155+
In same way, we can override `UseGuards` used in controllers during testing. For example, lets assume `CarController` has a guard `JWTGuard`
156156

157157
```python
158158
import typing
159159
from ellar.common.compatible import AttributeDict
160-
from ellar.common import Guards, Controller, ControllerBase
160+
from ellar.common import UseGuards, Controller, ControllerBase
161161
from ellar.core.guard import HttpBearerAuth
162162
from ellar.di import injectable
163163

@@ -169,7 +169,7 @@ class JWTGuard(HttpBearerAuth):
169169
return AttributeDict(is_authenticated=True, first_name='Ellar', last_name='ASGI Framework')
170170

171171

172-
@Guards(JWTGuard)
172+
@UseGuards(JWTGuard)
173173
@Controller('/car')
174174
class CarController(ControllerBase):
175175
...

docs/overview/custom_decorators.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,19 @@ The `version` decorator takes a list of values as an argument, for example `@ver
401401
This indicates that the `get_item_v2_v3` route function will handle version 2 and version 3 requests of the /create endpoint.
402402
This allows for multiple versions of the same endpoint to be handled by different route functions, each with their own logic and implementation.
403403

404-
### **GUARDS**
405-
**@Guards()** is a decorator that applies a protection class of type `GuardCanActivate` to a route function.
404+
### **UseGuards**
405+
**@UseGuards()** is a decorator that applies a protection class of type `GuardCanActivate` to a route function.
406406
These protection classes have a `can_execute` function that is called to determine whether a route function should be executed.
407407

408408
This decorator allows you to apply certain conditions or checks before a route function is executed, such as `authentication` or `authorization` checks.
409409
This can help to ensure that only authorized users can access certain resources.
410410

411411
More information on how to use this decorator can be found in the [Guard Documentation]()
412412

413-
A quick example on how to use `Guards` decorator:
413+
A quick example on how to use `UseGuards` decorator:
414414
```python
415415
import typing as t
416-
from ellar.common import get, Guards
416+
from ellar.common import get, UseGuards
417417
from ellar.core import APIKeyQuery, HTTPConnection
418418

419419

@@ -425,11 +425,11 @@ class MyAPIKeyQuery(APIKeyQuery):
425425

426426

427427
@get("/")
428-
@Guards(MyAPIKeyQuery(), )
428+
@UseGuards(MyAPIKeyQuery(), )
429429
async def get_guarded_items(self):
430430
return {'message': 'worked fine with `key`=`supersecret`'}
431431
```
432-
The `Guards` decorator, like the `version` decorator, takes a list of values as an argument.
432+
The `UseGuards` decorator, like the `version` decorator, takes a list of values as an argument.
433433
During a request, the provided guards are called in the order in which they are provided.
434434

435435
This allows you to apply multiple guards to a single route function and have them executed in a specific order.

docs/overview/guards.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,54 +57,54 @@ class RoleGuard(GuardCanActivate):
5757

5858
## **Applying guards**
5959
Guards can be **`controller-scoped`**, **`method-scoped`**, or **`global-scoped`**. We apply guards to controllers or route function by using `@Guards`.
60-
The `@Guards` takes a single argument, or a comma-separated list of arguments of `GuardCanActivate` types or instances.
60+
The `@UseGuards` takes a single argument, or a comma-separated list of arguments of `GuardCanActivate` types or instances.
6161

6262
```python
6363
import typing as t
6464

65-
def Guards(
65+
def UseGuards(
6666
*_guards: t.Type["GuardCanActivate"] | "GuardCanActivate"
6767
) -> t.Callable:
6868
...
6969
```
7070

7171
### **Controller-scoped**
72-
We set up controller scoped guards on controller by using `@Guards` decorator. For example:
72+
We set up controller scoped guards on controller by using `@UseGuards` decorator. For example:
7373
```python
7474
# project_name/cars/controllers.py
75-
from ellar.common import Controller, Guards
75+
from ellar.common import Controller, UseGuards
7676
from .guards import RoleGuard
7777

7878
@Controller()
79-
@Guards(RoleGuard)
79+
@UseGuards(RoleGuard)
8080
class CarsController:
8181
...
8282

8383
```
8484
The above example attaches the guard to every handler declared by this controller.
85-
If we wish the guard to apply only to a single method, we apply the `@Guards()` decorator at the method level.
85+
If we wish the guard to apply only to a single method, we apply the `@UseGuards()` decorator at the method level.
8686

8787
### **Method-scoped**
88-
We can also use `@Guards()` on route-function when necessary.
88+
We can also use `@UseGuards()` on route-function when necessary.
8989
```python
9090
# project_name/cars/controllers.py
91-
from ellar.common import Controller, Guards, get
91+
from ellar.common import Controller, UseGuards, get
9292
from .guards import RoleGuard
9393

9494
@Controller()
95-
@Guards(RoleGuard)
95+
@UseGuards(RoleGuard)
9696
class CarsController:
97-
@Guards(RoleGuard())
97+
@UseGuards(RoleGuard())
9898
@get('/guarded-route')
9999
def guarded_route(self):
100100
return "Passed Guard"
101101

102102
```
103-
In the example, we decorated `guarded_route` with `@Guards(RoleGuard())` with an instance of `RoleGuard`.
103+
In the example, we decorated `guarded_route` with `@UseGuards(RoleGuard())` with an instance of `RoleGuard`.
104104
When request execution for `/guarded-route`, `guarded_route` guard definition will be precedence over `CarsController` guard definitions.
105105

106106
### **Global-scope**
107-
Global guards are used across the whole application, for every controller and every route function but individual controller or route function `@Guards` definition can override `global` scoped guards.
107+
Global guards are used across the whole application, for every controller and every route function but individual controller or route function `@UseGuards` definition can override `global` scoped guards.
108108

109109
Global guards are applied at the `global_guards` parameter of the `AppFactory` creation level as shown below:
110110
```python

docs/throttling.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,18 @@ application = AppFactory.create_from_app_module(
5252
The above is also a valid configuration for `ThrottleModule` registration if you want to work with config.
5353

5454
If you add the `ThrottlerGuard` to your application `global_guards`, then all the incoming requests will be throttled by default.
55-
This can also be omitted in favor of `@Guards(ThrottlerGuard)`. The global guard check can be skipped using the `@skip_throttle()` decorator mentioned later.
55+
This can also be omitted in favor of `@UseGuards(ThrottlerGuard)`. The global guard check can be skipped using the `@skip_throttle()` decorator mentioned later.
5656

57-
Example with `@Guards(ThrottlerGuard)`
57+
Example with `@UseGuards(ThrottlerGuard)`
5858
```python
5959
# project_name/controller.py
60-
from ellar.common import Controller, Guards
60+
from ellar.common import Controller, UseGuards
6161
from ellar_throttler import throttle, ThrottlerGuard
6262

6363
@Controller()
6464
class AppController:
6565

66-
@Guards(ThrottlerGuard)
66+
@UseGuards(ThrottlerGuard)
6767
@throttle(limit=5, ttl=30)
6868
def normal(self):
6969
pass
@@ -95,12 +95,12 @@ a class that is skipped.
9595

9696
```python
9797
# project_name/controller.py
98-
from ellar.common import Controller, Guards
98+
from ellar.common import Controller, UseGuards
9999
from ellar_throttler import ThrottlerGuard, skip_throttle
100100

101101
@skip_throttle()
102102
@Controller()
103-
@Guards(ThrottlerGuard)
103+
@UseGuards(ThrottlerGuard)
104104
class AppController:
105105

106106
def do_skip(self):
@@ -193,7 +193,7 @@ class ThrottlerBehindProxyGuard(ThrottlerGuard):
193193
from .throttler_behind_proxy import ThrottlerBehindProxyGuard
194194

195195
@Controller('')
196-
@Guards(ThrottlerBehindProxyGuard)
196+
@UseGuards(ThrottlerBehindProxyGuard)
197197
class AppController:
198198
pass
199199
```

ellar/common/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from .datastructures import UploadFile
77
from .decorators import (
88
Controller,
9-
Guards,
109
Module,
10+
UseGuards,
1111
Version,
1212
exception_handler,
1313
extra_args,
@@ -127,7 +127,7 @@
127127
"ModuleRouter",
128128
"render",
129129
"Module",
130-
"Guards",
130+
"UseGuards",
131131
"Param",
132132
"ParamTypes",
133133
"set_metadata",

ellar/common/decorators/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from .exception import exception_handler
66
from .extra_args import extra_args
77
from .file import file
8-
from .guards import Guards
8+
from .guards import UseGuards
99
from .html import render, template_filter, template_global
1010
from .middleware import middleware
1111
from .modules import Module
@@ -17,7 +17,7 @@
1717
"serializer_filter",
1818
"Controller",
1919
"Version",
20-
"Guards",
20+
"UseGuards",
2121
"template_filter",
2222
"template_global",
2323
"file",

ellar/common/decorators/guards.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,28 @@
88
from ellar.common.models import GuardCanActivate
99

1010

11-
def Guards(
11+
def UseGuards(
1212
*_guards: t.Union[t.Type["GuardCanActivate"], "GuardCanActivate"]
1313
) -> t.Callable:
1414
"""
1515
=========CONTROLLER AND ROUTE FUNCTION DECORATOR ==============
1616
17-
Defines list of guards for a route function
18-
:param _guards: Guard Type or Instance
17+
Decorator that binds guards to the scope of the controller or method,
18+
depending on its context.
19+
20+
When `@UseGuards` is used at the controller level, the guard will be
21+
applied to every handler (method) in the controller.
22+
23+
When `@UseGuards` is used at the individual handler level, the guard
24+
will apply only to that specific method.
25+
26+
27+
Note:
28+
Guards can also be set up globally for all controllers and routes
29+
using `app.use_global_guards()`
30+
31+
:param _guards: A single guard instance or class, or a list of guard instances
32+
or classes.
1933
:return:
2034
"""
2135
return set_meta(GUARDS_KEY, list(_guards))

ellar/core/modules/builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,6 @@ def build(self, namespace: t.Dict) -> None:
8585
for name, item in namespace.items():
8686
for k, func in self._actions.items():
8787
if hasattr(item, k):
88-
value = getattr(item, k)
88+
value = item.__dict__.pop(k)
8989
func(value)
9090
self._cls.__MODULE_FIELDS__[name] = item

tests/test_decorators/test_controller.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22

3-
from ellar.common import Controller, ControllerBase, Guards, Version, set_metadata
3+
from ellar.common import Controller, ControllerBase, UseGuards, Version, set_metadata
44
from ellar.common.constants import (
55
CONTROLLER_METADATA,
66
GUARDS_KEY,
@@ -21,7 +21,7 @@
2121
name="test",
2222
)
2323
@Version("v1")
24-
@Guards()
24+
@UseGuards()
2525
class ControllerDecorationTest:
2626
pass
2727

0 commit comments

Comments
 (0)