Prompt for first-run setup when no accounts exist

This commit is contained in:
Jeffrey Hardy
2024-09-30 13:17:31 -04:00
parent dc60c9b1a2
commit 7863bb5862
8 changed files with 116 additions and 2 deletions
+23
View File
@@ -0,0 +1,23 @@
class FirstRunsController < ApplicationController
allow_unauthenticated_access
before_action :prevent_repeats
def show
end
def create
user = FirstRun.create!(user_params)
start_new_session_for user
redirect_to root_url
end
private
def prevent_repeats
redirect_to root_url unless Account.none?
end
def user_params
params.require(:user).permit(:name, :email_address, :password)
end
end
+7
View File
@@ -2,6 +2,8 @@ class SessionsController < ApplicationController
allow_unauthenticated_access only: %i[ new create ]
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_url, alert: "Try again later." }
before_action :require_first_run_completion
def new
end
@@ -18,4 +20,9 @@ class SessionsController < ApplicationController
terminate_session
redirect_to new_session_url
end
private
def require_first_run_completion
redirect_to first_run_url if Account.none?
end
end
+2
View File
@@ -0,0 +1,2 @@
module FirstRunsHelper
end
+6
View File
@@ -0,0 +1,6 @@
class FirstRun
def self.create!(user_attributes)
account = Account.create!(name: "Fizzy")
account.users.create!(user_attributes)
end
end
+45
View File
@@ -0,0 +1,45 @@
<% @page_title = "Set up Fizzy" %>
<div class="panel shadow center margin-block-double <%= "shake" if flash[:alert] %>" style="--panel-size: 55ch;">
<div class="bubble center" style="--bubble-color: var(--color-ink); --bubble-rotate: 90deg; --bubble-size: 12cqi;">
<svg class="bubble__svg" viewBox="0 0 990 990" xmlns="http://www.w3.org/2000/svg" style="stroke-width: 1.7em;">
<path d="m0 0h990v990h-990z" fill="none" stroke="none" />
<path d="m391.65 879.47c-110.52-15.95-212.21-91.86-255.92-191.23-66.78-143.65-41.62-347.61 48.08-481.17 368.33-516.3 1252.97 520.2 451.03 660.78-44.07 8.84-88.98 13.49-133.01 15.68-36.69 2-73.37 1.91-109.99-4.03z"/>
</svg>
<span class="bubble__bubble bubble__meta bubble__date" style="border-width: 0.5em;"></span>
<span class="bubble__bubble bubble__meta bubble__tag" style="border-width: 0.5em;">&nbsp; &nbsp; &nbsp; &nbsp;</span>
<span class="bubble__bubble bubble__meta bubble__tag" style="border-width: 0.5em;">&nbsp; &nbsp;</span>
</div>
<h1 class="margin-block-start-half margin-block-end-double">Fizzy</h1>
<%= form_with model: User.new, url: first_run_path, class: "flex flex-column gap txt-large" do |form| %>
<div class="flex align-center gap">
<%= translation_button :user_name %>
<label class="flex align-center gap input input--actor txt-large">
<%= form.text_field :name, class: "input", autocomplete: "name", placeholder: "Name", autofocus: true, required: true, data: { "1p-ignore": true } %>
<%= image_tag "person.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
</label>
</div>
<div class="flex align-center gap">
<%= translation_button :email_address %>
<label class="flex align-center gap input input--actor txt-large">
<%= form.email_field :email_address, class: "input", autocomplete: "username", placeholder: "Email address", required: true %>
<%= image_tag "email.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
</label>
</div>
<div class="flex align-center gap">
<%= translation_button :password %>
<label class="flex align-center gap input input--actor txt-large">
<%= form.password_field :password, class: "input", autocomplete: "new-password", placeholder: "Password", required: true, maxlength: 72 %>
<%= image_tag "password.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
</label>
</div>
<button type="submit" id="log_in" class="btn btn--reversed center">
<%= image_tag "arrow-right.svg", aria: { hidden: true }, size: 24 %>
<span class="for-screen-reader">Create your account</span>
</button>
<% end %>
</div>
+2 -2
View File
@@ -15,7 +15,7 @@
<%= form_with url: session_path, class: "flex flex-column gap txt-large" do |form| %>
<div class="flex align-center gap">
<%= translation_button(:email_address) %>
<%= translation_button :email_address %>
<label class="flex align-center gap input input--actor">
<%= form.email_field :email_address, required: true, class: "input full-width", autofocus: true, autocomplete: "username", placeholder: "Enter your email address" %>
<%= image_tag "email.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
@@ -23,7 +23,7 @@
</div>
<div class="flex align-center gap">
<%= translation_button(:password) %>
<%= translation_button :password %>
<label class="flex align-center gap input input--actor">
<%= form.password_field :password, required: true, class: "input full-width", autocomplete: "current-password", placeholder: "Enter your password", maxlength: 72 %>
<%= image_tag "password.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
+2
View File
@@ -1,6 +1,8 @@
Rails.application.routes.draw do
root "buckets#index"
resource :first_run
resource :session
resource :account do
@@ -0,0 +1,29 @@
require "test_helper"
class FirstRunsControllerTest < ActionDispatch::IntegrationTest
setup do
Account.destroy_all
end
test "show" do
get first_run_url
assert_response :ok
assert_select "title", text: "Set up Fizzy"
end
test "show after completion" do
Account.create! name: "Fizzy"
get first_run_url
assert_redirected_to root_url
end
test "create" do
assert_difference -> { Account.count }, +1 do
post first_run_url, params: { user: { name: "New", email_address: "new@37signals.com", password: "secret123456" } }
assert_redirected_to root_url
end
follow_redirect!
assert_response :ok
end
end