app/controllers/application_controller.rb

Summary

Maintainability
A
35 mins
Test Coverage
# frozen_string_literal: true

require 'securerandom'

#
# Base class of all API controllers. Handles low-level stuff like authentication and message
# uniformity.
#
class ApplicationController < ActionController::API
  include HttpAcceptLanguage::AutoLocale
  before_action :authenticate_request
  around_action :wrap_request

  attr_reader :current_user

  private

  def authenticate_request
    @current_user = AuthorizeApiRequest.call(request.headers).result
    error I18n.t('users.errors.not_authorized'), :unauthorized unless @current_user
  end

  def wrap_request
    old_time_zone = Time.zone
    set_time_zone
    yield
  rescue TZInfo::InvalidTimezoneIdentifier
    error I18n.t('common.errors.invalid_timezone', timezone: params[:timezone],
                                                   timezone_list_url: static_api_timezones_url), :bad_request
  rescue StandardError => e
    errorid = SecureRandom.uuid
    logger.error "Error ID #{errorid}: #{$!}, #{e.backtrace.join('\n')}"
    error I18n.t('common.errors.server_error', errorid: errorid), :internal_server_error
  ensure
    Time.zone = old_time_zone
  end

  def error(message, status)
    message(message, status, true)
  end

  def message(message, status, is_error = false, object = {}, object_type = '')
    render json: { message: message, is_error: is_error, object: object, object_type: object_type,
                   status_code: status_msg_to_number(status) }, status: status
  end

  def status_msg_to_number(status)
    Rack::Utils::SYMBOL_TO_STATUS_CODE[status]
  end

  #
  # Attempts to set the timezone for every request. Will fail with a 400 on an invalid timezone
  # If none specified, will default to UTC
  #
  def set_time_zone
    Time.zone = params[:timezone] || 'UTC'
  rescue StandardError
    logger.warn I18n.t('common.errors.invalid_timezone', timezone: params[:timezone],
                                                         timezone_list_url: static_api_timezones_url)
    raise TZInfo::InvalidTimezoneIdentifier
  end

  #
  # Some routes can only be performed by root
  #
  def require_root
    error I18n.t('common.errors.unauthorized'), :unauthorized unless current_user.is_root
  end

  #
  # The root user is not allowed to have jobs
  #
  def disallow_root
    error(I18n.t('common.errors.root_not_permitted'), :forbidden) && return if current_user.is_root?
  end
end