spontaneous 0.2.0.beta1 → 0.2.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (335) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.locat +42 -0
  4. data/.travis/gemfiles/Gemfile.empty +7 -0
  5. data/.travis.yml +18 -0
  6. data/Gemfile +12 -8
  7. data/LICENSE +1 -1
  8. data/Rakefile +15 -157
  9. data/Readme.markdown +1 -1
  10. data/application/css/core.css.scss +22 -146
  11. data/application/css/definitions.css.scss +7 -3
  12. data/application/css/dialogue.css.scss +26 -1
  13. data/application/css/editing.css.scss +70 -28
  14. data/application/css/font.css.scss +1 -1
  15. data/application/css/popover.css.scss +2 -0
  16. data/application/css/top.css.scss +231 -0
  17. data/application/js/add_alias_dialogue.js +1 -1
  18. data/application/js/add_home_dialogue.js +1 -1
  19. data/application/js/ajax.js +61 -31
  20. data/application/js/box.js +4 -4
  21. data/application/js/conflicted_field_dialogue.js +1 -1
  22. data/application/js/content.js +5 -5
  23. data/application/js/dom.js +5 -0
  24. data/application/js/edit_panel.js +1 -0
  25. data/application/js/editing.js +1 -1
  26. data/application/js/extensions.js +8 -0
  27. data/application/js/field/boolean.js +31 -0
  28. data/application/js/field/file.js +32 -4
  29. data/application/js/field/image.js +24 -9
  30. data/application/js/field/markdown.js +87 -59
  31. data/application/js/field/select.js +1 -1
  32. data/application/js/field/webvideo.js +6 -1
  33. data/application/js/init.js +2 -2
  34. data/application/js/jquery-selection-position.js +130 -0
  35. data/application/js/location.js +4 -25
  36. data/application/js/meta_view/user_admin.js +2 -2
  37. data/application/js/metadata.js +2 -2
  38. data/application/js/page_browser.js +1 -1
  39. data/application/js/panel/root_menu.js +0 -1
  40. data/application/js/popover.js +27 -12
  41. data/application/js/popover_view.js +20 -4
  42. data/application/js/preview.js +31 -16
  43. data/application/js/progress.js +22 -21
  44. data/application/js/publish.js +18 -7
  45. data/application/js/sharded_upload.js +9 -6
  46. data/application/js/spontaneous.js +3 -1
  47. data/application/js/top_bar.js +264 -173
  48. data/application/js/upload.js +12 -5
  49. data/application/js/upload_manager.js +4 -3
  50. data/application/js/user.js +1 -2
  51. data/application/js/views/box_view.js +1 -1
  52. data/application/js/views/page_view.js +16 -5
  53. data/application/js/views/piece_view.js +5 -4
  54. data/application/static/font/fontawesome-webfont-1c66a4738b40ef0f6b1abca0ba9a796d.ttf +0 -0
  55. data/application/views/index.erb +6 -14
  56. data/application/views/login.erb +6 -25
  57. data/application/views/schema_modification_error.html.erb +3 -7
  58. data/db/migrations/20130114120000_create_revision_tables.rb +2 -2
  59. data/db/migrations/20130813111009_increase_path_length.rb +14 -0
  60. data/gem-public_cert.pem +20 -0
  61. data/lib/spontaneous/asset/app_compiler.rb +44 -0
  62. data/lib/spontaneous/asset/environment.rb +225 -0
  63. data/lib/spontaneous/asset.rb +2 -67
  64. data/lib/spontaneous/box.rb +0 -1
  65. data/lib/spontaneous/capistrano/deploy.rb +2 -2
  66. data/lib/spontaneous/capistrano/sync.rb +1 -1
  67. data/lib/spontaneous/cli/init.rb +36 -13
  68. data/lib/spontaneous/cli/server.rb +0 -1
  69. data/lib/spontaneous/cli/site.rb +2 -1
  70. data/lib/spontaneous/cli.rb +3 -1
  71. data/lib/spontaneous/collections/entry_set.rb +4 -12
  72. data/lib/spontaneous/collections/hash_with_fallback.rb +20 -0
  73. data/lib/spontaneous/collections/prototype_set.rb +6 -5
  74. data/lib/spontaneous/crypt.rb +2 -2
  75. data/lib/spontaneous/data_mapper/content_model/associations.rb +115 -63
  76. data/lib/spontaneous/data_mapper.rb +1 -1
  77. data/lib/spontaneous/errors.rb +6 -0
  78. data/lib/spontaneous/extensions/object_space.rb +6 -0
  79. data/lib/spontaneous/facet.rb +1 -0
  80. data/lib/spontaneous/field/base.rb +86 -13
  81. data/lib/spontaneous/field/boolean.rb +65 -0
  82. data/lib/spontaneous/field/file.rb +17 -6
  83. data/lib/spontaneous/field/html.rb +13 -0
  84. data/lib/spontaneous/field/image/size.rb +76 -0
  85. data/lib/spontaneous/field/image.rb +99 -414
  86. data/lib/spontaneous/field/tags.rb +36 -0
  87. data/lib/spontaneous/field/update.rb +1 -1
  88. data/lib/spontaneous/field/webvideo/fallback.rb +41 -0
  89. data/lib/spontaneous/field/webvideo/vimeo.rb +113 -0
  90. data/lib/spontaneous/field/webvideo/vine.rb +94 -0
  91. data/lib/spontaneous/field/webvideo/youtube.rb +133 -0
  92. data/lib/spontaneous/field/webvideo.rb +100 -250
  93. data/lib/spontaneous/field.rb +1 -1
  94. data/lib/spontaneous/generators/site/Gemfile.tt +5 -14
  95. data/lib/spontaneous/generators/site/assets/README.md +20 -0
  96. data/lib/spontaneous/generators/site/assets/css/site.scss +8 -0
  97. data/lib/spontaneous/generators/site/assets/js/site.js +6 -0
  98. data/lib/spontaneous/generators/site/config/deploy.rb.tt +9 -0
  99. data/lib/spontaneous/generators/site/config/user_levels.yml +14 -3
  100. data/lib/spontaneous/generators/site/public/README.md +12 -0
  101. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +2 -2
  102. data/lib/spontaneous/generators/site.rb +77 -35
  103. data/lib/spontaneous/layout.rb +6 -7
  104. data/lib/spontaneous/loader.rb +21 -13
  105. data/lib/spontaneous/media/file.rb +22 -9
  106. data/lib/spontaneous/media/image/attributes.rb +33 -0
  107. data/lib/spontaneous/media/image/format/gif.rb +4 -0
  108. data/lib/spontaneous/media/image/format/jpg.rb +17 -0
  109. data/lib/spontaneous/media/image/format/png.rb +4 -0
  110. data/lib/spontaneous/media/image/format/webp.rb +26 -0
  111. data/lib/spontaneous/media/image/format.rb +79 -0
  112. data/lib/spontaneous/media/image/optimizer.rb +69 -0
  113. data/lib/spontaneous/media/image/processor.rb +17 -0
  114. data/lib/spontaneous/media/image/renderable.rb +52 -0
  115. data/lib/spontaneous/media/image/skeptick.rb +70 -0
  116. data/lib/spontaneous/media/image.rb +50 -0
  117. data/lib/spontaneous/media/temp_file.rb +4 -0
  118. data/lib/spontaneous/media.rb +1 -0
  119. data/lib/spontaneous/model/core/aliases.rb +14 -8
  120. data/lib/spontaneous/model/core/boxes.rb +5 -2
  121. data/lib/spontaneous/model/core/entries.rb +4 -0
  122. data/lib/spontaneous/model/core/entry.rb +1 -0
  123. data/lib/spontaneous/model/core/fields.rb +5 -2
  124. data/lib/spontaneous/model/core/locks.rb +16 -0
  125. data/lib/spontaneous/model/core/media.rb +1 -15
  126. data/lib/spontaneous/model/core.rb +31 -1
  127. data/lib/spontaneous/model/page/controllers.rb +2 -2
  128. data/lib/spontaneous/model/page/formats.rb +1 -4
  129. data/lib/spontaneous/model/page/layouts.rb +6 -2
  130. data/lib/spontaneous/model/page/locks.rb +8 -2
  131. data/lib/spontaneous/model/page/page_tree.rb +2 -2
  132. data/lib/spontaneous/model/page/paths.rb +74 -9
  133. data/lib/spontaneous/model/page.rb +11 -3
  134. data/lib/spontaneous/model.rb +6 -6
  135. data/lib/spontaneous/output/context/render_cache.rb +23 -0
  136. data/lib/spontaneous/output/context.rb +56 -30
  137. data/lib/spontaneous/output/helpers/script_helper.rb +9 -53
  138. data/lib/spontaneous/output/helpers/stylesheet_helper.rb +8 -40
  139. data/lib/spontaneous/output/template/renderer.rb +17 -5
  140. data/lib/spontaneous/output.rb +0 -1
  141. data/lib/spontaneous/paths.rb +6 -2
  142. data/lib/spontaneous/permissions/access_key.rb +18 -0
  143. data/lib/spontaneous/permissions/user.rb +1 -1
  144. data/lib/spontaneous/permissions.rb +4 -1
  145. data/lib/spontaneous/plugins/application/state.rb +19 -12
  146. data/lib/spontaneous/prototypes/field_prototype.rb +14 -8
  147. data/lib/spontaneous/published_revision.rb +7 -0
  148. data/lib/spontaneous/publishing/immediate.rb +43 -34
  149. data/lib/spontaneous/publishing/revision.rb +9 -6
  150. data/lib/spontaneous/rack/asset_server.rb +20 -0
  151. data/lib/spontaneous/rack/back/alias.rb +46 -0
  152. data/lib/spontaneous/rack/back/application_assets.rb +28 -0
  153. data/lib/spontaneous/rack/back/base.rb +34 -0
  154. data/lib/spontaneous/rack/back/changes.rb +19 -0
  155. data/lib/spontaneous/rack/back/content.rb +54 -0
  156. data/lib/spontaneous/rack/back/events.rb +38 -0
  157. data/lib/spontaneous/rack/back/field.rb +37 -0
  158. data/lib/spontaneous/rack/back/file.rb +118 -0
  159. data/lib/spontaneous/rack/back/helpers.rb +71 -0
  160. data/lib/spontaneous/rack/back/index.rb +16 -0
  161. data/lib/spontaneous/rack/back/login.rb +47 -0
  162. data/lib/spontaneous/rack/back/map.rb +24 -0
  163. data/lib/spontaneous/rack/back/page.rb +46 -0
  164. data/lib/spontaneous/rack/back/preview.rb +43 -0
  165. data/lib/spontaneous/rack/back/schema.rb +30 -0
  166. data/lib/spontaneous/rack/back/site.rb +25 -0
  167. data/lib/spontaneous/rack/back/site_assets.rb +13 -0
  168. data/lib/spontaneous/rack/back/unsupported_browser.rb +7 -0
  169. data/lib/spontaneous/rack/{user_admin.rb → back/user_admin.rb} +2 -5
  170. data/lib/spontaneous/rack/back.rb +85 -764
  171. data/lib/spontaneous/rack/cacheable_file.rb +3 -3
  172. data/lib/spontaneous/rack/front.rb +16 -9
  173. data/lib/spontaneous/rack/middleware/authenticate.rb +65 -0
  174. data/lib/spontaneous/rack/middleware/csrf.rb +66 -0
  175. data/lib/spontaneous/rack/middleware/reloader.rb +52 -0
  176. data/lib/spontaneous/rack/middleware/scope.rb +60 -0
  177. data/lib/spontaneous/rack/middleware.rb +6 -0
  178. data/lib/spontaneous/rack/page_controller.rb +18 -5
  179. data/lib/spontaneous/rack/public.rb +17 -11
  180. data/lib/spontaneous/rack.rb +34 -24
  181. data/lib/spontaneous/revision.rb +29 -2
  182. data/lib/spontaneous/schema/uid.rb +4 -3
  183. data/lib/spontaneous/schema/uid_map.rb +5 -24
  184. data/lib/spontaneous/schema.rb +1 -0
  185. data/lib/spontaneous/search/database.rb +8 -0
  186. data/lib/spontaneous/search/field.rb +1 -1
  187. data/lib/spontaneous/search/index.rb +3 -5
  188. data/lib/spontaneous/server.rb +1 -1
  189. data/lib/spontaneous/simultaneous.rb +1 -1
  190. data/lib/spontaneous/site/features.rb +4 -5
  191. data/lib/spontaneous/site/helpers.rb +22 -5
  192. data/lib/spontaneous/site/instance.rb +2 -2
  193. data/lib/spontaneous/site/selectors.rb +22 -3
  194. data/lib/spontaneous/storage/cloud.rb +13 -9
  195. data/lib/spontaneous/storage/local.rb +11 -6
  196. data/lib/spontaneous/style.rb +40 -23
  197. data/lib/spontaneous/utils/database/mysql_dumper.rb +1 -1
  198. data/lib/spontaneous/utils/smush_it.rb +1 -1
  199. data/lib/spontaneous/version.rb +1 -1
  200. data/lib/spontaneous.rb +35 -33
  201. data/spontaneous.gemspec +53 -787
  202. data/test/experimental/test_crypt.rb +56 -56
  203. data/test/experimental/test_features.rb +16 -27
  204. data/test/fixtures/assets/public1/css/data.css.scss +3 -0
  205. data/test/fixtures/assets/public1/css/image1.css.scss +4 -0
  206. data/test/fixtures/assets/public1/css/import.css.scss +1 -0
  207. data/test/fixtures/assets/public1/css/urlhash.css.scss +3 -0
  208. data/test/fixtures/assets/public1/js/a.js +1 -1
  209. data/test/fixtures/assets/public1/js/all.js +4 -0
  210. data/test/fixtures/assets/public1/js/{m.coffee → m.js.coffee} +1 -0
  211. data/test/fixtures/assets/public1/x.js +1 -0
  212. data/test/fixtures/assets/public2/css/all.css +4 -0
  213. data/test/fixtures/assets/public2/css/missing.css.scss +3 -0
  214. data/test/fixtures/assets/public2/i/y.png +0 -0
  215. data/test/fixtures/assets/public2/js/b.js +1 -1
  216. data/test/fixtures/assets/public2/js/c.js +1 -1
  217. data/test/fixtures/images/size.extended.webp +0 -0
  218. data/test/fixtures/images/size.lossless.webp +0 -0
  219. data/test/fixtures/images/size.lossy.webp +0 -0
  220. data/test/fixtures/schema/before.yml +4 -4
  221. data/test/fixtures/schema/schema.yml +1 -1
  222. data/test/fixtures/templates/aliases/aaa.html.cut +0 -0
  223. data/test/fixtures/templates/extended/partial_with_renderer.html.cut +1 -0
  224. data/test/fixtures/templates/extended/with_includes_and_renderer.html.cut +2 -0
  225. data/test/functional/test_application.rb +108 -106
  226. data/test/functional/test_back.rb +924 -930
  227. data/test/functional/test_front.rb +285 -238
  228. data/test/functional/test_user_manager.rb +75 -100
  229. data/test/integration/test_installation.rb +1 -1
  230. data/test/support/matchers.rb +12 -0
  231. data/test/support/minitest.rb +121 -0
  232. data/test/support/rack.rb +45 -0
  233. data/test/support/test_start_finish.rb +103 -0
  234. data/test/test_helper.rb +21 -68
  235. data/test/test_integration_helper.rb +1 -3
  236. data/test/unit/test_alias.rb +432 -408
  237. data/test/unit/test_asset_bundler.rb +58 -58
  238. data/test/unit/test_assets.rb +485 -155
  239. data/test/unit/test_async.rb +16 -37
  240. data/test/unit/test_authentication.rb +425 -457
  241. data/test/unit/test_boxes.rb +191 -191
  242. data/test/unit/test_changesets.rb +244 -254
  243. data/test/unit/test_config.rb +128 -142
  244. data/test/unit/test_content.rb +313 -359
  245. data/test/unit/test_content_inheritance.rb +29 -30
  246. data/test/unit/test_datamapper.rb +1205 -1080
  247. data/test/unit/test_datamapper_content.rb +49 -51
  248. data/test/unit/test_extensions.rb +23 -23
  249. data/test/unit/test_fields.rb +1488 -1180
  250. data/test/unit/test_formats.rb +158 -158
  251. data/test/unit/test_generators.rb +98 -40
  252. data/test/unit/test_helpers.rb +73 -76
  253. data/test/unit/test_image_size.rb +53 -22
  254. data/test/unit/test_images.rb +164 -165
  255. data/test/unit/test_layouts.rb +133 -122
  256. data/test/unit/test_logger.rb +14 -17
  257. data/test/unit/test_media.rb +69 -84
  258. data/test/unit/test_modifications.rb +513 -525
  259. data/test/unit/test_page.rb +462 -361
  260. data/test/unit/test_permissions.rb +379 -364
  261. data/test/unit/test_piece.rb +67 -75
  262. data/test/unit/test_plugins.rb +82 -89
  263. data/test/unit/test_prototype_set.rb +215 -216
  264. data/test/unit/test_prototypes.rb +114 -124
  265. data/test/unit/test_publishing.rb +252 -289
  266. data/test/unit/test_render.rb +167 -115
  267. data/test/unit/test_revisions.rb +436 -444
  268. data/test/unit/test_schema.rb +339 -309
  269. data/test/unit/test_search.rb +577 -574
  270. data/test/unit/test_serialisation.rb +136 -147
  271. data/test/unit/test_site.rb +252 -227
  272. data/test/unit/test_skeptick.rb +130 -0
  273. data/test/unit/test_storage.rb +46 -40
  274. data/test/unit/test_structure.rb +57 -66
  275. data/test/unit/test_styles.rb +104 -104
  276. data/test/unit/test_templates.rb +72 -57
  277. data/test/unit/test_type_hierarchy.rb +15 -16
  278. data/test/unit/test_visibility.rb +239 -257
  279. metadata +455 -326
  280. data/application/js/vendor/JS.Class-2.1.5/CHANGELOG +0 -283
  281. data/application/js/vendor/JS.Class-2.1.5/MIT-LICENSE +0 -30
  282. data/application/js/vendor/JS.Class-2.1.5/README +0 -30
  283. data/application/js/vendor/JS.Class-2.1.5/min/command.js +0 -1
  284. data/application/js/vendor/JS.Class-2.1.5/min/comparable.js +0 -1
  285. data/application/js/vendor/JS.Class-2.1.5/min/constant_scope.js +0 -1
  286. data/application/js/vendor/JS.Class-2.1.5/min/decorator.js +0 -1
  287. data/application/js/vendor/JS.Class-2.1.5/min/enumerable.js +0 -1
  288. data/application/js/vendor/JS.Class-2.1.5/min/forwardable.js +0 -1
  289. data/application/js/vendor/JS.Class-2.1.5/min/hash.js +0 -1
  290. data/application/js/vendor/JS.Class-2.1.5/min/linked_list.js +0 -1
  291. data/application/js/vendor/JS.Class-2.1.5/min/loader.js +0 -1
  292. data/application/js/vendor/JS.Class-2.1.5/min/method_chain.js +0 -1
  293. data/application/js/vendor/JS.Class-2.1.5/min/observable.js +0 -1
  294. data/application/js/vendor/JS.Class-2.1.5/min/package.js +0 -1
  295. data/application/js/vendor/JS.Class-2.1.5/min/proxy.js +0 -1
  296. data/application/js/vendor/JS.Class-2.1.5/min/ruby.js +0 -1
  297. data/application/js/vendor/JS.Class-2.1.5/min/set.js +0 -1
  298. data/application/js/vendor/JS.Class-2.1.5/min/stack_trace.js +0 -1
  299. data/application/js/vendor/JS.Class-2.1.5/min/state.js +0 -1
  300. data/application/js/vendor/JS.Class-2.1.5/min/stdlib.js +0 -16
  301. data/application/js/vendor/jquery-1.6.2.min.js +0 -18
  302. data/application/js/vendor/jquery-ui-1.8.16.custom.min.js +0 -791
  303. data/application/js/vendor/jquery-ui-1.8.9.custom.min.js +0 -415
  304. data/application/static/font/fontawesome-webfont-5c5c21100a346972a82c34c5e96ffcfe.ttf +0 -0
  305. data/application/static/select-arrow-6e7dd3745b00e934b0d7a3250c46558b.png +0 -0
  306. data/bin/limit-upload +0 -5
  307. data/bin/unlimit-upload +0 -3
  308. data/lib/spontaneous/asset/file.rb +0 -25
  309. data/lib/spontaneous/asset/source.rb +0 -28
  310. data/lib/spontaneous/image_size.rb +0 -123
  311. data/lib/spontaneous/output/assets/compression.rb +0 -58
  312. data/lib/spontaneous/output/assets.rb +0 -32
  313. data/lib/spontaneous/rack/around_back.rb +0 -20
  314. data/lib/spontaneous/rack/around_front.rb +0 -27
  315. data/lib/spontaneous/rack/around_preview.rb +0 -22
  316. data/lib/spontaneous/rack/assets.rb +0 -126
  317. data/lib/spontaneous/rack/authentication.rb +0 -20
  318. data/lib/spontaneous/rack/cookie_authentication.rb +0 -38
  319. data/lib/spontaneous/rack/helpers.rb +0 -52
  320. data/lib/spontaneous/rack/http.rb +0 -18
  321. data/lib/spontaneous/rack/media.rb +0 -30
  322. data/lib/spontaneous/rack/query_authentication.rb +0 -35
  323. data/lib/spontaneous/rack/reloader.rb +0 -45
  324. data/lib/spontaneous/rack/user_helpers.rb +0 -28
  325. /data/{README → application/js/field/markdown/text_command.js} +0 -0
  326. /data/application/js/vendor/{JS.Class-2.1.5/min/core.js → js.class-2.1.5.min.js} +0 -0
  327. /data/test/fixtures/assets/public1/css/{a.scss → a.css.scss} +0 -0
  328. /data/{lib/spontaneous/generators/site/public/css/site.scss → test/fixtures/assets/public1/x.css} +0 -0
  329. /data/{lib/spontaneous/generators/site/public/js/.empty_directory → test/fixtures/assets/public1/x.png} +0 -0
  330. /data/test/fixtures/assets/public2/css/{b.scss → b.css.scss} +0 -0
  331. /data/test/fixtures/assets/public2/js/{n.coffee → n.js.coffee} +0 -0
  332. /data/test/fixtures/back/{public → assets}/css/sass_include.scss +0 -0
  333. /data/test/fixtures/back/{public → assets}/css/sass_template.scss +0 -0
  334. /data/test/fixtures/back/{public → assets}/js/coffeescript.coffee +0 -0
  335. /data/{lib/spontaneous/generators/site/public/js/site.js → test/fixtures/templates/aliases/aa_alias.html.cut} +0 -0
