we5-browsercms 3.0.2 → 3.0.5

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 (76) hide show
  1. data/README.markdown +1 -0
  2. data/app/controllers/cms/content_block_controller.rb +25 -2
  3. data/app/controllers/cms/content_controller.rb +31 -2
  4. data/app/controllers/cms/dashboard_controller.rb +2 -1
  5. data/app/controllers/cms/error_handling.rb +9 -2
  6. data/app/controllers/cms/links_controller.rb +2 -0
  7. data/app/controllers/cms/pages_controller.rb +22 -18
  8. data/app/controllers/cms/section_nodes_controller.rb +1 -1
  9. data/app/controllers/cms/sections_controller.rb +12 -7
  10. data/app/controllers/cms/sessions_controller.rb +17 -10
  11. data/app/controllers/cms/users_controller.rb +8 -6
  12. data/app/helpers/cms/application_helper.rb +2 -6
  13. data/app/helpers/cms/menu_helper.rb +118 -146
  14. data/app/helpers/cms/page_helper.rb +2 -2
  15. data/app/models/attachment.rb +2 -2
  16. data/app/models/forgot_password_mailer.rb +12 -0
  17. data/app/models/group.rb +13 -2
  18. data/app/models/guest_user.rb +9 -3
  19. data/app/models/link.rb +2 -2
  20. data/app/models/page.rb +1 -1
  21. data/app/models/section.rb +7 -2
  22. data/app/models/user.rb +35 -17
  23. data/app/portlets/forgot_password_portlet.rb +27 -0
  24. data/app/portlets/reset_password_portlet.rb +28 -0
  25. data/app/views/cms/blocks/_toolbar_for_member.html.erb +3 -3
  26. data/app/views/cms/blocks/index.html.erb +11 -6
  27. data/app/views/cms/content/show.html.erb +3 -3
  28. data/app/views/cms/forgot_password_mailer/reset_password.text.html.erb +3 -0
  29. data/app/views/cms/forgot_password_mailer/reset_password.text.plain.erb +3 -0
  30. data/app/views/cms/menus/_menu.html.erb +9 -0
  31. data/app/views/cms/menus/_menu_item.html.erb +11 -0
  32. data/app/views/cms/pages/_edit_connector.html.erb +1 -1
  33. data/app/views/cms/pages/_edit_container.html.erb +1 -1
  34. data/app/views/cms/section_nodes/_node.html.erb +1 -1
  35. data/app/views/cms/sections/_form.html.erb +36 -34
  36. data/app/views/cms/shared/access_denied.html.erb +3 -0
  37. data/app/views/cms/users/change_password.html.erb +8 -6
  38. data/app/views/cms/users/index.html.erb +1 -1
  39. data/app/views/cms/users/show.html.erb +50 -0
  40. data/app/views/layouts/_cms_toolbar.html.erb +1 -1
  41. data/app/views/layouts/_page_toolbar.html.erb +7 -7
  42. data/app/views/layouts/cms/administration.html.erb +24 -7
  43. data/app/views/portlets/forgot_password/_form.html.erb +5 -0
  44. data/app/views/portlets/forgot_password/render.html.erb +14 -0
  45. data/app/views/portlets/reset_password/_form.html.erb +3 -0
  46. data/app/views/portlets/reset_password/render.html.erb +24 -0
  47. data/{we5-browsercms.gemspec → browsercms.gemspec} +72 -54
  48. data/db/migrate/20091109175123_browsercms_3_0_5.rb +9 -0
  49. data/lib/acts_as_list.rb +8 -4
  50. data/lib/cms/acts/content_block.rb +1 -1
  51. data/lib/cms/authentication/controller.rb +26 -7
  52. data/lib/cms/behaviors/attaching.rb +3 -3
  53. data/lib/cms/behaviors/publishing.rb +12 -1
  54. data/lib/cms/behaviors/rendering.rb +17 -4
  55. data/lib/cms/behaviors/versioning.rb +2 -2
  56. data/lib/cms/routes.rb +4 -0
  57. data/lib/tasks/cms.rake +0 -18
  58. data/public/javascripts/cms/content_library.js +36 -0
  59. data/public/javascripts/cms/sitemap.js +21 -9
  60. data/public/stylesheets/cms/form_layout.css +16 -2
  61. data/public/stylesheets/cms/nav.css +4 -3
  62. data/test/functional/cms/content_block_controller_test.rb +120 -0
  63. data/test/functional/cms/content_controller_test.rb +135 -80
  64. data/test/functional/cms/links_controller_test.rb +89 -1
  65. data/test/functional/cms/pages_controller_test.rb +138 -0
  66. data/test/functional/cms/section_nodes_controller_test.rb +45 -5
  67. data/test/functional/cms/sections_controller_test.rb +148 -1
  68. data/test/functional/cms/sessions_controller_test.rb +26 -2
  69. data/test/functional/cms/users_controller_test.rb +49 -2
  70. data/test/integration/cms/password_management_test.rb +57 -0
  71. data/test/test_helper.rb +3 -1
  72. data/test/unit/behaviors/attaching_test.rb +26 -0
  73. data/test/unit/helpers/menu_helper_test.rb +118 -278
  74. data/test/unit/models/group_test.rb +6 -0
  75. data/test/unit/models/user_test.rb +127 -29
  76. metadata +20 -3
@@ -66,6 +66,13 @@ class Cms::PagesControllerTest < ActionController::TestCase
66
66
  end
67
67
  end
68
68
 
