*: apply new black styling
This commit is contained in:
		| @ -104,7 +104,8 @@ class TestFlowsEnroll(SeleniumTestCase): | |||||||
|  |  | ||||||
|         self.wait_for_url(self.url("passbook_core:user-settings")) |         self.wait_for_url(self.url("passbook_core:user-settings")) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, "foo", |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             "foo", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" |             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" | ||||||
| @ -208,7 +209,8 @@ class TestFlowsEnroll(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "user-settings").click() |         self.driver.find_element(By.ID, "user-settings").click() | ||||||
|  |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, "foo", |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             "foo", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" |             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" | ||||||
|  | |||||||
| @ -21,5 +21,6 @@ class TestFlowsLogin(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) |         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) | ||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) |         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, USER().username, |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             USER().username, | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -48,7 +48,8 @@ class TestFlowsOTP(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "id_code").send_keys(Keys.ENTER) |         self.driver.find_element(By.ID, "id_code").send_keys(Keys.ENTER) | ||||||
|         self.wait_for_url(self.url("passbook_core:overview")) |         self.wait_for_url(self.url("passbook_core:overview")) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, USER().username, |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             USER().username, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_otp_totp_setup(self): |     def test_otp_totp_setup(self): | ||||||
| @ -62,7 +63,8 @@ class TestFlowsOTP(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) |         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) | ||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) |         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, USER().username, |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             USER().username, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.find_element(By.CSS_SELECTOR, ".pf-c-page__header").click() |         self.driver.find_element(By.CSS_SELECTOR, ".pf-c-page__header").click() | ||||||
| @ -107,7 +109,8 @@ class TestFlowsOTP(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) |         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) | ||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) |         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, USER().username, |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             USER().username, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.find_element(By.CSS_SELECTOR, ".pf-c-page__header").click() |         self.driver.find_element(By.CSS_SELECTOR, ".pf-c-page__header").click() | ||||||
|  | |||||||
| @ -77,7 +77,9 @@ class TestProviderOAuth2Github(SeleniumTestCase): | |||||||
|             authorization_flow=authorization_flow, |             authorization_flow=authorization_flow, | ||||||
|         ) |         ) | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name="Grafana", slug="grafana", provider=provider, |             name="Grafana", | ||||||
|  |             slug="grafana", | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:3000") |         self.driver.get("http://localhost:3000") | ||||||
| @ -129,7 +131,9 @@ class TestProviderOAuth2Github(SeleniumTestCase): | |||||||
|             authorization_flow=authorization_flow, |             authorization_flow=authorization_flow, | ||||||
|         ) |         ) | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name="Grafana", slug="grafana", provider=provider, |             name="Grafana", | ||||||
|  |             slug="grafana", | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:3000") |         self.driver.get("http://localhost:3000") | ||||||
| @ -143,13 +147,17 @@ class TestProviderOAuth2Github(SeleniumTestCase): | |||||||
|         sleep(1) |         sleep(1) | ||||||
|  |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             app.name, self.driver.find_element(By.ID, "application-name").text, |             app.name, | ||||||
|  |             self.driver.find_element(By.ID, "application-name").text, | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             "GitHub Compatibility: Access you Email addresses", |             "GitHub Compatibility: Access you Email addresses", | ||||||
|             self.driver.find_element(By.ID, "scope-user:email").text, |             self.driver.find_element(By.ID, "scope-user:email").text, | ||||||
|         ) |         ) | ||||||
|         self.driver.find_element(By.CSS_SELECTOR, ("[type=submit]"),).click() |         self.driver.find_element( | ||||||
|  |             By.CSS_SELECTOR, | ||||||
|  |             ("[type=submit]"), | ||||||
|  |         ).click() | ||||||
|  |  | ||||||
|         self.wait_for_url("http://localhost:3000/?orgId=1") |         self.wait_for_url("http://localhost:3000/?orgId=1") | ||||||
|         self.driver.get("http://localhost:3000/profile") |         self.driver.get("http://localhost:3000/profile") | ||||||
| @ -192,7 +200,9 @@ class TestProviderOAuth2Github(SeleniumTestCase): | |||||||
|             authorization_flow=authorization_flow, |             authorization_flow=authorization_flow, | ||||||
|         ) |         ) | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name="Grafana", slug="grafana", provider=provider, |             name="Grafana", | ||||||
|  |             slug="grafana", | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         negative_policy = ExpressionPolicy.objects.create( |         negative_policy = ExpressionPolicy.objects.create( | ||||||
|  | |||||||
| @ -104,7 +104,9 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name="Grafana", slug=APPLICATION_SLUG, provider=provider, |             name="Grafana", | ||||||
|  |             slug=APPLICATION_SLUG, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:3000") |         self.driver.get("http://localhost:3000") | ||||||
| @ -144,7 +146,9 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name="Grafana", slug=APPLICATION_SLUG, provider=provider, |             name="Grafana", | ||||||
|  |             slug=APPLICATION_SLUG, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:3000") |         self.driver.get("http://localhost:3000") | ||||||
| @ -203,7 +207,9 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name="Grafana", slug=APPLICATION_SLUG, provider=provider, |             name="Grafana", | ||||||
|  |             slug=APPLICATION_SLUG, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:3000") |         self.driver.get("http://localhost:3000") | ||||||
| @ -270,7 +276,9 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name="Grafana", slug=APPLICATION_SLUG, provider=provider, |             name="Grafana", | ||||||
|  |             slug=APPLICATION_SLUG, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:3000") |         self.driver.get("http://localhost:3000") | ||||||
| @ -282,7 +290,8 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) |         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) | ||||||
|  |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             app.name, self.driver.find_element(By.ID, "application-name").text, |             app.name, | ||||||
|  |             self.driver.find_element(By.ID, "application-name").text, | ||||||
|         ) |         ) | ||||||
|         self.wait.until( |         self.wait.until( | ||||||
|             ec.presence_of_element_located((By.CSS_SELECTOR, "[type=submit]")) |             ec.presence_of_element_located((By.CSS_SELECTOR, "[type=submit]")) | ||||||
| @ -340,7 +349,9 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name="Grafana", slug=APPLICATION_SLUG, provider=provider, |             name="Grafana", | ||||||
|  |             slug=APPLICATION_SLUG, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         negative_policy = ExpressionPolicy.objects.create( |         negative_policy = ExpressionPolicy.objects.create( | ||||||
|  | |||||||
| @ -100,7 +100,9 @@ class TestProviderOAuth2OIDC(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name=self.application_slug, slug=self.application_slug, provider=provider, |             name=self.application_slug, | ||||||
|  |             slug=self.application_slug, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|         self.container = self.setup_client() |         self.container = self.setup_client() | ||||||
|  |  | ||||||
| @ -141,7 +143,9 @@ class TestProviderOAuth2OIDC(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name=self.application_slug, slug=self.application_slug, provider=provider, |             name=self.application_slug, | ||||||
|  |             slug=self.application_slug, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|         self.container = self.setup_client() |         self.container = self.setup_client() | ||||||
|  |  | ||||||
| @ -189,7 +193,9 @@ class TestProviderOAuth2OIDC(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name=self.application_slug, slug=self.application_slug, provider=provider, |             name=self.application_slug, | ||||||
|  |             slug=self.application_slug, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|         self.container = self.setup_client() |         self.container = self.setup_client() | ||||||
|  |  | ||||||
| @ -202,7 +208,8 @@ class TestProviderOAuth2OIDC(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) |         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) | ||||||
|  |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             app.name, self.driver.find_element(By.ID, "application-name").text, |             app.name, | ||||||
|  |             self.driver.find_element(By.ID, "application-name").text, | ||||||
|         ) |         ) | ||||||
|         self.wait.until( |         self.wait.until( | ||||||
|             ec.presence_of_element_located((By.CSS_SELECTOR, "[type=submit]")) |             ec.presence_of_element_located((By.CSS_SELECTOR, "[type=submit]")) | ||||||
| @ -246,7 +253,9 @@ class TestProviderOAuth2OIDC(SeleniumTestCase): | |||||||
|         ) |         ) | ||||||
|         provider.save() |         provider.save() | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name=self.application_slug, slug=self.application_slug, provider=provider, |             name=self.application_slug, | ||||||
|  |             slug=self.application_slug, | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         negative_policy = ExpressionPolicy.objects.create( |         negative_policy = ExpressionPolicy.objects.create( | ||||||
|  | |||||||
| @ -84,7 +84,9 @@ class TestProviderSAML(SeleniumTestCase): | |||||||
|         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) |         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) | ||||||
|         provider.save() |         provider.save() | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name="SAML", slug="passbook-saml", provider=provider, |             name="SAML", | ||||||
|  |             slug="passbook-saml", | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|         self.container = self.setup_client(provider) |         self.container = self.setup_client(provider) | ||||||
|         self.driver.get("http://localhost:9009") |         self.driver.get("http://localhost:9009") | ||||||
| @ -121,7 +123,9 @@ class TestProviderSAML(SeleniumTestCase): | |||||||
|         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) |         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) | ||||||
|         provider.save() |         provider.save() | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name="SAML", slug="passbook-saml", provider=provider, |             name="SAML", | ||||||
|  |             slug="passbook-saml", | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|         self.container = self.setup_client(provider) |         self.container = self.setup_client(provider) | ||||||
|         self.driver.get("http://localhost:9009") |         self.driver.get("http://localhost:9009") | ||||||
| @ -131,7 +135,8 @@ class TestProviderSAML(SeleniumTestCase): | |||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) |         self.driver.find_element(By.ID, "id_password").send_keys(USER().username) | ||||||
|         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) |         self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             app.name, self.driver.find_element(By.ID, "application-name").text, |             app.name, | ||||||
|  |             self.driver.find_element(By.ID, "application-name").text, | ||||||
|         ) |         ) | ||||||
|         sleep(1) |         sleep(1) | ||||||
|         self.driver.find_element(By.CSS_SELECTOR, "[type=submit]").click() |         self.driver.find_element(By.CSS_SELECTOR, "[type=submit]").click() | ||||||
| @ -163,7 +168,9 @@ class TestProviderSAML(SeleniumTestCase): | |||||||
|         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) |         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) | ||||||
|         provider.save() |         provider.save() | ||||||
|         Application.objects.create( |         Application.objects.create( | ||||||
|             name="SAML", slug="passbook-saml", provider=provider, |             name="SAML", | ||||||
|  |             slug="passbook-saml", | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|         self.container = self.setup_client(provider) |         self.container = self.setup_client(provider) | ||||||
|         self.driver.get( |         self.driver.get( | ||||||
| @ -209,7 +216,9 @@ class TestProviderSAML(SeleniumTestCase): | |||||||
|         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) |         provider.property_mappings.set(SAMLPropertyMapping.objects.all()) | ||||||
|         provider.save() |         provider.save() | ||||||
|         app = Application.objects.create( |         app = Application.objects.create( | ||||||
|             name="SAML", slug="passbook-saml", provider=provider, |             name="SAML", | ||||||
|  |             slug="passbook-saml", | ||||||
|  |             provider=provider, | ||||||
|         ) |         ) | ||||||
|         PolicyBinding.objects.create(target=app, policy=negative_policy, order=0) |         PolicyBinding.objects.create(target=app, policy=negative_policy, order=0) | ||||||
|         self.container = self.setup_client(provider) |         self.container = self.setup_client(provider) | ||||||
|  | |||||||
| @ -144,13 +144,15 @@ class TestSourceOAuth2(SeleniumTestCase): | |||||||
|         self.driver.get(self.url("passbook_core:user-settings")) |         self.driver.get(self.url("passbook_core:user-settings")) | ||||||
|  |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, "foo", |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             "foo", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" |             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_name").get_attribute("value"), "admin", |             self.driver.find_element(By.ID, "id_name").get_attribute("value"), | ||||||
|  |             "admin", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_email").get_attribute("value"), |             self.driver.find_element(By.ID, "id_email").get_attribute("value"), | ||||||
| @ -225,13 +227,15 @@ class TestSourceOAuth2(SeleniumTestCase): | |||||||
|         self.driver.get(self.url("passbook_core:user-settings")) |         self.driver.get(self.url("passbook_core:user-settings")) | ||||||
|  |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, "foo", |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             "foo", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" |             self.driver.find_element(By.ID, "id_username").get_attribute("value"), "foo" | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_name").get_attribute("value"), "admin", |             self.driver.find_element(By.ID, "id_name").get_attribute("value"), | ||||||
|  |             "admin", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_email").get_attribute("value"), |             self.driver.find_element(By.ID, "id_email").get_attribute("value"), | ||||||
| @ -317,7 +321,8 @@ class TestSourceOAuth1(SeleniumTestCase): | |||||||
|         self.driver.get(self.url("passbook_core:user-settings")) |         self.driver.get(self.url("passbook_core:user-settings")) | ||||||
|  |  | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "user-settings").text, "example-user", |             self.driver.find_element(By.ID, "user-settings").text, | ||||||
|  |             "example-user", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             self.driver.find_element(By.ID, "id_username").get_attribute("value"), |             self.driver.find_element(By.ID, "id_username").get_attribute("value"), | ||||||
|  | |||||||
| @ -98,7 +98,9 @@ class TestSourceSAML(SeleniumTestCase): | |||||||
|         authentication_flow = Flow.objects.get(slug="default-source-authentication") |         authentication_flow = Flow.objects.get(slug="default-source-authentication") | ||||||
|         enrollment_flow = Flow.objects.get(slug="default-source-enrollment") |         enrollment_flow = Flow.objects.get(slug="default-source-enrollment") | ||||||
|         keypair = CertificateKeyPair.objects.create( |         keypair = CertificateKeyPair.objects.create( | ||||||
|             name="test-idp-cert", certificate_data=IDP_CERT, key_data=IDP_KEY, |             name="test-idp-cert", | ||||||
|  |             certificate_data=IDP_CERT, | ||||||
|  |             key_data=IDP_KEY, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         SAMLSource.objects.create( |         SAMLSource.objects.create( | ||||||
| @ -145,7 +147,9 @@ class TestSourceSAML(SeleniumTestCase): | |||||||
|         authentication_flow = Flow.objects.get(slug="default-source-authentication") |         authentication_flow = Flow.objects.get(slug="default-source-authentication") | ||||||
|         enrollment_flow = Flow.objects.get(slug="default-source-enrollment") |         enrollment_flow = Flow.objects.get(slug="default-source-enrollment") | ||||||
|         keypair = CertificateKeyPair.objects.create( |         keypair = CertificateKeyPair.objects.create( | ||||||
|             name="test-idp-cert", certificate_data=IDP_CERT, key_data=IDP_KEY, |             name="test-idp-cert", | ||||||
|  |             certificate_data=IDP_CERT, | ||||||
|  |             key_data=IDP_KEY, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         SAMLSource.objects.create( |         SAMLSource.objects.create( | ||||||
| @ -194,7 +198,9 @@ class TestSourceSAML(SeleniumTestCase): | |||||||
|         authentication_flow = Flow.objects.get(slug="default-source-authentication") |         authentication_flow = Flow.objects.get(slug="default-source-authentication") | ||||||
|         enrollment_flow = Flow.objects.get(slug="default-source-enrollment") |         enrollment_flow = Flow.objects.get(slug="default-source-enrollment") | ||||||
|         keypair = CertificateKeyPair.objects.create( |         keypair = CertificateKeyPair.objects.create( | ||||||
|             name="test-idp-cert", certificate_data=IDP_CERT, key_data=IDP_KEY, |             name="test-idp-cert", | ||||||
|  |             certificate_data=IDP_CERT, | ||||||
|  |             key_data=IDP_KEY, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         SAMLSource.objects.create( |         SAMLSource.objects.create( | ||||||
|  | |||||||
| @ -49,7 +49,9 @@ class YAMLField(forms.JSONField): | |||||||
|             converted = yaml.safe_load(value) |             converted = yaml.safe_load(value) | ||||||
|         except yaml.YAMLError: |         except yaml.YAMLError: | ||||||
|             raise forms.ValidationError( |             raise forms.ValidationError( | ||||||
|                 self.error_messages["invalid"], code="invalid", params={"value": value}, |                 self.error_messages["invalid"], | ||||||
|  |                 code="invalid", | ||||||
|  |                 params={"value": value}, | ||||||
|             ) |             ) | ||||||
|         if isinstance(converted, str): |         if isinstance(converted, str): | ||||||
|             return YAMLString(converted) |             return YAMLString(converted) | ||||||
|  | |||||||
| @ -191,10 +191,20 @@ urlpatterns = [ | |||||||
|     ), |     ), | ||||||
|     # Flows |     # Flows | ||||||
|     path("flows/", flows.FlowListView.as_view(), name="flows"), |     path("flows/", flows.FlowListView.as_view(), name="flows"), | ||||||
|     path("flows/create/", flows.FlowCreateView.as_view(), name="flow-create",), |  | ||||||
|     path("flows/import/", flows.FlowImportView.as_view(), name="flow-import",), |  | ||||||
|     path( |     path( | ||||||
|         "flows/<uuid:pk>/update/", flows.FlowUpdateView.as_view(), name="flow-update", |         "flows/create/", | ||||||
|  |         flows.FlowCreateView.as_view(), | ||||||
|  |         name="flow-create", | ||||||
|  |     ), | ||||||
|  |     path( | ||||||
|  |         "flows/import/", | ||||||
|  |         flows.FlowImportView.as_view(), | ||||||
|  |         name="flow-import", | ||||||
|  |     ), | ||||||
|  |     path( | ||||||
|  |         "flows/<uuid:pk>/update/", | ||||||
|  |         flows.FlowUpdateView.as_view(), | ||||||
|  |         name="flow-update", | ||||||
|     ), |     ), | ||||||
|     path( |     path( | ||||||
|         "flows/<uuid:pk>/execute/", |         "flows/<uuid:pk>/execute/", | ||||||
| @ -202,10 +212,14 @@ urlpatterns = [ | |||||||
|         name="flow-execute", |         name="flow-execute", | ||||||
|     ), |     ), | ||||||
|     path( |     path( | ||||||
|         "flows/<uuid:pk>/export/", flows.FlowExportView.as_view(), name="flow-export", |         "flows/<uuid:pk>/export/", | ||||||
|  |         flows.FlowExportView.as_view(), | ||||||
|  |         name="flow-export", | ||||||
|     ), |     ), | ||||||
|     path( |     path( | ||||||
|         "flows/<uuid:pk>/delete/", flows.FlowDeleteView.as_view(), name="flow-delete", |         "flows/<uuid:pk>/delete/", | ||||||
|  |         flows.FlowDeleteView.as_view(), | ||||||
|  |         name="flow-delete", | ||||||
|     ), |     ), | ||||||
|     # Property Mappings |     # Property Mappings | ||||||
|     path( |     path( | ||||||
| @ -273,9 +287,15 @@ urlpatterns = [ | |||||||
|         name="certificatekeypair-delete", |         name="certificatekeypair-delete", | ||||||
|     ), |     ), | ||||||
|     # Outposts |     # Outposts | ||||||
|     path("outposts/", outposts.OutpostListView.as_view(), name="outposts",), |  | ||||||
|     path( |     path( | ||||||
|         "outposts/create/", outposts.OutpostCreateView.as_view(), name="outpost-create", |         "outposts/", | ||||||
|  |         outposts.OutpostListView.as_view(), | ||||||
|  |         name="outposts", | ||||||
|  |     ), | ||||||
|  |     path( | ||||||
|  |         "outposts/create/", | ||||||
|  |         outposts.OutpostCreateView.as_view(), | ||||||
|  |         name="outpost-create", | ||||||
|     ), |     ), | ||||||
|     path( |     path( | ||||||
|         "outposts/<uuid:pk>/update/", |         "outposts/<uuid:pk>/update/", | ||||||
|  | |||||||
| @ -100,7 +100,9 @@ class FlowDebugExecuteView(LoginRequiredMixin, PermissionRequiredMixin, DetailVi | |||||||
|         plan = planner.plan(self.request, {PLAN_CONTEXT_PENDING_USER: request.user}) |         plan = planner.plan(self.request, {PLAN_CONTEXT_PENDING_USER: request.user}) | ||||||
|         self.request.session[SESSION_KEY_PLAN] = plan |         self.request.session[SESSION_KEY_PLAN] = plan | ||||||
|         return redirect_with_qs( |         return redirect_with_qs( | ||||||
|             "passbook_flows:flow-executor-shell", self.request.GET, flow_slug=flow.slug, |             "passbook_flows:flow-executor-shell", | ||||||
|  |             self.request.GET, | ||||||
|  |             flow_slug=flow.slug, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -114,7 +114,9 @@ info = openapi.Info( | |||||||
|     license=openapi.License(name="MIT License"), |     license=openapi.License(name="MIT License"), | ||||||
| ) | ) | ||||||
| SchemaView = get_schema_view( | SchemaView = get_schema_view( | ||||||
|     info, public=True, permission_classes=(CustomObjectPermissions,), |     info, | ||||||
|  |     public=True, | ||||||
|  |     permission_classes=(CustomObjectPermissions,), | ||||||
| ) | ) | ||||||
|  |  | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|  | |||||||
| @ -47,7 +47,10 @@ class Migration(migrations.Migration): | |||||||
|                 ), |                 ), | ||||||
|                 ("date", models.DateTimeField(auto_now_add=True)), |                 ("date", models.DateTimeField(auto_now_add=True)), | ||||||
|                 ("app", models.TextField()), |                 ("app", models.TextField()), | ||||||
|                 ("context", models.JSONField(blank=True, default=dict),), |                 ( | ||||||
|  |                     "context", | ||||||
|  |                     models.JSONField(blank=True, default=dict), | ||||||
|  |                 ), | ||||||
|                 ("client_ip", models.GenericIPAddressField(null=True)), |                 ("client_ip", models.GenericIPAddressField(null=True)), | ||||||
|                 ("created", models.DateTimeField(auto_now_add=True)), |                 ("created", models.DateTimeField(auto_now_add=True)), | ||||||
|                 ( |                 ( | ||||||
|  | |||||||
| @ -49,10 +49,15 @@ class Migration(migrations.Migration): | |||||||
|             ), |             ), | ||||||
|         ), |         ), | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name="event", name="user_json", field=models.JSONField(default=dict), |             model_name="event", | ||||||
|  |             name="user_json", | ||||||
|  |             field=models.JSONField(default=dict), | ||||||
|         ), |         ), | ||||||
|         migrations.RunPython(convert_user_to_json), |         migrations.RunPython(convert_user_to_json), | ||||||
|         migrations.RemoveField(model_name="event", name="user",), |         migrations.RemoveField( | ||||||
|  |             model_name="event", | ||||||
|  |             name="user", | ||||||
|  |         ), | ||||||
|         migrations.RenameField( |         migrations.RenameField( | ||||||
|             model_name="event", old_name="user_json", new_name="user" |             model_name="event", old_name="user_json", new_name="user" | ||||||
|         ), |         ), | ||||||
|  | |||||||
| @ -108,11 +108,18 @@ class Migration(migrations.Migration): | |||||||
|                 ("uuid", models.UUIDField(default=uuid.uuid4, editable=False)), |                 ("uuid", models.UUIDField(default=uuid.uuid4, editable=False)), | ||||||
|                 ("name", models.TextField(help_text="User's display name.")), |                 ("name", models.TextField(help_text="User's display name.")), | ||||||
|                 ("password_change_date", models.DateTimeField(auto_now_add=True)), |                 ("password_change_date", models.DateTimeField(auto_now_add=True)), | ||||||
|                 ("attributes", models.JSONField(blank=True, default=dict),), |                 ( | ||||||
|  |                     "attributes", | ||||||
|  |                     models.JSONField(blank=True, default=dict), | ||||||
|  |                 ), | ||||||
|             ], |             ], | ||||||
|             options={"permissions": (("reset_user_password", "Reset Password"),),}, |             options={ | ||||||
|  |                 "permissions": (("reset_user_password", "Reset Password"),), | ||||||
|  |             }, | ||||||
|             bases=(guardian.mixins.GuardianUserMixin, models.Model), |             bases=(guardian.mixins.GuardianUserMixin, models.Model), | ||||||
|             managers=[("objects", django.contrib.auth.models.UserManager()),], |             managers=[ | ||||||
|  |                 ("objects", django.contrib.auth.models.UserManager()), | ||||||
|  |             ], | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|             name="PropertyMapping", |             name="PropertyMapping", | ||||||
| @ -192,7 +199,9 @@ class Migration(migrations.Migration): | |||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|             ], |             ], | ||||||
|             options={"unique_together": {("user", "source")},}, |             options={ | ||||||
|  |                 "unique_together": {("user", "source")}, | ||||||
|  |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|             name="Token", |             name="Token", | ||||||
| @ -223,7 +232,10 @@ class Migration(migrations.Migration): | |||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|             ], |             ], | ||||||
|             options={"verbose_name": "Token", "verbose_name_plural": "Tokens",}, |             options={ | ||||||
|  |                 "verbose_name": "Token", | ||||||
|  |                 "verbose_name_plural": "Tokens", | ||||||
|  |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|             name="Provider", |             name="Provider", | ||||||
| @ -258,7 +270,10 @@ class Migration(migrations.Migration): | |||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|                 ("name", models.CharField(max_length=80, verbose_name="name")), |                 ("name", models.CharField(max_length=80, verbose_name="name")), | ||||||
|                 ("attributes", models.JSONField(blank=True, default=dict),), |                 ( | ||||||
|  |                     "attributes", | ||||||
|  |                     models.JSONField(blank=True, default=dict), | ||||||
|  |                 ), | ||||||
|                 ( |                 ( | ||||||
|                     "parent", |                     "parent", | ||||||
|                     models.ForeignKey( |                     models.ForeignKey( | ||||||
| @ -270,7 +285,9 @@ class Migration(migrations.Migration): | |||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|             ], |             ], | ||||||
|             options={"unique_together": {("name", "parent")},}, |             options={ | ||||||
|  |                 "unique_together": {("name", "parent")}, | ||||||
|  |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|             name="Application", |             name="Application", | ||||||
|  | |||||||
| @ -12,7 +12,10 @@ class Migration(migrations.Migration): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     operations = [ |     operations = [ | ||||||
|         migrations.RemoveField(model_name="application", name="skip_authorization",), |         migrations.RemoveField( | ||||||
|  |             model_name="application", | ||||||
|  |             name="skip_authorization", | ||||||
|  |         ), | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name="source", |             model_name="source", | ||||||
|             name="authentication_flow", |             name="authentication_flow", | ||||||
|  | |||||||
| @ -25,8 +25,14 @@ class Migration(migrations.Migration): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     operations = [ |     operations = [ | ||||||
|         migrations.RemoveField(model_name="user", name="is_superuser",), |         migrations.RemoveField( | ||||||
|         migrations.RemoveField(model_name="user", name="is_staff",), |             model_name="user", | ||||||
|  |             name="is_superuser", | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name="user", | ||||||
|  |             name="is_staff", | ||||||
|  |         ), | ||||||
|         migrations.RunPython(create_default_user), |         migrations.RunPython(create_default_user), | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name="user", |             model_name="user", | ||||||
|  | |||||||
| @ -13,7 +13,10 @@ def create_default_admin_group(apps: Apps, schema_editor: BaseDatabaseSchemaEdit | |||||||
|  |  | ||||||
|     # Creates a default admin group |     # Creates a default admin group | ||||||
|     group, _ = Group.objects.using(db_alias).get_or_create( |     group, _ = Group.objects.using(db_alias).get_or_create( | ||||||
|         is_superuser=True, defaults={"name": "passbook Admins",} |         is_superuser=True, | ||||||
|  |         defaults={ | ||||||
|  |             "name": "passbook Admins", | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|     group.users.set(User.objects.filter(username="pbadmin")) |     group.users.set(User.objects.filter(username="pbadmin")) | ||||||
|     group.save() |     group.save() | ||||||
| @ -26,8 +29,14 @@ class Migration(migrations.Migration): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     operations = [ |     operations = [ | ||||||
|         migrations.RemoveField(model_name="user", name="is_superuser",), |         migrations.RemoveField( | ||||||
|         migrations.RemoveField(model_name="user", name="is_staff",), |             model_name="user", | ||||||
|  |             name="is_superuser", | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name="user", | ||||||
|  |             name="is_staff", | ||||||
|  |         ), | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name="user", |             model_name="user", | ||||||
|             name="pb_groups", |             name="pb_groups", | ||||||
| @ -44,6 +53,9 @@ class Migration(migrations.Migration): | |||||||
|         ), |         ), | ||||||
|         migrations.RunPython(create_default_admin_group), |         migrations.RunPython(create_default_admin_group), | ||||||
|         migrations.AlterModelManagers( |         migrations.AlterModelManagers( | ||||||
|             name="user", managers=[("objects", passbook.core.models.UserManager()),], |             name="user", | ||||||
|  |             managers=[ | ||||||
|  |                 ("objects", passbook.core.models.UserManager()), | ||||||
|  |             ], | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  | |||||||
| @ -56,7 +56,12 @@ class Group(models.Model): | |||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |  | ||||||
|         unique_together = (("name", "parent",),) |         unique_together = ( | ||||||
|  |             ( | ||||||
|  |                 "name", | ||||||
|  |                 "parent", | ||||||
|  |             ), | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class UserManager(DjangoUserManager): | class UserManager(DjangoUserManager): | ||||||
|  | |||||||
| @ -30,9 +30,9 @@ def user_stages(context: RequestContext) -> List[UIUserSettings]: | |||||||
| def user_sources(context: RequestContext) -> List[UIUserSettings]: | def user_sources(context: RequestContext) -> List[UIUserSettings]: | ||||||
|     """Return a list of all sources which are enabled for the user""" |     """Return a list of all sources which are enabled for the user""" | ||||||
|     user = context.get("request").user |     user = context.get("request").user | ||||||
|     _all_sources: Iterable[Source] = ( |     _all_sources: Iterable[Source] = Source.objects.filter( | ||||||
|         Source.objects.filter(enabled=True).select_subclasses() |         enabled=True | ||||||
|     ) |     ).select_subclasses() | ||||||
|     matching_sources: List[UIUserSettings] = [] |     matching_sources: List[UIUserSettings] = [] | ||||||
|     for source in _all_sources: |     for source in _all_sources: | ||||||
|         user_settings = source.ui_user_settings |         user_settings = source.ui_user_settings | ||||||
|  | |||||||
| @ -36,7 +36,8 @@ class CertificateBuilder: | |||||||
|                 x509.Name( |                 x509.Name( | ||||||
|                     [ |                     [ | ||||||
|                         x509.NameAttribute( |                         x509.NameAttribute( | ||||||
|                             NameOID.COMMON_NAME, "passbook Self-signed Certificate", |                             NameOID.COMMON_NAME, | ||||||
|  |                             "passbook Self-signed Certificate", | ||||||
|                         ), |                         ), | ||||||
|                         x509.NameAttribute(NameOID.ORGANIZATION_NAME, "passbook"), |                         x509.NameAttribute(NameOID.ORGANIZATION_NAME, "passbook"), | ||||||
|                         x509.NameAttribute( |                         x509.NameAttribute( | ||||||
| @ -49,7 +50,8 @@ class CertificateBuilder: | |||||||
|                 x509.Name( |                 x509.Name( | ||||||
|                     [ |                     [ | ||||||
|                         x509.NameAttribute( |                         x509.NameAttribute( | ||||||
|                             NameOID.COMMON_NAME, "passbook Self-signed Certificate", |                             NameOID.COMMON_NAME, | ||||||
|  |                             "passbook Self-signed Certificate", | ||||||
|                         ), |                         ), | ||||||
|                     ] |                     ] | ||||||
|                 ) |                 ) | ||||||
|  | |||||||
| @ -58,7 +58,9 @@ class Command(BaseCommand):  # pragma: no cover | |||||||
|             help="How many processes should be started.", |             help="How many processes should be started.", | ||||||
|         ) |         ) | ||||||
|         parser.add_argument( |         parser.add_argument( | ||||||
|             "--csv", action="store_true", help="Output results as CSV", |             "--csv", | ||||||
|  |             action="store_true", | ||||||
|  |             help="Output results as CSV", | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def benchmark_flows(self, proc_count) -> str: |     def benchmark_flows(self, proc_count) -> str: | ||||||
|  | |||||||
| @ -53,7 +53,10 @@ class Migration(migrations.Migration): | |||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|             ], |             ], | ||||||
|             options={"verbose_name": "Flow", "verbose_name_plural": "Flows",}, |             options={ | ||||||
|  |                 "verbose_name": "Flow", | ||||||
|  |                 "verbose_name_plural": "Flows", | ||||||
|  |             }, | ||||||
|             bases=("passbook_policies.policybindingmodel",), |             bases=("passbook_policies.policybindingmodel",), | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|  | |||||||
| @ -21,13 +21,18 @@ class Migration(migrations.Migration): | |||||||
|             }, |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.RenameField( |         migrations.RenameField( | ||||||
|             model_name="flowstagebinding", old_name="flow", new_name="target", |             model_name="flowstagebinding", | ||||||
|  |             old_name="flow", | ||||||
|  |             new_name="target", | ||||||
|         ), |         ), | ||||||
|         migrations.RenameField( |         migrations.RenameField( | ||||||
|             model_name="flow", old_name="pbm", new_name="policybindingmodel_ptr", |             model_name="flow", | ||||||
|  |             old_name="pbm", | ||||||
|  |             new_name="policybindingmodel_ptr", | ||||||
|         ), |         ), | ||||||
|         migrations.AlterUniqueTogether( |         migrations.AlterUniqueTogether( | ||||||
|             name="flowstagebinding", unique_together={("target", "stage", "order")}, |             name="flowstagebinding", | ||||||
|  |             unique_together={("target", "stage", "order")}, | ||||||
|         ), |         ), | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name="flow", |             model_name="flow", | ||||||
|  | |||||||
| @ -42,16 +42,30 @@ def create_default_authentication_flow( | |||||||
|     flow, _ = Flow.objects.using(db_alias).update_or_create( |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         slug="default-authentication-flow", |         slug="default-authentication-flow", | ||||||
|         designation=FlowDesignation.AUTHENTICATION, |         designation=FlowDesignation.AUTHENTICATION, | ||||||
|         defaults={"name": "Welcome to passbook!",}, |         defaults={ | ||||||
|  |             "name": "Welcome to passbook!", | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).update_or_create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         target=flow, stage=identification_stage, defaults={"order": 0,}, |         target=flow, | ||||||
|  |         stage=identification_stage, | ||||||
|  |         defaults={ | ||||||
|  |             "order": 0, | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).update_or_create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         target=flow, stage=password_stage, defaults={"order": 1,}, |         target=flow, | ||||||
|  |         stage=password_stage, | ||||||
|  |         defaults={ | ||||||
|  |             "order": 1, | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).update_or_create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         target=flow, stage=login_stage, defaults={"order": 2,}, |         target=flow, | ||||||
|  |         stage=login_stage, | ||||||
|  |         defaults={ | ||||||
|  |             "order": 2, | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -70,12 +84,16 @@ def create_default_invalidation_flow( | |||||||
|     flow, _ = Flow.objects.using(db_alias).update_or_create( |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         slug="default-invalidation-flow", |         slug="default-invalidation-flow", | ||||||
|         designation=FlowDesignation.INVALIDATION, |         designation=FlowDesignation.INVALIDATION, | ||||||
|         defaults={"name": "Logout",}, |         defaults={ | ||||||
|  |             "name": "Logout", | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).update_or_create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         target=flow, |         target=flow, | ||||||
|         stage=UserLogoutStage.objects.using(db_alias).first(), |         stage=UserLogoutStage.objects.using(db_alias).first(), | ||||||
|         defaults={"order": 0,}, |         defaults={ | ||||||
|  |             "order": 0, | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -44,7 +44,9 @@ def create_default_source_enrollment_flow( | |||||||
|     flow, _ = Flow.objects.using(db_alias).update_or_create( |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         slug="default-source-enrollment", |         slug="default-source-enrollment", | ||||||
|         designation=FlowDesignation.ENROLLMENT, |         designation=FlowDesignation.ENROLLMENT, | ||||||
|         defaults={"name": "Welcome to passbook!",}, |         defaults={ | ||||||
|  |             "name": "Welcome to passbook!", | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|     PolicyBinding.objects.using(db_alias).update_or_create( |     PolicyBinding.objects.using(db_alias).update_or_create( | ||||||
|         policy=flow_policy, target=flow, defaults={"order": 0} |         policy=flow_policy, target=flow, defaults={"order": 0} | ||||||
| @ -114,14 +116,18 @@ def create_default_source_authentication_flow( | |||||||
|     # Create a policy that only allows this flow when doing an SSO Request |     # Create a policy that only allows this flow when doing an SSO Request | ||||||
|     flow_policy, _ = ExpressionPolicy.objects.using(db_alias).update_or_create( |     flow_policy, _ = ExpressionPolicy.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-authentication-if-sso", |         name="default-source-authentication-if-sso", | ||||||
|         defaults={"expression": FLOW_POLICY_EXPRESSION,}, |         defaults={ | ||||||
|  |             "expression": FLOW_POLICY_EXPRESSION, | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     # This creates a Flow used by sources to authenticate users |     # This creates a Flow used by sources to authenticate users | ||||||
|     flow, _ = Flow.objects.using(db_alias).update_or_create( |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         slug="default-source-authentication", |         slug="default-source-authentication", | ||||||
|         designation=FlowDesignation.AUTHENTICATION, |         designation=FlowDesignation.AUTHENTICATION, | ||||||
|         defaults={"name": "Welcome to passbook!",}, |         defaults={ | ||||||
|  |             "name": "Welcome to passbook!", | ||||||
|  |         }, | ||||||
|     ) |     ) | ||||||
|     PolicyBinding.objects.using(db_alias).update_or_create( |     PolicyBinding.objects.using(db_alias).update_or_create( | ||||||
|         policy=flow_policy, target=flow, defaults={"order": 0} |         policy=flow_policy, target=flow, defaults={"order": 0} | ||||||
|  | |||||||
| @ -47,6 +47,8 @@ class Migration(migrations.Migration): | |||||||
|         ), |         ), | ||||||
|         migrations.RunPython(add_title_for_defaults), |         migrations.RunPython(add_title_for_defaults), | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name="flow", name="title", field=models.TextField(), |             model_name="flow", | ||||||
|  |             name="title", | ||||||
|  |             field=models.TextField(), | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  | |||||||
| @ -21,6 +21,8 @@ class Migration(migrations.Migration): | |||||||
|             ), |             ), | ||||||
|         ), |         ), | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name="stage", name="name", field=models.TextField(unique=True), |             model_name="stage", | ||||||
|  |             name="name", | ||||||
|  |             field=models.TextField(unique=True), | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  | |||||||
| @ -177,6 +177,7 @@ class FlowPlanner: | |||||||
|                         marker = ReevaluateMarker(binding=binding, user=user) |                         marker = ReevaluateMarker(binding=binding, user=user) | ||||||
|                     plan.markers.append(marker) |                     plan.markers.append(marker) | ||||||
|         LOGGER.debug( |         LOGGER.debug( | ||||||
|             "f(plan): Finished building", flow=self.flow, |             "f(plan): Finished building", | ||||||
|  |             flow=self.flow, | ||||||
|         ) |         ) | ||||||
|         return plan |         return plan | ||||||
|  | |||||||
| @ -52,7 +52,8 @@ class TestFlowPlanner(TestCase): | |||||||
|             planner.plan(request) |             planner.plan(request) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.policies.engine.PolicyEngine.result", POLICY_RETURN_FALSE, |         "passbook.policies.engine.PolicyEngine.result", | ||||||
|  |         POLICY_RETURN_FALSE, | ||||||
|     ) |     ) | ||||||
|     def test_non_applicable_plan(self): |     def test_non_applicable_plan(self): | ||||||
|         """Test that empty plan raises exception""" |         """Test that empty plan raises exception""" | ||||||
|  | |||||||
| @ -39,7 +39,9 @@ class TestFlowTransfer(TransactionTestCase): | |||||||
|                 title=generate_client_id(), |                 title=generate_client_id(), | ||||||
|             ) |             ) | ||||||
|             FlowStageBinding.objects.update_or_create( |             FlowStageBinding.objects.update_or_create( | ||||||
|                 target=flow, stage=login_stage, order=0, |                 target=flow, | ||||||
|  |                 stage=login_stage, | ||||||
|  |                 order=0, | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|             exporter = FlowExporter(flow) |             exporter = FlowExporter(flow) | ||||||
| @ -59,7 +61,8 @@ class TestFlowTransfer(TransactionTestCase): | |||||||
|         stage_name = generate_client_id() |         stage_name = generate_client_id() | ||||||
|         with transaction_rollback(): |         with transaction_rollback(): | ||||||
|             flow_policy = ExpressionPolicy.objects.create( |             flow_policy = ExpressionPolicy.objects.create( | ||||||
|                 name=generate_client_id(), expression="return True", |                 name=generate_client_id(), | ||||||
|  |                 expression="return True", | ||||||
|             ) |             ) | ||||||
|             flow = Flow.objects.create( |             flow = Flow.objects.create( | ||||||
|                 slug=flow_slug, |                 slug=flow_slug, | ||||||
|  | |||||||
| @ -63,10 +63,12 @@ class TestFlowExecutor(TestCase): | |||||||
|             self.assertEqual(cancel_mock.call_count, 2) |             self.assertEqual(cancel_mock.call_count, 2) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.policies.engine.PolicyEngine.result", POLICY_RETURN_FALSE, |         "passbook.policies.engine.PolicyEngine.result", | ||||||
|  |         POLICY_RETURN_FALSE, | ||||||
|     ) |     ) | ||||||
|     def test_invalid_non_applicable_flow(self): |     def test_invalid_non_applicable_flow(self): | ||||||
|         """Tests that a non-applicable flow returns the correct error message""" |         """Tests that a non-applicable flow returns the correct error message""" | ||||||
| @ -85,7 +87,8 @@ class TestFlowExecutor(TestCase): | |||||||
|         self.assertInHTML(FlowNonApplicableException.__doc__, response.rendered_content) |         self.assertInHTML(FlowNonApplicableException.__doc__, response.rendered_content) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     def test_invalid_empty_flow(self): |     def test_invalid_empty_flow(self): | ||||||
|         """Tests that an empty flow returns the correct error message""" |         """Tests that an empty flow returns the correct error message""" | ||||||
| @ -117,7 +120,8 @@ class TestFlowExecutor(TestCase): | |||||||
|         response = self.client.get(url + f"?{NEXT_ARG_NAME}={dest}") |         response = self.client.get(url + f"?{NEXT_ARG_NAME}={dest}") | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|         self.assertJSONEqual( |         self.assertJSONEqual( | ||||||
|             force_str(response.content), {"type": "redirect", "to": dest}, |             force_str(response.content), | ||||||
|  |             {"type": "redirect", "to": dest}, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_multi_stage_flow(self): |     def test_multi_stage_flow(self): | ||||||
|  | |||||||
| @ -15,8 +15,12 @@ class TestHelperView(TestCase): | |||||||
|  |  | ||||||
|     def test_default_view(self): |     def test_default_view(self): | ||||||
|         """Test that ToDefaultFlow returns the expected URL""" |         """Test that ToDefaultFlow returns the expected URL""" | ||||||
|         flow = Flow.objects.filter(designation=FlowDesignation.INVALIDATION,).first() |         flow = Flow.objects.filter( | ||||||
|         response = self.client.get(reverse("passbook_flows:default-invalidation"),) |             designation=FlowDesignation.INVALIDATION, | ||||||
|  |         ).first() | ||||||
|  |         response = self.client.get( | ||||||
|  |             reverse("passbook_flows:default-invalidation"), | ||||||
|  |         ) | ||||||
|         expected_url = reverse( |         expected_url = reverse( | ||||||
|             "passbook_flows:flow-executor-shell", kwargs={"flow_slug": flow.slug} |             "passbook_flows:flow-executor-shell", kwargs={"flow_slug": flow.slug} | ||||||
|         ) |         ) | ||||||
| @ -25,13 +29,17 @@ class TestHelperView(TestCase): | |||||||
|  |  | ||||||
|     def test_default_view_invalid_plan(self): |     def test_default_view_invalid_plan(self): | ||||||
|         """Test that ToDefaultFlow returns the expected URL (with an invalid plan)""" |         """Test that ToDefaultFlow returns the expected URL (with an invalid plan)""" | ||||||
|         flow = Flow.objects.filter(designation=FlowDesignation.INVALIDATION,).first() |         flow = Flow.objects.filter( | ||||||
|  |             designation=FlowDesignation.INVALIDATION, | ||||||
|  |         ).first() | ||||||
|         plan = FlowPlan(flow_pk=flow.pk.hex + "aa") |         plan = FlowPlan(flow_pk=flow.pk.hex + "aa") | ||||||
|         session = self.client.session |         session = self.client.session | ||||||
|         session[SESSION_KEY_PLAN] = plan |         session[SESSION_KEY_PLAN] = plan | ||||||
|         session.save() |         session.save() | ||||||
|  |  | ||||||
|         response = self.client.get(reverse("passbook_flows:default-invalidation"),) |         response = self.client.get( | ||||||
|  |             reverse("passbook_flows:default-invalidation"), | ||||||
|  |         ) | ||||||
|         expected_url = reverse( |         expected_url = reverse( | ||||||
|             "passbook_flows:flow-executor-shell", kwargs={"flow_slug": flow.slug} |             "passbook_flows:flow-executor-shell", kwargs={"flow_slug": flow.slug} | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -103,7 +103,9 @@ class BaseEvaluator: | |||||||
|         param_keys = self._context.keys() |         param_keys = self._context.keys() | ||||||
|         try: |         try: | ||||||
|             compile( |             compile( | ||||||
|                 self.wrap_expression(expression, param_keys), self._filename, "exec", |                 self.wrap_expression(expression, param_keys), | ||||||
|  |                 self._filename, | ||||||
|  |                 "exec", | ||||||
|             ) |             ) | ||||||
|             return True |             return True | ||||||
|         except (ValueError, SyntaxError) as exc: |         except (ValueError, SyntaxError) as exc: | ||||||
|  | |||||||
| @ -71,7 +71,14 @@ def gravatar(email, size=None, rating=None): | |||||||
|         md5(email.encode("utf-8")).hexdigest(),  # nosec |         md5(email.encode("utf-8")).hexdigest(),  # nosec | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     parameters = [p for p in (("s", size or "158"), ("r", rating or "g"),) if p[1]] |     parameters = [ | ||||||
|  |         p | ||||||
|  |         for p in ( | ||||||
|  |             ("s", size or "158"), | ||||||
|  |             ("r", rating or "g"), | ||||||
|  |         ) | ||||||
|  |         if p[1] | ||||||
|  |     ] | ||||||
|  |  | ||||||
|     if parameters: |     if parameters: | ||||||
|         gravatar_url += "?" + urlencode(parameters, doseq=True) |         gravatar_url += "?" + urlencode(parameters, doseq=True) | ||||||
|  | |||||||
| @ -34,5 +34,8 @@ def bad_request_message( | |||||||
| ) -> TemplateResponse: | ) -> TemplateResponse: | ||||||
|     """Return generic error page with message, with status code set to 400""" |     """Return generic error page with message, with status code set to 400""" | ||||||
|     return TemplateResponse( |     return TemplateResponse( | ||||||
|         request, template, {"message": message, "card_title": _(title)}, status=400, |         request, | ||||||
|  |         template, | ||||||
|  |         {"message": message, "card_title": _(title)}, | ||||||
|  |         status=400, | ||||||
|     ) |     ) | ||||||
|  | |||||||
| @ -29,7 +29,9 @@ class DockerComposeView(LoginRequiredMixin, View): | |||||||
|     def get(self, request: HttpRequest, outpost_pk: str) -> HttpResponse: |     def get(self, request: HttpRequest, outpost_pk: str) -> HttpResponse: | ||||||
|         """Render docker-compose file""" |         """Render docker-compose file""" | ||||||
|         outpost: Outpost = get_object_for_user_or_404( |         outpost: Outpost = get_object_for_user_or_404( | ||||||
|             request.user, "passbook_outposts.view_outpost", pk=outpost_pk, |             request.user, | ||||||
|  |             "passbook_outposts.view_outpost", | ||||||
|  |             pk=outpost_pk, | ||||||
|         ) |         ) | ||||||
|         manifest = "" |         manifest = "" | ||||||
|         if outpost.type == OutpostType.PROXY: |         if outpost.type == OutpostType.PROXY: | ||||||
| @ -45,7 +47,9 @@ class KubernetesManifestView(LoginRequiredMixin, View): | |||||||
|     def get(self, request: HttpRequest, outpost_pk: str) -> HttpResponse: |     def get(self, request: HttpRequest, outpost_pk: str) -> HttpResponse: | ||||||
|         """Render deployment template""" |         """Render deployment template""" | ||||||
|         outpost: Outpost = get_object_for_user_or_404( |         outpost: Outpost = get_object_for_user_or_404( | ||||||
|             request.user, "passbook_outposts.view_outpost", pk=outpost_pk, |             request.user, | ||||||
|  |             "passbook_outposts.view_outpost", | ||||||
|  |             pk=outpost_pk, | ||||||
|         ) |         ) | ||||||
|         manifest = "" |         manifest = "" | ||||||
|         if outpost.type == OutpostType.PROXY: |         if outpost.type == OutpostType.PROXY: | ||||||
|  | |||||||
| @ -47,7 +47,8 @@ class PolicyBindingSerializer(ModelSerializer): | |||||||
|     # Because we're not interested in the PolicyBindingModel's PK but rather the subclasses PK, |     # Because we're not interested in the PolicyBindingModel's PK but rather the subclasses PK, | ||||||
|     # we have to manually declare this field |     # we have to manually declare this field | ||||||
|     target = PolicyBindingModelForeignKey( |     target = PolicyBindingModelForeignKey( | ||||||
|         queryset=PolicyBindingModel.objects.select_subclasses(), required=True, |         queryset=PolicyBindingModel.objects.select_subclasses(), | ||||||
|  |         required=True, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  | |||||||
| @ -16,7 +16,9 @@ class PolicyBindingForm(forms.ModelForm): | |||||||
|         queryset=PolicyBindingModel.objects.all().select_subclasses(), |         queryset=PolicyBindingModel.objects.all().select_subclasses(), | ||||||
|         to_field_name="pbm_uuid", |         to_field_name="pbm_uuid", | ||||||
|     ) |     ) | ||||||
|     policy = GroupedModelChoiceField(queryset=Policy.objects.all().select_subclasses(),) |     policy = GroupedModelChoiceField( | ||||||
|  |         queryset=Policy.objects.all().select_subclasses(), | ||||||
|  |     ) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |  | ||||||
|  | |||||||
| @ -12,7 +12,9 @@ class TestHIBPPolicy(TestCase): | |||||||
|  |  | ||||||
|     def test_false(self): |     def test_false(self): | ||||||
|         """Failing password case""" |         """Failing password case""" | ||||||
|         policy = HaveIBeenPwendPolicy.objects.create(name="test_false",) |         policy = HaveIBeenPwendPolicy.objects.create( | ||||||
|  |             name="test_false", | ||||||
|  |         ) | ||||||
|         request = PolicyRequest(get_anonymous_user()) |         request = PolicyRequest(get_anonymous_user()) | ||||||
|         request.context["password"] = "password" |         request.context["password"] = "password" | ||||||
|         result: PolicyResult = policy.passes(request) |         result: PolicyResult = policy.passes(request) | ||||||
| @ -21,7 +23,9 @@ class TestHIBPPolicy(TestCase): | |||||||
|  |  | ||||||
|     def test_true(self): |     def test_true(self): | ||||||
|         """Positive password case""" |         """Positive password case""" | ||||||
|         policy = HaveIBeenPwendPolicy.objects.create(name="test_true",) |         policy = HaveIBeenPwendPolicy.objects.create( | ||||||
|  |             name="test_true", | ||||||
|  |         ) | ||||||
|         request = PolicyRequest(get_anonymous_user()) |         request = PolicyRequest(get_anonymous_user()) | ||||||
|         request.context["password"] = generate_client_secret() |         request.context["password"] = generate_client_secret() | ||||||
|         result: PolicyResult = policy.passes(request) |         result: PolicyResult = policy.passes(request) | ||||||
|  | |||||||
| @ -32,7 +32,9 @@ class Migration(migrations.Migration): | |||||||
|                 ("order", models.IntegerField(default=0)), |                 ("order", models.IntegerField(default=0)), | ||||||
|                 ("timeout", models.IntegerField(default=30)), |                 ("timeout", models.IntegerField(default=30)), | ||||||
|             ], |             ], | ||||||
|             options={"abstract": False,}, |             options={ | ||||||
|  |                 "abstract": False, | ||||||
|  |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|             name="PolicyBinding", |             name="PolicyBinding", | ||||||
|  | |||||||
| @ -21,9 +21,18 @@ class Migration(migrations.Migration): | |||||||
|                 "verbose_name_plural": "Policies", |                 "verbose_name_plural": "Policies", | ||||||
|             }, |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.RemoveField(model_name="policy", name="negate",), |         migrations.RemoveField( | ||||||
|         migrations.RemoveField(model_name="policy", name="order",), |             model_name="policy", | ||||||
|         migrations.RemoveField(model_name="policy", name="timeout",), |             name="negate", | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name="policy", | ||||||
|  |             name="order", | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name="policy", | ||||||
|  |             name="timeout", | ||||||
|  |         ), | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name="policybinding", |             model_name="policybinding", | ||||||
|             name="negate", |             name="negate", | ||||||
| @ -41,7 +50,9 @@ class Migration(migrations.Migration): | |||||||
|             ), |             ), | ||||||
|         ), |         ), | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name="policybinding", name="order", field=models.IntegerField(), |             model_name="policybinding", | ||||||
|  |             name="order", | ||||||
|  |             field=models.IntegerField(), | ||||||
|         ), |         ), | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name="policybinding", |             model_name="policybinding", | ||||||
| @ -53,6 +64,7 @@ class Migration(migrations.Migration): | |||||||
|             ), |             ), | ||||||
|         ), |         ), | ||||||
|         migrations.AlterUniqueTogether( |         migrations.AlterUniqueTogether( | ||||||
|             name="policybinding", unique_together={("policy", "target", "order")}, |             name="policybinding", | ||||||
|  |             unique_together={("policy", "target", "order")}, | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  | |||||||
| @ -73,7 +73,10 @@ class PolicyAccessMixin(BaseMixin, AccessMixin): | |||||||
|         policy_engine.build() |         policy_engine.build() | ||||||
|         result = policy_engine.result |         result = policy_engine.result | ||||||
|         LOGGER.debug( |         LOGGER.debug( | ||||||
|             "AccessMixin user_has_access", user=user, app=application, result=result, |             "AccessMixin user_has_access", | ||||||
|  |             user=user, | ||||||
|  |             app=application, | ||||||
|  |             result=result, | ||||||
|         ) |         ) | ||||||
|         if not result.passing: |         if not result.passing: | ||||||
|             for message in result.messages: |             for message in result.messages: | ||||||
|  | |||||||
| @ -48,7 +48,9 @@ class PolicyProcess(Process): | |||||||
|  |  | ||||||
|     def execute(self) -> PolicyResult: |     def execute(self) -> PolicyResult: | ||||||
|         """Run actual policy, returns result""" |         """Run actual policy, returns result""" | ||||||
|         with Hub.current.start_span(op="policy.process.execute",) as span: |         with Hub.current.start_span( | ||||||
|  |             op="policy.process.execute", | ||||||
|  |         ) as span: | ||||||
|             span: Span |             span: Span | ||||||
|             span.set_data("policy", self.binding.policy) |             span.set_data("policy", self.binding.policy) | ||||||
|             span.set_data("request", self.request) |             span.set_data("request", self.request) | ||||||
|  | |||||||
| @ -283,7 +283,10 @@ class Migration(migrations.Migration): | |||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|             ], |             ], | ||||||
|             options={"verbose_name": "Token", "verbose_name_plural": "Tokens",}, |             options={ | ||||||
|  |                 "verbose_name": "Token", | ||||||
|  |                 "verbose_name_plural": "Tokens", | ||||||
|  |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|             name="AuthorizationCode", |             name="AuthorizationCode", | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ class Migration(migrations.Migration): | |||||||
|  |  | ||||||
|     operations = [ |     operations = [ | ||||||
|         migrations.RemoveField( |         migrations.RemoveField( | ||||||
|             model_name="oauth2provider", name="post_logout_redirect_uris", |             model_name="oauth2provider", | ||||||
|  |             name="post_logout_redirect_uris", | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  | |||||||
| @ -292,13 +292,19 @@ class OAuth2Provider(Provider): | |||||||
|                     "provider": self, |                     "provider": self, | ||||||
|                     "issuer": self.get_issuer(request), |                     "issuer": self.get_issuer(request), | ||||||
|                     "authorize": request.build_absolute_uri( |                     "authorize": request.build_absolute_uri( | ||||||
|                         reverse("passbook_providers_oauth2:authorize",) |                         reverse( | ||||||
|  |                             "passbook_providers_oauth2:authorize", | ||||||
|  |                         ) | ||||||
|                     ), |                     ), | ||||||
|                     "token": request.build_absolute_uri( |                     "token": request.build_absolute_uri( | ||||||
|                         reverse("passbook_providers_oauth2:token",) |                         reverse( | ||||||
|  |                             "passbook_providers_oauth2:token", | ||||||
|  |                         ) | ||||||
|                     ), |                     ), | ||||||
|                     "userinfo": request.build_absolute_uri( |                     "userinfo": request.build_absolute_uri( | ||||||
|                         reverse("passbook_providers_oauth2:userinfo",) |                         reverse( | ||||||
|  |                             "passbook_providers_oauth2:userinfo", | ||||||
|  |                         ) | ||||||
|                     ), |                     ), | ||||||
|                     "provider_info": request.build_absolute_uri( |                     "provider_info": request.build_absolute_uri( | ||||||
|                         reverse( |                         reverse( | ||||||
|  | |||||||
| @ -13,7 +13,11 @@ from passbook.providers.oauth2.views.token import TokenView | |||||||
| from passbook.providers.oauth2.views.userinfo import UserInfoView | from passbook.providers.oauth2.views.userinfo import UserInfoView | ||||||
|  |  | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     path("authorize/", AuthorizationFlowInitView.as_view(), name="authorize",), |     path( | ||||||
|  |         "authorize/", | ||||||
|  |         AuthorizationFlowInitView.as_view(), | ||||||
|  |         name="authorize", | ||||||
|  |     ), | ||||||
|     path("token/", csrf_exempt(TokenView.as_view()), name="token"), |     path("token/", csrf_exempt(TokenView.as_view()), name="token"), | ||||||
|     path( |     path( | ||||||
|         "userinfo/", |         "userinfo/", | ||||||
|  | |||||||
| @ -257,7 +257,8 @@ class OAuthFulfillmentStage(StageView): | |||||||
|                 ] |                 ] | ||||||
|             elif self.params.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID]: |             elif self.params.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID]: | ||||||
|                 token = self.provider.create_refresh_token( |                 token = self.provider.create_refresh_token( | ||||||
|                     user=self.request.user, scope=self.params.scope, |                     user=self.request.user, | ||||||
|  |                     scope=self.params.scope, | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|                 # Check if response_type must include access_token in the response. |                 # Check if response_type must include access_token in the response. | ||||||
| @ -272,7 +273,8 @@ class OAuthFulfillmentStage(StageView): | |||||||
|                 # We don't need id_token if it's an OAuth2 request. |                 # We don't need id_token if it's an OAuth2 request. | ||||||
|                 if SCOPE_OPENID in self.params.scope: |                 if SCOPE_OPENID in self.params.scope: | ||||||
|                     id_token = token.create_id_token( |                     id_token = token.create_id_token( | ||||||
|                         user=self.request.user, request=self.request, |                         user=self.request.user, | ||||||
|  |                         request=self.request, | ||||||
|                     ) |                     ) | ||||||
|                     id_token.nonce = self.params.nonce |                     id_token.nonce = self.params.nonce | ||||||
|  |  | ||||||
|  | |||||||
| @ -35,7 +35,8 @@ class TokenIntrospectionParams: | |||||||
|  |  | ||||||
|         if not self.token.id_token: |         if not self.token.id_token: | ||||||
|             LOGGER.debug( |             LOGGER.debug( | ||||||
|                 "token not an authentication token", token=self.token, |                 "token not an authentication token", | ||||||
|  |                 token=self.token, | ||||||
|             ) |             ) | ||||||
|             raise TokenIntrospectionError() |             raise TokenIntrospectionError() | ||||||
|  |  | ||||||
|  | |||||||
| @ -96,7 +96,8 @@ class TokenParams: | |||||||
|  |  | ||||||
|             except RefreshToken.DoesNotExist: |             except RefreshToken.DoesNotExist: | ||||||
|                 LOGGER.warning( |                 LOGGER.warning( | ||||||
|                     "Refresh token does not exist", token=raw_token, |                     "Refresh token does not exist", | ||||||
|  |                     token=raw_token, | ||||||
|                 ) |                 ) | ||||||
|                 raise TokenError("invalid_grant") |                 raise TokenError("invalid_grant") | ||||||
|  |  | ||||||
| @ -178,7 +179,8 @@ class TokenView(View): | |||||||
|  |  | ||||||
|         if self.params.authorization_code.is_open_id: |         if self.params.authorization_code.is_open_id: | ||||||
|             id_token = refresh_token.create_id_token( |             id_token = refresh_token.create_id_token( | ||||||
|                 user=self.params.authorization_code.user, request=self.request, |                 user=self.params.authorization_code.user, | ||||||
|  |                 request=self.request, | ||||||
|             ) |             ) | ||||||
|             id_token.nonce = self.params.authorization_code.nonce |             id_token.nonce = self.params.authorization_code.nonce | ||||||
|             id_token.at_hash = refresh_token.at_hash |             id_token.at_hash = refresh_token.at_hash | ||||||
| @ -221,13 +223,15 @@ class TokenView(View): | |||||||
|         provider: OAuth2Provider = self.params.refresh_token.provider |         provider: OAuth2Provider = self.params.refresh_token.provider | ||||||
|  |  | ||||||
|         refresh_token: RefreshToken = provider.create_refresh_token( |         refresh_token: RefreshToken = provider.create_refresh_token( | ||||||
|             user=self.params.refresh_token.user, scope=self.params.scope, |             user=self.params.refresh_token.user, | ||||||
|  |             scope=self.params.scope, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         # If the Token has an id_token it's an Authentication request. |         # If the Token has an id_token it's an Authentication request. | ||||||
|         if self.params.refresh_token.id_token: |         if self.params.refresh_token.id_token: | ||||||
|             refresh_token.id_token = refresh_token.create_id_token( |             refresh_token.id_token = refresh_token.create_id_token( | ||||||
|                 user=self.params.refresh_token.user, request=self.request, |                 user=self.params.refresh_token.user, | ||||||
|  |                 request=self.request, | ||||||
|             ) |             ) | ||||||
|             refresh_token.id_token.at_hash = refresh_token.at_hash |             refresh_token.id_token.at_hash = refresh_token.at_hash | ||||||
|  |  | ||||||
|  | |||||||
| @ -92,7 +92,10 @@ class ProxyProvider(OutpostModel, OAuth2Provider): | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     certificate = models.ForeignKey( |     certificate = models.ForeignKey( | ||||||
|         CertificateKeyPair, on_delete=models.SET_NULL, null=True, blank=True, |         CertificateKeyPair, | ||||||
|  |         on_delete=models.SET_NULL, | ||||||
|  |         null=True, | ||||||
|  |         blank=True, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     cookie_secret = models.TextField(default=get_cookie_secret) |     cookie_secret = models.TextField(default=get_cookie_secret) | ||||||
|  | |||||||
| @ -10,5 +10,8 @@ class Migration(migrations.Migration): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     operations = [ |     operations = [ | ||||||
|         migrations.RemoveField(model_name="samlprovider", name="processor_path",), |         migrations.RemoveField( | ||||||
|  |             model_name="samlprovider", | ||||||
|  |             name="processor_path", | ||||||
|  |         ), | ||||||
|     ] |     ] | ||||||
|  | |||||||
| @ -72,7 +72,10 @@ class SAMLProvider(Provider): | |||||||
|  |  | ||||||
|     digest_algorithm = models.CharField( |     digest_algorithm = models.CharField( | ||||||
|         max_length=50, |         max_length=50, | ||||||
|         choices=(("sha1", _("SHA1")), ("sha256", _("SHA256")),), |         choices=( | ||||||
|  |             ("sha1", _("SHA1")), | ||||||
|  |             ("sha256", _("SHA256")), | ||||||
|  |         ), | ||||||
|         default="sha256", |         default="sha256", | ||||||
|     ) |     ) | ||||||
|     signature_algorithm = models.CharField( |     signature_algorithm = models.CharField( | ||||||
|  | |||||||
| @ -47,7 +47,7 @@ SESSION_KEY_AUTH_N_REQUEST = "authn_request" | |||||||
|  |  | ||||||
|  |  | ||||||
| class SAMLSSOView(PolicyAccessMixin, View): | class SAMLSSOView(PolicyAccessMixin, View): | ||||||
|     """"SAML SSO Base View, which plans a flow and injects our final stage. |     """ "SAML SSO Base View, which plans a flow and injects our final stage. | ||||||
|     Calls get/post handler.""" |     Calls get/post handler.""" | ||||||
|  |  | ||||||
|     application: Application |     application: Application | ||||||
|  | |||||||
| @ -38,7 +38,11 @@ for _passbook_app in get_apps(): | |||||||
|     for module, mountpoint in mountpoints.items(): |     for module, mountpoint in mountpoints.items(): | ||||||
|         namespace = _passbook_app.label + module.replace(base_url_module, "") |         namespace = _passbook_app.label + module.replace(base_url_module, "") | ||||||
|         _path = path( |         _path = path( | ||||||
|             mountpoint, include((module, _passbook_app.label), namespace=namespace,), |             mountpoint, | ||||||
|  |             include( | ||||||
|  |                 (module, _passbook_app.label), | ||||||
|  |                 namespace=namespace, | ||||||
|  |             ), | ||||||
|         ) |         ) | ||||||
|         urlpatterns.append(_path) |         urlpatterns.append(_path) | ||||||
|         LOGGER.debug( |         LOGGER.debug( | ||||||
|  | |||||||
| @ -91,7 +91,8 @@ class LDAPSynchronizer: | |||||||
|             try: |             try: | ||||||
|                 defaults = self._build_object_properties(attributes) |                 defaults = self._build_object_properties(attributes) | ||||||
|                 user, created = User.objects.update_or_create( |                 user, created = User.objects.update_or_create( | ||||||
|                     attributes__ldap_uniq=uniq, defaults=defaults, |                     attributes__ldap_uniq=uniq, | ||||||
|  |                     defaults=defaults, | ||||||
|                 ) |                 ) | ||||||
|             except IntegrityError as exc: |             except IntegrityError as exc: | ||||||
|                 LOGGER.warning("Failed to create user", exc=exc) |                 LOGGER.warning("Failed to create user", exc=exc) | ||||||
|  | |||||||
| @ -69,7 +69,8 @@ class OAuthSource(Source): | |||||||
|     def ui_user_settings(self) -> Optional[UIUserSettings]: |     def ui_user_settings(self) -> Optional[UIUserSettings]: | ||||||
|         view_name = "passbook_sources_oauth:oauth-client-user" |         view_name = "passbook_sources_oauth:oauth-client-user" | ||||||
|         return UIUserSettings( |         return UIUserSettings( | ||||||
|             name=self.name, url=reverse(view_name, kwargs={"source_slug": self.slug}), |             name=self.name, | ||||||
|  |             url=reverse(view_name, kwargs={"source_slug": self.slug}), | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def __str__(self) -> str: |     def __str__(self) -> str: | ||||||
|  | |||||||
| @ -147,7 +147,9 @@ class OAuthCallback(OAuthClientMixin, View): | |||||||
|         plan = planner.plan(self.request, kwargs) |         plan = planner.plan(self.request, kwargs) | ||||||
|         self.request.session[SESSION_KEY_PLAN] = plan |         self.request.session[SESSION_KEY_PLAN] = plan | ||||||
|         return redirect_with_qs( |         return redirect_with_qs( | ||||||
|             "passbook_flows:flow-executor-shell", self.request.GET, flow_slug=flow.slug, |             "passbook_flows:flow-executor-shell", | ||||||
|  |             self.request.GET, | ||||||
|  |             flow_slug=flow.slug, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     # pylint: disable=unused-argument |     # pylint: disable=unused-argument | ||||||
|  | |||||||
| @ -21,7 +21,8 @@ class SAMLSourceForm(forms.ModelForm): | |||||||
|             designation=FlowDesignation.ENROLLMENT |             designation=FlowDesignation.ENROLLMENT | ||||||
|         ) |         ) | ||||||
|         self.fields["signing_kp"].queryset = CertificateKeyPair.objects.filter( |         self.fields["signing_kp"].queryset = CertificateKeyPair.objects.filter( | ||||||
|             certificate_data__isnull=False, key_data__isnull=False, |             certificate_data__isnull=False, | ||||||
|  |             key_data__isnull=False, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  | |||||||
| @ -14,12 +14,19 @@ class Migration(migrations.Migration): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     operations = [ |     operations = [ | ||||||
|         migrations.RemoveField(model_name="samlsource", name="auto_logout",), |         migrations.RemoveField( | ||||||
|         migrations.RenameField( |             model_name="samlsource", | ||||||
|             model_name="samlsource", old_name="idp_url", new_name="sso_url", |             name="auto_logout", | ||||||
|         ), |         ), | ||||||
|         migrations.RenameField( |         migrations.RenameField( | ||||||
|             model_name="samlsource", old_name="idp_logout_url", new_name="slo_url", |             model_name="samlsource", | ||||||
|  |             old_name="idp_url", | ||||||
|  |             new_name="sso_url", | ||||||
|  |         ), | ||||||
|  |         migrations.RenameField( | ||||||
|  |             model_name="samlsource", | ||||||
|  |             old_name="idp_logout_url", | ||||||
|  |             new_name="slo_url", | ||||||
|         ), |         ), | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name="samlsource", |             model_name="samlsource", | ||||||
|  | |||||||
| @ -191,5 +191,7 @@ class ResponseProcessor: | |||||||
|         kwargs[PLAN_CONTEXT_SSO] = True |         kwargs[PLAN_CONTEXT_SSO] = True | ||||||
|         request.session[SESSION_KEY_PLAN] = FlowPlanner(flow).plan(request, kwargs) |         request.session[SESSION_KEY_PLAN] = FlowPlanner(flow).plan(request, kwargs) | ||||||
|         return redirect_with_qs( |         return redirect_with_qs( | ||||||
|             "passbook_flows:flow-executor-shell", request.GET, flow_slug=flow.slug, |             "passbook_flows:flow-executor-shell", | ||||||
|  |             request.GET, | ||||||
|  |             flow_slug=flow.slug, | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -23,7 +23,8 @@ class TestConsentStage(TestCase): | |||||||
|             username="unittest", email="test@beryju.org" |             username="unittest", email="test@beryju.org" | ||||||
|         ) |         ) | ||||||
|         self.application = Application.objects.create( |         self.application = Application.objects.create( | ||||||
|             name="test-application", slug="test-application", |             name="test-application", | ||||||
|  |             slug="test-application", | ||||||
|         ) |         ) | ||||||
|         self.client = Client() |         self.client = Client() | ||||||
|  |  | ||||||
|  | |||||||
| @ -22,9 +22,13 @@ class TestDummyStage(TestCase): | |||||||
|             slug="test-dummy", |             slug="test-dummy", | ||||||
|             designation=FlowDesignation.AUTHENTICATION, |             designation=FlowDesignation.AUTHENTICATION, | ||||||
|         ) |         ) | ||||||
|         self.stage = DummyStage.objects.create(name="dummy",) |         self.stage = DummyStage.objects.create( | ||||||
|  |             name="dummy", | ||||||
|  |         ) | ||||||
|         FlowStageBinding.objects.create( |         FlowStageBinding.objects.create( | ||||||
|             target=self.flow, stage=self.stage, order=0, |             target=self.flow, | ||||||
|  |             stage=self.stage, | ||||||
|  |             order=0, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_valid_render(self): |     def test_valid_render(self): | ||||||
|  | |||||||
| @ -23,7 +23,12 @@ def send_mails(stage: EmailStage, *messages: List[EmailMultiAlternatives]): | |||||||
|  |  | ||||||
|  |  | ||||||
| @CELERY_APP.task( | @CELERY_APP.task( | ||||||
|     bind=True, autoretry_for=(SMTPException, ConnectionError,), retry_backoff=True |     bind=True, | ||||||
|  |     autoretry_for=( | ||||||
|  |         SMTPException, | ||||||
|  |         ConnectionError, | ||||||
|  |     ), | ||||||
|  |     retry_backoff=True, | ||||||
| ) | ) | ||||||
| # pylint: disable=unused-argument | # pylint: disable=unused-argument | ||||||
| def _send_mail_task(self, email_stage_pk: int, message: Dict[Any, Any]): | def _send_mail_task(self, email_stage_pk: int, message: Dict[Any, Any]): | ||||||
|  | |||||||
| @ -30,7 +30,9 @@ class TestEmailStage(TestCase): | |||||||
|             slug="test-email", |             slug="test-email", | ||||||
|             designation=FlowDesignation.AUTHENTICATION, |             designation=FlowDesignation.AUTHENTICATION, | ||||||
|         ) |         ) | ||||||
|         self.stage = EmailStage.objects.create(name="email",) |         self.stage = EmailStage.objects.create( | ||||||
|  |             name="email", | ||||||
|  |         ) | ||||||
|         FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) |         FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) | ||||||
|  |  | ||||||
|     def test_rendering(self): |     def test_rendering(self): | ||||||
|  | |||||||
| @ -32,7 +32,9 @@ class TestIdentificationStage(TestCase): | |||||||
|             template=Templates.DEFAULT_LOGIN, |             template=Templates.DEFAULT_LOGIN, | ||||||
|         ) |         ) | ||||||
|         FlowStageBinding.objects.create( |         FlowStageBinding.objects.create( | ||||||
|             target=self.flow, stage=self.stage, order=0, |             target=self.flow, | ||||||
|  |             stage=self.stage, | ||||||
|  |             order=0, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         # OAuthSource for the login view |         # OAuthSource for the login view | ||||||
| @ -92,7 +94,9 @@ class TestIdentificationStage(TestCase): | |||||||
|         self.stage.enrollment_flow = flow |         self.stage.enrollment_flow = flow | ||||||
|         self.stage.save() |         self.stage.save() | ||||||
|         FlowStageBinding.objects.create( |         FlowStageBinding.objects.create( | ||||||
|             target=flow, stage=self.stage, order=0, |             target=flow, | ||||||
|  |             stage=self.stage, | ||||||
|  |             order=0, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         response = self.client.get( |         response = self.client.get( | ||||||
| @ -113,7 +117,9 @@ class TestIdentificationStage(TestCase): | |||||||
|         self.stage.recovery_flow = flow |         self.stage.recovery_flow = flow | ||||||
|         self.stage.save() |         self.stage.save() | ||||||
|         FlowStageBinding.objects.create( |         FlowStageBinding.objects.create( | ||||||
|             target=flow, stage=self.stage, order=0, |             target=flow, | ||||||
|  |             stage=self.stage, | ||||||
|  |             order=0, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         response = self.client.get( |         response = self.client.get( | ||||||
|  | |||||||
| @ -58,7 +58,10 @@ class Migration(migrations.Migration): | |||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|                 ("expires", models.DateTimeField(blank=True, default=None, null=True)), |                 ("expires", models.DateTimeField(blank=True, default=None, null=True)), | ||||||
|                 ("fixed_data", models.JSONField(default=dict),), |                 ( | ||||||
|  |                     "fixed_data", | ||||||
|  |                     models.JSONField(default=dict), | ||||||
|  |                 ), | ||||||
|                 ( |                 ( | ||||||
|                     "created_by", |                     "created_by", | ||||||
|                     models.ForeignKey( |                     models.ForeignKey( | ||||||
|  | |||||||
| @ -41,7 +41,8 @@ class TestUserLoginStage(TestCase): | |||||||
|         self.assertEqual(InvitationStageForm(data).is_valid(), True) |         self.assertEqual(InvitationStageForm(data).is_valid(), True) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     def test_without_invitation_fail(self): |     def test_without_invitation_fail(self): | ||||||
|         """Test without any invitation, continue_flow_without_invitation not set.""" |         """Test without any invitation, continue_flow_without_invitation not set.""" | ||||||
|  | |||||||
| @ -14,7 +14,10 @@ def get_authentication_backends(): | |||||||
|             "django.contrib.auth.backends.ModelBackend", |             "django.contrib.auth.backends.ModelBackend", | ||||||
|             _("passbook-internal Userdatabase"), |             _("passbook-internal Userdatabase"), | ||||||
|         ), |         ), | ||||||
|         ("passbook.sources.ldap.auth.LDAPBackend", _("passbook LDAP"),), |         ( | ||||||
|  |             "passbook.sources.ldap.auth.LDAPBackend", | ||||||
|  |             _("passbook LDAP"), | ||||||
|  |         ), | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -71,7 +71,8 @@ def update_default_stage_change(apps: Apps, schema_editor: BaseDatabaseSchemaEdi | |||||||
|     Flow = apps.get_model("passbook_flows", "Flow") |     Flow = apps.get_model("passbook_flows", "Flow") | ||||||
|  |  | ||||||
|     flow = Flow.objects.get( |     flow = Flow.objects.get( | ||||||
|         slug="default-password-change", designation=FlowDesignation.STAGE_CONFIGURATION, |         slug="default-password-change", | ||||||
|  |         designation=FlowDesignation.STAGE_CONFIGURATION, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     stages = PasswordStage.objects.filter(name="default-authentication-password") |     stages = PasswordStage.objects.filter(name="default-authentication-password") | ||||||
|  | |||||||
| @ -45,7 +45,8 @@ class TestPasswordStage(TestCase): | |||||||
|         FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) |         FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     def test_without_user(self): |     def test_without_user(self): | ||||||
|         """Test without user""" |         """Test without user""" | ||||||
| @ -163,7 +164,8 @@ class TestPasswordStage(TestCase): | |||||||
|         self.assertNotIn(SESSION_KEY_PLAN, self.client.session) |         self.assertNotIn(SESSION_KEY_PLAN, self.client.session) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     @patch( |     @patch( | ||||||
|         "django.contrib.auth.backends.ModelBackend.authenticate", |         "django.contrib.auth.backends.ModelBackend.authenticate", | ||||||
|  | |||||||
| @ -65,7 +65,9 @@ class ListPolicyEngine(PolicyEngine): | |||||||
|  |  | ||||||
|     def _iter_bindings(self) -> Iterator[PolicyBinding]: |     def _iter_bindings(self) -> Iterator[PolicyBinding]: | ||||||
|         for policy in self.__list: |         for policy in self.__list: | ||||||
|             yield PolicyBinding(policy=policy,) |             yield PolicyBinding( | ||||||
|  |                 policy=policy, | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class PromptForm(forms.Form): | class PromptForm(forms.Form): | ||||||
|  | |||||||
| @ -64,7 +64,10 @@ class Migration(migrations.Migration): | |||||||
|                 ("placeholder", models.TextField(blank=True)), |                 ("placeholder", models.TextField(blank=True)), | ||||||
|                 ("order", models.IntegerField(default=0)), |                 ("order", models.IntegerField(default=0)), | ||||||
|             ], |             ], | ||||||
|             options={"verbose_name": "Prompt", "verbose_name_plural": "Prompts",}, |             options={ | ||||||
|  |                 "verbose_name": "Prompt", | ||||||
|  |                 "verbose_name_plural": "Prompts", | ||||||
|  |             }, | ||||||
|         ), |         ), | ||||||
|         migrations.CreateModel( |         migrations.CreateModel( | ||||||
|             name="PromptStage", |             name="PromptStage", | ||||||
|  | |||||||
| @ -33,7 +33,8 @@ class TestUserDeleteStage(TestCase): | |||||||
|         FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) |         FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     def test_no_user(self): |     def test_no_user(self): | ||||||
|         """Test without user set""" |         """Test without user set""" | ||||||
|  | |||||||
| @ -59,7 +59,8 @@ class TestUserLoginStage(TestCase): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     def test_without_user(self): |     def test_without_user(self): | ||||||
|         """Test a plan without any pending user, resulting in a denied""" |         """Test a plan without any pending user, resulting in a denied""" | ||||||
| @ -80,7 +81,8 @@ class TestUserLoginStage(TestCase): | |||||||
|         self.assertIsInstance(response, AccessDeniedResponse) |         self.assertIsInstance(response, AccessDeniedResponse) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     def test_without_backend(self): |     def test_without_backend(self): | ||||||
|         """Test a plan with pending user, without backend, resulting in a denied""" |         """Test a plan with pending user, without backend, resulting in a denied""" | ||||||
|  | |||||||
| @ -13,7 +13,9 @@ class UserLogoutStageView(StageView): | |||||||
|  |  | ||||||
|     def get(self, request: HttpRequest) -> HttpResponse: |     def get(self, request: HttpRequest) -> HttpResponse: | ||||||
|         LOGGER.debug( |         LOGGER.debug( | ||||||
|             "Logged out", user=request.user, flow_slug=self.executor.flow.slug, |             "Logged out", | ||||||
|  |             user=request.user, | ||||||
|  |             flow_slug=self.executor.flow.slug, | ||||||
|         ) |         ) | ||||||
|         logout(self.request) |         logout(self.request) | ||||||
|         return self.executor.stage_ok() |         return self.executor.stage_ok() | ||||||
|  | |||||||
| @ -33,7 +33,8 @@ class UserWriteStageView(StageView): | |||||||
|                 PLAN_CONTEXT_AUTHENTICATION_BACKEND |                 PLAN_CONTEXT_AUTHENTICATION_BACKEND | ||||||
|             ] = class_to_path(ModelBackend) |             ] = class_to_path(ModelBackend) | ||||||
|             LOGGER.debug( |             LOGGER.debug( | ||||||
|                 "Created new user", flow_slug=self.executor.flow.slug, |                 "Created new user", | ||||||
|  |                 flow_slug=self.executor.flow.slug, | ||||||
|             ) |             ) | ||||||
|         user = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] |         user = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] | ||||||
|         # Before we change anything, check if the user is the same as in the request |         # Before we change anything, check if the user is the same as in the request | ||||||
| @ -68,6 +69,8 @@ class UserWriteStageView(StageView): | |||||||
|             update_session_auth_hash(self.request, user) |             update_session_auth_hash(self.request, user) | ||||||
|             LOGGER.debug("Updated session hash", user=user) |             LOGGER.debug("Updated session hash", user=user) | ||||||
|         LOGGER.debug( |         LOGGER.debug( | ||||||
|             "Updated existing user", user=user, flow_slug=self.executor.flow.slug, |             "Updated existing user", | ||||||
|  |             user=user, | ||||||
|  |             flow_slug=self.executor.flow.slug, | ||||||
|         ) |         ) | ||||||
|         return self.executor.stage_ok() |         return self.executor.stage_ok() | ||||||
|  | |||||||
| @ -111,7 +111,8 @@ class TestUserWriteStage(TestCase): | |||||||
|         self.assertEqual(user_qs.first().attributes["some-custom-attribute"], "test") |         self.assertEqual(user_qs.first().attributes["some-custom-attribute"], "test") | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|         "passbook.flows.views.to_stage_response", TO_STAGE_RESPONSE_MOCK, |         "passbook.flows.views.to_stage_response", | ||||||
|  |         TO_STAGE_RESPONSE_MOCK, | ||||||
|     ) |     ) | ||||||
|     def test_without_data(self): |     def test_without_data(self): | ||||||
|         """Test without data results in error""" |         """Test without data results in error""" | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer