diff --git a/app/admin/admin_users.rb b/app/admin/admin_users.rb index fed0ec1..005fdb4 100644 --- a/app/admin/admin_users.rb +++ b/app/admin/admin_users.rb @@ -1,27 +1,74 @@ ActiveAdmin.register AdminUser do - permit_params :email, :password, :password_confirmation + permit_params :email, :name, :password + + action_item :back, only: :show do + link_to 'Back to Admin Users', admin_admin_users_path + end + + filter :name + filter :email index do selectable_column id_column + column :name column :email - column :current_sign_in_at - column :sign_in_count column :created_at + column :last_sign_in_at actions end - filter :email - filter :current_sign_in_at - filter :sign_in_count - filter :created_at + show do + attributes_table do + row :id + row :name + row :email + row :created_at + end + end form do |f| f.inputs do + f.input :name f.input :email - f.input :password - f.input :password_confirmation + f.input :password, required: resource.new_record? end f.actions end + + controller do + def update + @admin_user = AdminUser.find(permitted_params[:id]) + + if update_admin_user + redirect_to admin_admin_user_path(@admin_user), notice: 'Admin user was successfully updated.' + else + render :edit + end + end + + def create + @admin_user = AdminUser.new(admin_user_params) + + if @admin_user.save + redirect_to admin_admin_users_path, notice: 'Admin user was successfully created.' + else + render :new + end + end + + private + + def update_admin_user + if admin_user_params[:password].present? + @admin_user.update(admin_user_params) + else + @admin_user.update_without_password(admin_user_params) + end + end + + def admin_user_params + permitted_params[:admin_user] + end + end end diff --git a/app/models/admin_user.rb b/app/models/admin_user.rb index b512131..24d1da7 100644 --- a/app/models/admin_user.rb +++ b/app/models/admin_user.rb @@ -1,21 +1,42 @@ class AdminUser < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable - devise :database_authenticatable, :recoverable, - :rememberable, :validatable + devise :database_authenticatable, + :rememberable, + :trackable PASSWORD_SYMBOL_FORMAT = /\A(?=.*[^\w\s])[^\s]*\z/ PASSWORD_REPEATED_CHAR_FORMAT = /\A(?!.*(.)\1\1).*\z/ validates :name, presence: true - validates :email, presence: true, uniqueness: true, - format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email format" } + validates :email, presence: true + validates :email, uniqueness: true, + format: { with: URI::MailTo::EMAIL_REGEXP, + message: "must be a valid email format" }, if: -> { email.present? } + validates :password, presence: true, unless: :skip_password_validation? validates :password, length: { minimum: 8, maximum: 128 }, - format: { with: PASSWORD_SYMBOL_FORMAT, message: "must contain at least one symbol" } - validates :password, format: { with: PASSWORD_REPEATED_CHAR_FORMAT, message: "must not contain repeated characters" } + format: { with: PASSWORD_SYMBOL_FORMAT, + message: "must contain at least one symbol" }, + unless: :skip_password_validation?, if: -> { password.present? } + validates :password, format: { with: PASSWORD_REPEATED_CHAR_FORMAT, + message: "must not contain repeated characters" }, + unless: :skip_password_validation?, if: -> { password.present? } + + def update_without_password(params) + @skip_password_validation = true + super(params) + ensure + @skip_password_validation = false + end def self.ransackable_attributes(_auth_object = nil) %w[created_at email encrypted_password id id_value name remember_created_at reset_password_sent_at reset_password_token updated_at] end + + private + + def skip_password_validation? + @skip_password_validation || false + end end diff --git a/db/migrate/20250318094556_add_trackable_to_admin_users.rb b/db/migrate/20250318094556_add_trackable_to_admin_users.rb new file mode 100644 index 0000000..9098ca7 --- /dev/null +++ b/db/migrate/20250318094556_add_trackable_to_admin_users.rb @@ -0,0 +1,11 @@ +class AddTrackableToAdminUsers < ActiveRecord::Migration[8.0] + def change + change_table :admin_users, bulk: true do |t| + t.column :sign_in_count, :integer, default: 0, null: false + t.column :current_sign_in_at, :datetime + t.column :last_sign_in_at, :datetime + t.column :current_sign_in_ip, :string + t.column :last_sign_in_ip, :string + end + end +end diff --git a/db/schema.rb b/db/schema.rb index daf6dc3..06061b9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_01_16_103055) do +ActiveRecord::Schema[8.0].define(version: 2025_03_18_094556) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" @@ -23,6 +23,11 @@ t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "sign_in_count", default: 0, null: false + t.datetime "current_sign_in_at" + t.datetime "last_sign_in_at" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" t.index ["email"], name: "index_admin_users_on_email", unique: true t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true end diff --git a/spec/requests/admin/admin_users_controller_spec.rb b/spec/requests/admin/admin_users_controller_spec.rb new file mode 100644 index 0000000..7390875 --- /dev/null +++ b/spec/requests/admin/admin_users_controller_spec.rb @@ -0,0 +1,61 @@ +require 'rails_helper' + +RSpec.describe "Admin::AdminUsersController", type: :request do + let!(:admin_user) { create(:admin_user) } + + let(:admin_user_params) do + { email: 'admin.123@example.com', + name: 'test', + password: 'password@123' } + end + + before do + sign_in admin_user, scope: :admin_user + end + + describe "routes" do + context 'GET /admin/admin_users/new' do + it "should get new" do + get new_admin_admin_user_path + + expect(response).to have_http_status(:ok) + end + end + + context 'POST /admin/admin_users' do + let(:last_admin_user) { AdminUser.last } + + it 'creates the model successfully and redirects to index' do + post admin_admin_users_path, params: { admin_user: admin_user_params } + + expect(response).to redirect_to(admin_admin_users_path) + + follow_redirect! + + expect(response.body).to include('Admin user was successfully created.') + expect(last_admin_user.email).to be_eql admin_user_params[:email] + end + end + + context 'GET /admin/admin_users/:id/edit' do + it "should get edit" do + get edit_admin_admin_user_path(admin_user) + + expect(response).to have_http_status(:ok) + end + end + + context 'PATCH /admin/admin_users/:id' do + it 'updates the email successfully and redirects to show' do + patch admin_admin_user_path(admin_user), params: { admin_user: { email: '123@example.com' } } + + expect(response).to redirect_to(admin_admin_user_path(admin_user)) + + follow_redirect! + + expect(response.body).to include('Admin user was successfully updated.') + expect(admin_user.reload.email).to be_eql '123@example.com' + end + end + end +end