@@ -5,12 +5,12 @@ require File.expand_path('../../test_helper', __FILE__)
5
5
  # set :environment, :test
6
6
 
7
7
 
8
- class AuthenticationTest < MiniTest::Spec
9
- include ::Rack::Test::Methods
8
+ describe "Authentication" do
9
+ include RackTestMethods
10
10
 
11
11
  Permissions = Spontaneous::Permissions
12
12
 
13
- def create_user(name, level)
13
+ def self.create_user(name, level)
14
14
  user = Permissions::User.create({
15
15
  :name => "#{name.capitalize}",
16
16
  :email => "#{name}@example.org",
@@ -21,507 +21,475 @@ class AuthenticationTest < MiniTest::Spec
21
21
  user
22
22
  end
23
23
 
24
- @@version = 0
24
+ start do
25
+ site = setup_site
26
+
27
+ site.config.publishing_delay nil
28
+ site.config.site_domain "example.com"
29
+ site.config.site_id "example_com"
30
+
31
+ # Site.database = DB
32
+ site.paths.add :templates, File.expand_path("../../fixtures/public/templates", __FILE__)
33
+ let(:site) { site }
34
+
35
+ # see http://benprew.posterous.com/testing-sessions-with-sinatra
36
+ # app.send(:set, :sessions, false)
37
+ # S::Rack::Back::EditingInterface.set :sessions, false
38
+ class ::C < Piece
39
+ field :photo, :image, :write_level => :root
40
+ end
41
+ class ::D < Piece; end
42
+
43
+ class ::SitePage < Page
44
+ # page_style :default
45
+ field :editor_level, :user_level => :editor
46
+ field :admin_level, :user_level => :admin
47
+ field :root_level, :user_level => :root
48
+ field :mixed_level, :read_level => :editor, :write_level => :root
49
+ field :default_level
50
+
51
+ box :pages
52
+
53
+ box :editor_level, :user_level => :editor do
54
+ field :editor_level, :user_level => :editor
55
+ field :admin_level, :user_level => :admin
56
+ field :root_level, :user_level => :root
57
+ field :mixed_level, :read_level => :editor, :write_level => :root
58
+ field :default_level
59
+
60
+ allow :'D', :user_level => :editor
61
+ allow :'C', :user_level => :root
62
+ end
63
+
64
+ box :admin_level, :user_level => :admin do
65
+ field :editor_level, :user_level => :editor
66
+ field :admin_level, :user_level => :admin
67
+ field :root_level, :user_level => :root
68
+ field :mixed_level, :read_level => :editor, :write_level => :root
69
+ field :default_level
70
+
71
+ allow :'C', :user_level => :admin
72
+ allow :'D', :user_level => :root
73
+ end
74
+
75
+ box :root_level, :user_level => :root do
76
+ field :editor_level, :user_level => :editor
77
+ field :admin_level, :user_level => :admin
78
+ field :root_level, :user_level => :root
79
+ field :mixed_level, :read_level => :editor, :write_level => :root
80
+ field :default_level
81
+
82
+ allow :'C', :user_level => :root
83
+ end
84
+
85
+ box :mixed_level, :read_level => :editor, :write_level => :root do
86
+ field :editor_level, :user_level => :editor
87
+ field :admin_level, :user_level => :admin
88
+ field :root_level, :user_level => :root
89
+ field :mixed_level, :read_level => :editor, :write_level => :root
90
+ field :default_level
91
+
92
+ allow :'C', :user_level => :editor
93
+ end
94
+
95
+ box :default_level do
96
+ field :editor_level, :user_level => :editor
97
+ field :admin_level, :user_level => :admin
98
+ field :root_level, :user_level => :root
99
+ field :mixed_level, :read_level => :editor, :write_level => :root
100
+ field :default_level
101
+
102
+ allow :'C'
103
+ end
104
+ end
105
+ Content.delete
106
+ Permissions::User.delete
107
+ Permissions::AccessKey.delete
108
+ Spontaneous.environment = :test
109
+ Permissions::UserLevel.reset!
110
+ Permissions::UserLevel.stubs(:level_file).returns(File.expand_path('../../fixtures/permissions', __FILE__) / 'config/user_levels.yml')
111
+
112
+ root = SitePage.create
113
+ root.save
114
+
115
+ about = SitePage.create(:uid => 'about', :slug => "about")
116
+ root.pages << about
117
+ piece = C.new
118
+ root.boxes[:root_level] << piece
119
+ piece = C.new
120
+ root.boxes[:root_level] << piece
121
+ root.save
122
+
123
+ root_user = create_user('root', Permissions::UserLevel.root)
124
+ admin_user = create_user('admin', Permissions::UserLevel.admin)
125
+ editor_user = create_user('editor', Permissions::UserLevel.editor)
126
+ guest_user = create_user('guest', Permissions::UserLevel.none)
127
+ disabled_user = create_user('disabled', Permissions::UserLevel.admin)
128
+ disabled_user.update(:disabled => true)
129
+
130
+ let(:root) { root }
131
+ let(:about) { about }
132
+
133
+ let(:root_user) { root_user }
134
+ let(:admin_user) { admin_user }
135
+ let(:editor_user) { editor_user }
136
+ let(:guest_user) { guest_user }
137
+ let(:disabled_user) { disabled_user }
138
+ end
139
+
140
+ finish do
141
+ [:C, :D, :SitePage].each { |k| Object.send(:remove_const, k) rescue nil }
142
+ Content.delete
143
+ Permissions::User.delete
144
+ Permissions::AccessKey.delete
145
+ teardown_site
146
+ end
25
147
 
26
148
  def version
27
- @@version += 1
149
+ @version = (@version || 0) + 1
28
150
  end
29
151
 
30
152
  def app
31
153
  Spontaneous::Rack::Back.application
32
154
  end
33
155
 
34
- def root
35
- @root
36
- end
37
156
 
38
- def about
39
- @about
157
+ # Used by the various auth_* methods
158
+ def api_key
159
+ @key
40
160
  end
41
161
 
42
- def root_user
43
- @root_user
162
+ before do
163
+ clear_cookies
164
+ Spontaneous.stubs(:media_dir).returns(File.expand_path('../../fixtures/permissions/media', __FILE__))
44
165
  end
45
166
 
46
- def admin_user
47
- @admin_user
167
+ # These paths don't have to be accurate because we only ever test for failure
168
+ def post_paths
169
+ %(/site/home
170
+ /content/999/BOXID/TYPENAME
171
+ /file/999/BOXID
172
+ /shard/0000000000000000000000000000000000000000
173
+ /schema/delete
174
+ )
48
175
  end
49
176
 
50
- def editor_user
51
- @editor_user
177
+ def get_paths
178
+ %(/events
179
+ /users
180
+ /site
181
+ /map
182
+ /field/conflicts/999
183
+ /page/999
184
+ /alias/SCHEMAID/999/BOXID
185
+ /changes
186
+ /shard/0000000000000000000000000000000000000000
187
+ )
52
188
  end
53
189
 
54
- def guest_user
55
- @guest_user
56
- end
190
+ describe "Unauthorised sessions" do
191
+ it "redirect / to /@spontaneous" do
192
+ get "/"
193
+ assert last_response.status == 302
194
+ last_response.headers["Location"].must_match %r{/@spontaneous$}
195
+ end
57
196
 
58
- def disabled_user
59
- @disabled_user
60
- end
197
+ it "redirect /* to /@spontaneous" do
198
+ get "/about"
199
+ assert last_response.status == 302
200
+ last_response.headers["Location"].must_match %r{/@spontaneous$}
201
+ end
61
202
 
62
- def login_user(user, params={})
63
- post "/@spontaneous/login", {"user[login]" => user.login, "user[password]" => user.password}.merge(params)
64
- @user = user
65
- end
203
+ it "see a login page at /@spontaneous" do
204
+ get "/@spontaneous"
205
+ assert_login_page
206
+ end
66
207
 
67
- def auth_post(path, params={})
68
- key = @user.access_keys.first
69
- post(path, params.merge("__key" => key.key_id))
70
- end
208
+ it "see a login page for all GETs" do
209
+ get_paths.split.each do |path|
210
+ get "/@spontaneous#{path}"
211
+ assert_login_page path
212
+ end
213
+ end
71
214
 
72
- def auth_get(path, params={})
73
- key = @user.access_keys.first
74
- get(path, params.merge("__key" => key.key_id))
75
- end
215
+ it "see a login page for all POSTs" do
216
+ post_paths.split.each do |path|
217
+ post "/@spontaneous#{path}"
218
+ assert_login_page(path, "POST")
219
+ end
220
+ end
76
221
 
77
- def setup
78
- @site = setup_site
222
+ it "get access to static files" do
223
+ get "/@spontaneous/static/favicon.ico"
224
+ assert last_response.status == 200
225
+ end
79
226
 
80
- @site.config.publishing_delay nil
81
- @site.config.site_domain "example.com"
82
- @site.config.site_id "example_com"
227
+ it "get access to Javascript files" do
228
+ get "/@spontaneous/js/init.js"
229
+ assert last_response.status == 200
230
+ end
83
231
 
84
- # Site.database = DB
85
- @site.paths.add :templates, File.expand_path("../../fixtures/public/templates", __FILE__)
86
- # see http://benprew.posterous.com/testing-sessions-with-sinatra
87
- # app.send(:set, :sessions, false)
88
- S::Rack::Back::EditingInterface.set :sessions, false
89
- Spontaneous.stubs(:media_dir).returns(File.expand_path('../../fixtures/permissions/media', __FILE__))
90
- end
232
+ it "get access to CSS files" do
233
+ get "/@spontaneous/css/spontaneous.css"
234
+ assert last_response.status == 200
235
+ end
91
236
 
92
- def teardown
93
- teardown_site
94
- end
237
+ it "get access to media files" do
238
+ get '/media/image.jpg'
239
+ assert last_response.status == 200
240
+ end
241
+
242
+ it "has access to the unsupported browser page" do
243
+ get '/@spontaneous/unsupported'
244
+ assert last_response.status == 200
245
+ end
246
+
247
+ describe "Logging in" do
248
+ it "fail unless provided with a login & password" do
249
+ post "/@spontaneous/login", "user[login]" => "", "user[password]" => ""
250
+ assert_login_page("/@spontaneous/login", "POST")
251
+ end
252
+
253
+ it "fail for invalid login names" do
254
+ post "/@spontaneous/login", "user[login]" => "noone", "user[password]" => "wrong"
255
+ assert_login_page("/@spontaneous/login", "POST")
256
+ end
257
+
258
+ it "fail for invalid passwords" do
259
+ post "/@spontaneous/login", "user[login]" => "editor", "user[password]" => "wrong"
260
+ assert_login_page("/@spontaneous/login", "POST")
261
+ end
262
+
263
+ it "fail for disabled users" do
264
+ post "/@spontaneous/login", "user[login]" => "disabled", "user[password]" => "disabled_password"
265
+ assert_login_page("/@spontaneous/login", "POST")
266
+ end
267
+
268
+ it "succeed and redirect to /@spontaneous for correct login & password" do
269
+ # post "/@spontaneous/login", "user[login]" => "admin", "user[password]" => "admin_password"
270
+ @user, @key = login_user(admin_user, "origin" => "/103/preview")
271
+ assert last_response.status == 302, "Status was #{last_response.status} not 302"
272
+ last_response.headers["Location"].must_match %r{/@spontaneous/103/preview$}
273
+ end
274
+
275
+ it "set the secure flag for cookies delivered behind https" do
276
+ clear_cookies
277
+ rack_mock_session.cookie_jar[S::Rack::AUTH_COOKIE].must_be_nil
278
+ user = admin_user
279
+ post "https://example.org/@spontaneous/login", {"user[login]" => user.login, "user[password]" => user.password}
280
+ cookies = rack_mock_session.cookie_jar.instance_variable_get("@cookies")
281
+ cookie = cookies.detect { |c| c.name == S::Rack::AUTH_COOKIE }
282
+ assert cookie.secure?
283
+ end
284
+
285
+ it "succeed and return an api key value for correct login over XHR" do
286
+ key = Spontaneous::Permissions::AccessKey.new
287
+ Spontaneous::Permissions::AccessKey.expects(:new).returns(key)
288
+ post "/@spontaneous/login", { "user[login]" => "admin", "user[password]" => "admin_password" }, {"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
289
+ assert last_response.status == 200, "Status was #{last_response.status} not 200"
290
+ result = Spot::JSON.parse(last_response.body)
291
+ result[:key].must_equal key.key_id
292
+ result[:redirect].must_equal "/@spontaneous"
293
+ end
294
+ end
95
295
 
96
- def post_paths
97
- %(/save/#{root.id} /savebox/#{root.id}/#{root.boxes[:editor_level].schema_id} /content/#{root.id}/position/0 /file/upload/#{root.id} /file/replace/#{root.id} /file/wrap/#{root.id}/#{root.boxes[:pages].schema_id} /add/#{root.id}/#{root.boxes[:pages].schema_id}/#{SitePage.schema_id} /destroy/#{root.id} /slug/#{root.id} /slug/#{root.id}/unavailable /toggle/#{root.id} /schema/delete /schema/rename)
98
296
  end
99
297
 
100
- def get_paths
101
- %(/root /page/#{root.id} /metadata /map /map/#{root.id} /location/about)
298
+ describe "Invalid access keys" do
299
+ before do
300
+ @user, @key = login_user(editor_user)
301
+ @valid_key = rack_mock_session.cookie_jar[S::Rack::AUTH_COOKIE]
302
+ S::Permissions::AccessKey.expects(:authenticate).with(@valid_key, anything).returns(nil)
303
+ end
304
+
305
+ it "should show a login page" do
306
+ get '/@spontaneous'
307
+ assert_login_page
308
+ end
102
309
  end
103
310
 
104
- context "Authentication:" do
105
- setup do
106
- # Spontaneous::Schema.reset!
311
+ describe "Logged in users" do
312
+ before do
313
+ @user, @key = login_user(editor_user)
314
+ end
315
+
316
+ after do
317
+ clear_cookies
318
+ end
319
+
320
+ it "sets a long-lived cookie" do
321
+ cookies = rack_mock_session.cookie_jar.instance_variable_get("@cookies")
322
+ cookie = cookies.detect { |c| c.name == S::Rack::AUTH_COOKIE }
323
+ expiry = cookie.expires
324
+ expiry.must_be_instance_of Time
325
+ expiry.must_be_close_to Time.now + S::Rack::SESSION_LIFETIME, 1
326
+ end
327
+
328
+ it "are provided with a CSRF token" do
329
+ auth_get "/@spontaneous"
330
+ assert last_response.ok?
331
+ assert_contains_csrf_token @user.access_keys.first
332
+ end
107
333
 
108
- class C < Piece
109
- field :photo, :image, :write_level => :root
334
+ it "need to supply CSRF header for all POSTs" do
335
+ post_paths.split.delete_if { |path| }.each do |path|
336
+ post "/@spontaneous#{path}"
337
+ assert last_response.status == 401, "Status was #{last_response.status} not 401"
110
338
  end
111
- class D < Piece; end
339
+ end
112
340
 
113
- class SitePage < Page
114
- # page_style :default
115
- field :editor_level, :user_level => :editor
116
- field :admin_level, :user_level => :admin
117
- field :root_level, :user_level => :root
118
- field :mixed_level, :read_level => :editor, :write_level => :root
119
- field :default_level
341
+ it "need to supply CSRF header for all GETs" do
342
+ get_paths.split.each do |path|
343
+ get "/@spontaneous#{path}"
344
+ assert last_response.status == 401, "Status was #{last_response.status} not 401"
345
+ end
346
+ end
120
347
 
121
- box :pages
122
-
123
- box :editor_level, :user_level => :editor do
124
- field :editor_level, :user_level => :editor
125
- field :admin_level, :user_level => :admin
126
- field :root_level, :user_level => :root
127
- field :mixed_level, :read_level => :editor, :write_level => :root
128
- field :default_level
129
-
130
- allow :'AuthenticationTest::D', :user_level => :editor
131
- allow :'AuthenticationTest::C', :user_level => :root
132
- end
133
-
134
- box :admin_level, :user_level => :admin do
135
- field :editor_level, :user_level => :editor
136
- field :admin_level, :user_level => :admin
137
- field :root_level, :user_level => :root
138
- field :mixed_level, :read_level => :editor, :write_level => :root
139
- field :default_level
140
-
141
- allow :'AuthenticationTest::C', :user_level => :admin
142
- allow :'AuthenticationTest::D', :user_level => :root
143
- end
144
-
145
- box :root_level, :user_level => :root do
146
- field :editor_level, :user_level => :editor
147
- field :admin_level, :user_level => :admin
148
- field :root_level, :user_level => :root
149
- field :mixed_level, :read_level => :editor, :write_level => :root
150
- field :default_level
151
-
152
- allow :'AuthenticationTest::C', :user_level => :root
153
- end
154
-
155
- box :mixed_level, :read_level => :editor, :write_level => :root do
156
- field :editor_level, :user_level => :editor
157
- field :admin_level, :user_level => :admin
158
- field :root_level, :user_level => :root
159
- field :mixed_level, :read_level => :editor, :write_level => :root
160
- field :default_level
161
-
162
- allow :'AuthenticationTest::C', :user_level => :editor
163
- end
164
-
165
- box :default_level do
166
- field :editor_level, :user_level => :editor
167
- field :admin_level, :user_level => :admin
168
- field :root_level, :user_level => :root
169
- field :mixed_level, :read_level => :editor, :write_level => :root
170
- field :default_level
171
-
172
- allow :'AuthenticationTest::C'
173
- end
174
- end
175
- Content.delete
176
- Permissions::User.delete
177
- Permissions::AccessKey.delete
178
- Spontaneous.environment = :test
179
- Permissions::UserLevel.reset!
180
- Permissions::UserLevel.stubs(:level_file).returns(File.expand_path('../../fixtures/permissions', __FILE__) / 'config/user_levels.yml')
181
-
182
- ::Content.scope do
183
- @root = SitePage.create
184
- @root.save
185
-
186
- @about = SitePage.create(:uid => 'about', :slug => "about")
187
- @root.pages << @about
188
- piece = C.new
189
- @root.boxes[:root_level] << piece
190
- piece = C.new
191
- @root.boxes[:root_level] << piece
192
- @root.save
193
-
194
- @root_user = create_user('root', Permissions::UserLevel.root)
195
- @admin_user = create_user('admin', Permissions::UserLevel.admin)
196
- @editor_user = create_user('editor', Permissions::UserLevel.editor)
197
- @guest_user = create_user('guest', Permissions::UserLevel.none)
198
- @disabled_user = create_user('disabled', Permissions::UserLevel.admin)
199
- @disabled_user.update(:disabled => true)
348
+ it "can supply the CSRF token as a URL parameter" do
349
+ get_paths.split.each do |path|
350
+ get "/@spontaneous/site?#{S::Rack::CSRF_PARAM}=#{api_key.generate_csrf_token}"
351
+ assert last_response.status == 200, "#{path} Status was #{last_response.status} not 401"
200
352
  end
201
353
  end
202
354
 
203
- teardown do
204
- [:C, :D, :SitePage].each { |k| AuthenticationTest.send(:remove_const, k) rescue nil }
205
- Content.delete
206
- Permissions::User.delete
207
- Permissions::AccessKey.delete
355
+ it "be able to view the preview" do
356
+ get "/", preview: true
357
+ assert last_response.ok?
358
+ end
359
+
360
+ it "be able to view the editing interface" do
361
+ get "/@spontaneous"
362
+ assert last_response.ok?, "Expected 200 but got #{last_response.status}"
208
363
  end
209
364
 
210
- context "Unauthorised sessions" do
211
- should "redirect / to /@spontaneous" do
212
- get "/"
213
- assert last_response.status == 302
214
- last_response.headers["Location"].should =~ %r{/@spontaneous$}
365
+ it "be able to logout" do
366
+ auth_delete "/@spontaneous/logout"
367
+ assert last_response.status == 401
368
+ rack_mock_session.cookie_jar.merge(last_response.headers["set-cookie"])
369
+ rack_mock_session.cookie_jar[Spontaneous::Rack::AUTH_COOKIE].value.must_equal ""
370
+ end
371
+ end
372
+ describe "User levels" do
373
+ describe "Root access" do
374
+ before do
375
+ @user, @key = login_user(root_user)
215
376
  end
216
-
217
- should "redirect /* to /@spontaneous" do
218
- get "/about"
219
- assert last_response.status == 302
220
- last_response.headers["Location"].should =~ %r{/@spontaneous$}
221
- end
222
-
223
- should "see a login page at /@spontaneous" do
224
- get "/@spontaneous"
225
- assert_login_page
226
- end
227
-
228
- should "see a login page for all GETs" do
229
- get_paths.split.each do |path|
230
- get "/@spontaneous#{path}"
231
- assert_login_page path
232
- end
233
- end
234
-
235
- should "see a login page for all POSTs" do
236
- post_paths.split.each do |path|
237
- post "/@spontaneous#{path}"
238
- assert_login_page(path, "POST")
239
- end
240
- end
241
-
242
- should "get access to static files" do
243
- get "/@spontaneous/static/favicon.ico"
244
- assert last_response.status == 200
245
- end
246
-
247
- should "get access to Javascript files" do
248
- get "/@spontaneous/js/init.js"
249
- assert last_response.status == 200
250
- end
251
-
252
- should "get access to CSS files" do
253
- get "/@spontaneous/css/spontaneous.css"
254
- assert last_response.status == 200
255
- end
256
-
257
- should "get access to media files" do
258
- get '/media/image.jpg'
259
- assert last_response.status == 200
260
- end
261
-
262
- context "Logging in" do
263
- should "fail unless provided with a login & password" do
264
- post "/@spontaneous/login", "user[login]" => "", "user[password]" => ""
265
- assert_login_page("/@spontaneous/login", "POST")
266
- end
267
-
268
- should "fail for invalid login names" do
269
- post "/@spontaneous/login", "user[login]" => "noone", "user[password]" => "wrong"
270
- assert_login_page("/@spontaneous/login", "POST")
271
- end
272
-
273
- should "fail for invalid passwords" do
274
- post "/@spontaneous/login", "user[login]" => "editor", "user[password]" => "wrong"
275
- assert_login_page("/@spontaneous/login", "POST")
276
- end
277
-
278
- should "fail for disabled users" do
279
- post "/@spontaneous/login", "user[login]" => "disabled", "user[password]" => "disabled_password"
280
- assert_login_page("/@spontaneous/login", "POST")
281
- end
282
-
283
- should "succeed and redirect to /@spontaneous for correct login & password" do
284
- # post "/@spontaneous/login", "user[login]" => "admin", "user[password]" => "admin_password"
285
- login_user(@admin_user, "origin" => "/103/preview")
286
- assert last_response.status == 302, "Status was #{last_response.status} not 302"
287
- last_response.headers["Location"].should =~ %r{/@spontaneous/103/preview$}
288
- end
289
-
290
- should "set the secure flag for cookies delivered behind https" do
291
- clear_cookies
292
- rack_mock_session.cookie_jar[S::Rack::AUTH_COOKIE].should be_nil
293
- user = @admin_user
294
- post "https://example.org/@spontaneous/login", {"user[login]" => user.login, "user[password]" => user.password}
295
- cookies = rack_mock_session.cookie_jar.instance_variable_get("@cookies")
296
- cookie = cookies.detect { |c| c.name == S::Rack::AUTH_COOKIE }
297
- cookie.secure?.should be_true
298
- end
299
-
300
- should "set the secure flag for cookies delivered behind https when reauthenticating" do
301
- clear_cookies
302
- key = @admin_user.logged_in!
303
- post "https://example.org/@spontaneous/reauthenticate", "api_key" => key.key_id, "origin" => "/99/edit"
304
- cookies = rack_mock_session.cookie_jar.instance_variable_get("@cookies")
305
- cookie = cookies.detect { |c| c.name == S::Rack::AUTH_COOKIE }
306
- cookie.secure?.should be_true
307
- cookie_options = cookie.instance_variable_get("@options")
308
- cookie_options.key?("HttpOnly").should be_true
309
- end
310
-
311
- should "succeed and return an api key value for correct login over XHR" do
312
- key = Spontaneous::Permissions::AccessKey.new
313
- Spontaneous::Permissions::AccessKey.expects(:new).returns(key)
314
- post "/@spontaneous/login", { "user[login]" => "admin", "user[password]" => "admin_password" }, {"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
315
- assert last_response.status == 200, "Status was #{last_response.status} not 200"
316
- result = Spot::JSON.parse(last_response.body)
317
- result[:key].should == key.key_id
318
- result[:redirect].should == "/@spontaneous"
319
- end
320
-
321
- should "accept a valid API key for re-authentication" do
322
- key = @admin_user.logged_in!
323
- post "/@spontaneous/reauthenticate", "api_key" => key.key_id, "origin" => "/99/edit"
324
- assert last_response.status == 302, "Status was #{last_response.status} not 302"
325
- last_response.headers["Location"].should =~ %r{/@spontaneous/99/edit$}
326
- end
327
-
328
- should "reject invalid API key" do
329
- post "/@spontaneous/reauthenticate", "key" => "invalid"
330
- assert_login_page("/@spontaneous/reauthenticate", "POST")
331
- end
332
- end
333
-
334
- context "Logged in users" do
335
- setup do
336
- login_user(@editor_user)
337
- end
338
-
339
- teardown do
340
- clear_cookies
341
- end
342
-
343
- should "need to supply API key in params for all POSTs" do
344
- post_paths.split.each do |path|
345
- post "/@spontaneous#{path}"
346
- assert_login_page(path, "POST")
347
- end
348
- end
349
-
350
- should "need to supply API key in params for all GETs" do
351
- get_paths.split.each do |path|
352
- get "/@spontaneous#{path}"
353
- assert_login_page path
354
- end
355
- end
356
-
357
- should "be able to view the preview" do
358
- get "/"
359
- assert last_response.ok?
360
- end
361
-
362
- should "be able to view the editing interface" do
363
- get "/@spontaneous"
364
- assert last_response.ok?, "Expected 200 but got #{last_response.status}"
365
- end
366
-
367
- should "be able to logout" do
368
- auth_post "/@spontaneous/logout"
369
- assert last_response.status == 401
370
- rack_mock_session.cookie_jar.merge(last_response.headers["set-cookie"])
371
- rack_mock_session.cookie_jar[Spontaneous::Rack::AUTH_COOKIE].value.should == ""
372
- end
373
-
374
- # context "providing an API key in the request" do
375
- # should "be able to see previously forbidden fruit" do
376
- # get "/@spontaneous/root"
377
- # assert last_response.ok?
378
- # end
377
+
378
+ after do
379
+ clear_cookies
380
+ end
381
+
382
+ it "be able to update root level fields" do
383
+ field = root.fields.root_level
384
+ auth_put "/@spontaneous/content/#{root.id}", "field[#{field.schema_id}]" => "Updated"
385
+ assert last_response.ok?
386
+ root.reload.fields[:root_level].value.must_equal "Updated"
379
387
  end
380
388
 
389
+ it "be able to add to root level box" do
390
+ klass = C
391
+ auth_post "/@spontaneous/content/#{root.id}/#{root.boxes[:root_level].schema_id}/#{klass.schema_id}"
392
+ assert last_response.ok?
393
+ end
381
394
  end
395
+ describe "Admin access" do
396
+ before do
397
+ @user, @key = login_user(admin_user)
398
+ end
399
+
400
+ after do
401
+ clear_cookies
402
+ end
403
+
404
+ it "be able to update admin level fields" do
405
+ value = "Updated #{version}"
406
+ field = root.fields[:admin_level]
407
+ auth_put "/@spontaneous/content/#{root.id}", "field[#{field.schema_id}]" => value
408
+ assert last_response.ok?
409
+ root.reload.fields[:admin_level].value.must_equal value
410
+ end
411
+
412
+ it "not be able to add to root level box" do
413
+ auth_post "/@spontaneous/content/#{root.id}/#{root.boxes[:root_level].schema_id}/#{C.schema_id}"
414
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
415
+ end
416
+
417
+ it "not be able to add root level types to admin level box" do
418
+ auth_post "/@spontaneous/content/#{root.id}/#{root.boxes[:admin_level].schema_id}/#{D.schema_id}"
419
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
420
+ end
382
421
 
383
- context "User levels" do
384
- context "Root access" do
385
- setup do
386
- login_user(@root_user)
387
- end
388
-
389
- teardown do
390
- clear_cookies
391
- end
392
-
393
- should "be able to update root level fields" do
394
- field = root.fields.root_level
395
- auth_post "/@spontaneous/save/#{root.id}", "field[#{field.schema_id}]" => "Updated"
396
- assert last_response.ok?
397
- root.reload.fields[:root_level].value.should == "Updated"
398
- end
399
-
400
- should "be able to add to root level box" do
401
- klass = AuthenticationTest::C
402
- auth_post "/@spontaneous/add/#{root.id}/#{root.boxes[:root_level].schema_id}/#{klass.schema_id}"
403
- assert last_response.ok?
404
- end
405
- end
406
- context "Admin access" do
407
- setup do
408
- @root_copy = root
409
- login_user(@admin_user)
410
- end
411
-
412
- teardown do
413
- clear_cookies
414
- end
415
-
416
- # DISABLED: The ui should ensure that forbidden fields don't appear
417
- # the async update system simply ignores fields that the user can't
418
- # modify (see test_fields.rb).
419
- # should "not be able to update root level fields" do
420
- # value = "Updated #{version}"
421
- # field = root.fields[:root_level]
422
- # auth_post "/@spontaneous/save/#{root.id}", "field[#{field.schema_id}]" => value
423
- # assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
424
- # root.reload.fields[:root_level].value.should == @root_copy.root_level.value
425
- # end
426
-
427
- # should "not be able to update root level fields from admin level box" do
428
- # value = "Updated #{version}"
429
- # field = root.boxes[:admin_level].fields[:root_level]
430
- # auth_post "/@spontaneous/savebox/#{root.id}/#{root.boxes[:admin_level].schema_id}", "field[#{field.schema_id}]" => value
431
- # assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
432
- # end
433
-
434
- should "be able to update admin level fields" do
435
- value = "Updated #{version}"
436
- field = root.fields[:admin_level]
437
- auth_post "/@spontaneous/save/#{root.id}", "field[#{field.schema_id}]" => value
438
- assert last_response.ok?
439
- root.reload.fields[:admin_level].value.should == value
440
- end
441
-
442
- should "not be able to add to root level box" do
443
- auth_post "/@spontaneous/add/#{root.id}/#{root.boxes[:root_level].schema_id}/#{AuthenticationTest::C.schema_id}"
444
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
445
- end
446
-
447
- should "not be able to add root level types to admin level box" do
448
- auth_post "/@spontaneous/add/#{root.id}/#{root.boxes[:admin_level].schema_id}/#{AuthenticationTest::D.schema_id}"
449
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
450
- end
451
-
452
- should "be able to add to admin level box" do
453
- auth_post "/@spontaneous/add/#{root.id}/#{root.boxes[:admin_level].schema_id}/#{AuthenticationTest::C.schema_id}"
454
- # post "/@spontaneous/add/#{root.id}/admin_level/AuthenticationTest::C"
455
- assert last_response.ok?
456
- end
457
-
458
- should "not be able to update fields from root level box" do
459
- value = "Updated #{version}"
460
- field = root.fields[:editor_level]
461
- auth_post "/@spontaneous/savebox/#{root.id}/#{root.boxes[:root_level].schema_id}", "field[#{field.schema_id}]" => value
462
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
463
- end
464
-
465
- should "not be able to delete from root level box" do
466
- piece = root.boxes[:root_level].contents.first
467
- pieces = root.reload.boxes[:root_level].contents.length
468
- auth_post "/@spontaneous/destroy/#{piece.id}"
469
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
470
- root.reload.boxes[:root_level].contents.length.should == pieces
471
- end
472
- should "not be able to wrap files in root level box" do
473
- src_file = File.expand_path("../../fixtures/images/rose.jpg", __FILE__)
474
- auth_post "/@spontaneous/file/wrap/#{root.id}/#{root.boxes[:root_level].schema_id}", "file" => ::Rack::Test::UploadedFile.new(src_file, "image/jpeg")
475
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
476
- end
477
- should "not be able to wrap files in box if allow permissions don't permit it" do
478
- src_file = File.expand_path("../../fixtures/images/rose.jpg", __FILE__)
479
- # only type with an image field is C
480
- # editor_level box allows addition of type C but only by root
481
- # so the following should throw a perms error:
482
- auth_post "/@spontaneous/file/wrap/#{root.id}/#{root.boxes[:editor_level].schema_id}", "file" => ::Rack::Test::UploadedFile.new(src_file, "image/jpeg")
483
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
484
- end
485
- should "not be able to re-order pieces in root level box" do
486
- piece = root.boxes[:root_level].contents.last
487
- auth_post "/@spontaneous/content/#{piece.id}/position/0"
488
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
489
- root.reload.boxes[:root_level].contents.last.id.should == piece.id
490
- end
491
-
492
- should "not be able to replace root level fields" do
493
- piece = root.boxes[:root_level].contents.first
494
- src_file = File.expand_path("../../fixtures/images/rose.jpg", __FILE__)
495
- field = piece.fields[:photo]
496
- auth_post "/@spontaneous/file/replace/#{piece.id}", "file" => ::Rack::Test::UploadedFile.new(src_file, "image/jpeg"), "field" => field.schema_id
497
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
498
- end
499
-
500
- should "not be able to hide entries in root-level boxes" do
501
- piece = root.boxes[:root_level].contents.first
502
- auth_post "/@spontaneous/toggle/#{piece.id}"
503
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
504
- end
505
-
506
- should "not be allowed to update path of pages without permission"
507
- end
508
- context "Editor access" do
509
- setup do
510
- @root_copy = root
511
- login_user(@editor_user)
512
- end
513
-
514
- teardown do
515
- clear_cookies
516
- end
517
-
518
- should "not be able to retrieve the list of changes" do
519
- auth_get "/@spontaneous/publish/changes"
520
- assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
521
- end
422
+ it "be able to add to admin level box" do
423
+ auth_post "/@spontaneous/content/#{root.id}/#{root.boxes[:admin_level].schema_id}/#{C.schema_id}"
424
+ # post "/@spontaneous/add/#{root.id}/admin_level/C"
425
+ assert last_response.ok?
522
426
  end
427
+
428
+ it "not be able to update fields from root level box" do
429
+ value = "Updated #{version}"
430
+ field = root.fields[:editor_level]
431
+ auth_put "/@spontaneous/content/#{root.id}/#{root.boxes[:root_level].schema_id}", "field[#{field.schema_id}]" => value
432
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
433
+ end
434
+
435
+ it "not be able to delete from root level box" do
436
+ piece = root.boxes[:root_level].contents.first
437
+ pieces = root.reload.boxes[:root_level].contents.length
438
+ auth_delete "/@spontaneous/content/#{piece.id}"
439
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
440
+ root.reload.boxes[:root_level].contents.length.must_equal pieces
441
+ end
442
+ it "not be able to wrap files in root level box" do
443
+ src_file = File.expand_path("../../fixtures/images/rose.jpg", __FILE__)
444
+ auth_post "/@spontaneous/file/#{root.id}/#{root.boxes[:root_level].schema_id}", "file" => ::Rack::Test::UploadedFile.new(src_file, "image/jpeg")
445
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
446
+ end
447
+ it "not be able to wrap files in box if allow permissions don't permit it" do
448
+ src_file = File.expand_path("../../fixtures/images/rose.jpg", __FILE__)
449
+ # only type with an image field is C
450
+ # editor_level box allows addition of type C but only by root
451
+ # so the following should throw a perms error:
452
+ auth_post "/@spontaneous/file/#{root.id}/#{root.boxes[:editor_level].schema_id}", "file" => ::Rack::Test::UploadedFile.new(src_file, "image/jpeg")
453
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
454
+ end
455
+ it "not be able to re-order pieces in root level box" do
456
+ piece = root.boxes[:root_level].contents.last
457
+ auth_patch "/@spontaneous/content/#{piece.id}/position/0"
458
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
459
+ root.reload.boxes[:root_level].contents.last.id.must_equal piece.id
460
+ end
461
+
462
+ it "not be able to replace root level fields" do
463
+ piece = root.boxes[:root_level].contents.first
464
+ src_file = File.expand_path("../../fixtures/images/rose.jpg", __FILE__)
465
+ field = piece.fields[:photo]
466
+ auth_put "/@spontaneous/file/#{piece.id}", "file" => ::Rack::Test::UploadedFile.new(src_file, "image/jpeg"), "field" => field.schema_id
467
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
468
+ end
469
+
470
+ it "not be able to hide entries in root-level boxes" do
471
+ piece = root.boxes[:root_level].contents.first
472
+ auth_patch "/@spontaneous/content/#{piece.id}/toggle"
473
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
474
+ end
475
+
476
+ it "not be allowed to update path of pages without permission"
523
477
  end
478
+ describe "Editor access" do
479
+ before do
480
+ @user, @key = login_user(editor_user)
481
+ end
524
482
 
483
+ after do
484
+ clear_cookies
485
+ end
486
+
487
+ it "not be able to retrieve the list of changes" do
488
+ auth_get "/@spontaneous/changes"
489
+ assert last_response.status == 403, "Should have a permissions error 403 not #{last_response.status}"
490
+ end
491
+ end
525
492
  end
493
+
526
494
  end
527
495