flows: FlowStageBinding: rename .flow to .target to fix select_subclasses()

This commit is contained in:
Jens Langhammer 2020-07-03 23:34:44 +02:00
parent dd74b73b4f
commit d3b0992456
35 changed files with 119 additions and 81 deletions

View File

@ -105,10 +105,10 @@ class TestFlowsEnroll(SeleniumTestCase):
ident_stage.enrollment_flow = flow
ident_stage.save()
FlowStageBinding.objects.create(flow=flow, stage=first_stage, order=0)
FlowStageBinding.objects.create(flow=flow, stage=second_stage, order=1)
FlowStageBinding.objects.create(flow=flow, stage=user_write, order=2)
FlowStageBinding.objects.create(flow=flow, stage=user_login, order=3)
FlowStageBinding.objects.create(target=flow, stage=first_stage, order=0)
FlowStageBinding.objects.create(target=flow, stage=second_stage, order=1)
FlowStageBinding.objects.create(target=flow, stage=user_write, order=2)
FlowStageBinding.objects.create(target=flow, stage=user_login, order=3)
self.driver.get(self.live_server_url)
self.wait.until(
@ -206,11 +206,11 @@ class TestFlowsEnroll(SeleniumTestCase):
ident_stage.enrollment_flow = flow
ident_stage.save()
FlowStageBinding.objects.create(flow=flow, stage=first_stage, order=0)
FlowStageBinding.objects.create(flow=flow, stage=second_stage, order=1)
FlowStageBinding.objects.create(flow=flow, stage=user_write, order=2)
FlowStageBinding.objects.create(flow=flow, stage=email_stage, order=3)
FlowStageBinding.objects.create(flow=flow, stage=user_login, order=4)
FlowStageBinding.objects.create(target=flow, stage=first_stage, order=0)
FlowStageBinding.objects.create(target=flow, stage=second_stage, order=1)
FlowStageBinding.objects.create(target=flow, stage=user_write, order=2)
FlowStageBinding.objects.create(target=flow, stage=email_stage, order=3)
FlowStageBinding.objects.create(target=flow, stage=user_login, order=4)
self.driver.get(self.live_server_url)
self.driver.find_element(By.CSS_SELECTOR, "[role=enroll]").click()

View File

@ -35,7 +35,7 @@
</tr>
</thead>
<tbody role="rowgroup">
{% regroup object_list by flow as grouped_bindings %}
{% regroup object_list by target as grouped_bindings %}
{% for flow in grouped_bindings %}
<tr role="role">
<td>
@ -56,9 +56,9 @@
</td>
<th role="columnheader">
<div>
<div>{{ binding.flow.slug }}</div>
<div>{{ binding.target.slug }}</div>
<small>
{{ binding.flow.name }}
{{ binding.target.name }}
</small>
</div>
</th>

View File

@ -21,7 +21,7 @@ class StageBindingListView(LoginRequiredMixin, PermissionListMixin, ListView):
model = FlowStageBinding
permission_required = "passbook_flows.view_flowstagebinding"
paginate_by = 10
ordering = ["flow", "order"]
ordering = ["target", "order"]
template_name = "administration/stage_binding/list.html"

View File

@ -27,7 +27,7 @@ class FlowStageBindingSerializer(ModelSerializer):
class Meta:
model = FlowStageBinding
fields = ["pk", "flow", "stage", "re_evaluate_policies", "order", "policies"]
fields = ["pk", "target", "stage", "re_evaluate_policies", "order", "policies"]
class FlowStageBindingViewSet(ModelViewSet):

View File

@ -39,7 +39,7 @@ class FlowStageBindingForm(forms.ModelForm):
model = FlowStageBinding
fields = [
"flow",
"target",
"stage",
"re_evaluate_policies",
"order",

View File

@ -6,7 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_flows", "0002_default_flows"),
("passbook_flows", "0001_initial"),
]
operations = [

View File

@ -6,7 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_flows", "0005_provider_flows"),
("passbook_flows", "0003_auto_20200523_1133"),
]
operations = [

View File

@ -0,0 +1,42 @@
# Generated by Django 3.0.7 on 2020-07-03 20:59
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_policies", "0002_auto_20200528_1647"),
("passbook_flows", "0006_auto_20200629_0857"),
]
operations = [
migrations.AlterModelOptions(
name="flowstagebinding",
options={
"ordering": ["order", "target"],
"verbose_name": "Flow Stage Binding",
"verbose_name_plural": "Flow Stage Bindings",
},
),
migrations.RenameField(
model_name="flowstagebinding", old_name="flow", new_name="target",
),
migrations.RenameField(
model_name="flow", old_name="pbm", new_name="policybindingmodel_ptr",
),
migrations.AlterUniqueTogether(
name="flowstagebinding", unique_together={("target", "stage", "order")},
),
migrations.AlterField(
model_name="flow",
name="policybindingmodel_ptr",
field=models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
to="passbook_policies.PolicyBindingModel",
),
),
]

View File

@ -45,13 +45,13 @@ def create_default_authentication_flow(
defaults={"name": "Welcome to passbook!",},
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=identification_stage, defaults={"order": 0,},
target=flow, stage=identification_stage, defaults={"order": 0,},
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=password_stage, defaults={"order": 1,},
target=flow, stage=password_stage, defaults={"order": 1,},
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=login_stage, defaults={"order": 2,},
target=flow, stage=login_stage, defaults={"order": 2,},
)
@ -73,7 +73,7 @@ def create_default_invalidation_flow(
defaults={"name": "Logout",},
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow,
target=flow,
stage=UserLogoutStage.objects.using(db_alias).first(),
defaults={"order": 0,},
)
@ -82,7 +82,7 @@ def create_default_invalidation_flow(
class Migration(migrations.Migration):
dependencies = [
("passbook_flows", "0001_initial"),
("passbook_flows", "0007_auto_20200703_2059"),
("passbook_stages_user_login", "0001_initial"),
("passbook_stages_user_logout", "0001_initial"),
("passbook_stages_password", "0001_initial"),

View File

@ -80,17 +80,17 @@ def create_default_source_enrollment_flow(
)
binding, _ = FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=prompt_stage, defaults={"order": 0}
target=flow, stage=prompt_stage, defaults={"order": 0}
)
PolicyBinding.objects.using(db_alias).update_or_create(
policy=prompt_policy, target=binding, defaults={"order": 0}
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=user_write, defaults={"order": 1}
target=flow, stage=user_write, defaults={"order": 1}
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=user_login, defaults={"order": 2}
target=flow, stage=user_login, defaults={"order": 2}
)
@ -129,14 +129,14 @@ def create_default_source_authentication_flow(
name="default-source-authentication-login"
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=user_login, defaults={"order": 0}
target=flow, stage=user_login, defaults={"order": 0}
)
class Migration(migrations.Migration):
dependencies = [
("passbook_flows", "0003_auto_20200523_1133"),
("passbook_flows", "0008_default_flows"),
("passbook_policies", "0001_initial"),
("passbook_policies_expression", "0001_initial"),
("passbook_stages_prompt", "0001_initial"),

View File

@ -34,14 +34,14 @@ def create_default_provider_authorization_flow(
name="default-provider-authorization-consent"
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=stage, defaults={"order": 0}
target=flow, stage=stage, defaults={"order": 0}
)
class Migration(migrations.Migration):
dependencies = [
("passbook_flows", "0004_source_flows"),
("passbook_flows", "0009_source_flows"),
("passbook_stages_consent", "0001_initial"),
]

View File

@ -79,10 +79,6 @@ class Flow(PolicyBindingModel):
stages = models.ManyToManyField(Stage, through="FlowStageBinding", blank=True)
pbm = models.OneToOneField(
PolicyBindingModel, parent_link=True, on_delete=models.CASCADE, related_name="+"
)
@staticmethod
def with_policy(request: HttpRequest, **flow_filter) -> Optional["Flow"]:
"""Get a Flow by `**flow_filter` and check if the request from `request` can access it."""
@ -123,7 +119,7 @@ class FlowStageBinding(PolicyBindingModel):
fsb_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
flow = models.ForeignKey("Flow", on_delete=models.CASCADE)
target = models.ForeignKey("Flow", on_delete=models.CASCADE)
stage = models.ForeignKey(Stage, on_delete=models.CASCADE)
re_evaluate_policies = models.BooleanField(
@ -138,12 +134,12 @@ class FlowStageBinding(PolicyBindingModel):
objects = InheritanceManager()
def __str__(self) -> str:
return f"Flow Stage Binding #{self.order} {self.flow} -> {self.stage}"
return f"Flow Binding {self.target} -> {self.stage}"
class Meta:
ordering = ["order", "flow"]
ordering = ["order", "target"]
verbose_name = _("Flow Stage Binding")
verbose_name_plural = _("Flow Stage Bindings")
unique_together = (("flow", "stage", "order"),)
unique_together = (("target", "stage", "order"),)

View File

@ -146,7 +146,7 @@ class FlowPlanner:
.select_related()
):
binding: FlowStageBinding = stage.flowstagebinding_set.get(
flow__pk=self.flow.pk
target__pk=self.flow.pk
)
engine = PolicyEngine(binding, user, request)
engine.request.context = plan.context

View File

@ -25,13 +25,13 @@ def invalidate_flow_cache(sender, instance, **_):
total = delete_cache_prefix(f"{cache_key(instance)}*")
LOGGER.debug("Invalidating Flow cache", flow=instance, len=total)
if isinstance(instance, FlowStageBinding):
total = delete_cache_prefix(f"{cache_key(instance.flow)}*")
total = delete_cache_prefix(f"{cache_key(instance.target)}*")
LOGGER.debug(
"Invalidating Flow cache from FlowStageBinding", binding=instance, len=total
)
if isinstance(instance, Stage):
total = 0
for binding in FlowStageBinding.objects.filter(stage=instance):
prefix = cache_key(binding.flow)
prefix = cache_key(binding.target)
total += delete_cache_prefix(f"{prefix}*")
LOGGER.debug("Invalidating Flow cache from Stage", stage=instance, len=total)

View File

@ -73,7 +73,7 @@ class TestFlowPlanner(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy"), order=0
target=flow, stage=DummyStage.objects.create(name="dummy"), order=0
)
request = self.request_factory.get(
reverse("passbook_flows:flow-executor", kwargs={"flow_slug": flow.slug}),
@ -97,7 +97,7 @@ class TestFlowPlanner(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy"), order=0
target=flow, stage=DummyStage.objects.create(name="dummy"), order=0
)
user = User.objects.create(username="test-user")
@ -119,7 +119,7 @@ class TestFlowPlanner(TestCase):
)
FlowStageBinding.objects.create(
flow=flow,
target=flow,
stage=DummyStage.objects.create(name="dummy1"),
order=0,
re_evaluate_policies=True,
@ -145,10 +145,10 @@ class TestFlowPlanner(TestCase):
false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
)
binding2 = FlowStageBinding.objects.create(
flow=flow,
target=flow,
stage=DummyStage.objects.create(name="dummy2"),
order=1,
re_evaluate_policies=True,

View File

@ -107,10 +107,10 @@ class TestFlowExecutor(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
)
FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy2"), order=1
target=flow, stage=DummyStage.objects.create(name="dummy2"), order=1
)
exec_url = reverse(
@ -143,10 +143,10 @@ class TestFlowExecutor(TestCase):
false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
)
binding2 = FlowStageBinding.objects.create(
flow=flow,
target=flow,
stage=DummyStage.objects.create(name="dummy2"),
order=1,
re_evaluate_policies=True,
@ -194,16 +194,16 @@ class TestFlowExecutor(TestCase):
false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
)
binding2 = FlowStageBinding.objects.create(
flow=flow,
target=flow,
stage=DummyStage.objects.create(name="dummy2"),
order=1,
re_evaluate_policies=True,
)
binding3 = FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy3"), order=2
target=flow, stage=DummyStage.objects.create(name="dummy3"), order=2
)
PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0)
@ -261,22 +261,22 @@ class TestFlowExecutor(TestCase):
false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2)
binding = FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
)
binding2 = FlowStageBinding.objects.create(
flow=flow,
target=flow,
stage=DummyStage.objects.create(name="dummy2"),
order=1,
re_evaluate_policies=True,
)
binding3 = FlowStageBinding.objects.create(
flow=flow,
target=flow,
stage=DummyStage.objects.create(name="dummy3"),
order=2,
re_evaluate_policies=True,
)
binding4 = FlowStageBinding.objects.create(
flow=flow, stage=DummyStage.objects.create(name="dummy4"), order=2
target=flow, stage=DummyStage.objects.create(name="dummy4"), order=2
)
PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0)

View File

@ -32,7 +32,7 @@ class TestCaptchaStage(TestCase):
public_key=settings.RECAPTCHA_PUBLIC_KEY,
private_key=settings.RECAPTCHA_PRIVATE_KEY,
)
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_valid(self):
"""Test valid captcha"""

View File

@ -9,7 +9,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
("passbook_flows", "0004_source_flows"),
("passbook_flows", "0007_auto_20200703_2059"),
]
operations = [

View File

@ -27,7 +27,7 @@ class TestConsentStage(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
self.stage = ConsentStage.objects.create(name="consent",)
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_valid(self):
"""Test valid consent"""

View File

@ -24,7 +24,7 @@ class TestDummyStage(TestCase):
)
self.stage = DummyStage.objects.create(name="dummy",)
FlowStageBinding.objects.create(
flow=self.flow, stage=self.stage, order=0,
target=self.flow, stage=self.stage, order=0,
)
def test_valid_render(self):

View File

@ -31,7 +31,7 @@ class TestEmailStage(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
self.stage = EmailStage.objects.create(name="email",)
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_rendering(self):
"""Test with pending user"""

View File

@ -7,7 +7,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_flows", "0002_default_flows"),
("passbook_flows", "0003_auto_20200523_1133"),
("passbook_stages_identification", "0001_initial"),
]

View File

@ -7,7 +7,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_flows", "0005_provider_flows"),
("passbook_flows", "0007_auto_20200703_2059"),
("passbook_stages_identification", "0002_auto_20200530_2204"),
]

