Added the ability to log multiple access periods to each User and the ability to not only display these access periods but also remove them if accidentally entered.

This commit is contained in:
Ben 2024-04-12 02:40:09 -05:00
parent e7abc0fa50
commit b4cd83c2e7
7 changed files with 98 additions and 44 deletions

View File

@ -1,6 +1,6 @@
class AdminController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource class: User
before_action :check_admin
def new_user
@user = User.new
@ -9,7 +9,7 @@ class AdminController < ApplicationController
def create_user
@user = User.new(user_params)
if @user.save
redirect_to some_admin_path, notice: 'User was successfully created.' # Update the redirect path as needed
redirect_to users_path, notice: 'User was successfully created.'
else
render :new_user
end
@ -18,7 +18,13 @@ class AdminController < ApplicationController
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
# Ensure you permit the right parameters
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :phone, :company)
end
def check_admin
unless current_user.admin?
redirect_to root_path, alert: 'Not authorized'
end
end
end

View File

@ -10,14 +10,24 @@ class UsersController < ApplicationController
def new
@user = User.new
@user.access_periods.build unless @user.access_periods.any?
end
def edit
@user = User.find(params[:id])
@user.access_periods.build if @user.access_periods.empty?
end
def create
@user = User.new(user_params.except(:roles))
@user = User.new(user_params)
# Ensure an access period is built if none exist and no start_date is provided
if @user.access_periods.empty?
@user.access_periods.build(start_date: Date.today) # Set start date automatically
end
if @user.save
update_user_roles(@user, params[:user][:roles] || ['user'])
redirect_to users_path, notice: 'User was successfully created.'
@ -25,16 +35,29 @@ class UsersController < ApplicationController
render :new
end
end
def update
# Assumes @user is already set from a before_action callback
@user = User.find(params[:id]) # Assumes @user is already set from a before_action callback, so this line could be redundant if such a callback exists.
if @user.update(user_params.except(:roles))
# Check and update the access revoked status and end date
if params[:user][:access_revoked] == "1"
# This assumes that you always want to update the latest access period.
# Consider the logic if multiple access periods can exist and which one should be updated.
last_access_period = @user.access_periods.order(:created_at).last
last_access_period.update(end_date: Date.today) unless last_access_period.end_date.present?
end
# Update user roles if they are part of the form submission
update_user_roles(@user, user_params[:roles])
handle_access_revocation
redirect_to users_path, notice: 'User was successfully updated.'
else
render :edit
end
end
def show
@user = User.includes(:access_periods).find(params[:id])
@ -57,7 +80,7 @@ class UsersController < ApplicationController
:email, :password, :password_confirmation, :remember_me,
:first_name, :last_name, :phone, :company,
:access_revoked, :access_start_date, :access_end_date,
access_periods_attributes: [:id, :start_date, :end_date, :destroy],
access_periods_attributes: [:id, :start_date, :end_date, :_destroy],
roles: []
)
end
@ -79,12 +102,19 @@ class UsersController < ApplicationController
def update_user_roles(user, roles_names)
return if roles_names.blank? # Do nothing if no roles provided
user.roles.delete_all # Consider keeping this if role reset is truly intended
roles_names.each do |role_name|
user.add_role(role_name) unless role_name.blank?
end
end
def handle_access_revocation
if params[:user][:access_revoked] == "1"
current_period = @user.access_periods.find_or_initialize_by(end_date: nil)
current_period.update(end_date: Date.today) unless current_period.end_date.present?
elsif params[:user][:access_revoked] == "0" && @user.access_periods.last&.end_date.present?
@user.access_periods.build(start_date: Date.today)
end
end

View File

@ -1,3 +1,12 @@
class AccessPeriod < ApplicationRecord
belongs_to :user
before_validation :set_default_start_date, on: :create
validates :end_date, presence: true, if: -> { user&.access_revoked? }
private
def set_default_start_date
self.start_date ||= Date.today if self.new_record? && self.start_date.blank?
end
end

View File

@ -3,7 +3,7 @@
<div class="col-md-6">
<h2 class="mb-3 text-center">Create New User</h2>
<%= form_for(@user, url: users_path, html: { class: 'needs-validation', novalidate: true }) do |f| %>
<%= form_for(@user, url: admin_users_path, html: { class: 'needs-validation', novalidate: true }) do |f| %>
<div class="mb-3">
<%= f.label :first_name, 'First Name', class: 'form-label' %>
<%= f.text_field :first_name, class: 'form-control', placeholder: 'Enter first name', required: true %>
@ -16,7 +16,7 @@
<div class="mb-3">
<%= f.label :email, class: 'form-label' %>
<%= f.email_field :email, class: 'form-control', placeholder: 'Enter email', required: true, autocomplete: "new-password" %>
<%= f.email_field :email, class: 'form-control', placeholder: 'Enter email', required: true, autocomplete: "new-email" %>
</div>
<div class="mb-3">

View File

