Disable registration and implement user creation in the settings page

This commit is contained in:
Eugene Burmakin 2024-06-30 12:31:21 +02:00
parent 1fee34b3db
commit 2c9a88aba4
22 changed files with 229 additions and 22 deletions

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
class Settings::UsersController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_first_user!
def create
@user = User.new(
email: user_params[:email],
password: 'password',
password_confirmation: 'password'
)
if @user.save
redirect_to settings_url, notice: "User was successfully created, email is #{@user.email}, password is \"password\"."
else
redirect_to settings_url, notice: 'User could not be created.', status: :unprocessable_entity
end
end
private
def user_params
params.require(:user).permit(:email)
end
def authenticate_first_user!
return if current_user == User.first
redirect_to settings_users_url, notice: 'You are not authorized to perform this action.', status: :unauthorized
end
end

View file

@ -7,7 +7,7 @@
<%= render 'devise/registrations/api_key' %>
</div>
<div class="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100 px-5 py-5">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), class: 'form-body', html: { method: :put }) do |f| %>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), class: 'form-body', method: :put, data: { turbo_method: :put, turbo: false }) do |f| %>
<div class="form-control">
<%= f.label :email, class: 'label' do %>
<span class="label-text">Email</span>

View file

@ -5,11 +5,11 @@
</div>
<% end %>
<% if devise_mapping.registerable? && controller_name != 'registrations' %>
<div class='my-2'>
<%= link_to "Sign up", new_registration_path(resource_name) %>
</div>
<% end %>
<%# if devise_mapping.registerable? && controller_name != 'registrations' %>
<%# <div class='my-2'> %>
<%#= link_to "Sign up", new_registration_path(resource_name) %>
<%# </div> %>
<%# end %>
<% if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<div class='my-2'>

View file

@ -6,7 +6,7 @@
<h1 class="text-5xl font-bold">Dawarich</h1>
<p class="py-6 text-3xl">The only Dawarich you'll ever need.</p>
<%= link_to 'Sign up', new_user_registration_path, class: "rounded-lg py-3 px-5 my-3 bg-blue-600 text-white block font-medium" %>
<%#= link_to 'Sign up', new_user_registration_path, class: "rounded-lg py-3 px-5 my-3 bg-blue-600 text-white block font-medium" %>
<%= link_to 'Sign in', new_user_session_path, class: "rounded-lg py-3 px-5 bg-neutral text-neutral-content block font-medium" %>
</div>
</div>

View file

@ -26,7 +26,6 @@
<tr>
<th>Name</th>
<th>Processed</th>
<th>Doubles</th>
<th>Created at</th>
</tr>
</thead>
@ -37,10 +36,8 @@
<%= link_to import.name, import, class: 'underline hover:no-underline' %> (<%= import.source %>)
</td>
<td>
<%= "✅" if import.processed == import.raw_points %>
<%= "#{import.processed}/#{import.raw_points}" %>
<%= "#{number_with_delimiter import.points.size}" %>
</td>
<td><%= import.doubles %></td>
<td><%= import.created_at.strftime("%d.%m.%Y, %H:%M") %></td>
</tr>
<% end %>

View file

@ -1,11 +1,9 @@
<% content_for :title, 'Settings' %>
<div class="hero min-h-content bg-base-200">
<div class="hero-content flex-col lg:flex-row-reverse w-full my-10">
<div class="text-center lg:text-left">
<h1 class="text-5xl font-bold">Edit your Dawarich settings!</h1>
</div>
<div class="min-h-content bg-base-200 w-full">
<div class="flex flex-col lg:flex-row w-full my-10 space-x-4">
<div class="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100 px-5 py-5">
<h1 class="text-2xl font-bold">Edit your Dawarich settings!</h1>
<%= form_for :settings, url: settings_path, method: :patch, data: { turbo_method: :patch, turbo: false } do |f| %>
<div class="form-control my-2">
<%= f.label :meters_between_routes do %>
@ -85,5 +83,18 @@
</div>
<% end %>
</div>
<div class="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100 px-5 py-5">
<%= form_for :user, url: settings_users_path, method: :post, data: { turbo_method: :post, turbo: false } do |f| %>
<div class="form-control">
<%= f.label :email do %>
Email
<% end %>
<%= f.email_field :email, value: '', class: "input input-bordered" %>
</div>
<div class="form-control mt-5">
<%= f.submit "Create", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>

View file

@ -0,0 +1,17 @@
<%= form_with(model: settings_user, class: "contents") do |form| %>
<% if settings_user.errors.any? %>
<div id="error_explanation" class="bg-red-50 text-red-500 px-3 py-2 font-medium rounded-lg mt-3">
<h2><%= pluralize(settings_user.errors.count, "error") %> prohibited this settings_user from being saved:</h2>
<ul>
<% settings_user.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="inline">
<%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %>
</div>
<% end %>

View file

@ -0,0 +1,2 @@
<div id="<%= dom_id user %>">
</div>

View file

@ -0,0 +1,8 @@
<div class="mx-auto md:w-2/3 w-full">
<h1 class="font-bold text-4xl">Editing user</h1>
<%= render "form", settings_user: @settings_user %>
<%= link_to "Show this user", @settings_user, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
<%= link_to "Back to users", settings_users_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
</div>

View file

