browsercms 3.0.2 → 3.0.3

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 (64) hide show
  1. data/app/controllers/cms/content_block_controller.rb +25 -2
  2. data/app/controllers/cms/content_controller.rb +31 -2
  3. data/app/controllers/cms/dashboard_controller.rb +2 -1
  4. data/app/controllers/cms/error_handling.rb +9 -2
  5. data/app/controllers/cms/links_controller.rb +2 -0
  6. data/app/controllers/cms/pages_controller.rb +22 -18
  7. data/app/controllers/cms/section_nodes_controller.rb +1 -1
  8. data/app/controllers/cms/sections_controller.rb +12 -7
  9. data/app/controllers/cms/sessions_controller.rb +17 -10
  10. data/app/controllers/cms/users_controller.rb +8 -6
  11. data/app/helpers/cms/application_helper.rb +2 -6
  12. data/app/helpers/cms/menu_helper.rb +118 -146
  13. data/app/helpers/cms/page_helper.rb +2 -2
  14. data/app/models/attachment.rb +2 -2
  15. data/app/models/group.rb +13 -2
  16. data/app/models/guest_user.rb +9 -3
  17. data/app/models/link.rb +2 -2
  18. data/app/models/page.rb +1 -1
  19. data/app/models/section.rb +7 -2
  20. data/app/models/user.rb +35 -17
  21. data/app/views/cms/blocks/_toolbar_for_member.html.erb +3 -3
  22. data/app/views/cms/blocks/index.html.erb +11 -6
  23. data/app/views/cms/content/show.html.erb +3 -3
  24. data/app/views/cms/menus/_menu.html.erb +9 -0
  25. data/app/views/cms/menus/_menu_item.html.erb +11 -0
  26. data/app/views/cms/pages/_edit_connector.html.erb +1 -1
  27. data/app/views/cms/pages/_edit_container.html.erb +1 -1
  28. data/app/views/cms/section_nodes/_node.html.erb +1 -1
  29. data/app/views/cms/sections/_form.html.erb +36 -34
  30. data/app/views/cms/shared/access_denied.html.erb +3 -0
  31. data/app/views/cms/users/change_password.html.erb +8 -6
  32. data/app/views/cms/users/index.html.erb +1 -1
  33. data/app/views/cms/users/show.html.erb +50 -0
  34. data/app/views/layouts/_cms_toolbar.html.erb +1 -1
  35. data/app/views/layouts/_page_toolbar.html.erb +7 -7
  36. data/app/views/layouts/cms/administration.html.erb +24 -7
  37. data/browsercms.gemspec +13 -7
  38. data/lib/acts_as_list.rb +8 -4
  39. data/lib/cms/acts/content_block.rb +1 -1
  40. data/lib/cms/authentication/controller.rb +26 -7
  41. data/lib/cms/behaviors/attaching.rb +3 -3
  42. data/lib/cms/behaviors/publishing.rb +12 -1
  43. data/lib/cms/behaviors/rendering.rb +17 -4
  44. data/lib/cms/behaviors/versioning.rb +2 -2
  45. data/lib/cms/routes.rb +4 -0
  46. data/lib/tasks/cms.rake +0 -18
  47. data/public/javascripts/cms/content_library.js +36 -0
  48. data/public/javascripts/cms/sitemap.js +21 -9
  49. data/public/stylesheets/cms/form_layout.css +16 -2
  50. data/public/stylesheets/cms/nav.css +4 -3
  51. data/test/functional/cms/content_block_controller_test.rb +120 -0
  52. data/test/functional/cms/content_controller_test.rb +135 -80
  53. data/test/functional/cms/links_controller_test.rb +89 -1
  54. data/test/functional/cms/pages_controller_test.rb +138 -0
  55. data/test/functional/cms/section_nodes_controller_test.rb +45 -5
  56. data/test/functional/cms/sections_controller_test.rb +148 -1
  57. data/test/functional/cms/sessions_controller_test.rb +26 -2
  58. data/test/functional/cms/users_controller_test.rb +49 -2
  59. data/test/test_helper.rb +3 -1
  60. data/test/unit/behaviors/attaching_test.rb +26 -0
  61. data/test/unit/helpers/menu_helper_test.rb +118 -278
  62. data/test/unit/models/group_test.rb +6 -0
  63. data/test/unit/models/user_test.rb +127 -29
  64. metadata +12 -4
@@ -3,11 +3,8 @@ require File.join(File.dirname(__FILE__), '/../../test_helper')
3
3
  class Cms::SectionNodesControllerTest < ActionController::TestCase
4
4
  include Cms::ControllerTestHelper
5
5
 
6
- def setup
6
+ def test_index_as_admin
7
7
  login_as_cms_admin
8
- end
9
-
10
- def test_index
11
8
  @foo = Factory(:section, :name => "Foo", :parent => root_section)
12
9
  @bar = Factory(:section, :name => "Bar", :parent => @foo)
13
10
  @page = Factory(:page, :name => "Test Page", :section => @bar)
@@ -39,6 +36,49 @@ class Cms::SectionNodesControllerTest < ActionController::TestCase
39
36
  end
40
37
  end
41
38
 
39
+ end
40
+
41
+ class Cms::SectionNodesControllerPermissionsTest < ActionController::TestCase
42
+ tests Cms::SectionNodesController
43
+ include Cms::ControllerTestHelper
42
44
 
45
+ def setup
46
+ # DRYME copypaste from UserPermissionTest
47
+ @user = Factory(:user)
48
+ login_as(@user)
49
+ @group = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
50
+ @group.permissions << create_or_find_permission_named("edit_content")
51
+ @group.permissions << create_or_find_permission_named("publish_content")
52
+ @user.groups << @group
53
+
54
+ @editable_section = Factory(:section, :parent => root_section, :name => "Editable")
55
+ @group.sections << @editable_section
56
+ @editable_page = Factory(:page, :section => @editable_section, :name => "Editable Page")
57
+ @editable_link = Factory(:link, :section => @editable_section, :name => "Editable Link")
58
+
59
+ @noneditable_section = Factory(:section, :parent => root_section, :name => "Not Editable")
60
+ @noneditable_page = Factory(:page, :section => @noneditable_section, :name => "Non-Editable Page")
61
+ @noneditable_link = Factory(:link, :section => @noneditable_section, :name => "Non-Editable Link")
62
+
63
+ @noneditables = [@noneditable_section, @noneditable_page, @noneditable_link]
64
+ @editables = [@editable_section,
65
+ @editable_page,
66
+ @editable_link,]
67
+ end
43
68
 
44
- end
69
+ def test_index_as_contributor_with_subsections
70
+ get :index
71
+ assert_response :success
72
+
73
+ # Check that each non-editable has the non-editable class, and that each editable does not have
74
+ # the non-editable class
75
+ @noneditables.each do |ne|
76
+ assert_select "td.node.non-editable div", ne.name
77
+ end
78
+ @editables.each do |e|
79
+ td = css_select("td##{e.class.to_s.underscore}_#{e.id}", e.name).first
80
+ assert !td.attributes["class"].include?("non-editable")
81
+ end
82
+ end
83
+ end
84
+
@@ -13,8 +13,15 @@ class Cms::SectionsControllerTest < ActionController::TestCase
13
13
  assert_select "input[name=?][value=?]", "section[name]", root_section.name
14
14
  end
15
15
 
16
+ test "GET new should set the groups to the parent section's groups by default" do
17
+ @group = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
18
+ get :new, :section_id => root_section.to_param
19
+ assert_equal root_section.groups, assigns(:section).groups
20
+ assert !assigns(:section).groups.include?(@group)
21
+ end
22
+
16
23
  def test_update
17
- @section = Factory(:section, :name => "V1", :parent => root_section)
24
+ @section = Factory(:section, :name => "V1", :parent => root_section, :groups => root_section.groups)
18
25
 
19
26
  put :update, :id => @section.to_param, :section => {:name => "V2"}
20
27
  reset(:section)
@@ -76,3 +83,143 @@ class Cms::SectionFileBrowserControllerTest < ActionController::TestCase
76
83
  end