View File

@ -32,7 +32,7 @@ class TestIdentificationStage(TestCase):
template=Templates.DEFAULT_LOGIN,
)
FlowStageBinding.objects.create(
flow=self.flow, stage=self.stage, order=0,
target=self.flow, stage=self.stage, order=0,
)
# OAuthSource for the login view
@ -92,7 +92,7 @@ class TestIdentificationStage(TestCase):
self.stage.enrollment_flow = flow
self.stage.save()
FlowStageBinding.objects.create(
flow=flow, stage=self.stage, order=0,
target=flow, stage=self.stage, order=0,
)
response = self.client.get(
@ -113,7 +113,7 @@ class TestIdentificationStage(TestCase):
self.stage.recovery_flow = flow
self.stage.save()
FlowStageBinding.objects.create(
flow=flow, stage=self.stage, order=0,
target=flow, stage=self.stage, order=0,
)
response = self.client.get(

View File

@ -31,7 +31,7 @@ class TestUserLoginStage(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
self.stage = InvitationStage.objects.create(name="invitation")
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_form(self):
"""Test Form"""

View File

@ -9,7 +9,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
("passbook_flows", "0005_provider_flows"),
("passbook_flows", "0007_auto_20200703_2059"),
]
operations = [

View File

@ -9,7 +9,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
("passbook_flows", "0005_provider_flows"),
("passbook_flows", "0007_auto_20200703_2059"),
]
operations = [

View File

@ -75,10 +75,10 @@ def create_default_password_change(apps: Apps, schema_editor: BaseDatabaseSchema
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=prompt_stage, defaults={"order": 0}
target=flow, stage=prompt_stage, defaults={"order": 0}
)
FlowStageBinding.objects.using(db_alias).update_or_create(
flow=flow, stage=user_write, defaults={"order": 1}
target=flow, stage=user_write, defaults={"order": 1}
)

View File

@ -40,7 +40,7 @@ class TestPasswordStage(TestCase):
self.stage = PasswordStage.objects.create(
name="password", backends=["django.contrib.auth.backends.ModelBackend"]
)
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_without_user(self):
"""Test without user"""

View File

@ -93,7 +93,7 @@ class TestPromptStage(TestCase):
hidden_prompt.field_key: hidden_prompt.placeholder,
}
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_render(self):
"""Test render of form, check if all prompts are rendered correctly"""

View File

@ -26,7 +26,7 @@ class TestUserDeleteStage(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
self.stage = UserDeleteStage.objects.create(name="delete")
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_no_user(self):
"""Test without user set"""

View File

@ -27,7 +27,7 @@ class TestUserLoginStage(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
self.stage = UserLoginStage.objects.create(name="login")
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_valid_password(self):
"""Test with a valid pending user and backend"""

View File

@ -27,7 +27,7 @@ class TestUserLogoutStage(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
self.stage = UserLogoutStage.objects.create(name="logout")
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_valid_password(self):
"""Test with a valid pending user and backend"""

View File

@ -29,7 +29,7 @@ class TestUserWriteStage(TestCase):
designation=FlowDesignation.AUTHENTICATION,
)
self.stage = UserWriteStage.objects.create(name="write")
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
def test_user_create(self):
"""Test creation of user"""

View File

@ -502,7 +502,7 @@ paths:
description: ''
required: false
type: string
- name: flow
- name: target
in: query
description: ''
required: false
@ -5617,7 +5617,7 @@ definitions:
maxLength: 254
FlowStageBinding:
required:
- flow
- target
- stage
- order
type: object
@ -5627,8 +5627,8 @@ definitions:
type: string
format: uuid
readOnly: true
flow:
title: Flow
target:
title: Target
type: string
format: uuid
stage: