Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ahopkins committed Nov 5, 2017
1 parent 3859508 commit 5af0a77
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 75 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Example: The below example could be used in creating a "magic" passwordless logi

initialize(
app,
authenticate=lambda: True,
class_views=[
('/magic-login', MagicLoginHandler) # The path will be relative to the url prefix (which defaults to /auth)
]
Expand All @@ -138,6 +139,7 @@ Example:

initialize(
app,
authenticate=lambda: True,
store_refresh_token=store_refresh_token
)

Expand All @@ -159,6 +161,7 @@ Example:

initialize(
app,
authenticate=lambda: True,
retrieve_refresh_token=retrieve_refresh_token
)

Expand Down Expand Up @@ -187,6 +190,7 @@ Example:

initialize(
app,
authenticate=lambda: True,
retrieve_user=retrieve_user
)

Expand Down
10 changes: 8 additions & 2 deletions sanic_jwt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from sanic_jwt.blueprint import bp as sanic_jwt_auth_bp
from sanic_jwt.authentication import SanicJWTAuthentication
from sanic_jwt import settings
from sanic_jwt import settings, exceptions, utils


def initialize(
Expand All @@ -12,7 +12,7 @@ def initialize(
retrieve_user=None,
):
# Add settings
app.config.from_object(settings)
utils.load_settings(app, settings)

if class_views is not None:
# TODO:
Expand All @@ -32,3 +32,9 @@ def initialize(
setattr(app.auth, 'retrieve_refresh_token', retrieve_refresh_token)
if retrieve_user:
setattr(app.auth, 'retrieve_user', retrieve_user)

if app.config.SANIC_JWT_REFRESH_TOKEN_ENABLED and (
not store_refresh_token or
not retrieve_refresh_token
):
raise exceptions.RefreshTokenNotImplemented()
7 changes: 7 additions & 0 deletions sanic_jwt/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,10 @@ def build_claim_nbf(attr, config, *args, **kwargs):

def build_claim_aud(attr, *args, **kwargs):
return attr


def load_settings(app, settings):
for setting in dir(settings):
if setting.isupper() and setting not in app.config:
value = getattr(settings, setting)
setattr(app.config, setting, value)
58 changes: 0 additions & 58 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,58 +0,0 @@
from sanic import Sanic
from sanic.response import json
from sanic_jwt import exceptions
from sanic_jwt import initialize
from sanic_jwt.decorators import protected


class User(object):
def __init__(self, id, username, password):
self.user_id = id
self.username = username
self.password = password

def __str__(self):
return "User(id='%s')" % self.id


users = [
User(1, 'user1', 'abcxyz'),
User(2, 'user2', 'abcxyz'),
]

username_table = {u.username: u for u in users}
# userid_table = {u.user_id: u for u in users}


async def authenticate(request, *args, **kwargs):
username = request.json.get('username', None)
password = request.json.get('password', None)

if not username or not password:
raise exceptions.AuthenticationFailed("Missing username or password.")

user = username_table.get(username, None)
if user is None:
raise exceptions.AuthenticationFailed("User not found.")

if password != user.password:
raise exceptions.AuthenticationFailed("Password is incorrect.")

return user

app = Sanic()
initialize(
app,
authenticate=authenticate,
)


@app.route("/")
async def test(request):
return json({"hello": "world"})


@app.route("/protected")
@protected()
async def protected(request):
return json({"protected": True})
65 changes: 63 additions & 2 deletions tests/test_endpoints_auth.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,67 @@
import jwt
from sanic import Sanic
from sanic.response import json
from sanic_jwt import exceptions
from sanic_jwt import initialize
from sanic_jwt.decorators import protected


class User(object):
def __init__(self, id, username, password):
self.user_id = id
self.username = username
self.password = password

def __str__(self):
return "User(id='%s')" % self.id

def to_dict(self):
properties = ['user_id', 'username', ]
return {prop: getattr(self, prop, None) for prop in properties}


users = [
User(1, 'user1', 'abcxyz'),
User(2, 'user2', 'abcxyz'),
]

username_table = {u.username: u for u in users}
# userid_table = {u.user_id: u for u in users}


async def authenticate(request, *args, **kwargs):
username = request.json.get('username', None)
password = request.json.get('password', None)

if not username or not password:
raise exceptions.AuthenticationFailed("Missing username or password.")

user = username_table.get(username, None)
if user is None:
raise exceptions.AuthenticationFailed("User not found.")

if password != user.password:
raise exceptions.AuthenticationFailed("Password is incorrect.")

return user

app = Sanic()
initialize(
app,
authenticate=authenticate,
)


@app.route("/")
async def helloworld(request):
return json({"hello": "world"})


@app.route("/protected")
@protected()
async def protected(request):
return json({"protected": True})

from . import app

_, response = app.test_client.post('/auth', json={
'username': 'user1',
Expand All @@ -15,7 +76,7 @@ class TestEndpointsAuth(object):
def dispatch(self, path, method):
header_token = '{} {}'.format(app.config.SANIC_JWT_AUTHORIZATION_HEADER_PREFIX, access_token)
method = getattr(app.test_client, method)
request, response = method('/auth/verify', headers={
request, response = method(path, headers={
app.config.SANIC_JWT_AUTHORIZATION_HEADER: header_token
})
return request, response
Expand Down
79 changes: 66 additions & 13 deletions tests/test_endpoints_basic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,63 @@
import jwt
import jwt, pytest

from sanic import Sanic
from sanic.response import json
from sanic_jwt import exceptions
from . import app
from sanic_jwt import initialize
from sanic_jwt.decorators import protected


class User(object):
def __init__(self, id, username, password):
self.user_id = id
self.username = username
self.password = password

def __str__(self):
return "User(id='%s')" % self.id


users = [
User(1, 'user1', 'abcxyz'),
User(2, 'user2', 'abcxyz'),
]

username_table = {u.username: u for u in users}
# userid_table = {u.user_id: u for u in users}


async def authenticate(request, *args, **kwargs):
username = request.json.get('username', None)
password = request.json.get('password', None)

if not username or not password:
raise exceptions.AuthenticationFailed("Missing username or password.")

user = username_table.get(username, None)
if user is None:
raise exceptions.AuthenticationFailed("User not found.")

if password != user.password:
raise exceptions.AuthenticationFailed("Password is incorrect.")

return user

app = Sanic()
initialize(
app,
authenticate=authenticate,
)


@app.route("/")
async def helloworld(request):
return json({"hello": "world"})


@app.route("/protected")
@protected()
async def protected(request):
return json({"protected": True})


class TestEndpointsBasic(object):
Expand Down Expand Up @@ -32,14 +88,11 @@ def test_auth_proper_credentials(self):
assert app.config.SANIC_JWT_USER_ID in payload
assert 'exp' in payload

def test_auth_verify_missing_token(self):
try:
_, response = app.test_client.get('/auth/verify')
except Exception as e:
assert isinstance(e, exceptions.MissingAuthorizationHeader)

def test_auth_refresh_not_enabled(self):
try:
_, response = app.test_client.get('/auth/refresh')
except Exception as e:
assert isinstance(e, exceptions.MissingAuthorizationHeader)
# def test_auth_verify_missing_token(self):
# with pytest.raises(exceptions.MissingAuthorizationHeader):
# _, response = app.test_client.get('/auth/verify')
# assert response.status == 200

# def test_auth_refresh_not_enabled(self):
# with pytest.raises(exceptions.MissingAuthorizationHeader):
# _, response = app.test_client.post('/auth/refresh')
53 changes: 53 additions & 0 deletions tests/test_endpoints_extra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from sanic import Sanic, response
from sanic.views import HTTPMethodView
from sanic.response import json
from sanic_jwt import initialize


class MagicLoginHandler(HTTPMethodView):
async def options(self, request):
return response.text('', status=204)

async def post(self, request):
# create a magic login token and email it to the user

response = {
'magic-token': '123456789'
}
return json(response)


app = Sanic()
initialize(
app,
authenticate=lambda: True,
class_views=[
('/magic-login', MagicLoginHandler) # The path will be relative to the url prefix (which defaults to /auth)
]
)


class TestEndpointsExtra(object):
def dispatch(self, path, method):
# header_token = '{} {}'.format(app.config.SANIC_JWT_AUTHORIZATION_HEADER_PREFIX, access_token)
method = getattr(app.test_client, method)
request, response = method(path)
return request, response

def get(self, path):
return self.dispatch(path, 'get')

def post(self, path):
return self.dispatch(path, 'post')

def options(self, path):
return self.dispatch(path, 'options')

def test_verify_token(self):
_, response = self.options('/auth/magic-login')
assert response.status == 204

_, response = self.post('/auth/magic-login')

assert response.status == 200
assert response.json.get('magic-token') == '123456789'
Loading

0 comments on commit 5af0a77

Please sign in to comment.