diff --git a/README.md b/README.md index 731732beb..3ae6fb28a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# passbook +passbook logopassbook ![](https://img.shields.io/github/workflow/status/beryju/passbook/passbook-ci?style=flat-square) ![](https://img.shields.io/docker/pulls/beryju/passbook.svg?style=flat-square) diff --git a/docs/factors.md b/docs/factors.md deleted file mode 100644 index 8e55930c4..000000000 --- a/docs/factors.md +++ /dev/null @@ -1,23 +0,0 @@ -# Factors - -A factor represents a single authenticating factor for a user. Common examples of this would be a password or an OTP. These factors can be combined in any order, and can be dynamically enabled using policies. - -## Password Factor - -This is the standard Password Factor. It allows you to select which Backend the password is checked with. here you can also specify which Policies are used to check the password. You can also specify which Factors a User has to pass to recover their account. - -## Dummy Factor - -This factor waits a random amount of time. Mostly used for debugging. - -## E-Mail Factor - -This factor is mostly for recovery, and used in conjunction with the Password Factor. - -## OTP Factor - -This is your typical One-Time Password implementation, compatible with Authy and Google Authenticator. You can enfore this Factor so that every user has to configure it, or leave it optional. - -## Captcha Factor - -While this factor doesn't really authenticate a user, it is part of the Authentication Flow. passbook uses Google's reCaptcha implementation. diff --git a/docs/flow/flows.md b/docs/flow/flows.md new file mode 100644 index 000000000..954eee93d --- /dev/null +++ b/docs/flow/flows.md @@ -0,0 +1,45 @@ +# Flows + +Flows are a method of describing a sequence of stages. A stage represents a single verification or logic step. They are used to authenticate users, enroll them, and more. + +Upon Flow execution, a plan is generated, which contains all stages. This means upon execution, all attached policies are evaluated. This behaviour can be altered by enabling the `Re-evaluate Policies` option on the binding. + +To determine which flow is linked, passbook searches all Flows with the required designation and chooses the first instance the current user has access to. + +## Permissions + +Flows can have policies assigned to them, which determines if the current user is allowed to see and use this flow. + +## Designation + +Flows are designated for a single Purpose. This designation changes when a Flow is used. The following designations are available: + +### Authentication + +This is designates a flow to be used for authentication. + +The authentication flow should always contain a `user_login` stage, which attaches the staged user to the current session. + +### Invalidation + +This designates a flow to be used for the invalidation of a session. + +This stage should always contain a `user_logout` stage, which resets the current session. + +### Enrollment + +This designates a flow for enrollment. This flow can contain any amount of Prompt stages, E-Mail verification or Captchas. At the end to create the user, you can use the `user_write` stage, which either updates the currently staged user, or if none exists, creates a new one. + +### Unenrollment + +This designates a flow for unenrollment. This flow can contain any amount of verification, like `email` or captcha. To finally delete the account, use the `user_delete` stage. + +### Recovery + +This designates a flow for recovery. This flow normally contains an `identification` stage to find the user. Then it can contain any amount of verification, like `email` or captcha. +Afterwards, use the `prompt` stage to ask the user for a new password and use `user_write` to update the password. + +### Change Password + +This designates a flow for password changing. This flow can contain any amount of verification, like `email` or captcha. +Afterwards, use the `prompt` stage to ask the user for a new password and use `user_write` to update the password. diff --git a/docs/flow/stages/captcha/captcha-admin.png b/docs/flow/stages/captcha/captcha-admin.png new file mode 100644 index 000000000..f33a52972 Binary files /dev/null and b/docs/flow/stages/captcha/captcha-admin.png differ diff --git a/docs/flow/stages/captcha/captcha.md b/docs/flow/stages/captcha/captcha.md new file mode 100644 index 000000000..f9d730013 --- /dev/null +++ b/docs/flow/stages/captcha/captcha.md @@ -0,0 +1,7 @@ +# Captcha stage + +This stage adds a form of verification using [Google's ReCaptcha](https://www.google.com/recaptcha/intro/v3.html). + +This stage has two required fields. You need a Public and a Private key, both of which you can acquire at https://www.google.com/recaptcha/admin. + +![](captcha-admin.png) diff --git a/docs/flow/stages/dummy/dummy.md b/docs/flow/stages/dummy/dummy.md new file mode 100644 index 000000000..2321803cb --- /dev/null +++ b/docs/flow/stages/dummy/dummy.md @@ -0,0 +1,5 @@ +# Dummy stage + +This stage is used for development, and has no function. It presents the User with a form, that requires a single confirmation. + +![](dummy.png) diff --git a/docs/flow/stages/dummy/dummy.png b/docs/flow/stages/dummy/dummy.png new file mode 100644 index 000000000..7040e66cb Binary files /dev/null and b/docs/flow/stages/dummy/dummy.png differ diff --git a/docs/installation/install.md b/docs/installation/install.md deleted file mode 100755 index ebd88c387..000000000 --- a/docs/installation/install.md +++ /dev/null @@ -1,6 +0,0 @@ -# Installation - -There are two supported ways to install passbook: - -- [docker-compose](docker-compose.md) for test- or small productive setups -- [Kubernetes](./kubernetes.md) for larger Productive setups diff --git a/mkdocs.yml b/mkdocs.yml index cb31d86a1..cc2d5e525 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,16 +5,28 @@ copyright: "Copyright © 2019 - 2020 BeryJu.org" nav: - Home: index.md - Installation: - - Installation: installation/install.md - docker-compose: installation/docker-compose.md - Kubernetes: installation/kubernetes.md + - Flows: flow/flows.md + - Stages: + - Captcha Stage: flow/stages/captcha/captcha.md + - Dummy Stage: flow/stages/dummy/dummy.md + - E-Mail Stage: flow/stages/email/email.md + - Identification Stage: flow/stages/identification.md + - Invitation Stage: flow/stages/invitation.md + - OTP Stage: flow/stages/otp.md + - Password Stage: flow/stages/password.md + - Prompt Stage: flow/stages/prompt.md + - User Delete Stage: flow/stages/user_delete.md + - User Login Stage: flow/stages/user_login.md + - User Logout Stage: flow/stages/user_logout.md + - User Write Stage: flow/stages/user_write.md - Sources: sources.md - Providers: providers.md - Property Mappings: - Overview: property-mappings/index.md - Reference: - User Object: property-mappings/reference/user-object.md - - Factors: factors.md - Policies: - Overview: policies/index.md - Expression: policies/expression/index.md diff --git a/passbook/flows/forms.py b/passbook/flows/forms.py index 6f695050f..8c8d5bdc6 100644 --- a/passbook/flows/forms.py +++ b/passbook/flows/forms.py @@ -44,6 +44,9 @@ class FlowStageBindingForm(forms.ModelForm): "re_evaluate_policies", "order", ] + labels = { + "re_evaluate_policies": _("Re-evaluate Policies"), + } widgets = { "name": forms.TextInput(), } diff --git a/passbook/stages/email/forms.py b/passbook/stages/email/forms.py index e158743e1..7b65d7dad 100644 --- a/passbook/stages/email/forms.py +++ b/passbook/stages/email/forms.py @@ -34,6 +34,7 @@ class EmailStageForm(forms.ModelForm): widgets = { "name": forms.TextInput(), "host": forms.TextInput(), + "subject": forms.TextInput(), "username": forms.TextInput(), "password": forms.TextInput(), } diff --git a/passbook/stages/email/stage.py b/passbook/stages/email/stage.py index e0dce139b..705cc00e9 100644 --- a/passbook/stages/email/stage.py +++ b/passbook/stages/email/stage.py @@ -46,6 +46,9 @@ class EmailStageView(FormView, StageView): return super().get(request, *args, **kwargs) def form_invalid(self, form: EmailStageSendForm) -> HttpResponse: + if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: + messages.error(self.request, _("No pending user.")) + return super().form_invalid(form) pending_user = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] valid_delta = timedelta( minutes=self.executor.current_stage.token_expiry + 1 diff --git a/passbook/static/static/passbook/brand_inverted.svg b/passbook/static/static/passbook/brand_inverted.svg new file mode 100644 index 000000000..86711c6bb --- /dev/null +++ b/passbook/static/static/passbook/brand_inverted.svg @@ -0,0 +1,2 @@ +