Add credentials property to Request objects (#2357)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import logging
|
||||
import random
|
||||
import re
|
||||
@@ -204,3 +205,7 @@ def sanic_ext(ext_instance): # noqa
|
||||
yield sanic_ext
|
||||
with suppress(KeyError):
|
||||
del sys.modules["sanic_ext"]
|
||||
|
||||
|
||||
def encode_basic_auth_credentials(username, password):
|
||||
return base64.b64encode(f"{username}:{password}".encode()).decode("ascii")
|
||||
|
||||
@@ -15,9 +15,10 @@ from sanic_testing.testing import (
|
||||
)
|
||||
|
||||
from sanic import Blueprint, Sanic
|
||||
from sanic.exceptions import SanicException, ServerError
|
||||
from sanic.request import DEFAULT_HTTP_CONTENT_TYPE, Request, RequestParameters
|
||||
from sanic.exceptions import ServerError
|
||||
from sanic.request import DEFAULT_HTTP_CONTENT_TYPE, RequestParameters
|
||||
from sanic.response import html, json, text
|
||||
from tests.conftest import encode_basic_auth_credentials
|
||||
|
||||
|
||||
# ------------------------------------------------------------ #
|
||||
@@ -362,93 +363,95 @@ async def test_uri_template_asgi(app):
|
||||
assert request.uri_template == "/foo/<id:int>/bar/<name:[A-z]+>"
|
||||
|
||||
|
||||
def test_token(app):
|
||||
@pytest.mark.parametrize(
|
||||
("auth_type", "token"),
|
||||
[
|
||||
# uuid4 generated token set in "Authorization" header
|
||||
(None, "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"),
|
||||
# uuid4 generated token with API Token authorization
|
||||
("Token", "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"),
|
||||
# uuid4 generated token with Bearer Token authorization
|
||||
("Bearer", "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"),
|
||||
# no Authorization header
|
||||
(None, None),
|
||||
],
|
||||
)
|
||||
def test_token(app, auth_type, token):
|
||||
@app.route("/")
|
||||
async def handler(request):
|
||||
return text("OK")
|
||||
|
||||
# uuid4 generated token.
|
||||
token = "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"{token}",
|
||||
}
|
||||
if token:
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"{auth_type} {token}"
|
||||
if auth_type
|
||||
else f"{token}",
|
||||
}
|
||||
else:
|
||||
headers = {"content-type": "application/json"}
|
||||
|
||||
request, response = app.test_client.get("/", headers=headers)
|
||||
|
||||
assert request.token == token
|
||||
|
||||
token = "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"Token {token}",
|
||||
}
|
||||
|
||||
request, response = app.test_client.get("/", headers=headers)
|
||||
|
||||
assert request.token == token
|
||||
|
||||
token = "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"Bearer {token}",
|
||||
}
|
||||
|
||||
request, response = app.test_client.get("/", headers=headers)
|
||||
|
||||
assert request.token == token
|
||||
|
||||
# no Authorization headers
|
||||
headers = {"content-type": "application/json"}
|
||||
|
||||
request, response = app.test_client.get("/", headers=headers)
|
||||
|
||||
assert request.token is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_token_asgi(app):
|
||||
@pytest.mark.parametrize(
|
||||
("auth_type", "token", "username", "password"),
|
||||
[
|
||||
# uuid4 generated token set in "Authorization" header
|
||||
(None, "a1d895e0-553a-421a-8e22-5ff8ecb48cbf", None, None),
|
||||
# uuid4 generated token with API Token authorization
|
||||
("Token", "a1d895e0-553a-421a-8e22-5ff8ecb48cbf", None, None),
|
||||
# uuid4 generated token with Bearer Token authorization
|
||||
("Bearer", "a1d895e0-553a-421a-8e22-5ff8ecb48cbf", None, None),
|
||||
# username and password with Basic Auth authorization
|
||||
(
|
||||
"Basic",
|
||||
encode_basic_auth_credentials("some_username", "some_pass"),
|
||||
"some_username",
|
||||
"some_pass",
|
||||
),
|
||||
# no Authorization header
|
||||
(None, None, None, None),
|
||||
],
|
||||
)
|
||||
def test_credentials(app, capfd, auth_type, token, username, password):
|
||||
@app.route("/")
|
||||
async def handler(request):
|
||||
return text("OK")
|
||||
|
||||
# uuid4 generated token.
|
||||
token = "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"{token}",
|
||||
}
|
||||
if token:
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"{auth_type} {token}"
|
||||
if auth_type
|
||||
else f"{token}",
|
||||
}
|
||||
else:
|
||||
headers = {"content-type": "application/json"}
|
||||
|
||||
request, response = await app.asgi_client.get("/", headers=headers)
|
||||
request, response = app.test_client.get("/", headers=headers)
|
||||
|
||||
assert request.token == token
|
||||
if auth_type == "Basic":
|
||||
assert request.credentials.username == username
|
||||
assert request.credentials.password == password
|
||||
else:
|
||||
_, err = capfd.readouterr()
|
||||
with pytest.raises(AttributeError):
|
||||
request.credentials.password
|
||||
assert "Password is available for Basic Auth only" in err
|
||||
request.credentials.username
|
||||
assert "Username is available for Basic Auth only" in err
|
||||
|
||||
token = "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"Token {token}",
|
||||
}
|
||||
|
||||
request, response = await app.asgi_client.get("/", headers=headers)
|
||||
|
||||
assert request.token == token
|
||||
|
||||
token = "a1d895e0-553a-421a-8e22-5ff8ecb48cbf"
|
||||
headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"Bearer {token}",
|
||||
}
|
||||
|
||||
request, response = await app.asgi_client.get("/", headers=headers)
|
||||
|
||||
assert request.token == token
|
||||
|
||||
# no Authorization headers
|
||||
headers = {"content-type": "application/json"}
|
||||
|
||||
request, response = await app.asgi_client.get("/", headers=headers)
|
||||
|
||||
assert request.token is None
|
||||
if token:
|
||||
assert request.credentials.token == token
|
||||
assert request.credentials.auth_type == auth_type
|
||||
else:
|
||||
assert request.credentials is None
|
||||
assert not hasattr(request.credentials, "token")
|
||||
assert not hasattr(request.credentials, "auth_type")
|
||||
assert not hasattr(request.credentials, "_username")
|
||||
assert not hasattr(request.credentials, "_password")
|
||||
|
||||
|
||||
def test_content_type(app):
|
||||
@@ -1714,7 +1717,6 @@ async def test_request_query_args_custom_parsing_asgi(app):
|
||||
|
||||
|
||||
def test_request_cookies(app):
|
||||
|
||||
cookies = {"test": "OK"}
|
||||
|
||||
@app.get("/")
|
||||
@@ -1729,7 +1731,6 @@ def test_request_cookies(app):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_request_cookies_asgi(app):
|
||||
|
||||
cookies = {"test": "OK"}
|
||||
|
||||
@app.get("/")
|
||||
|
||||
Reference in New Issue
Block a user