arrthorizer 0.1.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. data/.gitignore +21 -0
  2. data/.travis.yml +6 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +32 -0
  6. data/Rakefile +8 -0
  7. data/arrthorizer.gemspec +24 -0
  8. data/config.ru +7 -0
  9. data/lib/arrthorizer/arrthorizer_exception.rb +11 -0
  10. data/lib/arrthorizer/context.rb +65 -0
  11. data/lib/arrthorizer/context_builder.rb +11 -0
  12. data/lib/arrthorizer/context_role.rb +31 -0
  13. data/lib/arrthorizer/permission.rb +14 -0
  14. data/lib/arrthorizer/privilege.rb +44 -0
  15. data/lib/arrthorizer/rails/configuration.rb +67 -0
  16. data/lib/arrthorizer/rails/controller_action.rb +45 -0
  17. data/lib/arrthorizer/rails/controller_concern.rb +70 -0
  18. data/lib/arrthorizer/rails/controller_configuration.rb +36 -0
  19. data/lib/arrthorizer/rails/controller_context_builder.rb +39 -0
  20. data/lib/arrthorizer/rails.rb +24 -0
  21. data/lib/arrthorizer/registry.rb +30 -0
  22. data/lib/arrthorizer/role.rb +31 -0
  23. data/lib/arrthorizer/roles.rb +19 -0
  24. data/lib/arrthorizer/version.rb +3 -0
  25. data/lib/arrthorizer.rb +28 -0
  26. data/lib/generators/arrthorizer/install/USAGE +9 -0
  27. data/lib/generators/arrthorizer/install/install_generator.rb +62 -0
  28. data/lib/generators/arrthorizer/install/templates/config.yml +49 -0
  29. data/spec/arrthorizer_exception/inner_spec.rb +21 -0
  30. data/spec/context/equals_spec.rb +44 -0
  31. data/spec/context/merge_spec.rb +37 -0
  32. data/spec/context_builder/build_spec.rb +12 -0
  33. data/spec/context_role/to_key_spec.rb +21 -0
  34. data/spec/context_spec.rb +49 -0
  35. data/spec/controllers/some_controller_spec.rb +79 -0
  36. data/spec/integration/registry/missing_handler_spec.rb +25 -0
  37. data/spec/integration/role_spec.rb +17 -0
  38. data/spec/internal/app/assets/images/rails.png +0 -0
  39. data/spec/internal/app/assets/javascripts/application.js +15 -0
  40. data/spec/internal/app/assets/javascripts/test.js.coffee +3 -0
  41. data/spec/internal/app/assets/stylesheets/application.css +13 -0
  42. data/spec/internal/app/assets/stylesheets/test.css.scss +3 -0
  43. data/spec/internal/app/controllers/application_controller.rb +3 -0
  44. data/spec/internal/app/controllers/some_controller.rb +17 -0
  45. data/spec/internal/app/helpers/application_helper.rb +2 -0
  46. data/spec/internal/app/helpers/test_helper.rb +2 -0
  47. data/spec/internal/app/mailers/.gitkeep +0 -0
  48. data/spec/internal/app/models/.gitkeep +0 -0
  49. data/spec/internal/app/roles/namespaced/context_role.rb +9 -0
  50. data/spec/internal/app/roles/unnamespaced_context_role.rb +6 -0
  51. data/spec/internal/app/views/layouts/application.html.erb +11 -0
  52. data/spec/internal/app/views/some/some_action.html.erb +2 -0
  53. data/spec/internal/config/application.rb +65 -0
  54. data/spec/internal/config/arrthorizer.yml +9 -0
  55. data/spec/internal/config/boot.rb +6 -0
  56. data/spec/internal/config/database.yml +25 -0
  57. data/spec/internal/config/environment.rb +5 -0
  58. data/spec/internal/config/routes.rb +3 -0
  59. data/spec/internal/db/schema.rb +3 -0
  60. data/spec/internal/log/.gitignore +1 -0
  61. data/spec/internal/public/favicon.ico +0 -0
  62. data/spec/permission/grant_spec.rb +14 -0
  63. data/spec/privilege/accessible_to_spec.rb +32 -0
  64. data/spec/privilege/get_spec.rb +35 -0
  65. data/spec/privilege/initialize_spec.rb +15 -0
  66. data/spec/privilege/make_accessible_to_spec.rb +22 -0
  67. data/spec/rails/.gitkeep +0 -0
  68. data/spec/rails/controller_action/initialize_spec.rb +42 -0
  69. data/spec/rails/controller_action/key_for_spec.rb +17 -0
  70. data/spec/rails/controller_action/to_key_spec.rb +14 -0
  71. data/spec/rails/controller_concern/arrthorizer_context_spec.rb +22 -0
  72. data/spec/rails/controller_concern/authorize_spec.rb +113 -0
  73. data/spec/rails/controller_concern/integration_spec.rb +75 -0
  74. data/spec/rails/controller_concern/to_prepare_context_spec.rb +38 -0
  75. data/spec/rails/controller_configuration/initialize_spec.rb +19 -0
  76. data/spec/role/get_spec.rb +29 -0
  77. data/spec/role/shared_examples/finding_the_right_role.rb +6 -0
  78. data/spec/spec_helper.rb +21 -0
  79. data/spec/support/reset.rb +26 -0
  80. metadata +244 -0
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/internal/db/*.sqlite3
19
+
20
+ .ruby-version
21
+ .ruby-gemset
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails', '~> 3.2.16'
4
+
5
+ # Specify your gem's dependencies in arrthorizer.gemspec
6
+ gemspec
7
+
8
+ group :test do
9
+ gem 'rake'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 René van den Berg
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ [![Build Status](https://travis-ci.org/ReneB/arrthorizer.png?branch=fyfbd_118)](https://travis-ci.org/ReneB/arrthorizer)
2
+ (The build is currently supposed to fail, since the gem is not in a releasable state yet)
3
+
4
+ # Arrthorizer
5
+
6
+ TODO: Write a gem description
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'arrthorizer'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install arrthorizer
21
+
22
+ ## Usage
23
+
24
+ TODO: Write usage instructions here
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
31
+ 4. Push to the branch (`git push origin my-new-feature`)
32
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RSpec::Core::RakeTask.new(:test)
7
+
8
+ task :default => :spec
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'arrthorizer/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "arrthorizer"
8
+ gem.version = Arrthorizer::VERSION
9
+ gem.authors = ["René van den Berg", "Lennaert Meijvogel"]
10
+ gem.email = ["rene.vandenberg@ogd.nl", "lennaert.meijvogel@ogd.nl"]
11
+ gem.description = %q{Contextual authorization for your Rails (3+) application}
12
+ gem.summary = %q{Contextual authorization for your Rails (3+) application}
13
+ gem.homepage = "https://github.com/BUS-ogd/arrthorizer"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'rails'
21
+ gem.add_development_dependency 'combustion', '~> 0.5.1'
22
+ gem.add_development_dependency 'sqlite3'
23
+ gem.add_development_dependency 'rspec-rails'
24
+ end
data/config.ru ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ Bundler.require :default, :development
5
+
6
+ Combustion.initialize!
7
+ run Combustion::Application
@@ -0,0 +1,11 @@
1
+ module Arrthorizer
2
+ class ArrthorizerException < StandardError
3
+ attr_reader :inner
4
+
5
+ def initialize(message = "Exception occurred", inner = $!)
6
+ super(message)
7
+
8
+ @inner = inner
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,65 @@
1
+ require 'ostruct'
2
+
3
+ module Arrthorizer
4
+ # Make it possible to specify the context that Arrthorizer can evaluate from inside the controller:
5
+ #
6
+ # class MyController
7
+ # to_prepare_context do |c|
8
+ # c.defaults do
9
+ # { bookcase: Cms::Bookcase.find(params[:id]) }
10
+ # end
11
+ #
12
+ # c.for_action(:some_action) do
13
+ # arrthorizer_defaults.merge({ bookcase: Cms::Book.find(params[:id]).bookcase })
14
+ # end
15
+ # end
16
+ # end
17
+ #
18
+ # class MyController
19
+ # to_prepare_context do |c|
20
+ # c.defaults do
21
+ # params
22
+ # end
23
+ # end
24
+ # end
25
+ #
26
+ # In non-Rails environments:
27
+ #
28
+ # class MySomething
29
+ # # probably include something like Arrthorizer::Config
30
+ # to_prepare_context do |c|
31
+ # c.defaults do
32
+ # { bookcase: Cms::Bookcase.find(params[:id]) }
33
+ # end
34
+ #
35
+ # if params[:action] == :edit
36
+ # arrthorizer_defaults.merge { author: User.find(params[:author_id] }
37
+ # end
38
+ # end
39
+ # end
40
+
41
+ class Context < OpenStruct
42
+ ConversionError = Class.new(Arrthorizer::ArrthorizerException)
43
+
44
+ def merge(hash)
45
+ self.class.new(to_hash.merge(hash))
46
+ end
47
+
48
+ def to_hash
49
+ marshal_dump
50
+ end
51
+
52
+ def ==(other)
53
+ to_hash == other.to_hash
54
+ end
55
+ end
56
+
57
+ module_function
58
+ def Context(contents)
59
+ return contents if contents.is_a? Context
60
+
61
+ return Context.new(contents.to_hash)
62
+ rescue NoMethodError
63
+ raise Arrthorizer::Context::ConversionError, "Can't convert #{contents} to an Arrthorizer::Context"
64
+ end
65
+ end
@@ -0,0 +1,11 @@
1
+ module Arrthorizer
2
+ class ContextBuilder
3
+ def build
4
+ Arrthorizer::Context.new
5
+ end
6
+
7
+ def build_from_hash(hash)
8
+ Arrthorizer::Context(hash)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ require 'singleton'
2
+
3
+ ##
4
+ # This is the superclass for all ContextRoles that the application may contain.
5
+ # A ContextRole is a role that a User may or may not have, depending on the
6
+ # current context. This can be things like 'the author of a certain post' or 'a
7
+ # member of the current group'
8
+ module Arrthorizer
9
+ class ContextRole < Role
10
+ include Singleton
11
+
12
+ def to_key
13
+ self.class.to_key
14
+ end
15
+
16
+ def self.to_key
17
+ name
18
+ end
19
+
20
+ def self.applies_to_user?(*args)
21
+ instance.applies_to_user?(*args)
22
+ end
23
+
24
+ def self.inherited(klass)
25
+ super
26
+
27
+ Role.register(klass.instance)
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,14 @@
1
+ module Arrthorizer
2
+ module Permission
3
+ InvalidPermission = Class.new(ArrthorizerException)
4
+
5
+ def self.grant(privilege, config = {})
6
+ privilege = Privilege.get(privilege)
7
+ role = Role.get(config[:to])
8
+
9
+ privilege.make_accessible_to(role)
10
+ rescue Registry::NotFound => e
11
+ raise InvalidPermission, e.message
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,44 @@
1
+ module Arrthorizer
2
+ class Privilege
3
+ attr_reader :name
4
+
5
+ def initialize(attrs)
6
+ @name = attrs[:name].to_s
7
+
8
+ (attrs[:roles] || []).each do |role|
9
+ self.make_accessible_to(role)
10
+ end
11
+
12
+ self.class.register(self)
13
+ end
14
+
15
+ def self.get(name_or_privilege)
16
+ registry.fetch(name_or_privilege)
17
+ end
18
+
19
+ def make_accessible_to(role)
20
+ permitted_roles.add(role)
21
+ end
22
+
23
+ def accessible_to?(role)
24
+ !!permitted_roles.fetch(role) { false }
25
+ end
26
+
27
+ def permitted_roles
28
+ @permitted_roles ||= Registry.new
29
+ end
30
+
31
+ def to_key
32
+ name
33
+ end
34
+
35
+ protected
36
+ def self.register(privilege)
37
+ registry.add(privilege)
38
+ end
39
+
40
+ def self.registry
41
+ @registry ||= Registry.new
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,67 @@
1
+ module Arrthorizer
2
+ module Rails
3
+ class Configuration
4
+ FileNotFound = Class.new(Arrthorizer::ArrthorizerException)
5
+
6
+ mattr_accessor :config_file
7
+ self.config_file = "config/arrthorizer.yml"
8
+
9
+ def self.load
10
+ Parser.new.process(config)
11
+ end
12
+
13
+ private
14
+ def self.config
15
+ @config ||= YAML.load(config_file_contents) || {}
16
+ end
17
+
18
+ def self.config_file_contents
19
+ File.read(config_file_location)
20
+ rescue Errno::ENOENT
21
+ raise FileNotFound, "Arrthorizer requires a config file at #{config_file}"
22
+ end
23
+
24
+ def self.config_file_location
25
+ ::Rails.root.join config_file
26
+ end
27
+
28
+ class Parser
29
+ def process(config)
30
+ config.each_pair do |privilege_name, configuration|
31
+ parse_privilege_node(privilege_name, OpenStruct.new(configuration))
32
+ end
33
+ end
34
+
35
+ private
36
+ def parse_privilege_node(name, description)
37
+ privilege = Arrthorizer::Privilege.new(name: name, roles: roles_from(description))
38
+
39
+ description.actions.each do |node|
40
+ controller_name = controller_from(node)
41
+
42
+ actions_from(node, controller_name).each do |action|
43
+ action.privilege = privilege
44
+ end
45
+ end
46
+ end
47
+
48
+ # node looks like this: { "actions" => { "controller_name" => ["namespaced/action_name"] }, roles: [ "Namespaced::Role" ] }
49
+ def roles_from(node)
50
+ (node.roles || []).map(&:constantize)
51
+ end
52
+
53
+ # node looks like this: { "controller_name" => ["namespaced/action_name", "another_action_name"] }
54
+ def controller_from(node)
55
+ node.keys.first
56
+ end
57
+
58
+ # node looks like this: { "controller_name" => ["namespaced/action_name", "another_action_name"] }
59
+ def actions_from(node, controller_name)
60
+ node[controller_name].map do |action_name|
61
+ Arrthorizer::Rails::ControllerAction.new(controller: controller_name, action: action_name)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,45 @@
1
+ module Arrthorizer
2
+ module Rails
3
+ class ControllerAction
4
+ ControllerNotDefined = Class.new(Arrthorizer::ArrthorizerException)
5
+ ActionNotDefined = Class.new(Arrthorizer::ArrthorizerException)
6
+
7
+ attr_accessor :privilege
8
+ attr_reader :controller_path, :action_name
9
+
10
+ def self.get_current(controller)
11
+ fetch(key_for(controller))
12
+ end
13
+
14
+ def initialize(attrs)
15
+ self.controller_path = attrs.fetch(:controller) { raise ControllerNotDefined }
16
+ self.action_name = attrs.fetch(:action) { raise ActionNotDefined }
17
+
18
+ self.class.register(self)
19
+ end
20
+
21
+ def to_key
22
+ "#{controller_path}##{action_name}"
23
+ end
24
+
25
+ private
26
+ attr_writer :controller_path, :action_name
27
+
28
+ def self.key_for(controller)
29
+ "#{controller.controller_path}##{controller.action_name}"
30
+ end
31
+
32
+ def self.fetch(key)
33
+ registry.fetch(key)
34
+ end
35
+
36
+ def self.register(controller_action)
37
+ registry.add(controller_action)
38
+ end
39
+
40
+ def self.registry
41
+ @registry ||= Registry.new
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,70 @@
1
+ module Arrthorizer
2
+ module Rails
3
+ module ControllerConcern
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ protected
8
+ class_attribute :arrthorizer_configuration, instance_writer: false
9
+
10
+ ##
11
+ # This is a hook method that provides access to the context for a
12
+ # given HTTP request. For each request, an Arrthorizer::Context object is
13
+ # built and provided to all ContextRoles that are configured as having
14
+ # access to the given controller action.
15
+ def arrthorizer_context
16
+ arrthorizer_context_builder.build_for_action
17
+ end
18
+
19
+ def arrthorizer_defaults
20
+ arrthorizer_context_builder.build_default
21
+ end
22
+
23
+ def authorize
24
+ action = Arrthorizer::Rails::ControllerAction.get_current(self)
25
+ roles = action.privilege.permitted_roles
26
+
27
+ roles.any? do |role|
28
+ role.applies_to_user?(current_user, arrthorizer_context)
29
+ end || forbidden
30
+ end
31
+
32
+ def forbidden
33
+ render text: 'Access Denied', status: :forbidden
34
+ end
35
+
36
+ def arrthorizer_context_builder
37
+ @context_builder ||= Arrthorizer::Rails::ControllerContextBuilder.new(self, arrthorizer_configuration)
38
+ end
39
+ end
40
+
41
+ module ClassMethods
42
+ ##
43
+ # This method sets up Arrthorizer to verify that a user has the proper
44
+ # rights to access a # given controller action. Options can be provided
45
+ # and are passed to before_filter.
46
+ def requires_authorization(options = {})
47
+ before_filter :authorize, options
48
+ end
49
+
50
+ ##
51
+ # This method sets up Arrthorizer to not verify requests to all (when
52
+ # no options are provided) or selected (when :only or :except are
53
+ # provided) actions in this controller and its subclasses.
54
+ # Options can be provided and are passed to skip_filter.
55
+ def does_not_require_authorization(options = {})
56
+ skip_filter :authorize, options
57
+ end
58
+
59
+ ##
60
+ # This is the configuration method for building Arrthorizer contexts from HTTP requests.
61
+ # The developer specifies how contexts for authorization checks should be built
62
+ # by providing a block to this method. For more information, check the documentation
63
+ # on Arrthorizer::Rails::ControllerConfiguration
64
+ def to_prepare_context(&block)
65
+ self.arrthorizer_configuration = Arrthorizer::Rails::ControllerConfiguration.new(&block)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,36 @@
1
+ module Arrthorizer
2
+ module Rails
3
+ class ControllerConfiguration
4
+ Error = Class.new(Arrthorizer::ArrthorizerException)
5
+
6
+ def initialize(&block)
7
+ yield self
8
+ rescue LocalJumpError
9
+ raise Error, "No builder block provided to ContextBuilder.new"
10
+ end
11
+
12
+ def defaults(&block)
13
+ self.defaults_block = block
14
+ end
15
+
16
+ def for_action(action, &block)
17
+ add_action_block(action, &block)
18
+ end
19
+
20
+ def block_for(action)
21
+ action_blocks.fetch(action) { defaults_block }
22
+ end
23
+
24
+ private
25
+ attr_accessor :defaults_block
26
+
27
+ def add_action_block(action, &block)
28
+ action_blocks[action] = block
29
+ end
30
+
31
+ def action_blocks
32
+ @action_blocks ||= HashWithIndifferentAccess.new
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ module Arrthorizer
2
+ module Rails
3
+ class ControllerContextBuilder < Arrthorizer::ContextBuilder
4
+ attr_accessor :controller, :configuration
5
+
6
+ def initialize(controller, configuration)
7
+ self.controller = controller
8
+ self.configuration = configuration
9
+ end
10
+
11
+ def build_default
12
+ config = config_for_action(nil)
13
+
14
+ build_from_block(&config)
15
+ end
16
+
17
+ def build_for_action
18
+ config = config_for_action(controller.action_name)
19
+
20
+ build_from_block(&config)
21
+ end
22
+
23
+ protected
24
+ def build_from_block(&config)
25
+ if block_given?
26
+ context_hash = controller.instance_eval(&config)
27
+
28
+ build_from_hash(context_hash)
29
+ else
30
+ build_from_hash({})
31
+ end
32
+ end
33
+
34
+ def config_for_action(action)
35
+ configuration.try(:block_for, action)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ module Arrthorizer
2
+ module Rails
3
+ autoload :ControllerAction, "arrthorizer/rails/controller_action"
4
+ autoload :ControllerConfiguration, "arrthorizer/rails/controller_configuration"
5
+ autoload :ControllerConcern, "arrthorizer/rails/controller_concern"
6
+ autoload :ControllerContextBuilder, "arrthorizer/rails/controller_context_builder"
7
+ autoload :Configuration, "arrthorizer/rails/configuration"
8
+
9
+ class Engine < ::Rails::Engine
10
+ config.to_prepare do
11
+ Arrthorizer::Rails::Configuration.load
12
+ end
13
+ end
14
+
15
+ module_function
16
+ def initialize!
17
+ ActionController::Base.send(:include, ControllerConcern)
18
+
19
+ if defined?(ActionController::API)
20
+ ActionController::API.send(:include, ControllerConcern)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ module Arrthorizer
2
+ class Registry
3
+ include Enumerable
4
+
5
+ NotFound = Class.new(ArrthorizerException)
6
+
7
+ def each(&block)
8
+ storage.values.each(&block)
9
+ end
10
+
11
+ def initialize
12
+ self.storage = Hash.new
13
+ end
14
+
15
+ def add(object)
16
+ storage[object.to_key] = object
17
+ end
18
+
19
+ def fetch(key, &block)
20
+ block ||= proc { raise NotFound, "Could not find value for #{key.inspect}" }
21
+
22
+ formatted_key = key.respond_to?(:to_key) ? key.to_key : key
23
+
24
+ storage.fetch(formatted_key, &block)
25
+ end
26
+
27
+ private
28
+ attr_accessor :storage
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ # This is the abstract superclass for all roles in the hierarchy.
2
+ module Arrthorizer
3
+ class Role
4
+ # Template method: This method is implemented in the
5
+ # ContextRole subclasses.
6
+ def applies_to_user?(user, context = {})
7
+ raise NotImplementedError, "#{self.name} does not implement #applies_to_user?(user, context)"
8
+ end
9
+
10
+ def self.get(name_or_role)
11
+ if name_or_role.respond_to?(:instance)
12
+ get(name_or_role.instance)
13
+ else
14
+ registry.fetch(name_or_role)
15
+ end
16
+ end
17
+
18
+ def self.register(role)
19
+ registry.add(role)
20
+ end
21
+
22
+ def self.registry
23
+ @registry ||= Registry.new
24
+ end
25
+
26
+ def to_key
27
+ name
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,19 @@
1
+ module Arrthorizer
2
+ class Everybody < Arrthorizer::ContextRole
3
+ def applies_to_user?(*args)
4
+ true
5
+ end
6
+ end
7
+
8
+ class Nobody < Arrthorizer::ContextRole
9
+ def applies_to_user?(*args)
10
+ false
11
+ end
12
+ end
13
+
14
+ class LoggedInUser < Arrthorizer::ContextRole
15
+ def applies_to_user?(user, context)
16
+ !user.nil?
17
+ end
18
+ end
19
+ end