andrewzielinski-lockdown 0.9.6

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 (59) hide show
  1. data/History.txt +195 -0
  2. data/README.txt +36 -0
  3. data/Rakefile +41 -0
  4. data/lib/lockdown.rb +70 -0
  5. data/lib/lockdown/context.rb +41 -0
  6. data/lib/lockdown/database.rb +105 -0
  7. data/lib/lockdown/frameworks/rails.rb +146 -0
  8. data/lib/lockdown/frameworks/rails/controller.rb +147 -0
  9. data/lib/lockdown/frameworks/rails/view.rb +61 -0
  10. data/lib/lockdown/helper.rb +95 -0
  11. data/lib/lockdown/orms/active_record.rb +68 -0
  12. data/lib/lockdown/permission.rb +204 -0
  13. data/lib/lockdown/rules.rb +289 -0
  14. data/lib/lockdown/session.rb +57 -0
  15. data/lib/lockdown/system.rb +57 -0
  16. data/rails_generators/lockdown/lockdown_generator.rb +273 -0
  17. data/rails_generators/lockdown/templates/app/controllers/permissions_controller.rb +22 -0
  18. data/rails_generators/lockdown/templates/app/controllers/sessions_controller.rb +39 -0
  19. data/rails_generators/lockdown/templates/app/controllers/user_groups_controller.rb +122 -0
  20. data/rails_generators/lockdown/templates/app/controllers/users_controller.rb +117 -0
  21. data/rails_generators/lockdown/templates/app/helpers/permissions_helper.rb +2 -0
  22. data/rails_generators/lockdown/templates/app/helpers/user_groups_helper.rb +2 -0
  23. data/rails_generators/lockdown/templates/app/helpers/users_helper.rb +2 -0
  24. data/rails_generators/lockdown/templates/app/models/permission.rb +13 -0
  25. data/rails_generators/lockdown/templates/app/models/profile.rb +10 -0
  26. data/rails_generators/lockdown/templates/app/models/user.rb +95 -0
  27. data/rails_generators/lockdown/templates/app/models/user_group.rb +15 -0
  28. data/rails_generators/lockdown/templates/app/views/permissions/index.html.erb +16 -0
  29. data/rails_generators/lockdown/templates/app/views/permissions/show.html.erb +26 -0
  30. data/rails_generators/lockdown/templates/app/views/sessions/new.html.erb +12 -0
  31. data/rails_generators/lockdown/templates/app/views/user_groups/edit.html.erb +33 -0
  32. data/rails_generators/lockdown/templates/app/views/user_groups/index.html.erb +20 -0
  33. data/rails_generators/lockdown/templates/app/views/user_groups/new.html.erb +31 -0
  34. data/rails_generators/lockdown/templates/app/views/user_groups/show.html.erb +29 -0
  35. data/rails_generators/lockdown/templates/app/views/users/edit.html.erb +51 -0
  36. data/rails_generators/lockdown/templates/app/views/users/index.html.erb +22 -0
  37. data/rails_generators/lockdown/templates/app/views/users/new.html.erb +50 -0
  38. data/rails_generators/lockdown/templates/app/views/users/show.html.erb +33 -0
  39. data/rails_generators/lockdown/templates/config/initializers/lockit.rb +1 -0
  40. data/rails_generators/lockdown/templates/db/migrate/create_admin_user.rb +17 -0
  41. data/rails_generators/lockdown/templates/db/migrate/create_permissions.rb +19 -0
  42. data/rails_generators/lockdown/templates/db/migrate/create_profiles.rb +26 -0
  43. data/rails_generators/lockdown/templates/db/migrate/create_user_groups.rb +19 -0
  44. data/rails_generators/lockdown/templates/db/migrate/create_users.rb +17 -0
  45. data/rails_generators/lockdown/templates/lib/lockdown/README +42 -0
  46. data/rails_generators/lockdown/templates/lib/lockdown/init.rb +122 -0
  47. data/spec/lockdown/database_spec.rb +158 -0
  48. data/spec/lockdown/frameworks/rails/controller_spec.rb +224 -0
  49. data/spec/lockdown/frameworks/rails/view_spec.rb +125 -0
  50. data/spec/lockdown/frameworks/rails_spec.rb +175 -0
  51. data/spec/lockdown/permission_spec.rb +156 -0
  52. data/spec/lockdown/rules_spec.rb +109 -0
  53. data/spec/lockdown/session_spec.rb +89 -0
  54. data/spec/lockdown/system_spec.rb +59 -0
  55. data/spec/lockdown_spec.rb +19 -0
  56. data/spec/rcov.opts +5 -0
  57. data/spec/spec.opts +3 -0
  58. data/spec/spec_helper.rb +1 -0
  59. metadata +112 -0
