Skip to content

Add first run functionality#4137

Open
LukasMalyszko wants to merge 13 commits intomasterfrom
first-run
Open

Add first run functionality#4137
LukasMalyszko wants to merge 13 commits intomasterfrom
first-run

Conversation

@LukasMalyszko
Copy link
Collaborator

@LukasMalyszko LukasMalyszko commented Jan 21, 2026

  • Include Pwpush::FirstRun module in ApplicationController.
  • Add boot_code attribute to User model.
  • Define routes for first run actions in users routes file.

Description

  • Added a first-run setup flow that forces a boot-code–gated admin signup when no users exist.
  • Introduced a boot code service stored in tmp and wired /first_run routes under Devise scope.
  • Added controller and system tests for boot code validity, short password, and invalid email cases.
  • Added a virtual boot_code attribute on User and a first-run signup view.

Related Issue

https://github.com/apnotic/pwpush-pro/issues/1456

Type of Change

  • 📚 Examples / docs / tutorials / dependencies update
  • 🔧 Bug fix (non-breaking change which fixes an issue)
  • 🥂 Improvement (non-breaking change which improves an existing feature)
  • 🚀 New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 🔐 Security fix

Checklist

  • I've written tests (if applicable) for all new methods and classes that I created. (rake test)
  • I've added documentation as necessary so users can easily use and understand this feature/fix.

- Include Pwpush::FirstRun module in ApplicationController.
- Add boot_code attribute to User model.
- Define routes for first run actions in users routes file.
- Store original settings for InvisibleCaptcha timestamp and spinner.
- Disable InvisibleCaptcha during test setup to ensure proper functionality.
- Restore original settings after tests to maintain state.
- Update form validation handling to disable native HTML5 validation for server-side error display.
- Adjust selector for invisible captcha input to improve test accuracy.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a first-run setup flow that requires a boot code to create the initial administrator account when no users exist in the system. The boot code is generated and stored in a temporary file, displayed in application logs, and must be entered during the first user registration to prevent unauthorized initial access.

Changes:

  • Added FirstRunBootCode service module to generate, validate, and manage boot codes stored in the tmp directory
  • Created Users::FirstRunsController for handling first-run registration with boot code validation
  • Added Pwpush::FirstRun concern to redirect all requests to first-run setup when no users exist
  • Implemented comprehensive controller and system tests for various first-run scenarios

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
app/services/first_run_boot_code.rb Service module for generating and validating boot codes with secure comparison
app/models/user.rb Added virtual boot_code attribute for first-run registration
app/controllers/users/first_runs_controller.rb Controller handling boot-code-gated admin account creation
app/controllers/concerns/pwpush/first_run.rb Concern that redirects to first-run setup when no users exist
app/controllers/application_controller.rb Includes the FirstRun concern to apply redirect logic globally
config/routes/users.rb Added routes for first-run GET and POST actions
app/views/users/first_runs/new.html.erb First-run signup form with boot code, email, and password fields
test/controllers/first_run_controller_test.rb Controller tests for redirect logic, boot code validation, and user creation
test/system/first_run_test.rb System tests for end-to-end first-run scenarios including validation errors

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Update first run boot code generation to ensure directory creation and handle existing files.
- Improve logging for first run setup requirements, clarifying boot code expiration conditions.
- Add new action in Users::FirstRunsController to build resource and set minimum password length.
- Refactor form labels in new user registration view for consistency and clarity.
- Clear user data in tests to maintain isolation and prevent interference between test cases.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 12 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Introduce boot_code_logged attribute to prevent repeated logging during first run setup.
- Update first run boot code file path to use the storage directory.
- Refactor boot code handling to support both plain and legacy formats.
- Implement transaction handling in Users::FirstRunsController to avoid race conditions during user creation.
- Adjust test cases to remove unnecessary parameters for cleaner requests.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Update Users::FirstRunsController to clear boot code after successful user sign-up.
- Enhance error handling in FirstRunBootCode to manage file read exceptions.
- Add password confirmation field to user registration form for improved security.
- Adjust tests to verify boot code file existence and user session integrity.
… file existence checks

- Add password confirmation field to user registration tests for enhanced security.
- Verify existence of the boot code file after code generation in tests.
- Ensure consistency in test cases by including password confirmation for various scenarios.
@LukasMalyszko
Copy link
Collaborator Author

image

- Replace I18n._ with _ for string translations in Users::FirstRunsController and new user registration view.
- Ensure consistency in translation method usage across the application.
- Simplify boot code logging in FirstRun module to only log when accessing the first run path.
- Update Users::FirstRunsController to enable timestamp and spinner for InvisibleCaptcha in production environment.
- Remove unnecessary boot code existence checks to streamline first run setup process.
@LukasMalyszko LukasMalyszko marked this pull request as ready for review January 22, 2026 07:51
@LukasMalyszko
Copy link
Collaborator Author

@pglombardo, @ozovalihasan - Please review PR

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Remove unnecessary boot_code_logged attribute from Pwpush::FirstRun module.
- Update transaction handling in Users::FirstRunsController to improve clarity and prevent race conditions.
- Simplify file writing in FirstRunBootCode by removing redundant conversion to string.
- Enhance code readability by adjusting presence checks in boot code reading logic.
Copy link
Collaborator

@ozovalihasan ozovalihasan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LukasMalyszko Great work 👍 I added a few suggestions. Please check them, and feel free to skip any of them.

unless Rails.env.test?
if request.path.start_with?(first_run_path)
boot_code = FirstRunBootCode.code
Rails.logger.info <<~MESSAGE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to log it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this the clue, to take boot code from logs.

Comment on lines 52 to 55
def configure_permitted_parameters
super
devise_parameter_sanitizer.permit(:sign_up, keys: [:boot_code])
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't see any reason to permit to :boot_code. I think we can remove this method. @LukasMalyszko what do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is not necessary for funcionality, but it was removinng some Devise warnings. But I can't now find what it was. I'll remove it.

Comment on lines 57 to 63
# Override to exclude boot_code from params passed to User model
def sign_up_params
params = super
return params unless params

params.except(:boot_code)
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I don't see any reason to use this method. Can you check it? If it is not necessary, we can remove it?

Copy link
Collaborator Author

@LukasMalyszko LukasMalyszko Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove too

Comment on lines 23 to 28
result = User.transaction do
# Re-check within a transaction to avoid race conditions with prevent_repeats
if User.exists?
redirect_to root_url
:redirected
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this transaction is necessary. Can you check first run implementation of Pro version? I think it is better to follow the approach of Pro.

Copy link
Collaborator Author

@LukasMalyszko LukasMalyszko Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transaction is not necessary too. It was sugested by Copilot to avoid race conditions, but as you are mention we should keep same as Pro has. So I'll remove transaction.

<% title(_('First Run Setup')) %>
<h2 class='my-3'><%= _('First Run Setup') %></h2>

<%= form_for(resource, as: resource_name, url: first_run_path) do |f| %>
Copy link
Collaborator

@ozovalihasan ozovalihasan Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<%= form_for(resource, as: resource_name, url: first_run_path) do |f| %>
<%= form_with(model: resource, as: resource_name, url: first_run_path) do |f| %>

If we update this line as suggested, we don't need the following line;

attr_accessor :boot_code

So, I prefer to update it as suggested and remove the line from user model. @LukasMalyszko What do you think? Should we update it as suggested.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, simpler is better. Good catch. Thanks

…saction block and streamline resource saving process. Update form helper in new.html.erb to use form_with for better compatibility. Remove unused boot_code attribute from User model.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants