turnstile 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest ADDED
@@ -0,0 +1,7 @@
1
+ README.rdoc
2
+ Rakefile
3
+ lib/turnstile.rb
4
+ lib/turnstile/authorization.rb
5
+ lib/turnstile/role.rb
6
+ lib/turnstile/rule.rb
7
+ Manifest
data/README.rdoc ADDED
@@ -0,0 +1,57 @@
1
+ Turnstile is a simple authorization module.
2
+ With turnstile you'll be able to define rules for each role to access your controllers and views.
3
+
4
+ = Roles, Rules and Privileges
5
+
6
+ You can define all roles, all rules and all privileges in the config file, placed in config/initializers/turnstile.rb
7
+
8
+ = Privileges
9
+
10
+
11
+ privilege :read do
12
+ allows_to :show, :index
13
+ denies_to :destroy, :create
14
+ end
15
+
16
+ privilege :manage do
17
+ allows_to :create, :new
18
+ allows_to :destroy
19
+ end
20
+
21
+
22
+ = Rules to Roles
23
+
24
+ role :reader do
25
+ can :read => :posts
26
+ can :read => :comments
27
+ end
28
+
29
+ role :admin do
30
+ inherits :reader
31
+ can :manage => :posts
32
+ end
33
+
34
+
35
+ = The Default Role
36
+
37
+
38
+ You need to set a role to be used when the current user has no role
39
+
40
+ default :reader
41
+
42
+
43
+ An example of config file can be found in config/initializers/turnstile.rb in this repo.
44
+
45
+ = The User Model
46
+
47
+ To set the model, so far it is hardcoded, so you need a string column called
48
+ user_role
49
+ in your user model, and be sure to have a method that returns the current user, called
50
+ current_user
51
+
52
+ = Controllers
53
+ For each controller that you want to monirate just call:
54
+
55
+ before_filter :verify_role_permissions!
56
+
57
+
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('turnstile', '0.1.0') do |p|
6
+ p.description = "Simple authorization for rails"
7
+ p.url = "http://github.com/milare/turnstile"
8
+ p.author = "Bruno Milare"
9
+ p.email = "milare@gmail.com"
10
+ p.ignore_pattern = ["spec/*", "config/initializers/*"]
11
+ p.development_dependencies = []
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,155 @@
1
+ # Turnstile::Authorization
2
+ # Module that is used as interface to the application
3
+ module Turnstile
4
+ module Authorization
5
+
6
+ # Keep track of all permissions defined
7
+ # A permission is defined in the setup with such as:
8
+ #
9
+ # privilege :manage do
10
+ # allows_to :create, :new
11
+ # end
12
+ @@permissions = {}
13
+
14
+ # used in tests so far, to perform the setup
15
+ def self.read_config_file
16
+ require File.expand_path(File.dirname(__FILE__) + '/../../config/initializers/turnstile')
17
+ end
18
+
19
+ # Run the config file with all definitions
20
+ def self.setup(&block)
21
+ yield if block_given?
22
+ end
23
+
24
+ # Used by tests to reset all configurations done
25
+ def self.reset
26
+ @@permissions = {}
27
+ Role.clear
28
+ end
29
+
30
+ # Finds a permission
31
+ # Turnstile::Authorization.find_permission(:manage)
32
+ def self.find_permission(permission_name)
33
+ @@permissions[permission_name]
34
+ end
35
+
36
+ # From setup defines the default role
37
+ # If the role is not found tries to define
38
+ # common names for guests
39
+ # The default role is used when there is no current role
40
+ def default(role_str)
41
+ role = Role.find(role_str.to_sym)
42
+ if !role
43
+ role ||= Role.find(:guest)
44
+ role ||= Role.find(:visitor)
45
+ if !role
46
+ Role.set_default_role(role)
47
+ else
48
+ Role.set_default_role(Role.first)
49
+ end
50
+ else
51
+ Role.set_default_role(role)
52
+ end
53
+ end
54
+
55
+
56
+ # Method used in each controller that requires authorization
57
+ # Actually it handles the requests performed by the controller
58
+ # and then check if the current_role id allowed to perfom the action
59
+ def verify_role_permissions!
60
+ if request || request.params
61
+ action = request.params[:action] ? request.params[:action] : nil
62
+ controller = request.params[:controller] ? request.params[:controller] : nil
63
+ if action and controller
64
+ if !current_role.is_allowed_to? action, controller
65
+ flash[:alert] = "Unauthorized action"
66
+ redirect_to root_path
67
+ end
68
+ else
69
+ redirect_to root_path
70
+ end
71
+ else
72
+ redirect_to root_path
73
+ end
74
+ end
75
+
76
+ # Returns the default role in this scope
77
+ def default_role
78
+ Role.default_role
79
+ end
80
+
81
+ # Helper to get current_role
82
+ # TODO: Find a way to get the current_user role in a dynamic way
83
+ # This way like current_user.user_role is too hardcoded
84
+ def current_role
85
+ current_role = current_user ? Role.find(current_user.user_role.to_sym) : nil
86
+ current_role ||= Role.default_role
87
+ end
88
+
89
+ # Set the current_role
90
+ def current_role=(role)
91
+ current_role = role
92
+ end
93
+
94
+ # Methods to define a permission
95
+ # privilege :manage do
96
+ # allows_to :create, :new
97
+ # denies_to :destroy
98
+ # end
99
+ def privilege(name, &block)
100
+ @current_permission = name
101
+ @@permissions[@current_permission] = {}
102
+ yield if block_given?
103
+ end
104
+
105
+ def allows_to(*actions)
106
+ @@permissions[@current_permission][:allow] ||= []
107
+ actions.each do |action|
108
+ @@permissions[@current_permission][:allow] << action
109
+ end
110
+ end
111
+
112
+ def denies_to(*actions)
113
+ @@permissions[@current_permission][:deny] ||= []
114
+ actions.each do |action|
115
+ @@permissions[@current_permission][:deny] << action
116
+ end
117
+ end
118
+
119
+ # Methods to set a privilege(permission) to a role
120
+ # role :admin do
121
+ # can :manage => :posts
122
+ # inherits :reader
123
+ # end
124
+ def role(role, &block)
125
+ @current_role = Role.find(role)
126
+ @current_role ||= Role.new(:name => role, :rules => [])
127
+ yield if block_given?
128
+ end
129
+
130
+ def inherits(role)
131
+ parent = Role.find(role)
132
+ parent ? @current_role.merge_rules(parent.rules) : @current_role.rules
133
+ end
134
+
135
+ def can(rules_set)
136
+ rules = []
137
+ rules_set.keys.each do |permission|
138
+ actions = Authorization.find_permission(permission)
139
+ controller = rules_set[permission]
140
+ if actions[:allow]
141
+ actions[:allow].each do |action|
142
+ rules << Rule.new(:action => action.to_s, :controller => controller.to_s, :allow => true, :active => true)
143
+ end
144
+ end
145
+ if actions[:deny]
146
+ actions[:deny].each do |action|
147
+ rules << Rule.new(:action => action.to_s, :controller => controller.to_s, :allow => false, :active => true)
148
+ end
149
+ end
150
+ end
151
+ @current_role.merge_rules(rules)
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,133 @@
1
+ # Role class
2
+ # Provides all needed methods to handle a role and its rules
3
+ class Role
4
+
5
+ attr_accessor :name, :rules
6
+
7
+ # Class variable to keep control of all roles
8
+ @@roles = {}
9
+
10
+ # Class variable to keep the default role, it means that if
11
+ # there is no current_role than the default is used
12
+ @@default = nil
13
+
14
+ # Class methods
15
+ # Adds a role to the roles hash
16
+ def self.add_role(role)
17
+ @@roles[role.name.to_sym] = role
18
+ end
19
+
20
+ def self.all_roles
21
+ @@roles
22
+ end
23
+
24
+ # Find a role by its name
25
+ # Role.find(:admin)
26
+ # returns Role or nil
27
+ def self.find(role_sym)
28
+ @@roles[role_sym]
29
+ end
30
+
31
+ def self.first
32
+ @@roles.first
33
+ end
34
+
35
+ # Remove all role from memory, used for tests so far
36
+ def self.clear
37
+ @@roles = {}
38
+ end
39
+
40
+ def self.set_default_role(role)
41
+ @@default = role
42
+ end
43
+
44
+ def self.default_role
45
+ @@default
46
+ end
47
+
48
+ def initialize(role)
49
+ @name = role[:name]
50
+ @rules = role[:rules]
51
+
52
+ # Helper for each initialized role
53
+ # is_role? for a role with name 'role'
54
+ # is_admin? when admin role is instantiated
55
+ Role.class_eval <<-METHOD
56
+ def is_#{@name}?
57
+ @name == '#{@name}'
58
+ end
59
+ METHOD
60
+
61
+ Role.add_role self
62
+ end
63
+
64
+
65
+ # Return all(array) controllers that an user can access
66
+ def accessible_controllers
67
+ controllers = []
68
+ @rules.each do |rule|
69
+ if rule.allows?
70
+ controllers << rule.controller
71
+ end
72
+ end
73
+ controllers.uniq
74
+ end
75
+
76
+ # Return the allowed actions in a controller for the current_role
77
+ def allowed_actions_in(controller)
78
+ actions = []
79
+ @rules.each do |rule|
80
+ if rule.controller == controller.to_s and rule.allows?
81
+ actions << rule.action
82
+ end
83
+ end
84
+ actions.uniq
85
+ end
86
+
87
+ # Return the denied actions in a controller for the current_role
88
+ def denied_actions_in(controller)
89
+ actions = []
90
+ @rules.each do |rule|
91
+ if rule.controller == controller.to_s and rule.denies?
92
+ actions << rule.action
93
+ end
94
+ end
95
+ actions.uniq
96
+ end
97
+
98
+ # Return if a role is allowed to perform an action in a controller
99
+ # current_role.is_allowed_to? :create, :posts
100
+ def is_allowed_to?(action, controller)
101
+ @rules.each do |rule|
102
+ if rule.action == action.to_s and rule.controller == controller.to_s
103
+ return rule.allows?
104
+ end
105
+ end
106
+ false
107
+ end
108
+
109
+ # Merges a set of rules with the current_role rules
110
+ # current_role.merge_rules(set_of_rules[])
111
+ # Used to apply rules to an user and for inheritance
112
+ def merge_rules(new_rules)
113
+ self.rules ||= []
114
+ new_set = new_rules
115
+ overwritten_set = remove_set = []
116
+
117
+ self.rules.each do |rule|
118
+ new_rules.each do |included_rule|
119
+ if included_rule.action == rule.action and included_rule.controller == rule.controller
120
+ overwritten_set << included_rule
121
+ remove_set << rule
122
+ new_set.delete(included_rule)
123
+ end
124
+ end
125
+ end
126
+ self.rules = self.rules - remove_set + overwritten_set + new_set
127
+ self.rules
128
+ end
129
+
130
+ end
131
+
132
+
133
+
@@ -0,0 +1,34 @@
1
+ # Rule class
2
+ # A simple to class to manipulate the array of rules
3
+ class Rule
4
+
5
+ attr_accessor :action, :controller, :allow, :active
6
+
7
+ def initialize(rules)
8
+
9
+ @action = rules[:action]
10
+ @controller = rules[:controller]
11
+ @allow = rules[:allow]
12
+ @active = rules[:active]
13
+ end
14
+
15
+ # The current rule allows or denies some action?
16
+ def allow_or_deny?
17
+ @allow == true ? :allow : :deny
18
+ end
19
+
20
+ def is_active?
21
+ @active
22
+ end
23
+
24
+ def allows?
25
+ @allow ? true : false
26
+ end
27
+
28
+ def denies?
29
+ @allow ? false : true
30
+ end
31
+
32
+
33
+
34
+ end
data/lib/turnstile.rb ADDED
@@ -0,0 +1,3 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/turnstile/role")
2
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/turnstile/rule")
3
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/turnstile/authorization")
data/turnstile.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{turnstile}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Bruno Milare"]
9
+ s.date = %q{2010-08-25}
10
+ s.description = %q{Simple authorization for rails}
11
+ s.email = %q{milare@gmail.com}
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/turnstile.rb", "lib/turnstile/authorization.rb", "lib/turnstile/role.rb", "lib/turnstile/rule.rb"]
13
+ s.files = ["README.rdoc", "Rakefile", "lib/turnstile.rb", "lib/turnstile/authorization.rb", "lib/turnstile/role.rb", "lib/turnstile/rule.rb", "Manifest", "turnstile.gemspec"]
14
+ s.homepage = %q{http://github.com/milare/turnstile}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Turnstile", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{turnstile}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Simple authorization for rails}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: turnstile
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Bruno Milare
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-25 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Simple authorization for rails
23
+ email: milare@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.rdoc
30
+ - lib/turnstile.rb
31
+ - lib/turnstile/authorization.rb
32
+ - lib/turnstile/role.rb
33
+ - lib/turnstile/rule.rb
34
+ files:
35
+ - README.rdoc
36
+ - Rakefile
37
+ - lib/turnstile.rb
38
+ - lib/turnstile/authorization.rb
39
+ - lib/turnstile/role.rb
40
+ - lib/turnstile/rule.rb
41
+ - Manifest
42
+ - turnstile.gemspec
43
+ has_rdoc: true
44
+ homepage: http://github.com/milare/turnstile
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --line-numbers
50
+ - --inline-source
51
+ - --title
52
+ - Turnstile
53
+ - --main
54
+ - README.rdoc
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 11
72
+ segments:
73
+ - 1
74
+ - 2
75
+ version: "1.2"
76
+ requirements: []
77
+
78
+ rubyforge_project: turnstile
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Simple authorization for rails
83
+ test_files: []
84
+