@@ -0,0 +1,158 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+
3
+ describe Lockdown::Database do
4
+ before do
5
+ Lockdown::System.stub!(:get_permissions).and_return([:permission])
6
+ Lockdown::System.stub!(:get_user_groups).and_return([:user_group])
7
+ end
8
+
9
+ describe "#sync_with_db" do
10
+ it "should call create_new_permissions, delete_extinct_permissions and maintain_user_groups" do
11
+ Lockdown::Database.should_receive :create_new_permissions
12
+ Lockdown::Database.should_receive :delete_extinct_permissions
13
+ Lockdown::Database.should_receive :maintain_user_groups
14
+
15
+ Lockdown::Database.sync_with_db
16
+ end
17
+ end
18
+
19
+ describe "#create_new_permissions" do
20
+ it "should create permission from @permissions" do
21
+ Lockdown::System.stub!(:permission_assigned_automatically?).and_return(false)
22
+
23
+ Permission = mock('Permission') unless defined?(Permission)
24
+ Permission.stub!(:find).and_return(false)
25
+ Permission.should_receive(:create).with(:name => 'Permission')
26
+
27
+ Lockdown::Database.create_new_permissions
28
+ end
29
+ end
30
+
31
+ describe "#delete_extinct_permissions" do
32
+ it "should create permission from @permissions" do
33
+ permission = mock('permission')
34
+ permission.stub!(:id).and_return("3344")
35
+ permission.stub!(:name).and_return("sweet permission")
36
+ permissions = [permission]
37
+
38
+ Permission = mock('Permission') unless defined?(Permission)
39
+ Permission.stub!(:find).with(:all).and_return(permissions)
40
+
41
+ Lockdown.should_receive(:database_execute).
42
+ with("delete from permissions_user_groups where permission_id = 3344")
43
+ permission.should_receive(:destroy)
44
+
45
+ Lockdown::Database.delete_extinct_permissions
46
+ end
47
+ end
48
+
49
+ describe "#maintain_user_groups" do
50
+ before do
51
+ UserGroup = mock('UserGroup') unless defined?(UserGroup)
52
+ end
53
+
54
+ it "should create user group for non-existent user group" do
55
+ UserGroup.should_receive(:find).
56
+ with(:first, :conditions => ["name = ?", "User Group"]).
57
+ and_return(false)
58
+
59
+ Lockdown::Database.should_receive(:create_user_group).
60
+ with("User Group",:user_group)
61
+
62
+ Lockdown::Database.maintain_user_groups
63
+ end
64
+
65
+ it "should sync user group permissions for existing user group" do
66
+ ug = mock('user group')
67
+
68
+ UserGroup.should_receive(:find).
69
+ with(:first, :conditions => ["name = ?", "User Group"]).
70
+ and_return(ug)
71
+
72
+ Lockdown::Database.should_receive(:remove_invalid_permissions).
73
+ with(ug,:user_group)
74
+
75
+ Lockdown::Database.should_receive(:add_valid_permissions).
76
+ with(ug,:user_group)
77
+
78
+ Lockdown::Database.maintain_user_groups
79
+ end
80
+ end
81
+
82
+ describe "#create_user_group" do
83
+ it "should create new user group" do
84
+ ug = mock('user group')
85
+ ug.stub!(:id).and_return(123)
86
+
87
+ UserGroup = mock('UserGroup') unless defined?(UserGroup)
88
+
89
+ UserGroup.should_receive(:create).
90
+ with(:name => "some group").
91
+ and_return(ug)
92
+
93
+ Lockdown::System.stub!(:permissions_for_user_group).
94
+ and_return([:perm])
95
+
96
+ perm = mock('permission')
97
+ perm.stub!(:id).and_return(3344)
98
+
99
+ Permission = mock('Permission') unless defined?(Permission)
100
+
101
+ Permission.should_receive(:find).
102
+ with(:first, :conditions => ["name = ?",'Perm']).
103
+ and_return(perm)
104
+
105
+ Lockdown.should_receive(:database_execute).
106
+ with("insert into permissions_user_groups(permission_id, user_group_id) values(3344, 123)")
107
+
108
+ Lockdown::Database.create_user_group("some group", :some_group)
109
+ end
110
+ end
111
+
112
+ describe "#remove_invalid_permissions" do
113
+ it "should remove permissions that no longer exist" do
114
+ permissions = [:good_perm, :bad_perm]
115
+
116
+ user_group = mock("user group", :name => "user group")
117
+
118
+ #returns what's in the database
119
+ user_group.stub!(:permissions).and_return(permissions)
120
+
121
+ #return what's defined in init.rb
122
+ Lockdown::System.stub!(:permissions_for_user_group).
123
+ and_return([:good_perm])
124
+
125
+ #delete what's not in init.rb
126
+ permissions.should_receive(:delete).with(:bad_perm)
127
+
128
+ Lockdown::Database.remove_invalid_permissions(user_group, :user_group)
129
+ end
130
+ end
131
+
132
+ describe "#add_invalid_permissions" do
133
+ it "should add permissions that are defined in init.rb" do
134
+ #return what's defined in init.rb
135
+ Lockdown::System.stub!(:permissions_for_user_group).
136
+ and_return([:defined_perm, :undefined_perm])
137
+
138
+ permissions = [:defined_perm]
139
+
140
+ user_group = mock("user group", :name => "user group")
141
+
142
+ #returns what's in the database
143
+ user_group.stub!(:permissions).and_return(permissions)
144
+
145
+ Permission = mock('Permission') unless defined?(Permission)
146
+
147
+ #get the permission object for the undefined_perm
148
+ Permission.should_receive(:find).
149
+ with(:first, :conditions => ["name = ?",'Undefined Perm']).
150
+ and_return(:undefined_perm)
151
+
152
+ #add the perm to the user group
153
+ permissions.should_receive(:<<).with(:undefined_perm)
154
+
155
+ Lockdown::Database.add_valid_permissions(user_group, :user_group)
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,224 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. .. .. spec_helper])
2
+
3
+ class TestAController
4
+ extend Lockdown::Frameworks::Rails::Controller
5
+ include Lockdown::Frameworks::Rails::Controller::Lock
6
+ end
7
+
8
+ describe Lockdown::Frameworks::Rails::Controller do
9
+ before do
10
+ @controller = TestAController
11
+
12
+ @actions = %w(posts/index posts/show posts/new posts/edit posts/create posts/update posts/destroy)
13
+
14
+ @lockdown = mock("lockdown")
15
+ end
16
+
17
+ describe "#available_actions" do
18
+ it "should return action_methods" do
19
+ post_controller = mock("PostController")
20
+ post_controller.stub!(:action_methods).and_return(@actions)
21
+
22
+ @controller.available_actions(post_controller).
23
+ should == @actions
24
+ end
25
+
26
+ it "should eql public_instance_methods - hidden_actions unless action_methods" do
27
+ post_controller = mock("PostController")
28
+ post_controller.stub!(:public_instance_methods).and_return(["m1", "m2", "h1"])
29
+ post_controller.stub!(:hidden_actions).and_return(["h1"])
30
+ @controller.available_actions(post_controller).
31
+ should == ["m1", "m2"]
32
+ end
33
+ end
34
+
35
+ describe "#controller_name" do
36
+ it "should return action_methods" do
37
+ post_controller = mock("PostController")
38
+ post_controller.stub!(:controller_name).and_return("PostController")
39
+
40
+ @controller.controller_name(post_controller).should == "PostController"
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ describe Lockdown::Frameworks::Rails::Controller::Lock do
47
+ before do
48
+ @controller = TestAController.new
49
+
50
+ @actions = %w(posts/index posts/show posts/new posts/edit posts/create posts/update posts/destroy)
51
+
52
+ @session = {:access_rights => @actions}
53
+
54
+ @controller.stub!(:session).and_return(@session)
55
+ end
56
+
57
+ describe "#configure_lockdown" do
58
+ it "should call check_session_expiry and store_location" do
59
+ @controller.should_receive(:check_session_expiry)
60
+ @controller.should_receive(:store_location)
61
+
62
+ @controller.configure_lockdown
63
+ end
64
+ end
65
+
66
+ describe "#set_current_user" do
67
+ it "should set who_did_it in Thread.current" do
68
+ Lockdown::System.stub!(:fetch).with(:who_did_it).and_return(:current_user_id)
69
+ @controller.stub!(:logged_in?).and_return(true)
70
+ @controller.stub!(:current_user_id).and_return(1234)
71
+
72
+ @controller.set_current_user
73
+
74
+ Thread.current[:who_did_it].should == 1234
75
+ end
76
+ end
77
+
78
+ describe "#check_request_authorization" do
79
+ it "should raise SecurityError if not authorized" do
80
+ @controller.stub!(:authorized?).and_return(false)
81
+ @controller.stub!(:params).and_return({:p => 1})
82
+
83
+ lambda{@controller.check_request_authorization}.
84
+ should raise_error(SecurityError)
85
+
86
+ end
87
+ end
88
+
89
+ describe "#path_allowed" do
90
+ it "should return false for an invalid path" do
91
+ @controller.path_allowed?("/no/good").should be_false
92
+ end
93
+ end
94
+
95
+ describe "#check_session_expiry" do
96
+ it "should set expiry if null" do
97
+ Lockdown::System.stub!(:fetch).with(:session_timeout).and_return(10)
98
+ @session[:expiry_time].should be_nil
99
+ @controller.check_session_expiry
100
+ @session[:expiry_time].should_not be_nil
101
+ end
102
+ end
103
+
104
+ describe "#store_location" do
105
+ it "should set prevpage and thispage" do
106
+ request = mock("request")
107
+ request.stub!(:method).and_return(:get)
108
+ @controller.stub!(:request).and_return(request)
109
+
110
+ @controller.stub!(:sent_from_uri).and_return("/blop")
111
+ @controller.store_location
112
+
113
+ @session[:prevpage].should == ''
114
+ @session[:thispage].should == '/blop'
115
+ end
116
+ end
117
+
118
+ describe "#sent_from_uri" do
119
+ it "should return request.request_uri" do
120
+ request = mock("request")
121
+ request.stub!(:request_uri).and_return("/blip")
122
+
123
+ @controller.stub!(:request).and_return(request)
124
+
125
+ @controller.sent_from_uri.should == "/blip"
126
+ end
127
+ end
128
+
129
+ describe "#authorized?" do
130
+ before do
131
+ @sample_url = "http://stonean.com/posts/index"
132
+ @a_path = "/a_path"
133
+
134
+ request = mock("request")
135
+ request.stub!(:method).and_return(:get)
136
+ @controller.stub!(:params).and_return({})
137
+ @controller.stub!(:request).and_return(request)
138
+
139
+ stonean_parts = ["http", nil, "stonean.com", nil, nil, "posts/index", nil, nil, nil]
140
+
141
+ a_path_parts = [nil, nil, nil, nil, nil, "/a_path", nil, nil, nil]
142
+
143
+ URI = mock('uri class') unless defined?(URI)
144
+ URI.stub!(:split).with(@sample_url).and_return(stonean_parts)
145
+ URI.stub!(:split).with(@a_path).and_return(a_path_parts)
146
+ end
147
+
148
+ it "should return false if url is nil" do
149
+ @controller.authorized?(nil).should be_false
150
+ end
151
+
152
+ it "should return true if current_user_is_admin" do
153
+ @controller.stub!(:current_user_is_admin?).and_return(true)
154
+ @controller.authorized?(@a_path).should be_true
155
+ end
156
+
157
+ it "should return false if path not in access_rights" do
158
+ @controller.authorized?(@a_path).should be_false
159
+ end
160
+
161
+ it "should return true if path is in access_rights" do
162
+ @controller.authorized?(@sample_url).should be_true
163
+ end
164
+
165
+ end
166
+
167
+ describe "#access_denied" do
168
+ end
169
+
170
+ describe "#path_from_hash" do
171
+ it "should return controller/action string" do
172
+ hash = {:controller => "users", :action => "show", :id => "1"}
173
+ @controller.path_from_hash(hash).should == "users/show"
174
+ end
175
+ end
176
+
177
+ describe "#remote_url?" do
178
+ it "should return false if domain is nil" do
179
+ @controller.remote_url?.should be_false
180
+ end
181
+
182
+ it "should return false if domain matches request domain" do
183
+ request = mock("request")
184
+ request.stub!(:host).and_return("stonean.com")
185
+ @controller.stub!(:request).and_return(request)
186
+ @controller.remote_url?("stonean.com").should be_false
187
+ end
188
+
189
+ it "should return true if subdomain differs" do
190
+ request = mock("request")
191
+ request.stub!(:host).and_return("blog.stonean.com")
192
+ @controller.stub!(:request).and_return(request)
193
+ @controller.remote_url?("stonean.com").should be_true
194
+ end
195
+
196
+ it "should return true if host doesn't match domain" do
197
+ request = mock("request")
198
+ request.stub!(:host).and_return("stonean.com")
199
+ @controller.stub!(:request).and_return(request)
200
+ @controller.remote_url?("google.com").should be_true
201
+ end
202
+ end
203
+
204
+ describe "#redirect_back_or_default" do
205
+ it "should redirect to default without session[:prevpage]" do
206
+ @controller.should_receive(:redirect_to).with("/")
207
+ @controller.redirect_back_or_default("/")
208
+ end
209
+
210
+ it "should redirect to session[:prevpage]" do
211
+ path = "/previous"
212
+ path.stub!(:blank?).and_return(false)
213
+ @session[:prevpage] = path
214
+ @controller.should_receive(:redirect_to).with(path)
215
+ @controller.redirect_back_or_default("/")
216
+ end
217
+ end
218
+
219
+ describe "#login_from_basic_auth?" do
220
+ end
221
+
222
+ describe "#get_auth_data" do
223
+ end
224
+ end
@@ -0,0 +1,125 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. .. .. spec_helper])
2
+
3
+ class TestAView
4
+ def link_to
5
+ "link_to"
6
+ end
7
+
8
+ def button_to
9
+ "button_to"
10
+ end
11
+
12
+ include Lockdown::Frameworks::Rails::View
13
+ end
14
+
15
+ describe Lockdown::Frameworks::Rails::Controller do
16
+
17
+ before do
18
+ @view = TestAView.new
19
+
20
+ @view.stub!(:url_for).and_return("posts/new")
21
+
22
+ @options = {:controller => "posts", :action => "new"}
23
+ end
24
+
25
+ describe "#link_to_secured" do
26
+ it "should return the link if authorized" do
27
+ link = "<a href='http://a.com'>my_link</a>"
28
+ @view.stub!(:authorized?).and_return(true)
29
+ @view.stub!(:link_to_open).and_return(link)
30
+ @view.link_to_secured("my link", @options).should == link
31
+ end
32
+
33
+ it "should return an empty string if authorized" do
34
+ @view.stub!(:authorized?).and_return(false)
35
+ @view.link_to_secured("my link", @options).should == ""
36
+ end
37
+
38
+ it "should attempt to remove a subdirectory if it exists" do
39
+ @view.should_receive(:remove_subdirectory).once
40
+ @view.stub!(:authorized?).and_return(false)
41
+ @view.link_to_secured("my link", @options).should == ""
42
+ end
43
+
44
+ end
45
+
46
+
47
+
48
+
49
+ describe "#button_to_secured" do
50
+ it "should return the link if authorized" do
51
+ link = "<a href='http://a.com'>my_link</a>"
52
+ @view.stub!(:authorized?).and_return(true)
53
+ @view.stub!(:button_to_open).and_return(link)
54
+
55
+ @view.button_to_secured("my link", @options).should == link
56
+ end
57
+
58
+ it "should return an empty string if authorized" do
59
+ @view.stub!(:authorized?).and_return(false)
60
+
61
+ @view.button_to_secured("my link", @options).should == ""
62
+ end
63
+
64
+ it "should attempt to remove a subdirectory if it exists" do
65
+ @view.should_receive(:remove_subdirectory).once
66
+ @view.stub!(:authorized?).and_return(false)
67
+ @view.button_to_secured("my link", @options).should == ""
68
+ end
69
+
70
+
71
+ end
72
+
73
+ describe "#link_to_or_show" do
74
+ it "should return the name if link_to returned an empty string" do
75
+ @view.stub!(:link_to).and_return('')
76
+
77
+ @view.link_to_or_show("my_link", @options).
78
+ should == "my_link"
79
+ end
80
+
81
+ it "should return the link if access is allowed" do
82
+ link = "<a href='http://a.com'>my_link</a>"
83
+ @view.stub!(:link_to).and_return(link)
84
+
85
+ @view.link_to_or_show("my_link", @options).
86
+ should == link
87
+ end
88
+ end
89
+
90
+ describe "#link_to_or_show" do
91
+ it "should return links separated by | " do
92
+ Lockdown::System.stub!(:fetch).with(:link_separator).and_return(' | ')
93
+ links = ["link_one", "link_two"]
94
+ @view.links(links).should == links.join(' | ')
95
+ end
96
+
97
+ it "should return links separated by | and handle empty strings" do
98
+ Lockdown::System.stub!(:fetch).with(:link_separator).and_return(' | ')
99
+ links = ["link_one", "link_two", ""]
100
+ @view.links(links).should == links.join(' | ')
101
+ end
102
+ end
103
+
104
+ describe "#remove_subdirectory" do
105
+
106
+ before(:each) do
107
+ Lockdown::System.should_receive(:fetch).with(:subdirectory).and_return 'test'
108
+ end
109
+
110
+ it "should remove subdirectory /test" do
111
+ @view.remove_subdirectory('/test/posts/new').should == '/posts/new'
112
+ end
113
+
114
+ it "should remove subdirectory 'test' without a leading /" do
115
+ @view.remove_subdirectory('test/posts/new').should == '/posts/new'
116
+ end
117
+
118
+ it "should leave the url untouched" do
119
+ @view.remove_subdirectory('/posts/new').should == '/posts/new'
120
+ end
121
+
122
+
123
+ end
124
+
125
+ end