first_boot: Use session to verify first boot welcome step

Closes: #2074

sunil's changes:

- Ensure that secret is not asked for a second time after creating admin user
and logging in (this happens due to discarding of old session and creating new
one).

- Ensure that this logic is not applied to user using FreedomBox images who are
not required to input the first wizard secret.

- Change the name of the session variable for readability.

Tests performed:

- Without the patch, start first boot wizard on the first browser on a
  FreedomBox image (or run the file `base64 < /dev/urandom | head -c 16 | sed -e
  's+$+\n+' > /var/lib/plinth/firstboot-wizard-secret`). Finish the welcome step
  with first wizard secret. Then open a second browser or from another computer
  visit the web interface. The first wizard secret is not asked and user can
  create an admin account.

- Repeat with fresh image again with the patch. To mimic fresh image, one may
  run `sudo rm -f /var/lib/plinth/plinth.sqlite3` and `echo "password" | | sudo
  /freedombox/actions/users remove-user tester`. This time when a different
  browser other than the one that provided the first wizard secret try to access
  the account creation page, a redirection will occur to welcome page. Providing
  the first wizard secret takes the user to account creation page.

- Accessing network first wizard page or internal pages on second browser also
  takes one back to the welcome page.

- Accessing help pages from second browser requires login.

- Accessing account login page from second browser is allowed. After creating
  the account from first browser, second browser can login and continue the
  wizard.

- Clearing cookies in the middle of the wizard takes the user back to welcome
  page.

- Clear cookies in the middles of the wizard. Visit the wizard, go to first boot
  welcome page. Provide secret and the wizard will continue where it was left
  off.

- Clear cookies in the middles of the wizard. Visit the wizard, go to first boot
  welcome page. Access login page, login as admin. Then first wizard secret is
  not asked. First wizard can be continued.

- On a fresh image, simply complete the first wizard. No change to earlier flow
  is noticed. First wizard secret is only asked once at the beginning.

- On a fresh image, remove the file /var/lib/plinth/firstboot-wizard-secret.
  First wizard can be completed without the secret.

[sunil: improvements to original patch by Kirill Schmidt]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Tested-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
Kirill Schmidt 2021-03-26 22:17:03 +01:00 committed by James Valleroy
parent 23757db9ec
commit 7e599958fe
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
2 changed files with 11 additions and 0 deletions

View File

@ -12,6 +12,7 @@ from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
from plinth.modules import first_boot
from plinth.utils import is_user_admin
LOGGER = logging.getLogger(__name__)
@ -35,6 +36,15 @@ class FirstBootMiddleware(MiddlewareMixin):
firstboot_completed = first_boot.is_completed()
user_requests_firstboot = first_boot.is_firstboot_url(request.path)
# If user requests a step other than the welcome step, verify that they
# indeed completed the secret verification by looking at the session.
if (user_requests_firstboot and
not request.path.startswith(reverse('first_boot:welcome')) and
first_boot.firstboot_wizard_secret_exists() and
not request.session.get('firstboot_secret_provided', False) and
not is_user_admin(request)):
return HttpResponseRedirect(reverse('first_boot:welcome'))
# Redirect to first boot if requesting normal page and first
# boot is not complete.
if not firstboot_completed and not user_requests_firstboot:

View File

@ -18,6 +18,7 @@ class WelcomeView(FormView):
def form_valid(self, form):
"""If form is valid, mark this step as done and move to next step."""
self.request.session['firstboot_secret_provided'] = True
first_boot.mark_step_done('firstboot_welcome')
return http.HttpResponseRedirect(reverse(first_boot.next_step()))