Skip to content

Instantly share code, notes, and snippets.

@lazaronixon
Last active April 11, 2023 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lazaronixon/69fadb22aa16a4e397715ab397c0cf4a to your computer and use it in GitHub Desktop.
Save lazaronixon/69fadb22aa16a4e397715ab397c0cf4a to your computer and use it in GitHub Desktop.
Application controller and concerns
class ApplicationController < ActionController::Base
include SetCurrentRequestDetails
include SetCurrentTimeZone
include Authenticate
include ForgeryProtection
include ErrorResponses
include SetSentryUser
include Permissions
end
# app/controllers/concerns/authenticate.rb
module Authenticate
extend ActiveSupport::Concern
included do
before_action :authenticate
end
private
def authenticate
if session = authenticate_with_http_token { |token, _| Session.with_user.find_signed(token) }
Current.session = session
else
request_http_token_authentication
end
end
end
# app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
attribute :user, :session, :user_agent, :ip_address
resets { Time.zone = nil }
def session=(session)
super; self.user = session.user
end
def time_zone=(time_zone)
Time.zone = time_zone
end
end
# app/controllers/concerns/error_responses.rb
module ErrorResponses
extend ActiveSupport::Concern
included do
rescue_from ActiveRecord::RecordInvalid, with: :unprocessable_entity
rescue_from ActiveRecord::RecordNotSaved, with: :unprocessable_entity
rescue_from ActiveRecord::NotNullViolation, with: :unprocessable_entity
rescue_from ActiveRecord::RecordNotUnique, with: :unprocessable_entity
end
private
def unprocessable_entity(error)
respond_to do |format|
format.json { render json: { error: error.message }, status: :unprocessable_entity }
format.any { head :unprocessable_entity }
end
end
def not_found
head :not_found
end
end
# app/controllers/concerns/forgery_protection.rb
module ForgeryProtection
extend ActiveSupport::Concern
included do
protect_from_forgery unless: -> { request.format.json? }
end
end
# app/controllers/concerns/permissions.rb
module Permissions
extend ActiveSupport::Concern
private
def require_my_physician
if Current.user.physician.blank?
render json: { error: "You didn't select your physician" }, status: :bad_request
end
end
def check_subscription
unless Current.user.on_trial_or_subscribed?
render json: { error: "You don't have an active subscription" }, status: :forbidden
end
end
def check_appointment_limit
if Current.user.reached_appointment_limit?
render json: { error: "The appointment limit for this user has been reached" }, status: :insufficient_storage
end
end
end
# app/controllers/concerns/set_current_request_details.rb
module SetCurrentRequestDetails
extend ActiveSupport::Concern
included do
before_action do
Current.user_agent = request.user_agent
Current.ip_address = request.ip
end
end
end
# app/controllers/concerns/set_current_time_zone.rb
module SetCurrentTimeZone
extend ActiveSupport::Concern
included do
before_action do
Current.time_zone = request.headers["X-Time-Zone"]
end
end
end
# app/controllers/concerns/set_sentry_user.rb
module SetSentryUser
extend ActiveSupport::Concern
included do
before_action :set_sentry_user, if: -> { Current.user }
end
private
def set_sentry_user
Sentry.set_user email: Current.user.email_address
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment