Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
uoy-faculty-rbac / lib / faculty_rbac / sinatra.rb
Size: Mime:
# frozen_string_literal: true

module FacultyRBAC
  # Helpers for authenticating within Sinatra apps
  module Sinatra
    # Helpers for sinatra apps
    module Helpers
      def rbac_auth(permission, **context)
        FacultyRBAC::Sinatra::RBACAuthHelper.new(permission, **context)
      end

      def custom_auth(identifier, *args, &block)
        return FacultyRBAC::Sinatra::CustomAuthHelper.new(identifier, args) unless block

        FacultyRBAC::Sinatra::CustomAuth.add(identifier, &block)
      end

      def check_auth(*auth_methods, params: {}) # rubocop:disable Metrics/MethodLength
        auth_methods.any? do |auth_method|
          case auth_method
          when FacultyRBAC::Sinatra::RBACAuthHelper
            next @logged_in_user.allowed_to?(auth_method.permission, **auth_method.context(params))
          when FacultyRBAC::Sinatra::CustomAuthHelper
            if FacultyRBAC::Sinatra::CustomAuth.exists? auth_method.identifier
              next instance_exec(*auth_method.args, &FacultyRBAC::Sinatra::CustomAuth.get(auth_method.identifier))
            end
          end

          raise "Unknown auth method: '#{auth_method}'"
        end
      end
    end

    # An wrapper for an RBAC auth check for the logged in user
    class RBACAuthHelper
      def initialize(permission, **context)
        @permission = permission
        @context = context
      end

      attr_accessor :permission

      def context(params = {})
        return @context if params.empty?

        @context.transform_values do |v|
          value = params.fetch(v, v)
          value = value.to_i if value.respond_to?(:to_i) && (value.to_i.to_s == value.to_s)
          value
        end
      end
    end

    # A wrapper for a custom auth check.
    class CustomAuthHelper
      def initialize(identifier, args = [])
        @identifier = identifier
        @args = args
      end

      def to_s
        @identifier.to_s
      end

      attr_reader :args, :identifier
    end

    # Helper class for defining custom authorisation methods
    module CustomAuth
      @methods = {}

      # We need a way of clearing @methods for testing this module...
      class << self
        attr_accessor :methods
      end

      module_function

      def add(identifier, &block)
        @methods[identifier] = block
      end

      def exists?(method)
        @methods.key? method
      end

      def get(method)
        @methods[method]
      end
    end

    def self.registered(app)
      app.helpers Helpers
      app.register Helpers

      app.set(:auth) do |*auth_methods|
        condition do
          raise http_status(403) unless check_auth(*auth_methods, params:)
        end
      end
    end
  end
end