77
84
 
78
85
  end
86
+
87
+ class Cms::SectionsControllerPermissionsTest < ActionController::TestCase
88
+ tests Cms::SectionsController
89
+ include Cms::ControllerTestHelper
90
+
91
+ def setup
92
+ # DRYME copypaste from UserPermissionTest
93
+ @user = Factory(:user)
94
+ @group = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
95
+ @group.permissions << create_or_find_permission_named("edit_content")
96
+ @group.permissions << create_or_find_permission_named("publish_content")
97
+ @user.groups << @group
98
+
99
+ @editable_section = Factory(:section, :parent => root_section, :name => "Editable")
100
+ @editable_subsection = Factory(:section, :parent => @editable_section, :name => "Editable Subsection")
101
+ @group.sections << @editable_section
102
+ @editable_page = Factory(:page, :section => @editable_section, :name => "Editable Page")
103
+ @editable_subpage = Factory(:page, :section => @editable_subsection, :name => "Editable SubPage")
104
+ @editable_link = Factory(:link, :section => @editable_section, :name => "Editable Link")
105
+ @editable_sublink = Factory(:link, :section => @editable_subsection, :name => "Editable SubLink")
106
+
107
+ @noneditable_section = Factory(:section, :parent => root_section, :name => "Not Editable")
108
+ @noneditable_page = Factory(:page, :section => @noneditable_section, :name => "Non-Editable Page")
109
+ @noneditable_link = Factory(:link, :section => @noneditable_section, :name => "Non-Editable Link")
110
+
111
+ @noneditables = [@noneditable_section, @noneditable_page, @noneditable_link]
112
+ @editables = [@editable_section, @editable_subsection,
113
+ @editable_page, @editable_subpage,
114
+ @editable_link, @editable_sublink]
115
+ end
116
+
117
+ def test_new_permissions
118
+ login_as(@user)
119
+
120
+ get :new, :section_id => @editable_section
121
+ assert_response :success
122
+
123
+ get :new, :section_id => @noneditable_section
124
+ assert_response 403
125
+ assert_template "cms/shared/access_denied"
126
+ end
127
+
128
+ test "POST create should set the groups to the parent section's groups for non-admin user" do
129
+ @group = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
130
+ login_as(@user)
131
+ get :new, :section_id => @editable_section
132
+ assert_equal @editable_section.groups, assigns(:section).groups
133
+ assert !assigns(:section).groups.include?(@group)
134
+ end
135
+
136
+ def test_create_permissions
137
+ login_as(@user)
138
+
139
+ post :create, :section_id => @editable_section, :name => "Another editable subsection"
140
+ assert_response :success
141
+
142
+ post :create, :section_id => @noneditable_section, :name => "Another non-editable subsection"
143
+ assert_response 403
144
+ assert_template "cms/shared/access_denied"
145
+ end
146
+
147
+ def test_edit_permissions
148
+ login_as(@user)
149
+
150
+ get :edit, :id => @editable_section
151
+ assert_response :success
152
+
153
+ get :edit, :id => @noneditable_section
154
+ assert_response 403
155
+ assert_template "cms/shared/access_denied"
156
+ end
157
+
158
+ def test_update_permissions
159
+ login_as(@user)
160
+
161
+ put :update, :id => @editable_section, :name => "Modified editable subsection"
162
+ assert_response :redirect
163
+
164
+ put :update, :id => @noneditable_section, :name => "Modified non-editable subsection"
165
+ assert_response 403
166
+ assert_template "cms/shared/access_denied"
167
+ end
168
+
169
+ def test_update_permissions_of_subsection
170
+ login_as(@user)
171
+
172
+ put :update, :id => @editable_section, :name => "Modified editable subsection"
173
+ assert_response :redirect
174
+
175
+ put :update, :id => @editable_subsection, :name => "Section below editable section"
176
+ assert_response 403
177
+ assert_template "cms/shared/access_denied"
178
+ end
179
+
180
+ test "PUT update should leave groups alone for non-admin user" do
181
+ @group2 = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
182
+ expected_groups = @editable_section.groups
183
+ login_as(@user)
184
+ put :update, :id => @editable_section
185
+ assert_response :redirect
186
+ assert_equal expected_groups, assigns(:section).groups
187
+ assert !assigns(:section).groups.include?(@group2)
188
+ end
189
+
190
+ test "PUT update should leave groups alone for non-admin user even if hack url" do
191
+ @group2 = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
192
+ expected_groups = @editable_section.groups
193
+ login_as(@user)
194
+ RAILS_DEFAULT_LOGGER.warn("starting...")
195
+ put :update, :id => @editable_section, :section => {:name => "new name", :group_ids => [@group, @group2]}
196
+ assert_response :redirect
197
+ assert_equal expected_groups, assigns(:section).groups
198
+ assert_equal "new name", assigns(:section).name
199
+ assert !assigns(:section).groups.include?(@group2)
200
+ end
201
+
202
+
203
+
204
+ test "PUT update should add groups for admin user" do
205
+ # This step is unnecessary in the actual cms, as you can't stop the admin from doing anything
206
+ Group.find(:first, :conditions => "code = 'cms-admin'").sections << @editable_subsection
207
+ @group2 = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
208
+ expected_groups = [@group, @group2]
209
+ login_as_cms_admin
210
+ put :update, :id => @editable_subsection, :section => {:name => "new name", :group_ids => [@group, @group2]}
211
+ assert_response :redirect
212
+ assert_equal expected_groups, assigns(:section).groups
213
+ end
214
+
215
+ def test_destroy_permissions
216
+ login_as(@user)
217
+
218
+ delete :destroy, :id => @editable_section
219
+ assert_response :redirect
220
+
221
+ delete :destroy, :id => @noneditable_section
222
+ assert_response 403
223
+ assert_template "cms/shared/access_denied"
224
+ end
225
+ end
@@ -2,6 +2,9 @@ require File.join(File.dirname(__FILE__), '/../../test_helper')
2
2
 
