Skip to content

Commit

Permalink
Merge pull request #156 from ahopkins/dev
Browse files Browse the repository at this point in the history
Version 1.3.1 - 2019-04-25
  • Loading branch information
ahopkins committed Apr 25, 2019
2 parents ec951d5 + 1a40cb9 commit cf4890e
Show file tree
Hide file tree
Showing 46 changed files with 235 additions and 157 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ test:

black:
black ./ -l 79 --safe
isort -rc sanic_jwt tests

release: clean
python setup.py sdist upload
python setup.py bdist_wheel upload
python setup.py sdist bdist_wheel
twine upload dist/*
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
# The short X.Y version.
version = u"1.3"
# The full version, including alpha/beta/rc tags.
release = u"1.3.0"
release = u"1.3.1"

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
12 changes: 12 additions & 0 deletions docs/source/pages/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ Changelog

The format is based on `Keep a Changelog <http://keepachangelog.com/en/1.0.0/>`_ and this project adheres to `Semantic Versioning <http://semver.org/spec/v2.0.0.html>`_.

++++++++++++++++++++++++++
Version 1.3.1 - 2019-04-25
++++++++++++++++++++++++++

| **Added**
| - Support for ``False`` and ``None`` scopes.
| **Changed**
| - Use ``request.args`` instead of ``request.query_args`` to resolve `Depracation Warning <https://sanic.readthedocs.io/en/19.03.1/sanic/request_data.html#request-data>`_.
|

++++++++++++++++++++++++++
Version 1.3.0 - 2019-04-24
++++++++++++++++++++++++++
Expand Down
4 changes: 4 additions & 0 deletions docs/source/pages/scoped.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ If you have initialized Sanic JWT on a ``Blueprint``, then you will need to pass
async def users(request, id):
...
.. note::

If you provide a ``False`` or ``None`` value to the ``@scoped`` decorator, it will effectively remove **all** protection. This means all requests, whether authenticated or not, will be accepted.

Parameters
~~~~~~~~~~

Expand Down
9 changes: 3 additions & 6 deletions sanic_jwt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "1.3.0"
__version__ = "1.3.1"
__author__ = "Adam Hopkins"
__credits__ = "Richard Kuesters"

Expand All @@ -7,12 +7,9 @@
from .authentication import Authentication
from .claim import Claim
from .configuration import Configuration
from .decorators import inject_user
from .decorators import protected
from .decorators import scoped
from .decorators import inject_user, protected, scoped
from .endpoints import BaseEndpoint
from .initialization import Initialize
from .initialization import initialize
from .initialization import Initialize, initialize
from .responses import Responses

logging.getLogger(__name__).addHandler(logging.NullHandler())
Expand Down
20 changes: 10 additions & 10 deletions sanic_jwt/authentication.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import inspect
import jwt
import logging
import warnings
from datetime import datetime, timedelta

from .exceptions import InvalidCustomClaimError
from .exceptions import InvalidVerification
from .exceptions import InvalidVerificationError
from .exceptions import SanicJWTException
from datetime import datetime
from datetime import timedelta
import jwt

from . import exceptions
from . import utils
from . import exceptions, utils
from .exceptions import (
InvalidCustomClaimError,
InvalidVerification,
InvalidVerificationError,
SanicJWTException
)

logger = logging.getLogger(__name__)
claim_label = {"iss": "issuer", "iat": "iat", "nbf": "nbf", "aud": "audience"}
Expand Down Expand Up @@ -279,7 +279,7 @@ def _get_token_from_query_string(self, request, refresh_token):
query_string_token_name = getattr(
self.config, query_string_token_name_key
)
return request.raw_args.get(query_string_token_name(), None)
return request.args.get(query_string_token_name(), None)

def _get_token(self, request, refresh_token=False):
"""
Expand Down
8 changes: 2 additions & 6 deletions sanic_jwt/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@
import copy
import logging

from . import exceptions
from . import utils
from .cache import get_cached
from .cache import is_cached
from .cache import to_cache

from . import exceptions, utils
from .cache import get_cached, is_cached, to_cache

defaults = {
"access_token_name": "access_token",
Expand Down
99 changes: 56 additions & 43 deletions sanic_jwt/decorators.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import logging

from contextlib import contextmanager
from copy import deepcopy
from functools import wraps
from inspect import isawaitable

from sanic import Blueprint
from sanic.views import HTTPMethodView
from sanic.response import redirect
from sanic.views import HTTPMethodView

from . import exceptions
from . import utils
from .cache import clear_cache
from .cache import to_cache
from . import exceptions, utils
from .cache import clear_cache, to_cache
from .validators import validate_scopes

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -139,49 +137,61 @@ def scoped(
def decorator(f):
@wraps(f)
async def decorated_function(request, *args, **kwargs):
protect_kwargs = deepcopy(kwargs)
protect_kwargs.update(
{
"initialized_on": initialized_on,
"kw": kw,
"request": request,
"f": f,
"return_response": False,
}
)
_, instance = await _do_protection(*args, **protect_kwargs)

if request.method == "OPTIONS":
return instance

user_scopes = instance.auth.extract_scopes(request)
override = instance.auth.override_scope_validator
destructure = instance.auth.destructure_scopes
if user_scopes is None:
# If there are no defined scopes in the payload,
# deny access
is_authorized = False
status = 403
reasons = "Invalid scope."
raise exceptions.Unauthorized(reasons, status_code=status)
if issubclass(request.__class__, HTTPMethodView):
request = args[0]

else:
is_authorized = await validate_scopes(
request,
scopes,
user_scopes,
require_all=require_all,
require_all_actions=require_all_actions,
override=override,
destructure=destructure,
request_args=args,
request_kwargs=kwargs,
if scopes is not None and scopes is not False:
protect_kwargs = deepcopy(kwargs)
protect_kwargs.update(
{
"initialized_on": initialized_on,
"kw": kw,
"request": request,
"f": f,
"return_response": False,
}
)
if not is_authorized:
_, instance = await _do_protection(*args, **protect_kwargs)

if request.method == "OPTIONS":
return instance

user_scopes = instance.auth.extract_scopes(request)
override = instance.auth.override_scope_validator
destructure = instance.auth.destructure_scopes
if user_scopes is None:
# If there are no defined scopes in the payload,
# deny access
is_authorized = False
status = 403
reasons = "Invalid scope."

# TODO:
# - add login_redirect_url
raise exceptions.Unauthorized(reasons, status_code=status)

else:
is_authorized = await validate_scopes(
request,
scopes,
user_scopes,
require_all=require_all,
require_all_actions=require_all_actions,
override=override,
destructure=destructure,
request_args=args,
request_kwargs=kwargs,
)
if not is_authorized:
status = 403
reasons = "Invalid scope."

# TODO:
# - add login_redirect_url
raise exceptions.Unauthorized(
reasons, status_code=status
)

# the user is authorized.
# run the handler method and return the response
# NOTE: it's possible to use return await.utils(f, ...) in
Expand All @@ -201,6 +211,9 @@ def inject_user(initialized_on=None, **kw):
def decorator(f):
@wraps(f)
async def decorated_function(request, *args, **kwargs):
if issubclass(request.__class__, HTTPMethodView):
request = args[0]

if initialized_on and isinstance(
initialized_on, Blueprint
): # noqa
Expand Down
6 changes: 2 additions & 4 deletions sanic_jwt/endpoints.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from sanic.response import json
from sanic.response import text
from sanic.response import json, text
from sanic.views import HTTPMethodView

from . import exceptions
from . import utils
from . import exceptions, utils
from .base import BaseDerivative
from .decorators import protected

Expand Down
11 changes: 3 additions & 8 deletions sanic_jwt/initialization.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import inspect

from collections import namedtuple

from sanic import Blueprint
from sanic import Sanic
from sanic import Blueprint, Sanic

from sanic_jwt import endpoints
from sanic_jwt import exceptions
from sanic_jwt import endpoints, exceptions
from sanic_jwt.authentication import Authentication
from sanic_jwt.configuration import Configuration
from sanic_jwt.decorators import inject_user
from sanic_jwt.decorators import protected
from sanic_jwt.decorators import scoped
from sanic_jwt.decorators import inject_user, protected, scoped
from sanic_jwt.responses import Responses

_Handler = namedtuple(
Expand Down
1 change: 0 additions & 1 deletion sanic_jwt/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import inspect
import logging
import os

from pathlib import Path

from . import exceptions
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def open_local(paths, mode="r", encoding="utf8"):

setup(
name="sanic-jwt",
version="1.3.0",
version=version,
description="JWT oauth flow for Sanic",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
13 changes: 4 additions & 9 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import pytest

from sanic import Blueprint
from sanic import Sanic
from sanic.response import json
from sanic.response import text
from sanic import Blueprint, Sanic
from sanic.response import json, text

from sanic_jwt import Initialize
from sanic_jwt import Claim
from sanic_jwt import exceptions
import pytest
from sanic_jwt import Claim, exceptions, Initialize
from sanic_jwt.decorators import protected


Expand Down
4 changes: 2 additions & 2 deletions tests/test_async_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"""


import pytest
import jwt
from sanic import Blueprint, Sanic
from sanic.response import text
from sanic.views import HTTPMethodView

import jwt
import pytest
from sanic_jwt import Authentication, initialize, protected

ALL_METHODS = ["GET", "OPTIONS"]
Expand Down
2 changes: 1 addition & 1 deletion tests/test_authentication.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest
from sanic import Sanic
from sanic.response import json

import pytest
from sanic_jwt import Authentication, exceptions, Initialize


Expand Down
2 changes: 1 addition & 1 deletion tests/test_authentication_custom.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from sanic import Sanic

import pytest
from sanic_jwt import Authentication, Initialize


Expand Down
2 changes: 1 addition & 1 deletion tests/test_cache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from sanic_jwt.cache import is_cached
from sanic_jwt import exceptions
from sanic_jwt.cache import is_cached


def test_cache_is_not_running():
Expand Down
1 change: 1 addition & 0 deletions tests/test_claims.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datetime import datetime, timedelta

import jwt

from freezegun import freeze_time


Expand Down
8 changes: 5 additions & 3 deletions tests/test_complete_authentication.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from datetime import datetime, timedelta

import jwt
import pytest
from sanic import Sanic
from sanic.response import json
from datetime import datetime, timedelta

import pytest
from freezegun import freeze_time
from sanic_jwt import Authentication, Initialize, exceptions, protected
from sanic_jwt import Authentication, exceptions, Initialize, protected


@pytest.yield_fixture
Expand Down
2 changes: 1 addition & 1 deletion tests/test_configuration.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest
from sanic import Sanic
from sanic.response import json

import pytest
from sanic_jwt import Configuration, exceptions, initialize, Initialize
from sanic_jwt.configuration import ConfigItem

Expand Down

0 comments on commit cf4890e

Please sign in to comment.