@ -2,66 +2,53 @@
<%# Display validation errors, if any %>
<% if user.errors.any? %>
<%# Error messages display block %>
<div class="alert alert-danger">
<strong>Please correct the following errors:</strong>
<ul>
<% user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%# User attributes fields %>
<%# First Name %>
<div class="mb-3">
<%= form.label :first_name, class: 'form-label' %>
<%= form.text_field :first_name, id: :user_first_name, class: 'form-control' %>
</div>
<%# Last Name %>
<div class="mb-3">
<%= form.label :last_name, class: 'form-label' %>
<%= form.text_field :last_name, id: :user_last_name, class: 'form-control' %>
</div>
<%# Email field %>
<div class="mb-3">
<%= form.label :email, class: 'form-label' %>
<%= form.email_field :email, id: :user_email, class: 'form-control' %>
</div>
<%# Phone Number %>
<div class="mb-3">
<%= form.label :phone, class: 'form-label' %>
<%= form.telephone_field :phone, id: :user_phone, class: 'form-control' %>
</div>
<%# Company %>
<div class="mb-3">
<%= form.label :company, class: 'form-label' %>
<%= form.text_field :company, id: :user_company, class: 'form-control' %>
</div>
<%# Assuming roles are assigned via checkboxes or a select dropdown %>
<div class="mb-3">
<%= form.label :roles, 'Assign Role(s)', class: 'form-label' %>
<%# Adjust this to your roles setup %>
<%= form.collection_select :roles, Role.all, :name, :name, {}, { multiple: true, class: 'form-select' } %>
</div>
<%# Access control fields %>
<div class="mb-3">
<%= form.check_box :access_revoked, class: 'form-check-input' %>
<%= form.label :access_revoked, 'Access Revoked', class: 'form-check-label' %>
</div>
<%# Date fields for access control %>
<%= form.fields_for :access_periods do |period_form| %>
<div class="mb-3">
<%= period_form.label :start_date, 'Access Start Date', class: 'form-label' %>
<%= period_form.date_field :start_date, class: 'form-control' %>
</div>
<div class="mb-3">
<%= period_form.label :end_date, 'Access End Date', class: 'form-label' %>
<%= period_form.date_field :end_date, class: 'form-control' %>
</div>
<% end %>
<h3>Access Periods</h3>
<h3>Access Periods</h3>
<table class="table">
<thead>
<tr>
@ -70,17 +57,37 @@
</tr>
</thead>
<tbody>
<% @user.access_periods.each do |period| %>
<% @user.access_periods.order(:start_date).each do |period| %>
<tr>
<td><%= period.start_date %></td>
<td><%= period.end_date || 'Currently has access' %></td>
<td><%= period.start_date ? period.start_date.strftime("%B %d, %Y") : 'Not set' %></td>
<td><%= period.end_date ? period.end_date.strftime("%B %d, %Y") : 'Currently has access' %></td>
</tr>
<% end %>
</tbody>
</table>
<%# Date fields for access control %>
<%= form.fields_for :access_periods do |period_form| %>
<div class="row">
<div class="col-md-5">
<%= period_form.label :start_date, 'Access Start Date' %>
<%= period_form.date_field :start_date, class: 'form-control' %>
</div>
<div class="col-md-5">
<%= period_form.label :end_date, 'Access End Date' %>
<%= period_form.date_field :end_date, class: 'form-control' %>
</div>
<% if period_form.object.persisted? %>
<div class="col-md-2">
<%= period_form.check_box :_destroy %>
<%= period_form.label :_destroy, 'Remove' %>
</div>
<% end %>
</div>
<% end %>
<%# Submit button %>
<div class="actions">
<div class="actions mt-3">
<%= form.submit 'Save', class: 'btn btn-dark' %>
</div>

View File

@ -41,7 +41,7 @@
<div class="col-12 d-flex justify-content-between mb-4">
<!-- Button for Admins to add a new user -->
<% if can?(:create, User) %> <!-- Checks if the current user has the permission to create new users -->
<%= link_to 'Add New User', new_user_admin_path, class: "btn btn-dark" %>
<%= link_to 'Add New User', new_admin_user_path, class: "btn btn-dark" %>
<% end %>
<%= link_to 'Back to Home', root_path, class: "btn btn-secondary" %> <!-- Adjust as needed -->

View File

@ -85,13 +85,15 @@ Rails.application.routes.draw do
resources :forms
resources :users
resource :admin, controller: 'admin', only: [] do
get 'users/new', to: 'admin#new_user', as: 'new_user'
post 'users', to: 'admin#create_user', as: 'create_user'
# Define other routes as needed
# Setup the routes under a scope to mimic namespace-like behavior without actual namespacing
scope '/admin', controller: :admin do
get 'users/new', as: 'new_admin_user', action: :new_user # for displaying the new user form
post 'users', as: 'admin_users', action: :create_user # for submitting the new user form
# You can add more admin routes here as needed
end
get 'home/index'
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html