@ -0,0 +1,21 @@
<div class="w-full">
<% if notice.present? %>
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block" id="notice"><%= notice %></p>
<% end %>
<% content_for :title, "Users" %>
<div class="flex justify-between items-center">
<h1 class="font-bold text-4xl">Users</h1>
<%= link_to "New user", new_settings_user_path, class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %>
</div>
<div id="settings_users" class="min-w-full">
<% @settings_users.each do |settings_user| %>
<%= render settings_user %>
<p>
<%= link_to "Show this user", settings_user, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
</p>
<% end %>
</div>
</div>

View file

@ -0,0 +1,7 @@
<div class="mx-auto md:w-2/3 w-full">
<h1 class="font-bold text-4xl">New user</h1>
<%= render "form", settings_user: @settings_user %>
<%= link_to "Back to users", settings_users_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
</div>

View file

@ -0,0 +1,15 @@
<div class="mx-auto md:w-2/3 w-full flex">
<div class="mx-auto">
<% if notice.present? %>
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block" id="notice"><%= notice %></p>
<% end %>
<%= render @settings_user %>
<%= link_to "Edit this user", edit_settings_user_path(@settings_user), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
<%= link_to "Back to users", settings_users_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
<div class="inline-block ml-2">
<%= button_to "Destroy this user", @settings_user, method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
</div>
</div>
</div>

View file

@ -64,7 +64,7 @@
</details>
<% else %>
<li><%= link_to 'Login', new_user_session_path %></li>
<li><%= link_to 'Register', new_user_registration_path %></li>
<li><%#= link_to 'Register', new_user_registration_path %></li>
<% end %>
</ul>
</div>

View file

@ -8,6 +8,9 @@ Rails.application.routes.draw do
mount Sidekiq::Web => '/sidekiq'
resources :settings, only: :index
namespace :settings do
resources :users
end
patch 'settings', to: 'settings#update'
get 'settings/theme', to: 'settings#theme'
@ -28,7 +31,13 @@ Rails.application.routes.draw do
get 'stats/:year', to: 'stats#show', constraints: { year: /\d{4}/ }
root to: 'home#index'
devise_for :users
devise_for :users, skip: [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
# And then modify the app/views/devise/shared/_links.erb
get 'map', to: 'map#index'

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddFogOfWarToDefaultSettings < ActiveRecord::Migration[7.1]
def change
change_column_default :users, :settings,
from: { meters_between_routes: '1000', minutes_between_routes: '60' },
to: { fog_of_war_meters: '100', meters_between_routes: '1000', minutes_between_routes: '60' }
end
end

18
db/schema.rb generated
View file

@ -10,10 +10,24 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2024_06_20_205120) do
ActiveRecord::Schema[7.1].define(version: 2024_06_30_093005) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "active_admin_comments", force: :cascade do |t|
t.string "namespace"
t.text "body"
t.string "resource_type"
t.bigint "resource_id"
t.string "author_type"
t.bigint "author_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author"
t.index ["namespace"], name: "index_active_admin_comments_on_namespace"
t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource"
end
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
@ -135,7 +149,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_06_20_205120) do
t.datetime "updated_at", null: false
t.string "api_key", default: "", null: false
t.string "theme", default: "dark", null: false
t.jsonb "settings", default: {"meters_between_routes"=>500, "minutes_between_routes"=>60}
t.jsonb "settings", default: {"fog_of_war_meters"=>"200", "meters_between_routes"=>"1000", "minutes_between_routes"=>"60"}
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
return if User.any?
User.create!(
email: 'user@domain.com',
password: 'password',
password_confirmation: 'password'
)
puts "User created: #{User.first.email} / password: 'password'"

View file

@ -32,5 +32,9 @@ bundle exec rails db:prepare
echo "Running DATA migrations..."
bundle exec rake data:migrate
# Run seeds
echo "Running seeds..."
bundle exec rake db:seed
# run passed commands
bundle exec ${@}

View file

@ -1,7 +1,10 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'users', type: :request do
describe 'POST /create' do
# Skip this because user registration is disabled
xdescribe 'POST /create' do
let(:user_params) do
{ user: FactoryBot.attributes_for(:user) }
end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Homes', type: :request do
@ -9,6 +11,7 @@ RSpec.describe 'Homes', type: :request do
it 'returns http success' do
get '/'
expect(response).to have_http_status(:success)
end
end

View file

@ -0,0 +1,44 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe '/settings/users', type: :request do
before do
sign_in create(:user)
end
describe 'POST /create' do
context 'with valid parameters' do
let(:valid_attributes) { { email: 'user@domain.com' } }
it 'creates a new User' do
expect do
post settings_users_url, params: { user: valid_attributes }
end.to change(User, :count).by(1)
end
it 'redirects to the created settings_user' do
post settings_users_url, params: { user: valid_attributes }
expect(response).to redirect_to(settings_url)
expect(flash[:notice]).to eq("User was successfully created, email is #{valid_attributes[:email]}, password is \"password\".")
end
end
context 'with invalid parameters' do
let(:invalid_attributes) { { email: nil } }
it 'does not create a new User' do
expect do
post settings_users_url, params: { user: invalid_attributes }
end.to change(User, :count).by(0)
end
it 'renders a response with 422 status (i.e. to display the "new" template)' do
post settings_users_url, params: { user: invalid_attributes }
expect(response).to have_http_status(:unprocessable_entity)
end
end
end
end