grant 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ coverage
2
+ rdoc
3
+ grant-*.gem
4
+ tmp/
5
+ pkg/
@@ -0,0 +1,11 @@
1
+ ## 2.0.0 (January 5, 2011)
2
+
3
+ Features:
4
+
5
+ - Removed the ability to protect adding and removing from association collections. See the [related issue](https://github.com/nearinfinity/grant/issues#issue/1) for details
6
+
7
+ ## 1.0.1 (December 29, 2010)
8
+
9
+ Changes:
10
+
11
+ - Changed Grant from strictly a Rails plugin to a Ruby gem. No functionality changes or bug fixes.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in grant.gemspec
4
+ gemspec
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ grant (2.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ activemodel (3.0.5)
10
+ activesupport (= 3.0.5)
11
+ builder (~> 2.1.2)
12
+ i18n (~> 0.4)
13
+ activerecord (3.0.5)
14
+ activemodel (= 3.0.5)
15
+ activesupport (= 3.0.5)
16
+ arel (~> 2.0.2)
17
+ tzinfo (~> 0.3.23)
18
+ activesupport (3.0.5)
19
+ arel (2.0.9)
20
+ builder (2.1.2)
21
+ diff-lcs (1.1.2)
22
+ i18n (0.5.0)
23
+ rspec (2.5.0)
24
+ rspec-core (~> 2.5.0)
25
+ rspec-expectations (~> 2.5.0)
26
+ rspec-mocks (~> 2.5.0)
27
+ rspec-core (2.5.1)
28
+ rspec-expectations (2.5.0)
29
+ diff-lcs (~> 1.1.2)
30
+ rspec-mocks (2.5.0)
31
+ sqlite3 (1.3.3)
32
+ sqlite3-ruby (1.3.3)
33
+ sqlite3 (>= 1.3.3)
34
+ tzinfo (0.3.24)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ activerecord (> 3.0.0)
41
+ grant!
42
+ rspec (= 2.5.0)
43
+ sqlite3-ruby (= 1.3.3)
@@ -26,7 +26,10 @@ Lastly, Grant can also be installed as a Rails plugin
26
26
 
27
27
  = Setup
28
28
 
29
- Grant needs to know who the current user is, but with no standard for doing so you'll have to do a little work to set things up. You simply need to set your current user model object as the Grant current user before any CRUD operations are performed. For example, in a Rails application you could add the following to your application_controller.rb
29
+ Grant needs to know who the current user is, but with no standard for
30
+ doing so you'll have to do a little work to set things up unless your
31
+ ApplicationController exposes a current_user method. If you don't
32
+ have a current_user method in ApplicationController, you simply need to set your current user model object as the Grant current user before any CRUD operations are performed. For example, in a Rails application you could add the following to your application_controller.rb
30
33
 
31
34
  class ApplicationController < ActionController::Base
32
35
  before_filter :set_current_user
@@ -38,14 +41,16 @@ Grant needs to know who the current user is, but with no standard for doing so y
38
41
  end
39
42
  end
40
43
 
44
+ The above is essentially what Grant does if you have a current_user
45
+ method in ApplicationController.
46
+
41
47
  = Usage
42
48
 
43
- To enable model security you simply include the Grant::ModelSecurity module in your model class. In the example below you see two grant statements. The first grants find (aka read) permission all the time. The second example grants create, update, and destroy permission when the passed block evaluates to true, which in this case happens when the model is editable by the current user. A Grant::Error is raised if any grant block evaluates to false or nil.
49
+ To enable grant you simply start calling the grant method.
50
+ Grant will initialize itself on the first invocation of the grant method
51
+ in a class. In the example below you see two grant statements. The first grants find (aka read) permission all the time. The second example grants create, update, and destroy permission when the passed block evaluates to true, which in this case happens when the model is editable by the current user. A Grant::Error is raised if any grant block evaluates to false or nil.
44
52
 
45
53
  class Book < ActiveRecord::Base
46
- include Grant::ModelSecurity
47
-
48
- has_many :tags
49
54
  grant(:find) { true }
50
55
  grant(:create, :update, :destroy) { |user, model| model.editable_by_user? user }
51
56
 
@@ -58,10 +63,12 @@ The valid actions to pass to a grant statement are :find, :create, :update, and
58
63
 
59
64
  = Integration
60
65
 
61
- There may be some instances where you need to perform an action on your model object without Grant stepping in and stopping you. In those cases you can include the Grant::Integration module for help.
66
+ There may be some instances where you need to perform an action on your
67
+ model object without Grant stepping in and stopping you. In those cases
68
+ you can include the Grant::Status module for help.
62
69
 
63
70
  class BooksController < ApplicationController
64
- include Grant::Integration
71
+ include Grant::Status
65
72
 
66
73
  def update
67
74
  book = Book.find(params[:id])
@@ -69,4 +76,4 @@ There may be some instances where you need to perform an action on your model ob
69
76
  end
70
77
  end
71
78
 
72
- Copyright (c) 2010 Near Infinity Corporation, released under the MIT license
79
+ Copyright (c) 2011 Near Infinity Corporation, released under the MIT license
@@ -0,0 +1,33 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+
3
+ require 'rake'
4
+ require 'rake/rdoctask'
5
+ require 'rspec/core/rake_task'
6
+ require 'bundler'
7
+
8
+ Bundler::GemHelper.install_tasks
9
+
10
+ desc 'Default: run specs'
11
+ task :default => :spec
12
+
13
+ desc "Run specs"
14
+ RSpec::Core::RakeTask.new do |t|
15
+ t.rspec_opts = %w(-fs --color)
16
+ end
17
+
18
+ desc "Run specs with RCov"
19
+ RSpec::Core::RakeTask.new(:rcov) do |t|
20
+ t.rspec_opts = %w(-fs --color)
21
+ t.rcov = true
22
+ t.rcov_opts = %w(--exclude "spec/*,gems/*")
23
+ end
24
+
25
+ desc 'Generate documentation for the gem.'
26
+ Rake::RDocTask.new(:rdoc) do |rdoc|
27
+ rdoc.rdoc_dir = 'rdoc'
28
+ rdoc.title = 'Grant'
29
+ rdoc.options << '--line-numbers' << '--inline-source'
30
+ rdoc.rdoc_files.include('README.rdoc')
31
+ rdoc.rdoc_files.include('lib/**/*.rb')
32
+ end
33
+
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'grant/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "grant"
7
+ s.version = Grant::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jeff Kunkle", "Matt Wizeman"]
10
+ s.homepage = "http://github.com/nearinfinity/grant"
11
+ s.summary = "Conscious security constraints for your ActiveRecord model objects"
12
+ s.description = "Grant is a Ruby gem and Rails plugin that forces you to make explicit security decisions about the operations performed on your ActiveRecord models."
13
+ s.license = "MIT"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency('rspec', '2.5.0')
21
+ s.add_development_dependency('sqlite3-ruby', '1.3.3')
22
+ s.add_development_dependency('activerecord', '> 3.0.0')
23
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'grant'
@@ -1,8 +1,26 @@
1
+ require 'active_record'
2
+ require 'grant/grantable'
3
+
4
+ # TODO: Remove these two requires when backwards compatibility with grant 2.0.0
5
+ # is no longer necessary
1
6
  require 'grant/integration'
2
7
  require 'grant/model_security'
3
- require 'grant/user'
4
- require 'grant/version'
5
8
 
6
9
  module Grant
7
10
  class Error < StandardError; end
8
- end
11
+ end
12
+
13
+ ActiveRecord::Base.send :include, Grant::Grantable
14
+
15
+ if defined?(ActionController) and defined?(ActionController::Base)
16
+
17
+ require 'grant/user'
18
+
19
+ ActionController::Base.class_eval do
20
+ before_filter do
21
+ Grant::User.current_user = self.current_user if self.respond_to?(:current_user)
22
+ end
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,22 @@
1
+ module Grant
2
+ class Config
3
+ attr_reader :actions
4
+
5
+ def self.valid_actions
6
+ @valid_actions ||= [:create, :find, :update, :destroy]
7
+ end
8
+
9
+ def initialize(*args)
10
+ @actions = args.map(&:to_sym)
11
+ validate_actions(@actions)
12
+ end
13
+
14
+ private
15
+
16
+ def validate_actions(actions)
17
+ raise Grant::Error.new "at least one action in #{Config.valid_actions.inspect} must be specified" if actions.empty?
18
+ raise Grant::Error.new "#{Config.valid_actions.inspect} are the only valid actions" unless actions.all? { |a| Config.valid_actions.include?(a.to_sym) }
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,41 @@
1
+ require 'grant/status'
2
+ require 'grant/config'
3
+ require 'grant/grantor'
4
+
5
+ module Grant
6
+ module Grantable
7
+
8
+ def self.included(base)
9
+ base.extend(ClassMethods)
10
+ end
11
+
12
+ module ClassMethods
13
+ def grant(*args, &blk)
14
+ include Grant::Status unless self.included_modules.include?(Grant::Status)
15
+ initialize_grant unless grant_initialized?
16
+
17
+ config = Grant::Config.new(*args)
18
+ config.actions.each do |action|
19
+ @grant_callbacks[action.to_sym].callback = blk
20
+ end
21
+ end
22
+
23
+ def initialize_grant
24
+ @grant_callbacks ||= {}
25
+ Grant::Config.valid_actions.each do |action|
26
+ grantor = Grant::Grantor.new(action)
27
+ @grant_callbacks[action] = grantor
28
+ send "#{action == :find ? 'after' : 'before'}_#{action}", grantor
29
+ end
30
+ @grant_initialized = true
31
+ end
32
+
33
+ def grant_initialized?
34
+ @grant_initialized == true
35
+ end
36
+ end
37
+
38
+ # ActiveRecord won't call the after_find handler unless it see's a specific after_find method defined
39
+ def after_find; end unless method_defined?(:after_find)
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ require 'grant/status'
2
+
3
+ module Grant
4
+ class Grantor
5
+ include Status
6
+
7
+ attr_writer :callback
8
+
9
+ def initialize(action)
10
+ self.class.send(:define_method, "#{action == :find ? 'after' : 'before'}_#{action}") do |model|
11
+ user = Grant::User.current_user
12
+ error(user, action, self) unless grant_disabled? || (@callback != nil && @callback.call(user, model))
13
+ end
14
+ end
15
+
16
+ def error(user, action, model)
17
+ msg = ["#{action} permission",
18
+ "not granted to #{user.class.name}:#{user.id}",
19
+ "for resource #{model.class.name}:#{model.id}"]
20
+ raise Grant::Error.new(msg.join(' '))
21
+ end
22
+ end
23
+ end
@@ -1,49 +1,7 @@
1
- require 'grant/thread_status'
2
-
1
+ # TODO: Remove this file when backwards compatibility with grant 2.0.0
2
+ # is no longer necessary
3
3
  module Grant
4
4
  module Integration
5
-
6
- def without_grant
7
- previously_disabled = grant_disabled?
8
- disable_grant
9
-
10
- begin
11
- result = yield if block_given?
12
- ensure
13
- enable_grant unless previously_disabled
14
- end
15
-
16
- result
17
- end
18
-
19
- def with_grant
20
- previously_disabled = grant_disabled?
21
- enable_grant
22
-
23
- begin
24
- result = yield if block_given?
25
- ensure
26
- disable_grant if previously_disabled
27
- end
28
-
29
- result
30
- end
31
-
32
- def disable_grant
33
- Grant::ThreadStatus.disable
34
- end
35
-
36
- def enable_grant
37
- Grant::ThreadStatus.enable
38
- end
39
-
40
- def grant_disabled?
41
- Grant::ThreadStatus.disabled?
42
- end
43
-
44
- def grant_enabled?
45
- Grant::ThreadStatus.enabled?
46
- end
47
-
5
+ include Status
48
6
  end
49
- end
7
+ end
@@ -1,55 +1,9 @@
1
- require 'grant/config_parser'
2
- require 'grant/user'
3
- require 'grant/thread_status'
1
+ # TODO: Remove this file when backwards compatibility with grant 2.0.0
2
+ # is no longer necessary
3
+ require 'grant/grantable'
4
4
 
5
5
  module Grant
6
6
  module ModelSecurity
7
-
8
- def self.included(base)
9
- [:create, :update, :destroy, :find].each do |action|
10
- callback = (action == :find ? "after_#{action}" : "before_#{action}")
11
- base.class_eval <<-RUBY
12
- def grant_#{callback}
13
- grant_raise_error(grant_current_user, '#{action}', self) unless grant_disabled?
14
- end
15
- RUBY
16
- base.send(callback.to_sym, "grant_#{callback}".to_sym)
17
- end
18
-
19
- base.extend ClassMethods
20
- end
21
-
22
- # ActiveRecord won't call the after_find handler unless it see's a specific after_find method defined
23
- def after_find; end
24
-
25
- def grant_current_user
26
- Grant::User.current_user
27
- end
28
-
29
- def grant_disabled?
30
- Grant::ThreadStatus.disabled? || @grant_disabled
31
- end
32
-
33
- def grant_raise_error(user, action, model, association_id=nil)
34
- msg = ["#{action} permission",
35
- "not granted to #{user.class.name}:#{user.id}",
36
- "for resource #{model.class.name}:#{model.id}"]
37
-
38
- raise Grant::Error.new(msg.join(' '))
39
- end
40
-
41
- module ClassMethods
42
- def grant(*args, &blk)
43
- actions = Grant::ConfigParser.extract_config(args)
44
- actions.each do |action|
45
- grant_callback = (action.to_sym == :find ? "grant_after_find" : "grant_before_#{action}").to_sym
46
- define_method(grant_callback) do
47
- grant_raise_error(grant_current_user, action, self) unless grant_disabled? || blk.call(grant_current_user, self)
48
- end
49
- end
50
- end
51
- end
52
-
7
+ include Grant::Grantable unless self.included_modules.include?(Grant::Grantable)
53
8
  end
54
-
55
9
  end
@@ -1,21 +1,21 @@
1
- require 'grant/integration'
1
+ require 'grant/status'
2
2
 
3
3
  module Grant
4
4
  module SpecHelpers
5
- include Grant::Integration
6
-
5
+ include Grant::Status
6
+
7
7
  def self.included(base)
8
8
  base.class_eval do
9
9
  before(:each) do
10
10
  disable_grant
11
11
  end
12
-
12
+
13
13
  after(:each) do
14
14
  enable_grant
15
15
  end
16
16
  end
17
17
  end
18
-
18
+
19
19
  end
20
20
  end
21
21