diff --git a/Gemfile.lock b/Gemfile.lock index 41e2abf..2012174 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -188,7 +188,7 @@ GEM language_server-protocol (3.17.0.5) lint_roller (1.1.0) logger (1.7.0) - loofah (2.25.1) + loofah (2.25.2) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.9.0) @@ -293,8 +293,8 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.7.0) - loofah (~> 2.25) + rails-html-sanitizer (1.7.1) + loofah (~> 2.25, >= 2.25.2) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) railties (8.1.3) actionpack (= 8.1.3) diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb new file mode 100644 index 0000000..e41a4b0 --- /dev/null +++ b/app/controllers/users/registrations_controller.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Users + class RegistrationsController < Devise::RegistrationsController + # rubocop:disable Rails/LexicallyScopedActionFilter + before_action :protect_demo_account!, only: %i[update destroy] + # rubocop:enable Rails/LexicallyScopedActionFilter + + private + + def protect_demo_account! + return unless current_user&.demo_account? + + redirect_to authenticated_root_path, + alert: t("users.registrations.demo_account_protected") + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 4ce0a9e..9ecf6ac 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,12 @@ # frozen_string_literal: true class User < ApplicationRecord + DEMO_EMAIL = "demo@example.com" + + def demo_account? + email == DEMO_EMAIL + end + devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable diff --git a/config/locales/en.yml b/config/locales/en.yml index 3a2948e..1d3d24f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -52,4 +52,8 @@ en: success: "Project successfully deleted." index: new_project: "New Project" - title: "Projects" \ No newline at end of file + title: "Projects" + + users: + registrations: + demo_account_protected: "Demo account settings are protected." \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 7f4d388..ccabe30 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true Rails.application.routes.draw do - devise_for :users + devise_for :users, controllers: { + registrations: "users/registrations" + } authenticated :user do root "dashboard#index", as: :authenticated_root diff --git a/spec/requests/users/registrations_spec.rb b/spec/requests/users/registrations_spec.rb new file mode 100644 index 0000000..cdfe2db --- /dev/null +++ b/spec/requests/users/registrations_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe "User registrations" do + describe "PATCH /users" do + context "when the current user is the demo user" do + let(:user) { create(:user, email: User::DEMO_EMAIL) } + + before { sign_in user } + + it "does not update the account" do + patch user_registration_path, params: { + user: { + email: "changed@example.com", + current_password: user.password + } + } + + expect(user.reload.email).to eq(User::DEMO_EMAIL) + end + + it "redirects with an alert" do + patch user_registration_path, params: { + user: { + email: "changed@example.com", + current_password: user.password + } + } + + expect(response).to redirect_to(authenticated_root_path) + expect(flash[:alert]).to eq( + I18n.t("users.registrations.demo_account_protected") + ) + end + end + + context "when the current user is not the demo user" do + let(:user) { create(:user) } + + before { sign_in user } + + it "allows the account to be updated" do + patch user_registration_path, params: { + user: { + email: "changed@example.com", + current_password: user.password + } + } + + expect(user.reload.email).to eq("changed@example.com") + end + end + end + + describe "DELETE /users" do + context "when the current user is the demo user" do + let!(:user) { create(:user, email: User::DEMO_EMAIL) } + + before { sign_in user } + + it "does not delete the account" do + expect do + delete user_registration_path + end.not_to change(User, :count) + end + + it "redirects with an alert" do + delete user_registration_path + + expect(response).to redirect_to(authenticated_root_path) + expect(flash[:alert]).to eq( + I18n.t("users.registrations.demo_account_protected") + ) + end + end + + context "when the current user is not the demo user" do + let!(:user) { create(:user) } + + before { sign_in user } + + it "deletes the account" do + expect do + delete user_registration_path + end.to change(User, :count).by(-1) + end + end + end +end