flows: update migrations to use update_or_create
This commit is contained in:
		| @ -20,42 +20,38 @@ def create_default_authentication_flow( | |||||||
|     ) |     ) | ||||||
|     db_alias = schema_editor.connection.alias |     db_alias = schema_editor.connection.alias | ||||||
|  |  | ||||||
|     if ( |     identification_stage, _ = IdentificationStage.objects.using( | ||||||
|         Flow.objects.using(db_alias) |         db_alias | ||||||
|         .filter(designation=FlowDesignation.AUTHENTICATION) |     ).update_or_create( | ||||||
|         .exists() |         name="default-authentication-identification", | ||||||
|     ): |         defaults={ | ||||||
|         # Only create default flow when none exist |             "user_fields": [UserFields.E_MAIL, UserFields.USERNAME], | ||||||
|         return |             "template": Templates.DEFAULT_LOGIN, | ||||||
|  |         }, | ||||||
|  |     ) | ||||||
|  |  | ||||||
|     if not IdentificationStage.objects.using(db_alias).exists(): |     password_stage, _ = PasswordStage.objects.using(db_alias).update_or_create( | ||||||
|         IdentificationStage.objects.using(db_alias).create( |         name="default-authentication-password", | ||||||
|             name="identification", |         defaults={"backends": ["django.contrib.auth.backends.ModelBackend"]}, | ||||||
|             user_fields=[UserFields.E_MAIL, UserFields.USERNAME], |     ) | ||||||
|             template=Templates.DEFAULT_LOGIN, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     if not PasswordStage.objects.using(db_alias).exists(): |     login_stage, _ = UserLoginStage.objects.using(db_alias).update_or_create( | ||||||
|         PasswordStage.objects.using(db_alias).create( |         name="default-authentication-login" | ||||||
|             name="password", backends=["django.contrib.auth.backends.ModelBackend"], |     ) | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     if not UserLoginStage.objects.using(db_alias).exists(): |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         UserLoginStage.objects.using(db_alias).create(name="authentication") |  | ||||||
|  |  | ||||||
|     flow = Flow.objects.using(db_alias).create( |  | ||||||
|         name="Welcome to passbook!", |  | ||||||
|         slug="default-authentication-flow", |         slug="default-authentication-flow", | ||||||
|         designation=FlowDesignation.AUTHENTICATION, |         designation=FlowDesignation.AUTHENTICATION, | ||||||
|  |         defaults={"name": "Welcome to passbook!",}, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=IdentificationStage.objects.using(db_alias).first(), order=0, |         flow=flow, stage=identification_stage, defaults={"order": 0,}, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=PasswordStage.objects.using(db_alias).first(), order=1, |         flow=flow, stage=password_stage, defaults={"order": 1,}, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=UserLoginStage.objects.using(db_alias).first(), order=2, |         flow=flow, stage=login_stage, defaults={"order": 2,}, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -67,24 +63,19 @@ def create_default_invalidation_flow( | |||||||
|     UserLogoutStage = apps.get_model("passbook_stages_user_logout", "UserLogoutStage") |     UserLogoutStage = apps.get_model("passbook_stages_user_logout", "UserLogoutStage") | ||||||
|     db_alias = schema_editor.connection.alias |     db_alias = schema_editor.connection.alias | ||||||
|  |  | ||||||
|     if ( |     UserLogoutStage.objects.using(db_alias).update_or_create( | ||||||
|         Flow.objects.using(db_alias) |         name="default-invalidation-logout" | ||||||
|         .filter(designation=FlowDesignation.INVALIDATION) |     ) | ||||||
|         .exists() |  | ||||||
|     ): |  | ||||||
|         # Only create default flow when none exist |  | ||||||
|         return |  | ||||||
|  |  | ||||||
|     if not UserLogoutStage.objects.using(db_alias).exists(): |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         UserLogoutStage.objects.using(db_alias).create(name="logout") |  | ||||||
|  |  | ||||||
|     flow = Flow.objects.using(db_alias).create( |  | ||||||
|         name="default-invalidation-flow", |  | ||||||
|         slug="default-invalidation-flow", |         slug="default-invalidation-flow", | ||||||
|         designation=FlowDesignation.INVALIDATION, |         designation=FlowDesignation.INVALIDATION, | ||||||
|  |         defaults={"name": "Logout",}, | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=UserLogoutStage.objects.using(db_alias).first(), order=0, |         flow=flow, | ||||||
|  |         stage=UserLogoutStage.objects.using(db_alias).first(), | ||||||
|  |         defaults={"order": 0,}, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -34,60 +34,63 @@ def create_default_source_enrollment_flow( | |||||||
|     db_alias = schema_editor.connection.alias |     db_alias = schema_editor.connection.alias | ||||||
|  |  | ||||||
|     # 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).create( |     flow_policy, _ = ExpressionPolicy.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-enrollment-if-sso", expression=FLOW_POLICY_EXPRESSION |         name="default-source-enrollment-if-sso", | ||||||
|  |         defaults={"expression": FLOW_POLICY_EXPRESSION}, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     # This creates a Flow used by sources to enroll users |     # This creates a Flow used by sources to enroll users | ||||||
|     # It makes sure that a username is set, and if not, prompts the user for a Username |     # It makes sure that a username is set, and if not, prompts the user for a Username | ||||||
|     flow = Flow.objects.using(db_alias).create( |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-enrollment", |  | ||||||
|         slug="default-source-enrollment", |         slug="default-source-enrollment", | ||||||
|         designation=FlowDesignation.ENROLLMENT, |         designation=FlowDesignation.ENROLLMENT, | ||||||
|  |         defaults={"name": "Welcome to passbook!",}, | ||||||
|     ) |     ) | ||||||
|     PolicyBinding.objects.using(db_alias).create( |     PolicyBinding.objects.using(db_alias).update_or_create( | ||||||
|         policy=flow_policy, target=flow, order=0 |         policy=flow_policy, target=flow, defaults={"order": 0} | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     # PromptStage to ask user for their username |     # PromptStage to ask user for their username | ||||||
|     prompt_stage = PromptStage.objects.using(db_alias).create( |     prompt_stage, _ = PromptStage.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-enrollment-username-prompt", |         name="default-source-enrollment-username-prompt", | ||||||
|     ) |     ) | ||||||
|     prompt_stage.fields.add( |     prompt, _ = Prompt.objects.using(db_alias).update_or_create( | ||||||
|         Prompt.objects.using(db_alias).create( |         field_key="username", | ||||||
|             field_key="username", |         defaults={ | ||||||
|             label="Username", |             "label": "Username", | ||||||
|             type=FieldTypes.TEXT, |             "type": FieldTypes.TEXT, | ||||||
|             required=True, |             "required": True, | ||||||
|             placeholder="Username", |             "placeholder": "Username", | ||||||
|         ) |         }, | ||||||
|     ) |     ) | ||||||
|  |     prompt_stage.fields.add(prompt) | ||||||
|  |  | ||||||
|     # Policy to only trigger prompt when no username is given |     # Policy to only trigger prompt when no username is given | ||||||
|     prompt_policy = ExpressionPolicy.objects.using(db_alias).create( |     prompt_policy, _ = ExpressionPolicy.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-enrollment-if-username", |         name="default-source-enrollment-if-username", | ||||||
|         expression=PROMPT_POLICY_EXPRESSION, |         defaults={"expression": PROMPT_POLICY_EXPRESSION}, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     # UserWrite stage to create the user, and login stage to log user in |     # UserWrite stage to create the user, and login stage to log user in | ||||||
|     user_write = UserWriteStage.objects.using(db_alias).create( |     user_write, _ = UserWriteStage.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-enrollment-write" |         name="default-source-enrollment-write" | ||||||
|     ) |     ) | ||||||
|     user_login = UserLoginStage.objects.using(db_alias).create( |     user_login, _ = UserLoginStage.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-enrollment-login" |         name="default-source-enrollment-login" | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     binding = FlowStageBinding.objects.using(db_alias).create( |     binding, _ = FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=prompt_stage, order=0 |         flow=flow, stage=prompt_stage, defaults={"order": 0} | ||||||
|     ) |     ) | ||||||
|     PolicyBinding.objects.using(db_alias).create( |     PolicyBinding.objects.using(db_alias).update_or_create( | ||||||
|         policy=prompt_policy, target=binding, order=0 |         policy=prompt_policy, target=binding, defaults={"order": 0} | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     FlowStageBinding.objects.using(db_alias).create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=user_write, order=1 |         flow=flow, stage=user_write, defaults={"order": 1} | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=user_login, order=2 |         flow=flow, stage=user_login, defaults={"order": 2} | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -107,25 +110,26 @@ def create_default_source_authentication_flow( | |||||||
|     db_alias = schema_editor.connection.alias |     db_alias = schema_editor.connection.alias | ||||||
|  |  | ||||||
|     # 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).create( |     flow_policy, _ = ExpressionPolicy.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-authentication-if-sso", expression=FLOW_POLICY_EXPRESSION |         name="default-source-authentication-if-sso", | ||||||
|  |         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).create( |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-authentication", |  | ||||||
|         slug="default-source-authentication", |         slug="default-source-authentication", | ||||||
|         designation=FlowDesignation.AUTHENTICATION, |         designation=FlowDesignation.AUTHENTICATION, | ||||||
|  |         defaults={"name": "Welcome to passbook!",}, | ||||||
|     ) |     ) | ||||||
|     PolicyBinding.objects.using(db_alias).create( |     PolicyBinding.objects.using(db_alias).update_or_create( | ||||||
|         policy=flow_policy, target=flow, order=0 |         policy=flow_policy, target=flow, defaults={"order": 0} | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     user_login = UserLoginStage.objects.using(db_alias).create( |     user_login, _ = UserLoginStage.objects.using(db_alias).update_or_create( | ||||||
|         name="default-source-authentication-login" |         name="default-source-authentication-login" | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).create( |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|         flow=flow, stage=user_login, order=0 |         flow=flow, stage=user_login, defaults={"order": 0} | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor | |||||||
| from passbook.flows.models import FlowDesignation | from passbook.flows.models import FlowDesignation | ||||||
|  |  | ||||||
|  |  | ||||||
| def create_default_provider_authz_flow( | def create_default_provider_authorization_flow( | ||||||
|     apps: Apps, schema_editor: BaseDatabaseSchemaEditor |     apps: Apps, schema_editor: BaseDatabaseSchemaEditor | ||||||
| ): | ): | ||||||
|     Flow = apps.get_model("passbook_flows", "Flow") |     Flow = apps.get_model("passbook_flows", "Flow") | ||||||
| @ -18,22 +18,24 @@ def create_default_provider_authz_flow( | |||||||
|     db_alias = schema_editor.connection.alias |     db_alias = schema_editor.connection.alias | ||||||
|  |  | ||||||
|     # Empty flow for providers where consent is implicitly given |     # Empty flow for providers where consent is implicitly given | ||||||
|     Flow.objects.using(db_alias).create( |     Flow.objects.using(db_alias).update_or_create( | ||||||
|         name="Authorize Application", |  | ||||||
|         slug="default-provider-authorization-implicit-consent", |         slug="default-provider-authorization-implicit-consent", | ||||||
|         designation=FlowDesignation.AUTHORIZATION, |         designation=FlowDesignation.AUTHORIZATION, | ||||||
|  |         defaults={"name": "Authorize Application"}, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     # Flow with consent form to obtain explicit user consent |     # Flow with consent form to obtain explicit user consent | ||||||
|     flow = Flow.objects.using(db_alias).create( |     flow, _ = Flow.objects.using(db_alias).update_or_create( | ||||||
|         name="Authorize Application", |  | ||||||
|         slug="default-provider-authorization-explicit-consent", |         slug="default-provider-authorization-explicit-consent", | ||||||
|         designation=FlowDesignation.AUTHORIZATION, |         designation=FlowDesignation.AUTHORIZATION, | ||||||
|  |         defaults={"name": "Authorize Application"}, | ||||||
|     ) |     ) | ||||||
|     stage = ConsentStage.objects.using(db_alias).create( |     stage, _ = ConsentStage.objects.using(db_alias).update_or_create( | ||||||
|         name="default-provider-authorization-consent" |         name="default-provider-authorization-consent" | ||||||
|     ) |     ) | ||||||
|     FlowStageBinding.objects.using(db_alias).create(flow=flow, stage=stage, order=0) |     FlowStageBinding.objects.using(db_alias).update_or_create( | ||||||
|  |         flow=flow, stage=stage, defaults={"order": 0} | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class Migration(migrations.Migration): | class Migration(migrations.Migration): | ||||||
| @ -43,4 +45,4 @@ class Migration(migrations.Migration): | |||||||
|         ("passbook_stages_consent", "0001_initial"), |         ("passbook_stages_consent", "0001_initial"), | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     operations = [migrations.RunPython(create_default_provider_authz_flow)] |     operations = [migrations.RunPython(create_default_provider_authorization_flow)] | ||||||
|  | |||||||
| @ -153,7 +153,7 @@ class Processor: | |||||||
|         self, request: HttpRequest, flow: Flow, **kwargs |         self, request: HttpRequest, flow: Flow, **kwargs | ||||||
|     ) -> HttpResponse: |     ) -> HttpResponse: | ||||||
|         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, | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ from django.core.validators import validate_email | |||||||
| from django.utils.translation import gettext_lazy as _ | from django.utils.translation import gettext_lazy as _ | ||||||
| from structlog import get_logger | from structlog import get_logger | ||||||
|  |  | ||||||
|  | from passbook.flows.models import Flow, FlowDesignation | ||||||
| from passbook.lib.utils.ui import human_list | from passbook.lib.utils.ui import human_list | ||||||
| from passbook.stages.identification.models import IdentificationStage, UserFields | from passbook.stages.identification.models import IdentificationStage, UserFields | ||||||
|  |  | ||||||
| @ -14,6 +15,15 @@ LOGGER = get_logger() | |||||||
| class IdentificationStageForm(forms.ModelForm): | class IdentificationStageForm(forms.ModelForm): | ||||||
|     """Form to create/edit IdentificationStage instances""" |     """Form to create/edit IdentificationStage instances""" | ||||||
|  |  | ||||||
|  |     def __init__(self, *args, **kwargs): | ||||||
|  |         super().__init__(*args, **kwargs) | ||||||
|  |         self.fields["enrollment_flow"].queryset = Flow.objects.filter( | ||||||
|  |             designation=FlowDesignation.ENROLLMENT | ||||||
|  |         ) | ||||||
|  |         self.fields["recovery_flow"].queryset = Flow.objects.filter( | ||||||
|  |             designation=FlowDesignation.RECOVERY | ||||||
|  |         ) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |  | ||||||
|         model = IdentificationStage |         model = IdentificationStage | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| """Prompt forms""" | """Prompt forms""" | ||||||
| from django import forms | from django import forms | ||||||
|  | from django.contrib.admin.widgets import FilteredSelectMultiple | ||||||
|  | from django.utils.translation import gettext_lazy as _ | ||||||
| from guardian.shortcuts import get_anonymous_user | from guardian.shortcuts import get_anonymous_user | ||||||
|  |  | ||||||
| from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan | from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan | ||||||
| @ -16,6 +18,7 @@ class PromptStageForm(forms.ModelForm): | |||||||
|         fields = ["name", "fields"] |         fields = ["name", "fields"] | ||||||
|         widgets = { |         widgets = { | ||||||
|             "name": forms.TextInput(), |             "name": forms.TextInput(), | ||||||
|  |             "fields": FilteredSelectMultiple(_("prompts"), False), | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer