module API module V1 class ApplicationController < ActionController::API prepend_view_path Rails.root.join("app/views/api/v1") attr_reader :current_user before_action :authenticate! before_action :set_expand before_action :set_pii include Pundit::Authorization include ActionController::HttpAuthentication::Token::ControllerMethods rescue_from Pundit::NotAuthorizedError do |e| render json: { error: "not_authorized" }, status: :forbidden end rescue_from ActiveRecord::RecordNotFound do |e| render json: { error: "resource_not_found", message: ("Couldn't locate that #{e.model.constantize.model_name.human}." if e.model) }.compact_blank, status: :not_found end rescue_from ActiveRecord::RecordInvalid do |e| render json: { error: "validation_error", messages: e.record.errors.full_messages }, status: :bad_request end rescue_from ActiveRecord::RecordNotUnique do |e| render json: { error: "idempotency_error", messages: ["a record by that idempotency key already exists!"] }, status: :bad_request end rescue_from ActionController::ParameterMissing do |e| render json: { error: "missing_parameter", messages: [e.message] }, status: :bad_request end private def set_expand @expand = params[:expand].to_s.split(",").map { |e| e.strip.to_sym } end def set_pii = @pii = current_token&.pii? def authenticate! @current_token = authenticate_with_http_token { |t, _options| APIKey.find_by(token: t) } unless @current_token&.active? return render json: { error: "invalid_auth" }, status: :unauthorized end @current_user = if current_token&.may_impersonate? && params[:impersonate].present? begin User.find_by!(slack_id: params[:impersonate]) rescue ActiveRecord::RecordNotFound render json: { error: "impersonate_error", message: "couldn't find that user" }, status: :bad_request end else current_token&.user end end attr_reader :current_token end end end