blob: 07bc8a38d8514f8661d8a3d7ad53602b5ff14a61 [file]
#!/usr/bin/env python3
import time
import re
import pytest
import quart
import asfquart.auth
from asfquart.auth import Requirements as R
def _string_to_re(s):
"""convert arbitrary string to fullmatch regex"""
return re.escape(s) + '$'
@pytest.mark.auth
async def test_auth_basics():
app = asfquart.construct("foobar", token_file=None)
# Generic auth test, just requires a valid session
@asfquart.auth.require
async def requires_session():
pass
# Test with no session, should fail
quart.session = {}
with pytest.raises(asfquart.auth.AuthenticationFailed, match=_string_to_re(R.E_NOT_LOGGED_IN)):
await requires_session()
# Test with session, should work.
quart.session = {app.app_id: {"uts": time.time(), "foo": "bar"}}
await requires_session()
# Test with a bad requirement, should fail with a TypeError.
with pytest.raises(TypeError):
@asfquart.auth.require({R.member, print})
async def requires_bad_thing():
pass
# Same bad one, but with explicit any_of
with pytest.raises(TypeError):
@asfquart.auth.require(any_of={R.member, print})
async def requires_bad_thingy():
pass
@pytest.mark.auth
async def test_mfa_auth():
"""MFA tests"""
app = asfquart.construct("foobar", token_file=None)
@asfquart.auth.require(R.mfa_enabled)
async def requires_mfa():
pass
# Test MFA with no session, should fail exactly like auth_required
quart.session = {}
with pytest.raises(asfquart.auth.AuthenticationFailed, match=_string_to_re(R.E_NOT_LOGGED_IN)):
await requires_mfa()
# Test with session without MFA, should fail.
quart.session = {app.app_id: {"uts": time.time(), "foo": "bar"}}
with pytest.raises(asfquart.auth.AuthenticationFailed, match=_string_to_re(R.E_NO_MFA)):
await requires_mfa()
# Test with session with MFA, should work.
quart.session = {app.app_id: {"uts": time.time(), "foo": "bar", "mfa": True}}
await requires_mfa()
@pytest.mark.auth
async def test_role_auth():
"""Role tests"""
app = asfquart.construct("foobar", token_file=None)
# Set up some role tests
@asfquart.auth.require # no args implies any valid account
async def test_committer_auth():
pass
@asfquart.auth.require(R.member)
async def test_member_auth():
pass
@asfquart.auth.require({R.member, R.chair})
async def test_member_and_chair_auth():
pass
@asfquart.auth.require(any_of={R.member, R.chair})
async def test_member_or_chair_auth():
pass
# Test role with no session, should fail exactly like auth_required
quart.session = {}
with pytest.raises(asfquart.auth.AuthenticationFailed, match=_string_to_re(R.E_NOT_LOGGED_IN)):
await test_committer_auth()
# Test with session , should work
quart.session = {app.app_id: {"uts": time.time(), "foo": "bar"}}
await test_committer_auth()
# Test with a role we don't have, should fail
with pytest.raises(asfquart.auth.AuthenticationFailed, match=_string_to_re(R.E_NOT_MEMBER)):
await test_member_auth()
# Test with for both member and chair, while only being member. should pass on member check, fail on chair
quart.session = {app.app_id: {"uts": time.time(), "foo": "bar", "isMember": True}}
with pytest.raises(asfquart.auth.AuthenticationFailed, match=_string_to_re(R.E_NOT_CHAIR)):
await test_member_and_chair_auth()
# Test for either member of chair, should work as we have chair (but not member)
quart.session = {app.app_id: {"uts": time.time(), "foo": "bar", "isChair": True}}
await test_member_or_chair_auth()
# Test for both member and chair, when we are both. should work.
quart.session = {app.app_id: {"uts": time.time(), "foo": "bar", "isMember": True, "isChair": True}}
await test_member_and_chair_auth()