canaille-globuzma/tests/oidc/test_consent.py

212 lines
6.6 KiB
Python

from urllib.parse import parse_qs
from urllib.parse import urlsplit
from canaille.app import models
from . import client_credentials
def test_no_logged_no_access(testclient):
testclient.get("/consent", status=403)
def test_revokation(testclient, client, consent, logged_user, token):
res = testclient.get("/consent", status=200)
res.mustcontain(client.client_name)
res.mustcontain("Revoke access")
res.mustcontain(no="Restore access")
assert not consent.revoked
assert not token.revoked
res = testclient.get(f"/consent/revoke/{consent.consent_id}", status=302)
assert ("success", "The access has been revoked") in res.flashes
res = res.follow(status=200)
res.mustcontain(no="Revoke access")
res.mustcontain("Restore access")
consent.reload()
assert consent.revoked
token.reload()
assert token.revoked
def test_revokation_already_revoked(testclient, client, consent, logged_user):
consent.revoke()
assert consent.revoked
res = testclient.get(f"/consent/revoke/{consent.consent_id}", status=302)
assert ("error", "The access is already revoked") in res.flashes
res = res.follow(status=200)
consent.reload()
assert consent.revoked
def test_restoration(testclient, client, consent, logged_user, token):
consent.revoke()
assert consent.revoked
token.reload()
assert token.revoked
res = testclient.get(f"/consent/restore/{consent.consent_id}", status=302)
assert ("success", "The access has been restored") in res.flashes
res = res.follow(status=200)
consent.reload()
assert not consent.revoked
token.reload()
assert token.revoked
def test_restoration_already_restored(testclient, client, consent, logged_user, token):
assert not consent.revoked
res = testclient.get(f"/consent/restore/{consent.consent_id}", status=302)
assert ("error", "The access is not revoked") in res.flashes
res = res.follow(status=200)
def test_invalid_consent_revokation(testclient, client, logged_user):
res = testclient.get("/consent/revoke/invalid", status=302)
assert ("success", "The access has been revoked") not in res.flashes
assert ("error", "Could not revoke this access") in res.flashes
def test_someone_else_consent_revokation(testclient, client, consent, logged_moderator):
res = testclient.get(f"/consent/revoke/{consent.consent_id}", status=302)
assert ("success", "The access has been revoked") not in res.flashes
assert ("error", "Could not revoke this access") in res.flashes
def test_invalid_consent_restoration(testclient, client, logged_user):
res = testclient.get("/consent/restore/invalid", status=302)
assert ("success", "The access has been restored") not in res.flashes
assert ("error", "Could not restore this access") in res.flashes
def test_someone_else_consent_restoration(
testclient, client, consent, logged_moderator
):
res = testclient.get(f"/consent/restore/{consent.consent_id}", status=302)
assert ("success", "The access has been restore") not in res.flashes
assert ("error", "Could not restore this access") in res.flashes
def test_oidc_authorization_after_revokation(
testclient, logged_user, client, keypair, consent
):
consent.revoke()
assert consent.revoked
res = testclient.get(
"/oauth/authorize",
params=dict(
response_type="code",
client_id=client.client_id,
scope="openid profile",
nonce="somenonce",
),
status=200,
)
res = res.form.submit(name="answer", value="accept", status=302)
consents = models.Consent.query(client=client, subject=logged_user)
consent.reload()
assert consents[0] == consent
assert not consent.revoked
params = parse_qs(urlsplit(res.location).query)
code = params["code"][0]
res = testclient.post(
"/oauth/token",
params=dict(
grant_type="authorization_code",
code=code,
scope="openid profile",
redirect_uri=client.redirect_uris[0],
),
headers={"Authorization": f"Basic {client_credentials(client)}"},
status=200,
)
access_token = res.json["access_token"]
token = models.Token.get(access_token=access_token)
assert token.client == client
assert token.subject == logged_user
def test_preconsented_client_appears_in_consent_list(testclient, client, logged_user):
assert not client.preconsent
res = testclient.get("/consent/pre-consents")
res.mustcontain(no=client.client_name)
client.preconsent = True
client.save()
res = testclient.get("/consent/pre-consents")
res.mustcontain(client.client_name)
def test_revoke_preconsented_client(testclient, client, logged_user, token):
client.preconsent = True
client.save()
assert not models.Consent.get()
assert not token.revoked
res = testclient.get(f"/consent/revoke-preconsent/{client.client_id}", status=302)
assert ("success", "The access has been revoked") in res.flashes
consent = models.Consent.get()
assert consent.client == client
assert consent.subject == logged_user
assert consent.scope == ["openid", "email", "profile", "groups", "address", "phone"]
assert not consent.issue_date
token.reload()
assert token.revoked
res = testclient.get(f"/consent/restore/{consent.consent_id}", status=302)
assert ("success", "The access has been restored") in res.flashes
consent.reload()
assert not consent.revoked
assert consent.issue_date
token.reload()
assert token.revoked
res = testclient.get(f"/consent/revoke/{consent.consent_id}", status=302)
assert ("success", "The access has been revoked") in res.flashes
consent.reload()
assert consent.revoked
assert consent.issue_date
def test_revoke_invalid_preconsented_client(testclient, logged_user):
res = testclient.get("/consent/revoke-preconsent/invalid", status=302)
assert ("error", "Could not revoke this access") in res.flashes
def test_revoke_preconsented_client_with_manual_consent(
testclient, logged_user, client, consent
):
client.preconsent = True
client.save()
res = testclient.get(f"/consent/revoke-preconsent/{client.client_id}", status=302)
res = res.follow()
assert ("success", "The access has been revoked") in res.flashes
def test_revoke_preconsented_client_with_manual_revokation(
testclient, logged_user, client, consent
):
client.preconsent = True
client.save()
consent.revoke()
consent.save()
res = testclient.get(f"/consent/revoke-preconsent/{client.client_id}", status=302)
res = res.follow()
assert ("error", "The access is already revoked") in res.flashes