69
+ def test_version
70
+ create_page
71
+ @page.update_attributes(:name => "V2")
72
+ get :version, :id => @page.to_param, :version => 1
73
+ assert_response :success
74
+ end
75
+
69
76
  def test_revert_to
70
77
  create_page
71
78
  @page.update_attributes(:name => "V2")
@@ -87,3 +94,134 @@ class Cms::PagesControllerTest < ActionController::TestCase
87
94
  end
88
95
 
89
96
  end
97
+
98
+ class Cms::PagesControllerPermissionsTest < ActionController::TestCase
99
+ tests Cms::PagesController
100
+ include Cms::ControllerTestHelper
101
+
102
+ def setup
103
+ # DRYME copypaste from UserPermissionTest
104
+ @user = Factory(:user)
105
+ @group = Factory(:group, :name => "Test", :group_type => Factory(:group_type, :name => "CMS User", :cms_access => true))
106
+ @group.permissions << create_or_find_permission_named("edit_content")
107
+ @group.permissions << create_or_find_permission_named("publish_content")
108
+ @user.groups << @group
109
+
110
+ @editable_section = Factory(:section, :parent => root_section, :name => "Editable")
111
+ @editable_subsection = Factory(:section, :parent => @editable_section, :name => "Editable Subsection")
112
+ @group.sections << @editable_section
113
+ @editable_page = Factory(:page, :section => @editable_section, :name => "Editable Page")
114
+ @editable_subpage = Factory(:page, :section => @editable_subsection, :name => "Editable SubPage")
115
+ @editable_link = Factory(:link, :section => @editable_section, :name => "Editable Link")
116
+ @editable_sublink = Factory(:link, :section => @editable_subsection, :name => "Editable SubLink")
117
+
118
+ @noneditable_section = Factory(:section, :parent => root_section, :name => "Not Editable")
119
+ @noneditable_page = Factory(:page, :section => @noneditable_section, :name => "Non-Editable Page")
120
+ @noneditable_link = Factory(:link, :section => @noneditable_section, :name => "Non-Editable Link")
121
+
122
+ @noneditables = [@noneditable_section, @noneditable_page, @noneditable_link]
123
+ @editables = [@editable_section, @editable_subsection,
124
+ @editable_page, @editable_subpage,
125
+ @editable_link, @editable_sublink]
126
+ end
127
+
128
+ def test_new_permissions
129
+ login_as(@user)
130
+
131
+ get :new, :section_id => @editable_section
132
+ assert_response :success
133
+
134
+ get :new, :section_id => @noneditable_section
135
+ assert_response 403
136
+ assert_template "cms/shared/access_denied"
137
+ end
138
+
139
+ def test_create_permissions
140
+ login_as(@user)
141
+
142
+ post :create, :section_id => @editable_section, :name => "Another editable page"
143
+ assert_response :success
144
+
145
+ post :create, :section_id => @noneditable_section, :name => "Another non-editable page"
146
+ assert_response 403
147
+ assert_template "cms/shared/access_denied"
148
+ end
149
+
150
+ def test_edit_permissions
151
+ login_as(@user)
152
+
153
+ get :edit, :id => @editable_page
154
+ assert_response :success
155
+
156
+ get :edit, :id => @noneditable_page
157
+ assert_response 403
158
+ assert_template "cms/shared/access_denied"
159
+ end
160
+
161
+ def test_update_permissions
162
+ login_as(@user)
163
+
164
+ # Regular update
165
+ put :update, :id => @editable_page, :name => "Modified editable page"
166
+ assert_response :redirect
167
+
168
+ put :update, :id => @noneditable_page, :name => "Modified non-editable page"
169
+ assert_response 403
170
+ assert_template "cms/shared/access_denied"
171
+
172
+ # archive
173
+ put :archive, :id => @editable_page
174
+ assert_response :redirect
175
+
176
+ put :archive, :id => @noneditable_page
177
+ assert_response 403
178
+ assert_template "cms/shared/access_denied"
179
+
180
+ # hide
181
+ put :hide, :id => @editable_page
182
+ assert_response :redirect
183
+
184
+ put :hide, :id => @noneditable_page
185
+ assert_response 403
186
+ assert_template "cms/shared/access_denied"
187
+
188
+ # publish
189
+ put :publish, :id => @editable_page
190
+ assert_response :redirect
191
+
192
+ put :publish, :id => @noneditable_page
193
+ assert_response 403
194
+ assert_template "cms/shared/access_denied"
195
+
196
+ # publish many
197
+ put :publish, :page_ids => [@editable_page.id]
198
+ assert_response :redirect
199
+
200
+ put :publish, :page_ids => [@noneditable_page.id]
201
+ assert_response 403
202
+
203
+ put :publish, :page_ids => [@editable_page.id, @noneditable_page.id]
204
+ assert_response 403
205
+
206
+ # revert_to
207
+ # can't find route...
208
+ # put :revert_to, :id => @editable_page.id
209
+ # assert_response :redirect
210
+
211
+ # put :revert_to, :id => @noneditable_page.id
212
+ # assert_response :error # shouldn't it be 403?
213
+ end
214
+
215
+ def test_destroy_permissions
216
+ login_as(@user)
217
+
218
+ delete :destroy, :id => @editable_page
219
+ assert_response :redirect
220
+
221
+ delete :destroy, :id => @noneditable_page
222
+ assert_response 403
223
+ assert_template "cms/shared/access_denied"
224
+ end
225
+ end
226
+
227
+
@@ -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