3
3
  class Cms::SessionsControllerTest < ActionController::TestCase
4
4
  include Cms::ControllerTestHelper
5
+ def teardown
6
+ User.current = nil
7
+ end
5
8
 
6
9
  def test_not_redirected_to_cms_site_if_public_site
7
10
  @request.host = "foo.com"
@@ -19,6 +22,22 @@ class Cms::SessionsControllerTest < ActionController::TestCase
19
22
  assert_select "title", "CMS Login"
20
23
  end
21
24
 
25
+ def test_return_to
26
+ user = Factory(:user)
27
+ expected_url = "/expected_url"
28
+
29
+ post :create, {:success_url => "", :login => user.login, :password => "password"}, {:return_to => expected_url }
30
+ assert_redirected_to(expected_url)
31
+ end
32
+ def test_success_url_overrides_return_to
33
+ user = Factory(:user)
34
+ expected_url = "/expected_url"
35
+
36
+ post :create, {:success_url => expected_url, :login => user.login, :password => "password"}, {:return_to => "/somewhere_else" }
37
+
38
+ assert_redirected_to(expected_url)
39
+ end
40
+
22
41
  end
23
42
 
24
43
  class Cms::SessionsControllerCacheEnabledTest < ActionController::TestCase
@@ -48,5 +67,10 @@ class Cms::SessionsControllerCacheEnabledTest < ActionController::TestCase
48
67
  log @response.body
49
68
  assert_select "title", "CMS Login"
50
69
  end
51
-
52
- end
70
+
71
+ test "destroy" do
72
+ Cms::SessionsController.any_instance.expects(:logout_user)
73
+ delete :destroy
74
+ assert_redirected_to "/"
75
+ end
76
+ end
@@ -6,7 +6,6 @@ class Cms::UsersControllerTest < ActionController::TestCase
6
6
  def setup
7
7
  login_as_cms_admin
8
8
  @user = User.first
9
-
10
9
  end
11
10
 
12
11
  def test_index
@@ -132,6 +131,11 @@ class Cms::UsersControllerTest < ActionController::TestCase
132
131
  assert_select "input#user_expires_at"
