e2e: add OIDC Provider test against grafana, more formatting, minor bug fixes
This commit is contained in:
parent
8c6a4a4968
commit
73e7158178
|
@ -0,0 +1,300 @@
|
|||
{
|
||||
"id": "7d9b2407-1520-4c04-b040-68e8ada9aecc",
|
||||
"version": "2.0",
|
||||
"name": "passbook",
|
||||
"url": "http://localhost:8000",
|
||||
"tests": [{
|
||||
"id": "94b39863-74ec-4b7d-98c5-2b380b6d2c55",
|
||||
"name": "passbook login simple",
|
||||
"commands": [{
|
||||
"id": "e60e4382-4f96-44c3-ba06-5e18609c9c2b",
|
||||
"comment": "",
|
||||
"command": "open",
|
||||
"target": "/flows/default-authentication-flow/?next=%2F",
|
||||
"targets": [],
|
||||
"value": ""
|
||||
}, {
|
||||
"id": "b2652f24-931e-45b0-b01d-2f0ac0f74db8",
|
||||
"comment": "",
|
||||
"command": "click",
|
||||
"target": "id=id_uid_field",
|
||||
"targets": [
|
||||
["id=id_uid_field", "id"],
|
||||
["name=uid_field", "name"],
|
||||
["css=#id_uid_field", "css:finder"],
|
||||
["xpath=//input[@id='id_uid_field']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div/input", "xpath:idRelative"],
|
||||
["xpath=//div/input", "xpath:position"]
|
||||
],
|
||||
"value": ""
|
||||
}, {
|
||||
"id": "f1930f8a-984a-4076-a925-20937bb2f8d3",
|
||||
"comment": "",
|
||||
"command": "type",
|
||||
"target": "id=id_uid_field",
|
||||
"targets": [
|
||||
["id=id_uid_field", "id"],
|
||||
["name=uid_field", "name"],
|
||||
["css=#id_uid_field", "css:finder"],
|
||||
["xpath=//input[@id='id_uid_field']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div/input", "xpath:idRelative"],
|
||||
["xpath=//div/input", "xpath:position"]
|
||||
],
|
||||
"value": "admin@example.tld"
|
||||
}, {
|
||||
"id": "0b568ee3-1bed-4821-a3bc-f6b960dbed9d",
|
||||
"comment": "",
|
||||
"command": "sendKeys",
|
||||
"target": "id=id_uid_field",
|
||||
"targets": [
|
||||
["id=id_uid_field", "id"],
|
||||
["name=uid_field", "name"],
|
||||
["css=#id_uid_field", "css:finder"],
|
||||
["xpath=//input[@id='id_uid_field']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div/input", "xpath:idRelative"],
|
||||
["xpath=//div/input", "xpath:position"]
|
||||
],
|
||||
"value": "${KEY_ENTER}"
|
||||
}, {
|
||||
"id": "6d98e479-2825-484d-996a-ccf350d2761f",
|
||||
"comment": "",
|
||||
"command": "type",
|
||||
"target": "id=id_password",
|
||||
"targets": [
|
||||
["id=id_password", "id"],
|
||||
["name=password", "name"],
|
||||
["css=#id_password", "css:finder"],
|
||||
["xpath=//input[@id='id_password']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div[2]/input", "xpath:idRelative"],
|
||||
["xpath=//div[2]/input", "xpath:position"]
|
||||
],
|
||||
"value": "pbadmin"
|
||||
}, {
|
||||
"id": "6f7abec6-ff44-4eb5-ae23-520c1c29a706",
|
||||
"comment": "",
|
||||
"command": "sendKeys",
|
||||
"target": "id=id_password",
|
||||
"targets": [
|
||||
["id=id_password", "id"],
|
||||
["name=password", "name"],
|
||||
["css=#id_password", "css:finder"],
|
||||
["xpath=//input[@id='id_password']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div[2]/input", "xpath:idRelative"],
|
||||
["xpath=//div[2]/input", "xpath:position"]
|
||||
],
|
||||
"value": "${KEY_ENTER}"
|
||||
}, {
|
||||
"id": "04c5876f-1405-4077-a98b-e911f09113d7",
|
||||
"comment": "",
|
||||
"command": "assertText",
|
||||
"target": "xpath=//a[contains(@href, '/-/user/')]",
|
||||
"targets": [
|
||||
["linkText=pbadmin", "linkText"],
|
||||
["css=.pf-c-page__header-tools-group:nth-child(2) > .pf-c-button", "css:finder"],
|
||||
["xpath=//a[contains(text(),'pbadmin')]", "xpath:link"],
|
||||
["xpath=//div[@id='page-default-nav-example']/header/div[3]/div[2]/a", "xpath:idRelative"],
|
||||
["xpath=//a[contains(@href, '/-/user/')]", "xpath:href"],
|
||||
["xpath=//div[2]/a", "xpath:position"],
|
||||
["xpath=//a[contains(.,'pbadmin')]", "xpath:innerText"]
|
||||
],
|
||||
"value": "pbadmin"
|
||||
}]
|
||||
}, {
|
||||
"id": "61948b3c-3012-4f97-aa52-bc8f34fec333",
|
||||
"name": "passbook enroll simple",
|
||||
"commands": [{
|
||||
"id": "0f4884b3-4891-41bc-956d-1fa433e892e9",
|
||||
"comment": "",
|
||||
"command": "open",
|
||||
"target": "/flows/default-authentication-flow/?next=%2F",
|
||||
"targets": [],
|
||||
"value": ""
|
||||
}, {
|
||||
"id": "84d3861f-a60c-4650-8689-535f82b39577",
|
||||
"comment": "",
|
||||
"command": "click",
|
||||
"target": "linkText=Sign up.",
|
||||
"targets": [
|
||||
["linkText=Sign up.", "linkText"],
|
||||
["css=.pf-c-login__main-footer-band-item > a", "css:finder"],
|
||||
["xpath=//a[contains(text(),'Sign up.')]", "xpath:link"],
|
||||
["xpath=//main[@id='flow-body']/footer/div/p/a", "xpath:idRelative"],
|
||||
["xpath=//a[contains(@href, '/flows/default-enrollment-flow/')]", "xpath:href"],
|
||||
["xpath=//a", "xpath:position"],
|
||||
["xpath=//a[contains(.,'Sign up.')]", "xpath:innerText"]
|
||||
],
|
||||
"value": ""
|
||||
}, {
|
||||
"id": "a32435ca-d84a-41e7-a915-fcbbc5f88341",
|
||||
"comment": "",
|
||||
"command": "type",
|
||||
"target": "id=id_username",
|
||||
"targets": [
|
||||
["id=id_username", "id"],
|
||||
["name=username", "name"],
|
||||
["css=#id_username", "css:finder"],
|
||||
["xpath=//input[@id='id_username']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div/input", "xpath:idRelative"],
|
||||
["xpath=//div/input", "xpath:position"]
|
||||
],
|
||||
"value": "foo"
|
||||
}, {
|
||||
"id": "3b5dcf53-8297-46c5-88b7-11c2eb25f34f",
|
||||
"comment": "",
|
||||
"command": "type",
|
||||
"target": "id=id_password",
|
||||
"targets": [
|
||||
["id=id_password", "id"],
|
||||
["name=password", "name"],
|
||||
["css=#id_password", "css:finder"],
|
||||
["xpath=//input[@id='id_password']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div[2]/input", "xpath:idRelative"],
|
||||
["xpath=//div[2]/input", "xpath:position"]
|
||||
],
|
||||
"value": "pbadmin"
|
||||
}, {
|
||||
"id": "e948d61c-dae6-4994-b56f-ff130892b342",
|
||||
"comment": "",
|
||||
"command": "type",
|
||||
"target": "id=id_password_repeat",
|
||||
"targets": [
|
||||
["id=id_password_repeat", "id"],
|
||||
["name=password_repeat", "name"],
|
||||
["css=#id_password_repeat", "css:finder"],
|
||||
["xpath=//input[@id='id_password_repeat']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div[3]/input", "xpath:idRelative"],
|
||||
["xpath=//div[3]/input", "xpath:position"]
|
||||
],
|
||||
"value": "pbadmin"
|
||||
}, {
|
||||
"id": "e7527bfc-ec74-4d96-86f0-5a3a55a59025",
|
||||
"comment": "",
|
||||
"command": "click",
|
||||
"target": "css=.pf-c-button",
|
||||
"targets": [
|
||||
["css=.pf-c-button", "css:finder"],
|
||||
["xpath=//button[@type='submit']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div[4]/button", "xpath:idRelative"],
|
||||
["xpath=//button", "xpath:position"],
|
||||
["xpath=//button[contains(.,'Continue')]", "xpath:innerText"]
|
||||
],
|
||||
"value": ""
|
||||
}, {
|
||||
"id": "434b842c-a659-4ff5-aca8-06a6a3489597",
|
||||
"comment": "",
|
||||
"command": "type",
|
||||
"target": "id=id_name",
|
||||
"targets": [
|
||||
["id=id_name", "id"],
|
||||
["name=name", "name"],
|
||||
["css=#id_name", "css:finder"],
|
||||
["xpath=//input[@id='id_name']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div/input", "xpath:idRelative"],
|
||||
["xpath=//div/input", "xpath:position"]
|
||||
],
|
||||
"value": "some name"
|
||||
}, {
|
||||
"id": "cbc43a1b-2cfe-46e2-85bc-476fb32c6cb1",
|
||||
"comment": "",
|
||||
"command": "type",
|
||||
"target": "id=id_email",
|
||||
"targets": [
|
||||
["id=id_email", "id"],
|
||||
["name=email", "name"],
|
||||
["css=#id_email", "css:finder"],
|
||||
["xpath=//input[@id='id_email']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div[2]/input", "xpath:idRelative"],
|
||||
["xpath=//div[2]/input", "xpath:position"]
|
||||
],
|
||||
"value": "foo@bar.baz"
|
||||
}, {
|
||||
"id": "e74389a0-228b-4312-9677-e9add6358de3",
|
||||
"comment": "",
|
||||
"command": "click",
|
||||
"target": "css=.pf-c-button",
|
||||
"targets": [
|
||||
["css=.pf-c-button", "css:finder"],
|
||||
["xpath=//button[@type='submit']", "xpath:attributes"],
|
||||
["xpath=//main[@id='flow-body']/div/form/div[3]/button", "xpath:idRelative"],
|
||||
["xpath=//button", "xpath:position"],
|
||||
["xpath=//button[contains(.,'Continue')]", "xpath:innerText"]
|
||||
],
|
||||
"value": ""
|
||||
}, {
|
||||
"id": "3e22f9c2-5ebd-49c2-81b1-340fa0435bbc",
|
||||
"comment": "",
|
||||
"command": "click",
|
||||
"target": "linkText=foo",
|
||||
"targets": [
|
||||
["linkText=foo", "linkText"],
|
||||
["css=.pf-c-page__header-tools-group:nth-child(2) > .pf-c-button", "css:finder"],
|
||||
["xpath=//a[contains(text(),'foo')]", "xpath:link"],
|
||||
["xpath=//div[@id='page-default-nav-example']/header/div[3]/div[2]/a", "xpath:idRelative"],
|
||||
["xpath=//a[contains(@href, '/-/user/')]", "xpath:href"],
|
||||
["xpath=//div[2]/a", "xpath:position"],
|
||||
["xpath=//a[contains(.,'foo')]", "xpath:innerText"]
|
||||
],
|
||||
"value": ""
|
||||
}, {
|
||||
"id": "60124cfd-f11c-4d7f-8b01-bef54c8cbd73",
|
||||
"comment": "",
|
||||
"command": "assertText",
|
||||
"target": "xpath=//a[contains(@href, '/-/user/')]",
|
||||
"targets": [
|
||||
["linkText=foo", "linkText"],
|
||||
["css=.pf-c-page__header-tools-group:nth-child(2) > .pf-c-button", "css:finder"],
|
||||
["xpath=//a[contains(text(),'foo')]", "xpath:link"],
|
||||
["xpath=//div[@id='page-default-nav-example']/header/div[3]/div[2]/a", "xpath:idRelative"],
|
||||
["xpath=//a[contains(@href, '/-/user/')]", "xpath:href"],
|
||||
["xpath=//div[2]/a", "xpath:position"],
|
||||
["xpath=//a[contains(.,'foo')]", "xpath:innerText"]
|
||||
],
|
||||
"value": "foo"
|
||||
}, {
|
||||
"id": "429ee61b-9991-4919-8131-55f8e1bd9a0d",
|
||||
"comment": "",
|
||||
"command": "assertValue",
|
||||
"target": "id=id_username",
|
||||
"targets": [],
|
||||
"value": "foo"
|
||||
}, {
|
||||
"id": "f6c50760-52ed-4c1d-b232-30f8afe144eb",
|
||||
"comment": "",
|
||||
"command": "assertText",
|
||||
"target": "id=id_name",
|
||||
"targets": [
|
||||
["id=id_name", "id"],
|
||||
["name=name", "name"],
|
||||
["css=#id_name", "css:finder"],
|
||||
["xpath=//input[@id='id_name']", "xpath:attributes"],
|
||||
["xpath=//main[@id='main-content']/section/div/div/div/div[2]/form/div[2]/div/input", "xpath:idRelative"],
|
||||
["xpath=//div[2]/div/input", "xpath:position"]
|
||||
],
|
||||
"value": "some name"
|
||||
}, {
|
||||
"id": "b26905b5-89b5-4b41-abf5-a9f848f08622",
|
||||
"comment": "",
|
||||
"command": "assertText",
|
||||
"target": "id=id_email",
|
||||
"targets": [
|
||||
["id=id_email", "id"],
|
||||
["name=email", "name"],
|
||||
["css=#id_email", "css:finder"],
|
||||
["xpath=//input[@id='id_email']", "xpath:attributes"],
|
||||
["xpath=//main[@id='main-content']/section/div/div/div/div[2]/form/div[3]/div/input", "xpath:idRelative"],
|
||||
["xpath=//div[3]/div/input", "xpath:position"]
|
||||
],
|
||||
"value": "foo@bar.baz"
|
||||
}]
|
||||
}],
|
||||
"suites": [{
|
||||
"id": "495657fb-3f5e-4431-877c-4d0b248c0841",
|
||||
"name": "Default Suite",
|
||||
"persistSession": false,
|
||||
"parallel": false,
|
||||
"timeout": 300,
|
||||
"tests": ["94b39863-74ec-4b7d-98c5-2b380b6d2c55"]
|
||||
}],
|
||||
"urls": ["http://localhost:8000/"],
|
||||
"plugins": []
|
||||
}
|
|
@ -4,14 +4,14 @@ from selenium import webdriver
|
|||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||
|
||||
from e2e.utils import apply_default_data
|
||||
from passbook.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||
from passbook.policies.expression.models import ExpressionPolicy
|
||||
from passbook.policies.models import PolicyBinding
|
||||
from passbook.stages.identification.models import IdentificationStage
|
||||
from passbook.stages.prompt.models import FieldTypes, Prompt, PromptStage
|
||||
from passbook.stages.user_login.models import UserLoginStage
|
||||
from passbook.stages.user_write.models import UserWriteStage
|
||||
from passbook.stages.identification.models import IdentificationStage
|
||||
from e2e.utils import apply_default_data
|
||||
|
||||
|
||||
class TestEnroll2Step(StaticLiveServerTestCase):
|
||||
|
|
|
@ -4,6 +4,7 @@ from selenium import webdriver
|
|||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
|
||||
from e2e.utils import apply_default_data
|
||||
|
||||
|
||||
|
@ -24,9 +25,7 @@ class TestLogin(StaticLiveServerTestCase):
|
|||
|
||||
def test_login(self):
|
||||
"""test default login flow"""
|
||||
self.driver.get(
|
||||
f"{self.live_server_url}/flows/default-authentication-flow/"
|
||||
)
|
||||
self.driver.get(f"{self.live_server_url}/flows/default-authentication-flow/")
|
||||
self.driver.find_element(By.ID, "id_uid_field").click()
|
||||
self.driver.find_element(By.ID, "id_uid_field").send_keys("pbadmin")
|
||||
self.driver.find_element(By.ID, "id_uid_field").send_keys(Keys.ENTER)
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
"""test OpenID Provider flow"""
|
||||
from time import sleep
|
||||
|
||||
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||
from oauth2_provider.generators import generate_client_id, generate_client_secret
|
||||
from oidc_provider.models import Client, ResponseType
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
|
||||
from docker import DockerClient, from_env
|
||||
from docker.models.containers import Container
|
||||
from docker.types import Healthcheck
|
||||
from e2e.utils import apply_default_data, ensure_rsa_key
|
||||
from passbook.core.models import Application
|
||||
from passbook.flows.models import Flow
|
||||
from passbook.providers.oidc.models import OpenIDProvider
|
||||
|
||||
|
||||
class TestProviderOIDC(StaticLiveServerTestCase):
|
||||
"""test OpenID Provider flow"""
|
||||
|
||||
def setUp(self):
|
||||
self.driver = webdriver.Remote(
|
||||
command_executor="http://localhost:4444/wd/hub",
|
||||
desired_capabilities=DesiredCapabilities.CHROME,
|
||||
)
|
||||
self.driver.implicitly_wait(30)
|
||||
apply_default_data()
|
||||
self.client_id = generate_client_id()
|
||||
self.client_secret = generate_client_secret()
|
||||
self.container = self.setup_client()
|
||||
|
||||
def setup_client(self) -> Container:
|
||||
"""Setup client grafana container which we test OIDC against"""
|
||||
client: DockerClient = from_env()
|
||||
container = client.containers.run(
|
||||
image="grafana/grafana:latest",
|
||||
detach=True,
|
||||
name="passbook-e2e-grafana-client",
|
||||
network_mode="host",
|
||||
auto_remove=True,
|
||||
healthcheck=Healthcheck(
|
||||
test=["CMD", "wget", "--spider", "http://localhost:3000"],
|
||||
interval=5 * 100 * 1000000,
|
||||
start_period=1 * 100 * 1000000,
|
||||
),
|
||||
environment={
|
||||
"GF_AUTH_GENERIC_OAUTH_ENABLED": "true",
|
||||
"GF_AUTH_GENERIC_OAUTH_CLIENT_ID": self.client_id,
|
||||
"GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET": self.client_secret,
|
||||
"GF_AUTH_GENERIC_OAUTH_SCOPES": "openid email profile",
|
||||
"GF_AUTH_GENERIC_OAUTH_AUTH_URL": (
|
||||
f"{self.live_server_url}/application/oidc/authorize"
|
||||
),
|
||||
"GF_AUTH_GENERIC_OAUTH_TOKEN_URL": (
|
||||
f"{self.live_server_url}/application/oidc/token"
|
||||
),
|
||||
"GF_AUTH_GENERIC_OAUTH_API_URL": (
|
||||
f"{self.live_server_url}/application/oidc/userinfo"
|
||||
),
|
||||
"GF_LOG_LEVEL": "debug",
|
||||
},
|
||||
)
|
||||
while True:
|
||||
container.reload()
|
||||
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
|
||||
if status == "healthy":
|
||||
return container
|
||||
sleep(1)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
self.driver.quit()
|
||||
self.container.kill()
|
||||
|
||||
def test_redirect_uri_error(self):
|
||||
"""test OpenID Provider flow (invalid redirect URI, check error message)"""
|
||||
# Bootstrap all needed objects
|
||||
authorization_flow = Flow.objects.get(slug="default-provider-authorization")
|
||||
client = Client.objects.create(
|
||||
name="grafana",
|
||||
client_type="confidential",
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
_redirect_uris="http://localhost:3000/",
|
||||
_scope="openid userinfo",
|
||||
)
|
||||
# At least one of these objects must exist
|
||||
ensure_rsa_key()
|
||||
# This response_code object might exist or not, depending on the order the tests are run
|
||||
rp_type, _ = ResponseType.objects.get_or_create(value="code")
|
||||
client.response_types.set([rp_type])
|
||||
client.save()
|
||||
provider = OpenIDProvider.objects.create(
|
||||
oidc_client=client, authorization_flow=authorization_flow,
|
||||
)
|
||||
Application.objects.create(
|
||||
name="Grafana", slug="grafana", provider=provider,
|
||||
)
|
||||
|
||||
self.driver.get(f"http://localhost:3000")
|
||||
self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click()
|
||||
self.driver.find_element(By.ID, "id_uid_field").click()
|
||||
self.driver.find_element(By.ID, "id_uid_field").send_keys("pbadmin")
|
||||
self.driver.find_element(By.ID, "id_uid_field").send_keys(Keys.ENTER)
|
||||
self.driver.find_element(By.ID, "id_password").send_keys("pbadmin")
|
||||
self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER)
|
||||
sleep(2)
|
||||
self.assertEqual(
|
||||
self.driver.find_element(By.CLASS_NAME, "pf-c-title").text,
|
||||
"Redirect URI Error",
|
||||
)
|
||||
|
||||
def test_authorization_no_consent(self):
|
||||
"""test OpenID Provider flow (default authorization flow without consent)"""
|
||||
# Bootstrap all needed objects
|
||||
authorization_flow = Flow.objects.get(slug="default-provider-authorization")
|
||||
client = Client.objects.create(
|
||||
name="grafana",
|
||||
client_type="confidential",
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
_redirect_uris="http://localhost:3000/login/generic_oauth",
|
||||
_scope="openid profile email",
|
||||
reuse_consent=False,
|
||||
require_consent=False,
|
||||
)
|
||||
# At least one of these objects must exist
|
||||
ensure_rsa_key()
|
||||
# This response_code object might exist or not, depending on the order the tests are run
|
||||
rp_type, _ = ResponseType.objects.get_or_create(value="code")
|
||||
client.response_types.set([rp_type])
|
||||
client.save()
|
||||
provider = OpenIDProvider.objects.create(
|
||||
oidc_client=client, authorization_flow=authorization_flow,
|
||||
)
|
||||
Application.objects.create(
|
||||
name="Grafana", slug="grafana", provider=provider,
|
||||
)
|
||||
|
||||
self.driver.get("http://localhost:3000")
|
||||
self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click()
|
||||
self.driver.find_element(By.ID, "id_uid_field").click()
|
||||
self.driver.find_element(By.ID, "id_uid_field").send_keys("pbadmin")
|
||||
self.driver.find_element(By.ID, "id_uid_field").send_keys(Keys.ENTER)
|
||||
self.driver.find_element(By.ID, "id_password").send_keys("pbadmin")
|
||||
self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER)
|
||||
self.driver.find_element(By.XPATH, "//a[contains(@href, '/profile')]").click()
|
||||
# sleep()
|
||||
self.assertEqual(
|
||||
self.driver.find_element(By.CLASS_NAME, "page-header__title").text,
|
||||
"passbook Default Admin",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.driver.find_element(
|
||||
By.XPATH,
|
||||
"/html/body/grafana-app/div/div/div/react-profile-wrapper/form[1]/div[1]/div/input",
|
||||
).get_attribute("value"),
|
||||
"passbook Default Admin",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.driver.find_element(
|
||||
By.XPATH,
|
||||
"/html/body/grafana-app/div/div/div/react-profile-wrapper/form[1]/div[2]/div/input",
|
||||
).get_attribute("value"),
|
||||
"root@localhost",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.driver.find_element(
|
||||
By.XPATH,
|
||||
"/html/body/grafana-app/div/div/div/react-profile-wrapper/form[1]/div[3]/div/input",
|
||||
).get_attribute("value"),
|
||||
"root@localhost",
|
||||
)
|
16
e2e/utils.py
16
e2e/utils.py
|
@ -1,8 +1,10 @@
|
|||
"""passbook e2e testing utilities"""
|
||||
|
||||
from glob import glob
|
||||
from importlib.util import module_from_spec, spec_from_file_location
|
||||
from inspect import getmembers, isfunction
|
||||
from importlib.util import spec_from_file_location, module_from_spec
|
||||
|
||||
from Cryptodome.PublicKey import RSA
|
||||
from django.apps import apps
|
||||
from django.db import connection, transaction
|
||||
from django.db.utils import IntegrityError
|
||||
|
@ -15,7 +17,7 @@ def apply_default_data():
|
|||
migration_files = glob("**/migrations/*.py", recursive=True)
|
||||
matches = []
|
||||
for migration in migration_files:
|
||||
with open(migration, 'r+') as migration_file:
|
||||
with open(migration, "r+") as migration_file:
|
||||
# Check if they have a `RunPython`
|
||||
if "RunPython" in migration_file.read():
|
||||
matches.append(migration)
|
||||
|
@ -34,3 +36,13 @@ def apply_default_data():
|
|||
func(apps, schema_editor)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
|
||||
def ensure_rsa_key():
|
||||
"""Ensure that at least one RSAKey Object exists, create one if none exist"""
|
||||
from oidc_provider.models import RSAKey
|
||||
|
||||
if not RSAKey.objects.exists():
|
||||
key = RSA.generate(2048)
|
||||
rsakey = RSAKey(key=key.exportKey("PEM").decode("utf8"))
|
||||
rsakey.save()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
"""Django manage.py"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
from defusedxml import defuse_stdlib
|
||||
|
||||
defuse_stdlib()
|
||||
|
|
|
@ -39,6 +39,11 @@ class FlowPlan:
|
|||
context: Dict[str, Any] = field(default_factory=dict)
|
||||
markers: List[StageMarker] = field(default_factory=list)
|
||||
|
||||
def append(self, stage: Stage, marker: Optional[StageMarker] = None):
|
||||
"""Append `stage` to all stages, optionall with stage marker"""
|
||||
self.stages.append(stage)
|
||||
self.markers.append(marker or StageMarker())
|
||||
|
||||
def next(self) -> Optional[Stage]:
|
||||
"""Return next pending stage from the bottom of the list"""
|
||||
if not self.has_stages:
|
||||
|
@ -54,7 +59,6 @@ class FlowPlan:
|
|||
self.markers.remove(marker)
|
||||
if not self.has_stages:
|
||||
return None
|
||||
# pylint: disable=not-callable
|
||||
return self.next()
|
||||
return marked_stage
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ LOGGER = get_logger()
|
|||
# Argument used to redirect user after login
|
||||
NEXT_ARG_NAME = "next"
|
||||
SESSION_KEY_PLAN = "passbook_flows_plan"
|
||||
SESSION_KEY_NEXT = "passbook_flows_shell_next"
|
||||
|
||||
|
||||
@method_decorator(xframe_options_sameorigin, name="dispatch")
|
||||
|
@ -127,7 +128,10 @@ class FlowExecutorView(View):
|
|||
def _flow_done(self) -> HttpResponse:
|
||||
"""User Successfully passed all stages"""
|
||||
self.cancel()
|
||||
next_param = self.request.GET.get(NEXT_ARG_NAME, "passbook_core:overview")
|
||||
# Since this is wrapped by the ExecutorShell, the next argument is saved in the session
|
||||
next_param = self.request.session.get(
|
||||
SESSION_KEY_NEXT, "passbook_core:overview"
|
||||
)
|
||||
return redirect_with_qs(next_param)
|
||||
|
||||
def stage_ok(self) -> HttpResponse:
|
||||
|
@ -210,6 +214,8 @@ class FlowExecutorShellView(TemplateView):
|
|||
def get_context_data(self, **kwargs) -> Dict[str, Any]:
|
||||
kwargs["exec_url"] = reverse("passbook_flows:flow-executor", kwargs=self.kwargs)
|
||||
kwargs["msg_url"] = reverse("passbook_api:messages-list")
|
||||
if NEXT_ARG_NAME in self.request.GET:
|
||||
self.request.session[SESSION_KEY_NEXT] = self.request.GET[NEXT_ARG_NAME]
|
||||
return kwargs
|
||||
|
||||
|
||||
|
|
|
@ -10,5 +10,5 @@ def userinfo(claims: Dict[str, Any], user: User) -> Dict[str, Any]:
|
|||
claims["given_name"] = user.name
|
||||
claims["family_name"] = user.name
|
||||
claims["email"] = user.email
|
||||
|
||||
claims["preferred_username"] = user.username
|
||||
return claims
|
||||
|
|
|
@ -61,7 +61,7 @@ class AuthorizationFlowInitView(AccessMixin, LoginRequiredMixin, View):
|
|||
PLAN_CONTEXT_PARAMS: endpoint.params,
|
||||
},
|
||||
)
|
||||
plan.stages.append(in_memory_stage(OIDCStage))
|
||||
plan.append(in_memory_stage(OIDCStage))
|
||||
self.request.session[SESSION_KEY_PLAN] = plan
|
||||
return redirect_with_qs(
|
||||
"passbook_flows:flow-executor-shell",
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#!/bin/bash -xe
|
||||
isort -rc passbook
|
||||
isort -rc .
|
||||
pyright
|
||||
black passbook
|
||||
black .
|
||||
./manage.py generate_swagger -o swagger.yaml -f yaml
|
||||
scripts/coverage.sh
|
||||
bandit -r passbook
|
||||
bandit -r .
|
||||
pylint passbook
|
||||
prospector
|
||||
|
|
Reference in New Issue