Skip to content

Commit e483b0a

Browse files
authored
Merge pull request #302 from eadwinCode/ninja_145_upgrade
fix: Refactored CSRF And Upgraded To Ninja v1.4.5
2 parents e826eaf + 03d2937 commit e483b0a

File tree

9 files changed

+18
-187
lines changed

9 files changed

+18
-187
lines changed

ninja_extra/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Django Ninja Extra - Class Based Utility and more for Django Ninja(Fast Django REST framework)"""
22

3-
__version__ = "0.30.1"
3+
__version__ = "0.30.2"
44

55
import django
66

ninja_extra/controllers/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
ModelService,
1313
ModelServiceBase,
1414
)
15-
from .response import Detail, Id, Ok
1615
from .route import (
1716
Route,
1817
RouteInvalidParameterException,
@@ -40,9 +39,6 @@
4039
"AsyncRouteFunction",
4140
"RouteFunction",
4241
"Route",
43-
"Ok",
44-
"Id",
45-
"Detail",
4642
"ModelControllerBase",
4743
"ModelConfig",
4844
"ModelService",

ninja_extra/controllers/base.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
from ninja_extra.constants import ROUTE_FUNCTION, THROTTLED_FUNCTION, THROTTLED_OBJECTS
4141
from ninja_extra.context import RouteContext
42-
from ninja_extra.exceptions import APIException, NotFound, PermissionDenied, bad_request
42+
from ninja_extra.exceptions import APIException, NotFound, PermissionDenied
4343
from ninja_extra.helper import get_function_name
4444
from ninja_extra.operation import Operation, PathView
4545
from ninja_extra.permissions import (
@@ -58,7 +58,6 @@
5858

5959
from .model import ModelConfig, ModelControllerBuilder, ModelService
6060
from .registry import ControllerRegistry
61-
from .response import Detail, Id, Ok
6261
from .route.route_functions import AsyncRouteFunction, RouteFunction
6362

6463
if TYPE_CHECKING: # pragma: no cover
@@ -151,11 +150,6 @@ def some_method_name(self):
151150
throttling_classes: List[Type["BaseThrottle"]] = []
152151
throttling_init_kwargs: Optional[Dict[Any, Any]] = None
153152

154-
Ok = Ok # TODO: remove soonest
155-
Id = Id # TODO: remove soonest
156-
Detail = Detail # TODO: remove soonest
157-
bad_request = bad_request # TODO: remove soonest
158-
159153
@classmethod
160154
def get_api_controller(cls) -> "APIController":
161155
if not cls._api_controller:
@@ -520,8 +514,6 @@ def __call__(self, cls: ControllerClassType) -> ControllerClassType:
520514
DeprecationWarning,
521515
stacklevel=2,
522516
)
523-
# if not hasattr(cls, "service"):
524-
# cls.service = ModelService(cls.model_config.model)
525517

526518
compute_api_route_function(cls, self)
527519

ninja_extra/controllers/response.py

Lines changed: 0 additions & 35 deletions
This file was deleted.

ninja_extra/main.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warnings
12
from importlib import import_module
23
from typing import (
34
Any,
@@ -56,14 +57,25 @@ def __init__(
5657
app_name: str = "ninja",
5758
**kwargs: Any,
5859
) -> None:
60+
# add a warning if there csrf is True
61+
if csrf:
62+
(
63+
warnings.warn(
64+
(
65+
"CSRF is deprecated and will be removed in a future version"
66+
"see https://django-ninja.dev/reference/csrf for more details."
67+
),
68+
DeprecationWarning,
69+
stacklevel=2,
70+
),
71+
)
5972
super(NinjaExtraAPI, self).__init__(
6073
title=title,
6174
version=version,
6275
description=description,
6376
openapi_url=openapi_url,
6477
docs_url=docs_url,
6578
urls_namespace=urls_namespace,
66-
csrf=csrf,
6779
auth=auth,
6880
renderer=renderer,
6981
parser=parser,

ninja_extra/operation.py

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from django.http.response import HttpResponse, HttpResponseBase
2121
from django.utils.encoding import force_str
2222
from ninja.constants import NOT_SET, NOT_SET_TYPE
23-
from ninja.errors import AuthenticationError
2423
from ninja.operation import (
2524
AsyncOperation as NinjaAsyncOperation,
2625
)
@@ -33,7 +32,6 @@
3332
from ninja.signature import is_async
3433
from ninja.throttling import BaseThrottle
3534
from ninja.types import TCallable
36-
from ninja.utils import check_csrf
3735

3836
from ninja_extra.compatible import asynccontextmanager
3937
from ninja_extra.constants import ROUTE_CONTEXT_VAR
@@ -255,45 +253,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
255253
sync_to_async(super()._result_to_response),
256254
)
257255

258-
async def _run_checks(self, request: HttpRequest) -> Optional[HttpResponse]: # type: ignore
259-
"""Runs security checks for each operation"""
260-
# csrf:
261-
if self.api.csrf:
262-
error = check_csrf(request, self.view_func)
263-
if error:
264-
return error
265-
266-
# auth:
267-
if self.auth_callbacks:
268-
error = await self._run_authentication(request) # type: ignore[assignment]
269-
if error:
270-
return error
271-
272-
# Throttling:
273-
if self.throttle_objects:
274-
error = self._check_throttles(request) # type: ignore
275-
if error:
276-
return error
277-
278-
return None
279-
280-
async def _run_authentication(self, request: HttpRequest) -> Optional[HttpResponse]: # type: ignore
281-
for callback in self.auth_callbacks:
282-
try:
283-
is_coroutine = getattr(callback, "is_coroutine", False)
284-
if is_coroutine:
285-
result = await callback(request)
286-
else:
287-
result = callback(request)
288-
except Exception as exc:
289-
return self.api.on_exception(request, exc)
290-
291-
if result:
292-
request.auth = result # type: ignore
293-
return None
294-
295-
return self.api.on_exception(request, AuthenticationError())
296-
297256
@asynccontextmanager
298257
async def _prep_run( # type:ignore
299258
self, request: HttpRequest, **kw: Any

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ classifiers = [
4242

4343
requires = [
4444
"Django >= 2.2",
45-
"django-ninja == 1.4.3",
45+
"django-ninja == 1.4.5",
4646
"injector >= 0.19.0",
4747
"asgiref",
4848
"contextlib2"

tests/test_async_auth.py

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -82,72 +82,29 @@ def _build_request(self, *args, **kwargs):
8282
return request
8383

8484
csrf_OFF = NinjaExtraAPI(urls_namespace="csrf_OFF")
85-
csrf_ON = NinjaExtraAPI(urls_namespace="csrf_ON", csrf=True)
8685

8786
@csrf_OFF.post("/post")
8887
async def post_off(request):
8988
return {"success": True}
9089

91-
@csrf_ON.post("/post")
92-
async def post_on(request):
93-
return {"success": True}
94-
95-
@csrf_ON.post("/post-async-sync-auth", auth=SyncKeyCookie())
96-
async def auth_with_sync_auth(request):
97-
return {"success": True}
98-
9990
TOKEN = "1bcdefghij2bcdefghij3bcdefghij4bcdefghij5bcdefghij6bcdefghijABCD"
10091
COOKIES = {settings.CSRF_COOKIE_NAME: TOKEN}
10192

102-
@pytest.mark.asyncio
103-
async def test_auth_with_sync_auth_fails():
104-
async_client = TestAsyncClient(csrf_ON)
105-
res = await async_client.post("/post-async-sync-auth")
106-
assert res.status_code == 401
107-
assert res.json() == {"detail": "Authentication credentials were not provided."}
108-
109-
@pytest.mark.asyncio
110-
async def test_auth_with_sync_auth_works():
111-
async_client = TestAsyncClient(csrf_ON)
112-
res = await async_client.post(
113-
"/post-async-sync-auth", COOKIES={"key": "keycookiersecret"}
114-
)
115-
assert res.status_code == 200
116-
assert res.json() == {"success": True}
117-
11893
@pytest.mark.asyncio
11994
async def test_csrf_off():
12095
async_client = TestAsyncCSRFClient(csrf_OFF)
12196
res = await async_client.post("/post", COOKIES=COOKIES)
12297
assert res.status_code == 200
12398

124-
@pytest.mark.asyncio
125-
async def test_csrf_on():
126-
async_client = TestAsyncCSRFClient(csrf_ON)
127-
res = await async_client.post("/post", COOKIES=COOKIES)
128-
assert res.status_code == 403
129-
130-
# check with token in formdata
131-
response = await async_client.post(
132-
"/post", {"csrfmiddlewaretoken": TOKEN}, COOKIES=COOKIES
133-
)
134-
assert response.status_code == 200
135-
136-
# check with headers
137-
response = await async_client.post(
138-
"/post", COOKIES=COOKIES, headers={"X-CSRFTOKEN": TOKEN}
139-
)
140-
assert response.status_code == 200
141-
14299

143100
if not django.VERSION < (3, 1):
144-
api = NinjaExtraAPI(csrf=True, urls_namespace="async_auth")
101+
api = NinjaExtraAPI(urls_namespace="async_auth")
145102

146103
for path, auth in [
147104
("callable", callable_auth),
148105
("apikeyquery", KeyQuery()),
149106
("apikeyheader", KeyHeader()),
150-
("apikeycookie", KeyCookie()),
107+
("apikeycookie", KeyCookie(csrf=True)),
151108
("basic", BasicAuth()),
152109
("bearer", BearerAuth()),
153110
]:

tests/test_controller_response.py

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)