Finished phase005
This commit is contained in:
@@ -1,7 +1,59 @@
|
||||
class ApplicationController < ActionController::Base
|
||||
AUTH_TOKEN_COOKIE = :auth_token
|
||||
|
||||
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
||||
allow_browser versions: :modern
|
||||
|
||||
# Changes to the importmap will invalidate the etag for HTML responses
|
||||
stale_when_importmap_changes
|
||||
|
||||
before_action :rotate_access_key_if_needed
|
||||
before_action :load_current_user
|
||||
before_action :require_identified_user
|
||||
|
||||
helper_method :current_user, :identified?
|
||||
|
||||
private
|
||||
|
||||
def rotate_access_key_if_needed
|
||||
AccessKey.rotate_if_needed!
|
||||
end
|
||||
|
||||
def load_current_user
|
||||
Current.user_session = UserSession.find_by_token(cookies.encrypted[AUTH_TOKEN_COOKIE])
|
||||
Current.user = Current.user_session&.user
|
||||
Current.user_session&.touch(:last_used_at)
|
||||
end
|
||||
|
||||
def require_identified_user
|
||||
return if identified?
|
||||
|
||||
redirect_to identify_path, alert: "Identify yourself before using Car Tracker."
|
||||
end
|
||||
|
||||
def current_user
|
||||
Current.user
|
||||
end
|
||||
|
||||
def identified?
|
||||
current_user.present?
|
||||
end
|
||||
|
||||
def sign_in(user)
|
||||
user_session, raw_token = UserSession.create_for!(user)
|
||||
Current.user_session = user_session
|
||||
Current.user = user
|
||||
cookies.encrypted[AUTH_TOKEN_COOKIE] = {
|
||||
value: raw_token,
|
||||
httponly: true,
|
||||
same_site: :lax
|
||||
}
|
||||
end
|
||||
|
||||
def sign_out
|
||||
Current.user_session&.destroy!
|
||||
Current.user_session = nil
|
||||
Current.user = nil
|
||||
cookies.delete(AUTH_TOKEN_COOKIE)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
class FuelEntriesController < ApplicationController
|
||||
def create
|
||||
@vehicle = Vehicle.find(params[:vehicle_id])
|
||||
@fuel_entry = @vehicle.fuel_entries.build(fuel_entry_params)
|
||||
@fuel_entry.updated_by_user = Current.user
|
||||
|
||||
if save_fuel_entry
|
||||
redirect_to @vehicle, notice: "Fuel entry recorded."
|
||||
else
|
||||
prepare_vehicle_show
|
||||
render "vehicles/show", status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fuel_entry_params
|
||||
params.require(:fuel_entry).permit(:odometer, :gallons_pumped, :price_paid, :date)
|
||||
end
|
||||
|
||||
def save_fuel_entry
|
||||
saved = false
|
||||
|
||||
FuelEntry.transaction do
|
||||
if @fuel_entry.save
|
||||
update_vehicle_odometer(@fuel_entry.odometer)
|
||||
saved = true
|
||||
end
|
||||
end
|
||||
|
||||
saved
|
||||
end
|
||||
|
||||
def update_vehicle_odometer(odometer)
|
||||
return unless odometer > @vehicle.current_odometer
|
||||
|
||||
@vehicle.update!(current_odometer: odometer)
|
||||
end
|
||||
|
||||
def prepare_vehicle_show
|
||||
@maintenance_schedules = @vehicle.maintenance_schedules.order(:maintenance_type)
|
||||
@fuel_entries = @vehicle.fuel_entries.includes(:updated_by_user).order(date: :desc, created_at: :desc)
|
||||
@maintenance_entries = @vehicle.maintenance_entries.includes(:updated_by_user).order(date: :desc, created_at: :desc)
|
||||
@maintenance_entry = @vehicle.maintenance_entries.build(date: Date.current)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
class MaintenanceEntriesController < ApplicationController
|
||||
ODOMETER_WARNING_THRESHOLD = 500
|
||||
|
||||
def create
|
||||
@vehicle = Vehicle.find(params[:vehicle_id])
|
||||
original_odometer = @vehicle.current_odometer
|
||||
@maintenance_entry = @vehicle.maintenance_entries.build(maintenance_entry_params)
|
||||
@maintenance_entry.updated_by_user = Current.user
|
||||
|
||||
if save_maintenance_entry
|
||||
set_old_odometer_warning(original_odometer)
|
||||
redirect_to @vehicle, notice: "Maintenance entry recorded."
|
||||
else
|
||||
prepare_vehicle_show
|
||||
render "vehicles/show", status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def maintenance_entry_params
|
||||
params.require(:maintenance_entry).permit(:name, :notes, :odometer, :cost, :date)
|
||||
end
|
||||
|
||||
def save_maintenance_entry
|
||||
saved = false
|
||||
|
||||
MaintenanceEntry.transaction do
|
||||
if @maintenance_entry.save
|
||||
update_vehicle_odometer(@maintenance_entry.odometer)
|
||||
saved = true
|
||||
end
|
||||
end
|
||||
|
||||
saved
|
||||
end
|
||||
|
||||
def update_vehicle_odometer(odometer)
|
||||
return unless odometer > @vehicle.current_odometer
|
||||
|
||||
@vehicle.update!(current_odometer: odometer)
|
||||
end
|
||||
|
||||
def set_old_odometer_warning(original_odometer)
|
||||
return unless @maintenance_entry.odometer < original_odometer - ODOMETER_WARNING_THRESHOLD
|
||||
|
||||
message = "Maintenance odometer is more than 500 miles behind the current vehicle odometer."
|
||||
flash[:warning] = message
|
||||
Rails.logger.warn(
|
||||
"#{message} vehicle_id=#{@vehicle.id} maintenance_entry_id=#{@maintenance_entry.id} " \
|
||||
"entry_odometer=#{@maintenance_entry.odometer} vehicle_odometer=#{original_odometer}"
|
||||
)
|
||||
end
|
||||
|
||||
def prepare_vehicle_show
|
||||
@maintenance_schedules = @vehicle.maintenance_schedules.order(:maintenance_type)
|
||||
@fuel_entries = @vehicle.fuel_entries.includes(:updated_by_user).order(date: :desc, created_at: :desc)
|
||||
@maintenance_entries = @vehicle.maintenance_entries.includes(:updated_by_user).order(date: :desc, created_at: :desc)
|
||||
@fuel_entry = @vehicle.fuel_entries.build(date: Date.current)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
class SessionsController < ApplicationController
|
||||
skip_before_action :require_identified_user, only: %i[new create destroy]
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def create
|
||||
access_key = AccessKey.current
|
||||
|
||||
unless access_key.matches?(session_params[:key])
|
||||
Rails.logger.warn("Invalid access key identification attempt for email=#{session_params[:email]}")
|
||||
flash.now[:alert] = "The access key is not valid."
|
||||
return render :new, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
user = find_or_build_user
|
||||
return render :new, status: :unprocessable_entity unless user
|
||||
|
||||
sign_in(user)
|
||||
redirect_to vehicles_path, notice: "You have been identified."
|
||||
end
|
||||
|
||||
def destroy
|
||||
sign_out
|
||||
redirect_to identify_path, notice: "You have been logged out."
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def session_params
|
||||
params.permit(:name, :email, :key)
|
||||
end
|
||||
|
||||
def find_or_build_user
|
||||
email = session_params[:email].to_s.strip.downcase
|
||||
name = session_params[:name].to_s.strip
|
||||
user = User.find_by(email: email)
|
||||
|
||||
if user
|
||||
return user if user.name == name
|
||||
|
||||
flash.now[:alert] = "The name does not match the existing user for that email."
|
||||
return nil
|
||||
end
|
||||
|
||||
user = User.new(name: name, email: email)
|
||||
return user if user.save
|
||||
|
||||
flash.now[:alert] = user.errors.full_messages.to_sentence
|
||||
nil
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,81 @@
|
||||
class VehiclesController < ApplicationController
|
||||
before_action :set_vehicle, only: %i[show edit update destroy]
|
||||
|
||||
def index
|
||||
@status = params[:status]
|
||||
@vehicles = vehicles_for_status(@status).order(:make, :model, :year)
|
||||
end
|
||||
|
||||
def show
|
||||
prepare_show
|
||||
end
|
||||
|
||||
def new
|
||||
@vehicle = Vehicle.new
|
||||
end
|
||||
|
||||
def create
|
||||
@vehicle = Vehicle.new(vehicle_params)
|
||||
|
||||
if @vehicle.save
|
||||
redirect_to @vehicle, notice: "Vehicle created."
|
||||
else
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
if @vehicle.update(vehicle_params)
|
||||
redirect_to @vehicle, notice: "Vehicle updated."
|
||||
else
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@vehicle.update(active: false)
|
||||
redirect_to vehicles_path, notice: "Vehicle deactivated."
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_vehicle
|
||||
@vehicle = Vehicle.find(params[:id])
|
||||
end
|
||||
|
||||
def vehicles_for_status(status)
|
||||
case status
|
||||
when "inactive"
|
||||
Vehicle.where(active: false)
|
||||
when "all"
|
||||
Vehicle.all
|
||||
else
|
||||
Vehicle.where(active: true)
|
||||
end
|
||||
end
|
||||
|
||||
def vehicle_params
|
||||
params.require(:vehicle).permit(
|
||||
:make,
|
||||
:model,
|
||||
:year,
|
||||
:color,
|
||||
:vin,
|
||||
:licence_plate,
|
||||
:current_odometer,
|
||||
:fuel_tank_size,
|
||||
:active
|
||||
)
|
||||
end
|
||||
|
||||
def prepare_show
|
||||
@maintenance_schedules = @vehicle.maintenance_schedules.order(:maintenance_type)
|
||||
@fuel_entries = @vehicle.fuel_entries.includes(:updated_by_user).order(date: :desc, created_at: :desc)
|
||||
@maintenance_entries = @vehicle.maintenance_entries.includes(:updated_by_user).order(date: :desc, created_at: :desc)
|
||||
@fuel_entry ||= @vehicle.fuel_entries.build(date: Date.current)
|
||||
@maintenance_entry ||= @vehicle.maintenance_entries.build(date: Date.current)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user