lockdown_vail 1.6.2.1

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 (67) hide show
  1. data/.gitignore +6 -0
  2. data/README.txt +36 -0
  3. data/Rakefile +38 -0
  4. data/VERSION +1 -0
  5. data/lib/lockdown/context.rb +41 -0
  6. data/lib/lockdown/database.rb +41 -0
  7. data/lib/lockdown/errors.rb +11 -0
  8. data/lib/lockdown/frameworks/rails/controller.rb +187 -0
  9. data/lib/lockdown/frameworks/rails/view.rb +50 -0
  10. data/lib/lockdown/frameworks/rails.rb +114 -0
  11. data/lib/lockdown/helper.rb +111 -0
  12. data/lib/lockdown/orms/active_record.rb +68 -0
  13. data/lib/lockdown/permission.rb +222 -0
  14. data/lib/lockdown/references.rb +19 -0
  15. data/lib/lockdown/rspec_helper.rb +114 -0
  16. data/lib/lockdown/rules.rb +372 -0
  17. data/lib/lockdown/session.rb +66 -0
  18. data/lib/lockdown/system.rb +58 -0
  19. data/lib/lockdown.rb +87 -0
  20. data/lockdown.gemspec +118 -0
  21. data/lockdown_vail.gemspec +120 -0
  22. data/rails_generators/lockdown/lockdown_generator.rb +274 -0
  23. data/rails_generators/lockdown/templates/app/controllers/permissions_controller.rb +22 -0
  24. data/rails_generators/lockdown/templates/app/controllers/sessions_controller.rb +39 -0
  25. data/rails_generators/lockdown/templates/app/controllers/user_groups_controller.rb +122 -0
  26. data/rails_generators/lockdown/templates/app/controllers/users_controller.rb +117 -0
  27. data/rails_generators/lockdown/templates/app/helpers/permissions_helper.rb +2 -0
  28. data/rails_generators/lockdown/templates/app/helpers/user_groups_helper.rb +2 -0
  29. data/rails_generators/lockdown/templates/app/helpers/users_helper.rb +2 -0
  30. data/rails_generators/lockdown/templates/app/models/permission.rb +13 -0
  31. data/rails_generators/lockdown/templates/app/models/profile.rb +10 -0
  32. data/rails_generators/lockdown/templates/app/models/user.rb +95 -0
  33. data/rails_generators/lockdown/templates/app/models/user_group.rb +15 -0
  34. data/rails_generators/lockdown/templates/app/views/permissions/index.html.erb +16 -0
  35. data/rails_generators/lockdown/templates/app/views/permissions/show.html.erb +26 -0
  36. data/rails_generators/lockdown/templates/app/views/sessions/new.html.erb +12 -0
  37. data/rails_generators/lockdown/templates/app/views/user_groups/edit.html.erb +33 -0
  38. data/rails_generators/lockdown/templates/app/views/user_groups/index.html.erb +20 -0
  39. data/rails_generators/lockdown/templates/app/views/user_groups/new.html.erb +31 -0
  40. data/rails_generators/lockdown/templates/app/views/user_groups/show.html.erb +29 -0
  41. data/rails_generators/lockdown/templates/app/views/users/edit.html.erb +51 -0
  42. data/rails_generators/lockdown/templates/app/views/users/index.html.erb +22 -0
  43. data/rails_generators/lockdown/templates/app/views/users/new.html.erb +50 -0
  44. data/rails_generators/lockdown/templates/app/views/users/show.html.erb +33 -0
  45. data/rails_generators/lockdown/templates/config/initializers/lockit.rb +1 -0
  46. data/rails_generators/lockdown/templates/db/migrate/create_admin_user.rb +17 -0
  47. data/rails_generators/lockdown/templates/db/migrate/create_permissions.rb +19 -0
  48. data/rails_generators/lockdown/templates/db/migrate/create_profiles.rb +26 -0
  49. data/rails_generators/lockdown/templates/db/migrate/create_user_groups.rb +19 -0
  50. data/rails_generators/lockdown/templates/db/migrate/create_users.rb +17 -0
  51. data/rails_generators/lockdown/templates/lib/lockdown/README +42 -0
  52. data/rails_generators/lockdown/templates/lib/lockdown/init.rb +136 -0
  53. data/spec/lockdown/context_spec.rb +191 -0
  54. data/spec/lockdown/database_spec.rb +66 -0
  55. data/spec/lockdown/frameworks/rails/controller_spec.rb +240 -0
  56. data/spec/lockdown/frameworks/rails/view_spec.rb +87 -0
  57. data/spec/lockdown/frameworks/rails_spec.rb +163 -0
  58. data/spec/lockdown/permission_spec.rb +156 -0
  59. data/spec/lockdown/rspec_helper_spec.rb +41 -0
  60. data/spec/lockdown/rules_spec.rb +245 -0
  61. data/spec/lockdown/session_spec.rb +125 -0
  62. data/spec/lockdown/system_spec.rb +51 -0
  63. data/spec/lockdown_spec.rb +19 -0
  64. data/spec/rcov.opts +5 -0
  65. data/spec/spec.opts +3 -0
  66. data/spec/spec_helper.rb +8 -0
  67. metadata +140 -0
@@ -0,0 +1,111 @@
1
+ require 'active_support'
2
+
3
+ module Lockdown
4
+ module Helper
5
+ def class_name_from_file(str)
6
+ str.split(".")[0].split("/").collect{|s| camelize(s) }.join("::")
7
+ end
8
+
9
+ # If str_sym is a Symbol (:users), return "Users"
10
+ # If str_sym is a String ("Users"), return :users
11
+ def convert_reference_name(str_sym)
12
+ if str_sym.is_a?(Symbol)
13
+ titleize(str_sym)
14
+ else
15
+ str_sym.underscore.tr(' ','_').to_sym
16
+ end
17
+ end
18
+
19
+ def user_group_class
20
+ eval(user_group_model_string)
21
+ end
22
+
23
+ def user_groups_hbtm_reference
24
+ user_group_model_string.underscore.pluralize.to_sym
25
+ end
26
+
27
+ def user_group_id_reference
28
+ user_group_model_string.underscore + "_id"
29
+ end
30
+
31
+ def user_class
32
+ eval(user_model_string)
33
+ end
34
+
35
+ def users_hbtm_reference
36
+ user_model_string.underscore.pluralize.to_sym
37
+ end
38
+
39
+ def user_id_reference
40
+ user_model_string.underscore + "_id"
41
+ end
42
+
43
+ def user_group_model_string
44
+ Lockdown.system.fetch(:user_group_model) || "UserGroup"
45
+ end
46
+
47
+ def user_model_string
48
+ Lockdown.system.fetch(:user_model) || "User"
49
+ end
50
+
51
+ def get_string(value)
52
+ if value.respond_to?(:name)
53
+ string_name(value.name)
54
+ else
55
+ string_name(value)
56
+ end
57
+ end
58
+
59
+ def get_symbol(value)
60
+ if value.respond_to?(:name)
61
+ symbol_name(value.name)
62
+ elsif value.is_a?(String)
63
+ symbol_name(value)
64
+ else
65
+ value
66
+ end
67
+ end
68
+
69
+ def camelize(str)
70
+ str.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
71
+ end
72
+
73
+ def random_string(len = 10)
74
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
75
+ Array.new(len){||chars[rand(chars.size)]}.join
76
+ end
77
+
78
+ def administrator_group_string
79
+ string_name(administrator_group_symbol)
80
+ end
81
+
82
+ def administrator_group_symbol
83
+ :administrators
84
+ end
85
+
86
+ private
87
+
88
+ def string_name(str_sym)
89
+ str_sym.is_a?(Symbol) ? convert_reference_name(str_sym) : str_sym
90
+ end
91
+
92
+ def symbol_name(str_sym)
93
+ str_sym.is_a?(String) ? convert_reference_name(str_sym) : str_sym
94
+ end
95
+
96
+ def titleize(str)
97
+ humanize(underscore(str)).gsub(/\b([a-z])/) { $1.capitalize }
98
+ end
99
+
100
+ def humanize(str)
101
+ str.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
102
+ end
103
+
104
+ def underscore(str)
105
+ str.to_s.gsub(/::/, '/').
106
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
107
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
108
+ tr("-", "_").downcase
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,68 @@
1
+ module Lockdown
2
+ module Orms
3
+ module ActiveRecord
4
+ class << self
5
+ def use_me?
6
+ Object.const_defined?("ActiveRecord") && ::ActiveRecord.const_defined?("Base")
7
+ end
8
+
9
+ def included(mod)
10
+ mod.extend Lockdown::Orms::ActiveRecord::Helper
11
+ mixin
12
+ end
13
+
14
+ def mixin
15
+ Lockdown.orm_parent.class_eval do
16
+ include Lockdown::Orms::ActiveRecord::Stamps
17
+ end
18
+ end
19
+ end # class block
20
+
21
+ module Helper
22
+ def orm_parent
23
+ ::ActiveRecord::Base
24
+ end
25
+
26
+ def database_execute(query)
27
+ orm_parent.connection.execute(query)
28
+ end
29
+
30
+ def database_query(query)
31
+ orm_parent.connection.execute(query)
32
+ end
33
+
34
+ def database_table_exists?(klass)
35
+ klass.table_exists?
36
+ end
37
+ end
38
+
39
+ module Stamps
40
+ def self.included(base)
41
+ base.class_eval do
42
+ alias_method :create_without_stamps, :create
43
+ alias_method :create, :create_with_stamps
44
+ alias_method :update_without_stamps, :update
45
+ alias_method :update, :update_with_stamps
46
+ end
47
+ end
48
+
49
+ def current_who_did_it
50
+ Thread.current[:who_did_it]
51
+ end
52
+
53
+ def create_with_stamps
54
+ pid = current_who_did_it || Lockdown::System.fetch(:default_who_did_it)
55
+ self[:created_by] = pid if self.respond_to?(:created_by)
56
+ self[:updated_by] = pid if self.respond_to?(:updated_by)
57
+ create_without_stamps
58
+ end
59
+
60
+ def update_with_stamps
61
+ pid = current_who_did_it || Lockdown::System.fetch(:default_who_did_it)
62
+ self[:updated_by] = pid if self.respond_to?(:updated_by)
63
+ update_without_stamps
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,222 @@
1
+ module Lockdown
2
+ class Controller
3
+ attr_accessor :name, :access_methods, :only_methods, :except_methods
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ @except_methods = []
8
+ end
9
+
10
+ def set_access_methods
11
+ if @only_methods
12
+ @access_methods = paths_for(@name, *@only_methods)
13
+ else
14
+ @access_methods = paths_for(@name)
15
+ end
16
+
17
+ apply_exceptions if @except_methods.length > 0
18
+ end
19
+
20
+ private
21
+
22
+ def apply_exceptions
23
+ exceptions = paths_for(@name, *@except_methods)
24
+ @access_methods = @access_methods - exceptions
25
+ end
26
+
27
+ def paths_for(str_sym, *methods)
28
+ Lockdown::System.paths_for(str_sym, *methods)
29
+ end
30
+ end
31
+
32
+ class Model
33
+ attr_accessor :name, :controller_method, :model_method, :association, :param
34
+
35
+ def initialize(name, param = :id)
36
+ @name = name
37
+ @param = param
38
+ end
39
+
40
+ def class_name
41
+ self.name.to_s.camelize
42
+ end
43
+
44
+ end
45
+
46
+ class Permission
47
+ attr_reader :name, :controllers, :models
48
+
49
+ # A Permission is a set of rules that are, through UserGroups, assigned
50
+ # to users to allow access to system resources.
51
+ #
52
+ # ==== Summary of controller oriented methods:
53
+ #
54
+ # # defines which controller we're talking about
55
+ # .with_controller(:controller_name) #all_methods is the default
56
+ #
57
+ # # only these methods on the controller
58
+ # .only_methods(:meth1, :meth2)
59
+ #
60
+ # # all controller methods except these
61
+ # .except_methods(:meth1, :meth2)
62
+ #
63
+ # ==== Summary of model oriented methods:
64
+ #
65
+ # # defines which model we're talking about
66
+ # .to_model(:model)
67
+ #
68
+ # # model_method is simply a public method on :model
69
+ # .where(:model_method)
70
+ #
71
+ # # controller_method must equal model_method
72
+ # .equals(:controller_method)
73
+ #
74
+ # # controller_method.include?(model_method)
75
+ # .is_in(:controller_method)
76
+ #
77
+ #
78
+ # ==== Example:
79
+ #
80
+ # # Define a permission called 'Manage Users' that allows users access
81
+ # # all methods on the users_controller
82
+ #
83
+ # set_permission(:manage_users).
84
+ # with_controller(:users)
85
+ #
86
+ # # Define a permission called "My Account" that only allows a user access
87
+ # # to methods show and update and the current_user_id must match the id
88
+ # # of the user being modified
89
+ #
90
+ # set_permission(:my_account).
91
+ # with_controller(:users).
92
+ # only_methods(:show, :update).
93
+ # to_model(:user).
94
+ # where(:current_user_id).
95
+ # equals(:id)
96
+ #
97
+ def initialize(name_symbol)
98
+ @name = name_symbol
99
+ @controllers = {}
100
+ @models = {}
101
+ @current_context = Lockdown::RootContext.new(name_symbol)
102
+ @public_access = false
103
+ @protected_access = false
104
+ end
105
+
106
+ def with_controller(name_symbol)
107
+ validate_context
108
+
109
+ controller = Controller.new(name_symbol)
110
+ @controllers[name_symbol] = controller
111
+ @current_context = Lockdown::ControllerContext.new(name_symbol)
112
+ self
113
+ end
114
+
115
+ alias_method :and_controller, :with_controller
116
+
117
+ def only_methods(*methods)
118
+ validate_context
119
+
120
+ current_controller.only_methods = methods
121
+ @current_context = Lockdown::RootContext.new(@name)
122
+ self
123
+ end
124
+
125
+ def except_methods(*methods)
126
+ validate_context
127
+
128
+ current_controller.except_methods = methods
129
+
130
+ @current_context = Lockdown::RootContext.new(@name)
131
+ self
132
+ end
133
+
134
+ def to_model(name_symbol, param = :id)
135
+ validate_context
136
+
137
+ @models[name_symbol] = Model.new(name_symbol, param)
138
+ @current_context = Lockdown::ModelContext.new(name_symbol)
139
+ self
140
+ end
141
+
142
+ def where(model_method)
143
+ validate_context
144
+
145
+ current_model.model_method = model_method
146
+ @current_context = Lockdown::ModelWhereContext.new(current_context.name)
147
+ self
148
+ end
149
+
150
+ def equals(controller_method)
151
+ validate_context
152
+
153
+ associate_controller_method(controller_method, :==)
154
+ @current_context = Lockdown::RootContext.new(@name)
155
+ self
156
+ end
157
+
158
+ def is_in(controller_method)
159
+ validate_context
160
+
161
+ associate_controller_method(controller_method, :include?)
162
+ @current_context = Lockdown::RootContext.new(@name)
163
+ self
164
+ end
165
+
166
+ alias_method :includes, :is_in
167
+
168
+ def public_access?
169
+ @public_access
170
+ end
171
+
172
+ def protected_access?
173
+ @protected_access
174
+ end
175
+
176
+ def set_as_public_access
177
+ if protected_access?
178
+ raise Lockdown::PermissionScopeCollision, "Permission: #{name} already marked as protected and trying to set as public."
179
+ end
180
+ @public_access = true
181
+ end
182
+
183
+ def set_as_protected_access
184
+ if public_access?
185
+ raise Lockdown::PermissionScopeCollision, "Permission: #{name} already marked as public and trying to set as protected."
186
+ end
187
+ @protected_access = true
188
+ end
189
+
190
+ def current_context
191
+ @current_context
192
+ end
193
+
194
+ def current_controller
195
+ @controllers[current_context.name]
196
+ end
197
+
198
+ def current_model
199
+ @models[current_context.name]
200
+ end
201
+
202
+ def ==(other)
203
+ name == other.name
204
+ end
205
+
206
+ private
207
+
208
+ def associate_controller_method(controller_method, association)
209
+ current_model.controller_method = controller_method
210
+ current_model.association = association
211
+ @current_context = Lockdown::RootContext.new(@name)
212
+ end
213
+
214
+ def validate_context
215
+ method_trace = caller.first;
216
+ calling_method = caller.first[/#{__FILE__}:(\d+):in `(.*)'/,2]
217
+ unless current_context.allows?(calling_method)
218
+ raise Lockdown::InvalidRuleContext, "Method: #{calling_method} was called on wrong context #{current_context}. Allowed methods are: #{current_context.allowed_methods.join(',')}."
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,19 @@
1
+ module Lockdown
2
+ module References
3
+ def helper
4
+ Lockdown::Helper
5
+ end
6
+
7
+ def rules
8
+ Lockdown::Rules
9
+ end
10
+
11
+ def session
12
+ Lockdown::Session
13
+ end
14
+
15
+ def system
16
+ Lockdown::System
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,114 @@
1
+ module Lockdown
2
+ module RspecHelper
3
+ def self.included(mod)
4
+ Lockdown.maybe_parse_init
5
+ end
6
+
7
+ def login_admin
8
+ login_user(:admin)
9
+ end
10
+
11
+ def login_with_groups(*user_group_symbols)
12
+ user_group_symbols = [user_group_symbols] unless Array === user_group_symbols
13
+ session[:user_groups] = user_group_symbols
14
+ end
15
+
16
+ alias login_with_group login_with_groups
17
+
18
+ def login_with_permissions(*permissions_symbols)
19
+ access_rights = Lockdown::System.standard_authorized_user_rights
20
+ permissions_symbols.each do |ps|
21
+ access_rights << Lockdown::System.access_rights_for_permission(ps)
22
+ end
23
+ login_user
24
+ controller.session[:access_rights] = access_rights.flatten.uniq
25
+ end
26
+
27
+ alias login_with_permission login_with_permissions
28
+
29
+ def login_standard
30
+ login_user
31
+ end
32
+
33
+ def public_user
34
+ setup_public_user
35
+ end
36
+
37
+
38
+ private
39
+
40
+ def login_user(user_type = :standard)
41
+ initialize_user(user_type)
42
+
43
+ create_user_session
44
+
45
+ controller.stub!(:current_user).and_return(@current_user)
46
+ end
47
+
48
+ def setup_public_user
49
+ controller.session[:access_rights] = Lockdown::System.public_access
50
+ end
51
+
52
+ def all_actions(hash = {})
53
+ methods = controller.send :action_methods
54
+
55
+ if excepts = hash.delete(:except)
56
+ excepts = Array.new(excepts)
57
+ methods.reject!{|m| excepts.include?(m.to_sym)}
58
+ end
59
+
60
+ Lockdown::System.paths_for(controller.controller_name,methods.to_a).sort
61
+ end
62
+
63
+ def only_actions(*actions)
64
+ Lockdown::System.paths_for(controller.controller_name,actions).sort
65
+ end
66
+
67
+ def allowed_actions
68
+ if rights = controller.session[:access_rights]
69
+ if rights == :all
70
+ all_actions
71
+ else
72
+ name = controller.controller_name
73
+ rights.collect{|r| r if r =~ /^#{name}\// || r == name}.compact.sort
74
+ end
75
+ else
76
+ []
77
+ end
78
+ end
79
+
80
+ def initialize_user(user_type)
81
+ @current_user = mock_user
82
+
83
+ if user_type == :admin
84
+ set_user_group(Lockdown.administrator_group_symbol)
85
+ end
86
+ end
87
+
88
+ # You may want to override this method
89
+ def mock_user
90
+ mock_model User,
91
+ :user_groups => [],
92
+ :first_name => 'John',
93
+ :last_name => 'Smith',
94
+ :password => "mysecret",
95
+ :password_confirmation => "mysecret"
96
+ end
97
+
98
+ def create_user_session
99
+ controller.send :add_lockdown_session_values, @current_user
100
+ end
101
+
102
+ # Lockdown.convert_reference_name converts :users to "Users"
103
+ def set_user_group(sym)
104
+ user_group = mock_user_group
105
+ user_group.stub!(:name).and_return( Lockdown.convert_reference_name(sym) )
106
+ @current_user.stub!(Lockdown.user_groups_hbtm_reference).and_return([user_group])
107
+ end
108
+
109
+ # You may want to override this method
110
+ def mock_user_group
111
+ mock_model(UserGroup)
112
+ end
113
+ end
114
+ end