authorization 1.0.11

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the authorization plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the authorization plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Authorization'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README.txt')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+ begin
25
+ require "jeweler"
26
+ Jeweler::Tasks.new do |gem|
27
+ gem.name = "authorization"
28
+ gem.summary = "Authoization plugin for authorizing."
29
+ gem.files = Dir["*", "{lib}/**/*","{generators}/**/*","{tasks}/**/*","{doc}/**/*"]
30
+ gem.require_paths=[".","lib"]
31
+ gem.author="Bill Katz"
32
+ gem.homepage="https://github.com/g5search/rails-authorization-plugin"
33
+ gem.description="Rails 3 compatible rails-authorization-plugin gem"
34
+ end
35
+
36
+ Jeweler::GemcutterTasks.new
37
+ rescue LoadError
38
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
39
+ end
data/UPGRADE.rdoc ADDED
@@ -0,0 +1,13 @@
1
+ = Instructions for Upgrading
2
+
3
+ Scroll down to the last time you updated the plugin, then follow the upgrade steps upward till you get back to this message.
4
+
5
+ == 25/12/08 - Changes has_and_belongs_to_many to a has_many :through association
6
+
7
+ * Copy generators/role_model/templates/role_model.rb to app/models/role.rb
8
+ * Copy generators/role_model/templates/role_user_model.rb to app/models/role_user.rb
9
+ * Open each file and replace the erb code (<%= %>) with the correct model class name below
10
+
11
+ role.rb -> Role
12
+
13
+ role_user.rb -> RoleUser
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.11
data/about.yml ADDED
@@ -0,0 +1,8 @@
1
+ author: Bill Katz
2
+ summary: Adds a flexible mechanism for authorization.
3
+ description: "Adds a flexible mechanism for authorization. Differs from other authorization systems in the following ways: (1) You can specify roles programmatically with model code or use a mixin to keep roles in a database. (2) The plugin uses a clean language for specifying authorization expressions. (3) Ability to handle roles on instances of a model. (4) Rights are explicitly declared in controller and view code. (5) Different levels of authorization complexity are provided through mixins available with the plugin. If you don't want to use the database for authorization, you mixin a HardwiredRoles module. If you want full database support for roles on model instances, you mixin the ObjectRolesTable module."
4
+ homepage: http://www.writertopia.com/developers/authorization
5
+ plugin: http://svn.writertopia.com/svn/plugins/authorization/
6
+ license: MIT
7
+ version: 1.0.10
8
+ rails_version: 2.0+
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{authorization}
8
+ s.version = "1.0.11"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Bill Katz"]
12
+ s.date = %q{2010-11-10}
13
+ s.description = %q{Rails 3 compatible rails-authorization-plugin gem}
14
+ s.extra_rdoc_files = [
15
+ "README.rdoc",
16
+ "README.txt",
17
+ "README_developers.txt"
18
+ ]
19
+ s.files = [
20
+ "CHANGELOG.txt",
21
+ "MIT-LICENSE",
22
+ "README.rdoc",
23
+ "README.txt",
24
+ "README_developers.txt",
25
+ "Rakefile",
26
+ "UPGRADE.rdoc",
27
+ "VERSION",
28
+ "about.yml",
29
+ "authorization.gemspec",
30
+ "doc/authorization_example.gif",
31
+ "doc/authorization_example.rb",
32
+ "generators/role_model/USAGE",
33
+ "generators/role_model/role_model_generator.rb",
34
+ "generators/role_model/templates/fixtures.yml",
35
+ "generators/role_model/templates/migration.rb",
36
+ "generators/role_model/templates/model.rb",
37
+ "generators/role_model/templates/role_model.rb",
38
+ "generators/role_model/templates/role_user_model.rb",
39
+ "generators/role_model/templates/unit_test.rb",
40
+ "init.rb",
41
+ "install.rb",
42
+ "lib/authorization.rb",
43
+ "lib/publishare/exceptions.rb",
44
+ "lib/publishare/hardwired_roles.rb",
45
+ "lib/publishare/identity.rb",
46
+ "lib/publishare/object_roles_table.rb",
47
+ "lib/publishare/parser.rb",
48
+ "tasks/authorization_tasks.rake"
49
+ ]
50
+ s.homepage = %q{https://github.com/g5search/rails-authorization-plugin}
51
+ s.rdoc_options = ["--charset=UTF-8"]
52
+ s.require_paths = [".", "lib"]
53
+ s.rubygems_version = %q{1.3.7}
54
+ s.summary = %q{Authoization plugin for authorizing.}
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
+ else
62
+ end
63
+ else
64
+ end
65
+ end
66
+
Binary file
@@ -0,0 +1,38 @@
1
+ class MeetingController < ApplicationController
2
+
3
+ permit "rubyists and wanna_be_rubyists", :except => :public_page
4
+
5
+ def public_page
6
+ render :text => "We're all in Chicago"
7
+ end
8
+
9
+ def secret_info
10
+ permit "(matz or dhh) and interested in Answers" do
11
+ render :text => "The Answer = 42"
12
+ end
13
+ end
14
+
15
+ def find_apprentice
16
+ @founder = User.find_by_name('matz')
17
+ permit "'inner circle' of :founder" do
18
+ if request.post?
19
+ apprentice = User.find_by_skillset(params[:uber_hacker])
20
+ ruby_community = Group.find_by_name('Ruby')
21
+ ruby_community.accepts_role 'yarv_builder', apprentice
22
+ end
23
+ end
24
+ end
25
+
26
+ def rails_conf
27
+ @meeting = Meeting.find_by_name('RailsConf')
28
+ permit "attendees of :meeting or swedish_mensa_supermodels" do
29
+ venue = Hotel.find_by_name("Wyndham O'Hare")
30
+ current_user.is_traveller_to venue
31
+ if permit? "traveller to :venue and not speaker"
32
+ Partay.all_night_long
33
+ @misdeeds = current_user.is_participant_in_what
34
+ end
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,20 @@
1
+ Description:
2
+ The role_model generator creates a Role model for use with the Authorization plugin.
3
+
4
+ The generator takes a model name as its argument, which at this time must be 'Role'.
5
+
6
+ The generator creates a Role model class in app/models, a test suite in
7
+ test/unit, test fixtures in test/fixtures/roles.yml, and a migration
8
+ in the db/migrate directory.
9
+
10
+ Example:
11
+ ./script/generate role_model Role
12
+
13
+ This will create a Role model:
14
+ Model: app/models/role.rb
15
+ Test: test/unit/role_test.rb
16
+ Fixtures: test/fixtures/roles.yml
17
+ Migration: db/migrate/XXX_add_role.rb
18
+
19
+ You should then run 'rake db:migrate'.
20
+
@@ -0,0 +1,35 @@
1
+ # Shamelessly derived from Rick Olsen's acts_as_attachment
2
+ class RoleModelGenerator < Rails::Generator::NamedBase
3
+ default_options :skip_migration => false
4
+
5
+ def manifest
6
+ record do |m|
7
+ # Check for class naming collisions.
8
+ m.class_collisions class_path, class_name, "#{class_name}Test"
9
+
10
+ # Model, test, and fixture directories.
11
+ m.directory File.join('app/models', class_path)
12
+ m.directory File.join('test/unit', class_path)
13
+ m.directory File.join('test/fixtures', class_path)
14
+
15
+ # Model class, unit test, and fixtures.
16
+ m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
17
+ m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
18
+ m.template 'fixtures.yml', File.join('test/fixtures', class_path, "#{table_name}.yml")
19
+
20
+ unless options[:skip_migration]
21
+ m.migration_template 'migration.rb', 'db/migrate', :assigns => {
22
+ :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
23
+ }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
24
+ end
25
+ end
26
+ end
27
+
28
+ protected
29
+ def add_options!(opt)
30
+ opt.separator ''
31
+ opt.separator 'Options:'
32
+ opt.on("--skip-migration",
33
+ "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
+ first:
3
+ id: 1
4
+ another:
5
+ id: 2
@@ -0,0 +1,21 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :<%= (table_name < 'users') ? "#{table_name}_users" : "users_#{table_name}" %>, :id => false, :force => true do |t|
5
+ t.integer :user_id, :<%= singular_name %>_id
6
+ t.timestamps
7
+ end
8
+
9
+ create_table :<%= table_name %>, :force => true do |t|
10
+ t.string :name, :authorizable_type, :limit => 40
11
+ t.integer :authorizable_id
12
+ t.timestamps
13
+ end
14
+ end
15
+
16
+ def self.down
17
+ drop_table :<%= table_name %>
18
+ drop_table :<%= (table_name < 'users') ? "#{table_name}_users" : "users_#{table_name}" %>
19
+ end
20
+
21
+ end
@@ -0,0 +1,8 @@
1
+ # Defines named roles for users that may be applied to
2
+ # objects in a polymorphic fashion. For example, you could create a role
3
+ # "moderator" for an instance of a model (i.e., an object), a model class,
4
+ # or without any specification at all.
5
+ class <%= class_name %> < ActiveRecord::Base
6
+ has_and_belongs_to_many :users
7
+ belongs_to :authorizable, :polymorphic => true
8
+ end
@@ -0,0 +1,9 @@
1
+ # Defines named roles for users that may be applied to
2
+ # objects in a polymorphic fashion. For example, you could create a role
3
+ # "moderator" for an instance of a model (i.e., an object), a model class,
4
+ # or without any specification at all.
5
+ class <%= class_name %> < ActiveRecord::Base
6
+ has_many :roles_users, :dependent => :delete_all
7
+ has_many :users, :through => :roles_users
8
+ belongs_to :authorizable, :polymorphic => true
9
+ end
@@ -0,0 +1,5 @@
1
+ # The table that links roles with users (generally named RoleUser.rb)
2
+ class <%= (class_name < 'User') ? "#{class_name.pluralize}User" : "Users#{class_name}" %> < ActiveRecord::Base
3
+ belongs_to :user
4
+ belongs_to :role
5
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
2
+
3
+ class <%= class_name %>Test < Test::Unit::TestCase
4
+ fixtures :<%= table_name %>
5
+
6
+ # Replace this with your real tests.
7
+ def test_truth
8
+ assert true
9
+ end
10
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/lib/authorization'
data/install.rb ADDED
@@ -0,0 +1,2 @@
1
+ puts IO.read(File.join(File.dirname(__FILE__), 'README.txt'))
2
+
@@ -0,0 +1,176 @@
1
+ require File.dirname(__FILE__) + '/publishare/exceptions'
2
+ require File.dirname(__FILE__) + '/publishare/parser'
3
+
4
+ module Authorization
5
+ module Base
6
+
7
+ # Modify these constants in your environment.rb to tailor the plugin to
8
+ # your authentication system
9
+ if not Object.constants.include? "LOGIN_REQUIRED_REDIRECTION"
10
+ LOGIN_REQUIRED_REDIRECTION = {
11
+ :controller => 'session',
12
+ :action => 'new'
13
+ }
14
+ end
15
+ if not Object.constants.include? "PERMISSION_DENIED_REDIRECTION"
16
+ PERMISSION_DENIED_REDIRECTION = ''
17
+ end
18
+ if not Object.constants.include? "STORE_LOCATION_METHOD"
19
+ STORE_LOCATION_METHOD = :store_location
20
+ end
21
+
22
+ def self.included( recipient )
23
+ recipient.extend( ControllerClassMethods )
24
+ recipient.class_eval do
25
+ include ControllerInstanceMethods
26
+ end
27
+ end
28
+
29
+ module ControllerClassMethods
30
+
31
+ # Allow class-level authorization check.
32
+ # permit is used in a before_filter fashion and passes arguments to the before_filter.
33
+ def permit( authorization_expression, *args )
34
+ filter_keys = [ :only, :except ]
35
+ filter_args, eval_args = {}, {}
36
+ if args.last.is_a? Hash
37
+ filter_args.merge!( args.last.reject {|k,v| not filter_keys.include? k } )
38
+ eval_args.merge!( args.last.reject {|k,v| filter_keys.include? k } )
39
+ end
40
+ before_filter( filter_args ) do |controller|
41
+ controller.permit( authorization_expression, eval_args )
42
+ end
43
+ end
44
+ end
45
+
46
+ module ControllerInstanceMethods
47
+ include Authorization::Base::EvalParser # RecursiveDescentParser is another option
48
+
49
+ # Permit? turns off redirection by default and takes no blocks
50
+ def permit?( authorization_expression, *args )
51
+ @options = { :allow_guests => false, :redirect => false }
52
+ @options.merge!( args.last.is_a?( Hash ) ? args.last : {} )
53
+
54
+ has_permission?( authorization_expression )
55
+ end
56
+
57
+ # Allow method-level authorization checks.
58
+ # permit (without a question mark ending) calls redirect on denial by default.
59
+ # Specify :redirect => false to turn off redirection.
60
+ def permit( authorization_expression, *args )
61
+ @options = { :allow_guests => false, :redirect => true }
62
+ @options.merge!( args.last.is_a?( Hash ) ? args.last : {} )
63
+
64
+ if has_permission?( authorization_expression )
65
+ yield if block_given?
66
+ elsif @options[:redirect]
67
+ handle_redirection
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def has_permission?( authorization_expression )
74
+ @current_user = get_user
75
+ if not @options[:allow_guests]
76
+ # We aren't logged in, or an exception has already been raised.
77
+ # Test for both nil and :false symbol as restful_authentication plugin
78
+ # will set current user to ':false' on a failed login (patch by Ho-Sheng Hsiao).
79
+ if @current_user.nil? || @current_user == :false
80
+ return false
81
+ elsif not @current_user.respond_to? :id
82
+ raise( UserDoesntImplementID, "User doesn't implement #id")
83
+ elsif not @current_user.respond_to? :has_role?
84
+ raise( UserDoesntImplementRoles, "User doesn't implement #has_role?" )
85
+ end
86
+ end
87
+ parse_authorization_expression( authorization_expression )
88
+ end
89
+
90
+ # Handle redirection within permit if authorization is denied.
91
+ def handle_redirection
92
+ return if not self.respond_to?( :redirect_to )
93
+
94
+ # Store url in session for return if this is available from
95
+ # authentication
96
+ send( STORE_LOCATION_METHOD ) if respond_to? STORE_LOCATION_METHOD
97
+ if @current_user && !@current_user.nil? && @current_user != :false
98
+ flash[:notice] = @options[:permission_denied_message] || "Permission denied. You cannot access the requested page."
99
+ redirect_to @options[:permission_denied_redirection] || @current_user.uri
100
+ else
101
+ flash[:notice] = @options[:login_required_message] || "Login is required to access the requested page."
102
+ redirect_to @options[:login_required_redirection] || LOGIN_REQUIRED_REDIRECTION
103
+ end
104
+ false # Want to short-circuit the filters
105
+ end
106
+
107
+ # Try to find current user by checking options hash and instance method in that order.
108
+ def get_user
109
+ if @options[:user]
110
+ @options[:user]
111
+ elsif @options[:get_user_method]
112
+ send( @options[:get_user_method] )
113
+ elsif self.respond_to? :current_user
114
+ current_user
115
+ elsif not @options[:allow_guests]
116
+ raise( CannotObtainUserObject, "Couldn't find #current_user or @user, and nothing appropriate found in hash" )
117
+ end
118
+ end
119
+
120
+ # Try to find a model to query for permissions
121
+ def get_model( str )
122
+ if str =~ /\s*([A-Z]+\w*)\s*/
123
+ # Handle model class
124
+ begin
125
+ Module.const_get( str )
126
+ rescue
127
+ raise CannotObtainModelClass, "Couldn't find model class: #{str}"
128
+ end
129
+ elsif str =~ /\s*:*(\w+)\s*/
130
+ # Handle model instances
131
+ model_name = $1
132
+ model_symbol = model_name.to_sym
133
+ if @options[model_symbol]
134
+ @options[model_symbol]
135
+ elsif instance_variables.include?( '@'+model_name )
136
+ instance_variable_get( '@'+model_name )
137
+ # Note -- while the following code makes autodiscovery more convenient, it's a little too much side effect & security question
138
+ # elsif self.params[:id]
139
+ # eval_str = model_name.camelize + ".find(#{self.params[:id]})"
140
+ # eval eval_str
141
+ else
142
+ raise CannotObtainModelObject, "Couldn't find model (#{str}) in hash or as an instance variable"
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ end
149
+ end
150
+ ActionController::Base.send( :include, Authorization::Base ) if defined?(ActionController)
151
+ ActionView::Base.send( :include, Authorization::Base::ControllerInstanceMethods ) if defined?(ActionView)
152
+
153
+ # You can perform authorization at varying degrees of complexity.
154
+ # Choose a style of authorization below (see README.txt) and the appropriate
155
+ # mixin will be used for your app.
156
+
157
+ # When used with the auth_test app, we define this in config/environment.rb
158
+ # AUTHORIZATION_MIXIN = "hardwired"
159
+ if not Object.constants.include? "AUTHORIZATION_MIXIN"
160
+ AUTHORIZATION_MIXIN = "object roles"
161
+ end
162
+
163
+ case AUTHORIZATION_MIXIN
164
+ when "hardwired"
165
+ require File.dirname(__FILE__) + '/publishare/hardwired_roles'
166
+ ActiveRecord::Base.send( :include,
167
+ Authorization::HardwiredRoles::UserExtensions,
168
+ Authorization::HardwiredRoles::ModelExtensions
169
+ )
170
+ when "object roles"
171
+ require File.dirname(__FILE__) + '/publishare/object_roles_table'
172
+ ActiveRecord::Base.send( :include,
173
+ Authorization::ObjectRolesTable::UserExtensions,
174
+ Authorization::ObjectRolesTable::ModelExtensions
175
+ )
176
+ end