*: add pyright type checking
This commit is contained in:
parent
80d90b91e8
commit
813dd2894f
|
@ -52,6 +52,13 @@ jobs:
|
||||||
run: sudo pip install -U wheel pipenv && pipenv install --dev
|
run: sudo pip install -U wheel pipenv && pipenv install --dev
|
||||||
- name: Lint with bandit
|
- name: Lint with bandit
|
||||||
run: pipenv run bandit -r passbook
|
run: pipenv run bandit -r passbook
|
||||||
|
pyright:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
- name: Run pyright
|
||||||
|
run: pyright
|
||||||
# Actual CI tests
|
# Actual CI tests
|
||||||
migrations:
|
migrations:
|
||||||
needs:
|
needs:
|
||||||
|
|
|
@ -66,7 +66,9 @@ class EventAction(Enum):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def as_choices():
|
def as_choices():
|
||||||
"""Generate choices of actions used for database"""
|
"""Generate choices of actions used for database"""
|
||||||
return tuple((x, y.value) for x, y in EventAction.__members__.items())
|
return tuple(
|
||||||
|
(x, y.value) for x, y in getattr(EventAction, "__members__").items()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Event(UUIDModel):
|
class Event(UUIDModel):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""passbook expression policy evaluator"""
|
"""passbook expression policy evaluator"""
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Any, Dict
|
from typing import TYPE_CHECKING, Any, Dict, Optional
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from jinja2 import Undefined
|
from jinja2 import Undefined
|
||||||
|
@ -72,7 +72,7 @@ class Evaluator:
|
||||||
except TemplateSyntaxError as exc:
|
except TemplateSyntaxError as exc:
|
||||||
return PolicyResult(False, str(exc))
|
return PolicyResult(False, str(exc))
|
||||||
try:
|
try:
|
||||||
result = expression.render(
|
result: Optional[Any] = expression.render(
|
||||||
request=request, **self._get_expression_context(request)
|
request=request, **self._get_expression_context(request)
|
||||||
)
|
)
|
||||||
if isinstance(result, Undefined):
|
if isinstance(result, Undefined):
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
"""passbook OAuth2 Views"""
|
"""passbook OAuth2 Views"""
|
||||||
|
from typing import Optional
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.forms import Form
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, redirect, reverse
|
from django.shortcuts import get_object_or_404, redirect, reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from oauth2_provider.views.base import AuthorizationView
|
from oauth2_provider.views.base import AuthorizationView
|
||||||
|
@ -36,7 +39,7 @@ class OAuthPermissionDenied(PermissionDeniedView):
|
||||||
class PassbookAuthorizationView(AccessMixin, AuthorizationView):
|
class PassbookAuthorizationView(AccessMixin, AuthorizationView):
|
||||||
"""Custom OAuth2 Authorization View which checks policies, etc"""
|
"""Custom OAuth2 Authorization View which checks policies, etc"""
|
||||||
|
|
||||||
_application = None
|
_application: Optional[Application] = None
|
||||||
|
|
||||||
def _inject_response_type(self):
|
def _inject_response_type(self):
|
||||||
"""Inject response_type into querystring if not set"""
|
"""Inject response_type into querystring if not set"""
|
||||||
|
@ -47,7 +50,7 @@ class PassbookAuthorizationView(AccessMixin, AuthorizationView):
|
||||||
reverse("passbook_providers_oauth:oauth2-ok-authorize") + "?" + querystring
|
reverse("passbook_providers_oauth:oauth2-ok-authorize") + "?" + querystring
|
||||||
)
|
)
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
"""Update OAuth2Provider's skip_authorization state"""
|
"""Update OAuth2Provider's skip_authorization state"""
|
||||||
# Get client_id to get provider, so we can update skip_authorization field
|
# Get client_id to get provider, so we can update skip_authorization field
|
||||||
client_id = request.GET.get("client_id")
|
client_id = request.GET.get("client_id")
|
||||||
|
@ -69,12 +72,12 @@ class PassbookAuthorizationView(AccessMixin, AuthorizationView):
|
||||||
# Some clients don't pass response_type, so we default to code
|
# Some clients don't pass response_type, so we default to code
|
||||||
if "response_type" not in request.GET:
|
if "response_type" not in request.GET:
|
||||||
return self._inject_response_type()
|
return self._inject_response_type()
|
||||||
actual_response = super().dispatch(request, *args, **kwargs)
|
actual_response = AuthorizationView.dispatch(self, request, *args, **kwargs)
|
||||||
if actual_response.status_code == 400:
|
if actual_response.status_code == 400:
|
||||||
LOGGER.debug(request.GET.get("redirect_uri"))
|
LOGGER.debug("Bad request", redirect_uri=request.GET.get("redirect_uri"))
|
||||||
return actual_response
|
return actual_response
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form: Form):
|
||||||
# User has clicked on "Authorize"
|
# User has clicked on "Authorize"
|
||||||
Event.new(
|
Event.new(
|
||||||
EventAction.AUTHORIZE_APPLICATION, authorized_application=self._application,
|
EventAction.AUTHORIZE_APPLICATION, authorized_application=self._application,
|
||||||
|
@ -84,4 +87,4 @@ class PassbookAuthorizationView(AccessMixin, AuthorizationView):
|
||||||
user=self.request.user,
|
user=self.request.user,
|
||||||
application=self._application,
|
application=self._application,
|
||||||
)
|
)
|
||||||
return super().form_valid(form)
|
return AuthorizationView.form_valid(self, form)
|
||||||
|
|
|
@ -100,7 +100,7 @@ class SAMLProvider(Provider):
|
||||||
self._meta.get_field("processor_path").choices = get_provider_choices()
|
self._meta.get_field("processor_path").choices = get_provider_choices()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def processor(self) -> Processor:
|
def processor(self) -> Optional[Processor]:
|
||||||
"""Return selected processor as instance"""
|
"""Return selected processor as instance"""
|
||||||
if not self._processor:
|
if not self._processor:
|
||||||
try:
|
try:
|
||||||
|
@ -163,4 +163,6 @@ class SAMLPropertyMapping(PropertyMapping):
|
||||||
|
|
||||||
def get_provider_choices():
|
def get_provider_choices():
|
||||||
"""Return tuple of class_path, class name of all providers."""
|
"""Return tuple of class_path, class name of all providers."""
|
||||||
return [(class_to_path(x), x.__name__) for x in Processor.__subclasses__()]
|
return [
|
||||||
|
(class_to_path(x), x.__name__) for x in Processor.__dict__["__subclasses__"]()
|
||||||
|
]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/bin/bash -xe
|
#!/bin/bash -xe
|
||||||
isort -rc passbook
|
isort -rc passbook
|
||||||
|
pyright
|
||||||
black passbook
|
black passbook
|
||||||
scripts/coverage.sh
|
scripts/coverage.sh
|
||||||
bandit -r passbook
|
bandit -r passbook
|
||||||
|
|
Reference in New Issue