133
132
  end
134
133
 
134
+ def test_show
135
+ get :show, :id => @user.id
136
+ assert_response :success
137
+ end
138
+
135
139
  def test_update
136
140
  put :update, :id => @user.id, :user => { :first_name => "First"}
137
141
  reset(:user)
@@ -181,4 +185,47 @@ class Cms::UsersControllerTest < ActionController::TestCase
181
185
  @user_with_login = Factory(:user, :login => "mylogin")
182
186
  end
183
187
 
184
- end
188
+ end
189
+
190
+ class Cms::UsersControllerNonAdminTest < ActionController::TestCase
191
+ tests Cms::UsersController
192
+ include Cms::ControllerTestHelper
193
+
194
+ def setup
195
+ @user = Factory.build(:user)
196
+ @user.groups = [groups(:group_3)]
197
+ @user.save!
198
+ login_as(@user)
199
+ end
200
+
201
+ def test_show_self
202
+ get :show, :id => @user.id
203
+ assert_response :success
204
+ end
205
+
206
+ def test_show_other
207
+ get :show, :id => Factory(:user).id
208
+ assert @response.body.include?("Access Denied")
209
+ end
210
+
211
+ def test_change_password_self
212
+ get :change_password, :id => @user.id
213
+ assert_response :success
214
+ end
215
+
216
+ def test_change_password_other
217
+ get :change_password, :id => Factory(:user).id
218
+ assert @response.body.include?("Access Denied")
219
+ end
220
+
221
+ def test_update_password_self
222
+ put :update_password, :id => @user.id,
223
+ :user => {:password => "something_else", :password_confirmation => "something_else"}
224
+ assert_redirected_to cms_user_path(@user)
225
+ end
226
+
227
+ def test_update_password_other
228
+ put :update_password, :id => Factory(:user).id
229
+ assert @response.body.include?("Access Denied")
230
+ end
231
+ end
data/test/test_helper.rb CHANGED
@@ -2,6 +2,8 @@ ENV["RAILS_ENV"] = "test"
2
2
  require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
3
3
  require 'test_help'
4
4
  require 'action_view/test_case'
5
+ require 'mocha'
6
+ require 'redgreen'
5
7
 
6
8
  class ActiveSupport::TestCase
7
9
  # Transactional fixtures accelerate your tests by wrapping each test method
@@ -97,7 +99,7 @@ class ActiveSupport::TestCase
97
99
  end
98
100
 
99
101
  def guest_group
100
- Group.find_by_code("guest") || Factory(:group, :code => "guest")
102
+ Group.guest || Factory(:group, :code => Group::GUEST_CODE)
101
103
  end
102
104
 
103
105
  def login_as(user)
@@ -81,6 +81,32 @@ class DefaultAttachableTest < ActiveSupport::TestCase
81
81
  assert_equal "/attachments/foo.jpg", @attachable.attachment_file_path
82
82
  assert @attachable.attachment.published?
83
83
  end
84
+
85
+ def test_create_without_attachment_and_then_add_attachment_on_edit
86
+ @attachable = DefaultAttachable.new(:name => "File Name",
87
+ :attachment_file => nil, :publish_on_save => true)
88
+
89
+ assert_difference 'DefaultAttachable.count' do
90
+ assert_valid @attachable
91
+ @attachable.save!
92
+ end
93
+
94
+ assert_nil @attachable.attachment_file_path
95
+
96
+ reset(:attachable)
97
+
98
+ @attachable.attachment_file = @file
99
+ @attachable.save
100
+ @attachable.publish
101
+ assert_equal "/attachments/foo.jpg", @attachable.attachment_file_path
102
+
103
+ reset(:attachable)
104
+
105
+ assert_equal @section, @attachable.attachment_section
106
+ assert_equal @section.id, @attachable.attachment_section_id
107
+ assert_equal "/attachments/foo.jpg", @attachable.attachment_file_path
108
+ assert @attachable.attachment.published?
109
+ end
84
110
 
85
111
 
86
112
  end