trusona/trusona-server-sdk-ruby

View on GitHub
lib/trusona/services/base_service.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
95%
# frozen_string_literal: true

module Trusona
  module Services
    #
    ## The starting point for building other services that interact with the
    ## Trusona API
    class BaseService
      attr_accessor :resource_path

      def initialize(client: Trusona::Api::HTTPClient.new,
                     mapper: Trusona::Mappers::BaseMapper.new)
        @client = client
        @mapper = mapper
        @resource_path = '/base-service'
      end

      def index
        handle(@client.get(collection_path))
      end

      def get(resource)
        raise Trusona::InvalidResourceError unless resource.id

        handle(@client.get(member_path(resource)), resource)
      end

      def create(resource)
        raise Trusona::InvalidResourceError unless resource.valid?

        handle(@client.post(collection_path, resource.to_json), resource)
      end

      def update(resource)
        raise Trusona::InvalidResourceError unless resource.id

        handle(@client.patch(member_path(resource), resource.to_json), resource)
      end

      def delete(resource)
        raise Trusona::InvalidResourceError unless resource.id

        handle(@client.delete(member_path(resource)), resource)
      end

      def collection_path
        @resource_path
      end

      def member_path(resource)
        [collection_path, resource.id].join('/')
      end

      private

      def verify_response(response)
        raise Trusona::SigningError unless response.verified?
      end

      # rubocop:disable Metrics/MethodLength
      # rubocop:disable Metrics/CyclomaticComplexity
      def handle(response, resource = {})
        @response = response

        raise if resource.nil?

        case response.code
        when 200..299
          success(response, resource)
        when 400
          bad_request
        when 404
          not_found
        when 403
          unauthorized
        when 422
          unprocessable_entity
        when 424
          failed_dependency
        when 500..599
          server_error
        else
          raise Trusona::RequestError, readable_error
        end
      end
      # rubocop:enable Metrics/MethodLength
      # rubocop:enable Metrics/CyclomaticComplexity

      def success(response, resource)
        verify_response(response)
        @mapper.map(response, resource)
      end

      def bad_request
        raise Trusona::BadRequestError, readable_error
      end

      def unprocessable_entity
        raise Trusona::UnprocessableEntityError, readable_error
      end

      def failed_dependency
        raise Trusona::FailedDependencyError, readable_error
      end

      def not_found
        raise Trusona::ResourceNotFoundError, readable_error
      end

      def unauthorized
        raise Trusona::UnauthorizedRequestError, readable_error
      end

      def server_error
        raise Trusona::ApiError
      end

      def readable_error
        default = '[UNKNOWN] Error - An unknown error has occurred.'
        return default unless @response

        body = @response.to_h
        msg = []
        msg << "[#{body['error']}] #{body['message']} - #{body['description']}"
        return msg.join("\n") unless body['field_errors']

        body['field_errors'].each do |field|
          msg << "\t #{field.join(' => ')}"
        end

        msg.join("\n")
      end
    end
  end
end