You've already forked bthlabs-jsonrpc
v1.1.0b1
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# django-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from .auth_checks import ( # noqa
|
||||
# bthlabs-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from .auth_checks import ( # noqa: F401
|
||||
has_perms,
|
||||
is_authenticated,
|
||||
is_staff,
|
||||
)
|
||||
from .views import JSONRPCView # noqa
|
||||
from .codecs import DjangoJSONCodec # noqa: F401
|
||||
from .executor import DjangoExecutor # noqa: F401
|
||||
from .serializer import DjangoJSONRPCSerializer # noqa: F401
|
||||
from .views import JSONRPCView # noqa: F401
|
||||
|
||||
__version__ = '1.0.0'
|
||||
__version__ = '1.1.0b1'
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# django-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
# bthlabs-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# django-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
# bthlabs-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from django.http import HttpRequest
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# bthlabs-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from bthlabs_jsonrpc_core import JSONCodec
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
|
||||
|
||||
class DjangoJSONCodec(JSONCodec):
|
||||
"""Django-specific JSON codec"""
|
||||
|
||||
# pragma mark - Public interface
|
||||
|
||||
def encode(self, payload: typing.Any, **encoder_kwargs) -> str:
|
||||
"""
|
||||
Before handing off control to the superclass, this method will default
|
||||
the *cls* encoder kwarg to
|
||||
:py:class:`django.core.serializers.json.DjangoJSONEncoder`.
|
||||
"""
|
||||
effective_encoder_kwargs = {
|
||||
'cls': DjangoJSONEncoder,
|
||||
**encoder_kwargs,
|
||||
}
|
||||
|
||||
return super().encode(payload, **effective_encoder_kwargs)
|
||||
@@ -1,28 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# django-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
# bthlabs-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from bthlabs_jsonrpc_core import Executor, JSONRPCAccessDeniedError
|
||||
from bthlabs_jsonrpc_core import Codec, Executor, JSONRPCAccessDeniedError
|
||||
from django.http import HttpRequest
|
||||
|
||||
from bthlabs_jsonrpc_django.serializer import DjangoJSONRPCSerializer
|
||||
|
||||
TCanCall = typing.Callable[[HttpRequest, str, list, dict], bool]
|
||||
|
||||
|
||||
class DjangoExecutor(Executor):
|
||||
"""Django-specific executor"""
|
||||
|
||||
serializer = DjangoJSONRPCSerializer
|
||||
|
||||
def __init__(self,
|
||||
request: HttpRequest,
|
||||
can_call: typing.Callable,
|
||||
namespace: typing.Optional[str] = None):
|
||||
super().__init__(namespace=namespace)
|
||||
self.request: HttpRequest = request
|
||||
self.can_call: typing.Callable = can_call
|
||||
can_call: TCanCall,
|
||||
namespace: str | None = None,
|
||||
codec: Codec | None = None):
|
||||
super().__init__(namespace=namespace, codec=codec)
|
||||
self.request = request
|
||||
self.can_call = can_call
|
||||
|
||||
def enrich_args(self, args):
|
||||
# pragma mark - Public interface
|
||||
|
||||
def enrich_args(self, args: list) -> list:
|
||||
"""
|
||||
Injects the current :py:class:`django.http.HttpRequest` as the first
|
||||
argument.
|
||||
"""
|
||||
return [self.request, *super().enrich_args(args)]
|
||||
|
||||
def before_call(self, method, args, kwargs):
|
||||
def before_call(self, method: str, args: list, kwargs: dict):
|
||||
"""
|
||||
Executes *can_call* and raises :py:exc:`JSONRPCAccessDeniedError`
|
||||
accordingly.
|
||||
"""
|
||||
can_call = self.can_call(self.request, method, args, kwargs)
|
||||
if can_call is False:
|
||||
raise JSONRPCAccessDeniedError(data='can_call')
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# django-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
# bthlabs-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from bthlabs_jsonrpc_core import JSONRPCSerializer
|
||||
from django.db.models import QuerySet
|
||||
|
||||
|
||||
class DjangoJSONRPCSerializer(JSONRPCSerializer):
|
||||
SEQUENCE_TYPES = (QuerySet, *JSONRPCSerializer.SEQUENCE_TYPES)
|
||||
"""Django-specific serializer"""
|
||||
SEQUENCE_TYPES: typing.Any = (QuerySet, *JSONRPCSerializer.SEQUENCE_TYPES)
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# django-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
# bthlabs-jsonrpc-django | (c) 2022-present Tomek Wójcik | MIT License
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from bthlabs_jsonrpc_core import Executor
|
||||
from bthlabs_jsonrpc_core.codecs import Codec
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import HttpRequest, HttpResponse, JsonResponse
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.decorators import classonlymethod
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.generic.base import View
|
||||
|
||||
from bthlabs_jsonrpc_django.codecs import DjangoJSONCodec
|
||||
from bthlabs_jsonrpc_django.executor import DjangoExecutor
|
||||
|
||||
|
||||
@@ -35,18 +38,19 @@ class JSONRPCView(View):
|
||||
]
|
||||
"""
|
||||
|
||||
# pragma mark - Private class attributes
|
||||
|
||||
# The executor class.
|
||||
executor: Executor = DjangoExecutor
|
||||
|
||||
# pragma mark - Public class attributes
|
||||
|
||||
#: The executor class.
|
||||
executor: type[DjangoExecutor] = DjangoExecutor
|
||||
|
||||
#: List of auth check functions.
|
||||
auth_checks: list[typing.Callable] = []
|
||||
|
||||
#: Namespace of this endpoint.
|
||||
namespace: typing.Optional[str] = None
|
||||
namespace: str | None = None
|
||||
|
||||
#: The codec class.
|
||||
codec: type[Codec] = DjangoJSONCodec
|
||||
|
||||
# pragma mark - Private interface
|
||||
|
||||
@@ -69,6 +73,19 @@ class JSONRPCView(View):
|
||||
if has_auth is False:
|
||||
raise PermissionDenied('This RPC endpoint requires auth.')
|
||||
|
||||
def get_executor(self, request: HttpRequest) -> DjangoExecutor:
|
||||
"""
|
||||
Returns an executor configured for the *request*.
|
||||
|
||||
:meta private:
|
||||
"""
|
||||
return self.executor(
|
||||
request,
|
||||
self.can_call,
|
||||
self.namespace,
|
||||
codec=self.get_codec(request),
|
||||
)
|
||||
|
||||
def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
"""
|
||||
Dispatches the *request*.
|
||||
@@ -84,7 +101,7 @@ class JSONRPCView(View):
|
||||
|
||||
self.ensure_auth(request)
|
||||
|
||||
return handler(request, *args, **kwargs)
|
||||
return handler(request, *args, **kwargs) # type: ignore[misc]
|
||||
|
||||
def post(self, request: HttpRequest) -> HttpResponse:
|
||||
"""
|
||||
@@ -92,15 +109,18 @@ class JSONRPCView(View):
|
||||
|
||||
:meta private:
|
||||
"""
|
||||
executor = self.executor(
|
||||
request, self.can_call, self.namespace,
|
||||
)
|
||||
executor = self.get_executor(request)
|
||||
|
||||
serializer = executor.execute(request.body)
|
||||
if serializer is None:
|
||||
return HttpResponse('')
|
||||
|
||||
return JsonResponse(serializer.data, safe=False)
|
||||
codec = self.get_codec(request)
|
||||
|
||||
return HttpResponse(
|
||||
content=codec.encode(serializer.data),
|
||||
content_type=codec.get_content_type(),
|
||||
)
|
||||
|
||||
# pragma mark - Public interface
|
||||
|
||||
@@ -120,3 +140,7 @@ class JSONRPCView(View):
|
||||
etc. The default implementation returns ``True``.
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_codec(self, request: HttpRequest) -> Codec:
|
||||
"""Returns a codec configured for the *request*."""
|
||||
return self.codec()
|
||||
|
||||
Reference in New Issue
Block a user