spontaneous 0.1.0.alpha1

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 (556) hide show
  1. data/Gemfile +49 -0
  2. data/Gemfile.lock +146 -0
  3. data/LICENSE +0 -0
  4. data/README +0 -0
  5. data/Rakefile +284 -0
  6. data/Readme.markdown +7 -0
  7. data/application/css/add_alias_dialogue.scss +27 -0
  8. data/application/css/definitions.scss +249 -0
  9. data/application/css/developer.scss +9 -0
  10. data/application/css/editing.scss +649 -0
  11. data/application/css/login.scss +91 -0
  12. data/application/css/min/54ee0ed3c7fac7632bd5c020d69e9a2503e0c88c.css +1 -0
  13. data/application/css/min/c256adc144e2bdd0b0539356b04eb62db01e1dc3.css +1 -0
  14. data/application/css/popover.scss +335 -0
  15. data/application/css/schema_error.scss +90 -0
  16. data/application/css/spontaneous.scss +111 -0
  17. data/application/css/unsupported.scss +16 -0
  18. data/application/css/v2.scss +1606 -0
  19. data/application/css/variables.scss +80 -0
  20. data/application/js/add_alias_dialogue.js +59 -0
  21. data/application/js/add_home_dialogue.js +59 -0
  22. data/application/js/ajax.js +99 -0
  23. data/application/js/authentication.js +22 -0
  24. data/application/js/box.js +104 -0
  25. data/application/js/box_container.js +82 -0
  26. data/application/js/compatibility.js +132 -0
  27. data/application/js/conflicted_field_dialogue.js +92 -0
  28. data/application/js/content.js +224 -0
  29. data/application/js/content_area.js +44 -0
  30. data/application/js/dialogue.js +196 -0
  31. data/application/js/dom.js +71 -0
  32. data/application/js/edit_dialogue.js +137 -0
  33. data/application/js/edit_panel.js +232 -0
  34. data/application/js/editing.js +42 -0
  35. data/application/js/entry.js +13 -0
  36. data/application/js/extensions.js +104 -0
  37. data/application/js/field.js +4 -0
  38. data/application/js/field_preview.js +55 -0
  39. data/application/js/field_types/date_field.js +16 -0
  40. data/application/js/field_types/file_field.js +71 -0
  41. data/application/js/field_types/image_field.js +358 -0
  42. data/application/js/field_types/markdown_field.js +656 -0
  43. data/application/js/field_types/string_field.js +185 -0
  44. data/application/js/image.js +72 -0
  45. data/application/js/init.js +34 -0
  46. data/application/js/load.js +4 -0
  47. data/application/js/location.js +157 -0
  48. data/application/js/login.js +53 -0
  49. data/application/js/min/492a209de8ee955fa9c729a765377495001e11b1.js +17 -0
  50. data/application/js/min/80f684d77c940887a1d4a63e3a96102e993baa98.js +88 -0
  51. data/application/js/min/b8abf302a824c35385ff517b34111e1710ff3b37.js +2 -0
  52. data/application/js/min/c7140ec9475e5bf868b901e0621338d7d162358b.js +3 -0
  53. data/application/js/min/f07f2bd6630ee31e1c2288ec223383d8f0658ba6.js +2 -0
  54. data/application/js/page.js +43 -0
  55. data/application/js/page_browser.js +147 -0
  56. data/application/js/page_entry.js +47 -0
  57. data/application/js/popover.js +99 -0
  58. data/application/js/popover_view.js +56 -0
  59. data/application/js/preview.js +64 -0
  60. data/application/js/progress.js +358 -0
  61. data/application/js/properties.js +90 -0
  62. data/application/js/publish.js +187 -0
  63. data/application/js/require.js +129 -0
  64. data/application/js/sharded_upload.js +206 -0
  65. data/application/js/side_bar.js +30 -0
  66. data/application/js/spontaneous.js +6 -0
  67. data/application/js/state.js +64 -0
  68. data/application/js/status_bar.js +47 -0
  69. data/application/js/top_bar.js +368 -0
  70. data/application/js/types.js +98 -0
  71. data/application/js/upload.js +88 -0
  72. data/application/js/upload_manager.js +319 -0
  73. data/application/js/user.js +37 -0
  74. data/application/js/vendor/.DS_Store +0 -0
  75. data/application/js/vendor/JS.Class-2.1.5/CHANGELOG +283 -0
  76. data/application/js/vendor/JS.Class-2.1.5/MIT-LICENSE +30 -0
  77. data/application/js/vendor/JS.Class-2.1.5/README +30 -0
  78. data/application/js/vendor/JS.Class-2.1.5/min/command.js +1 -0
  79. data/application/js/vendor/JS.Class-2.1.5/min/comparable.js +1 -0
  80. data/application/js/vendor/JS.Class-2.1.5/min/constant_scope.js +1 -0
  81. data/application/js/vendor/JS.Class-2.1.5/min/core.js +1 -0
  82. data/application/js/vendor/JS.Class-2.1.5/min/decorator.js +1 -0
  83. data/application/js/vendor/JS.Class-2.1.5/min/enumerable.js +1 -0
  84. data/application/js/vendor/JS.Class-2.1.5/min/forwardable.js +1 -0
  85. data/application/js/vendor/JS.Class-2.1.5/min/hash.js +1 -0
  86. data/application/js/vendor/JS.Class-2.1.5/min/linked_list.js +1 -0
  87. data/application/js/vendor/JS.Class-2.1.5/min/loader.js +1 -0
  88. data/application/js/vendor/JS.Class-2.1.5/min/method_chain.js +1 -0
  89. data/application/js/vendor/JS.Class-2.1.5/min/observable.js +1 -0
  90. data/application/js/vendor/JS.Class-2.1.5/min/package.js +1 -0
  91. data/application/js/vendor/JS.Class-2.1.5/min/proxy.js +1 -0
  92. data/application/js/vendor/JS.Class-2.1.5/min/ruby.js +1 -0
  93. data/application/js/vendor/JS.Class-2.1.5/min/set.js +1 -0
  94. data/application/js/vendor/JS.Class-2.1.5/min/stack_trace.js +1 -0
  95. data/application/js/vendor/JS.Class-2.1.5/min/state.js +1 -0
  96. data/application/js/vendor/JS.Class-2.1.5/min/stdlib.js +16 -0
  97. data/application/js/vendor/JS.Class-2.1.5/src/command.js +93 -0
  98. data/application/js/vendor/JS.Class-2.1.5/src/comparable.js +37 -0
  99. data/application/js/vendor/JS.Class-2.1.5/src/constant_scope.js +48 -0
  100. data/application/js/vendor/JS.Class-2.1.5/src/core.js +1060 -0
  101. data/application/js/vendor/JS.Class-2.1.5/src/decorator.js +50 -0
  102. data/application/js/vendor/JS.Class-2.1.5/src/enumerable.js +505 -0
  103. data/application/js/vendor/JS.Class-2.1.5/src/forwardable.js +22 -0
  104. data/application/js/vendor/JS.Class-2.1.5/src/hash.js +334 -0
  105. data/application/js/vendor/JS.Class-2.1.5/src/linked_list.js +114 -0
  106. data/application/js/vendor/JS.Class-2.1.5/src/loader.js +553 -0
  107. data/application/js/vendor/JS.Class-2.1.5/src/method_chain.js +172 -0
  108. data/application/js/vendor/JS.Class-2.1.5/src/observable.js +55 -0
  109. data/application/js/vendor/JS.Class-2.1.5/src/package.js +472 -0
  110. data/application/js/vendor/JS.Class-2.1.5/src/proxy.js +58 -0
  111. data/application/js/vendor/JS.Class-2.1.5/src/ruby.js +44 -0
  112. data/application/js/vendor/JS.Class-2.1.5/src/set.js +332 -0
  113. data/application/js/vendor/JS.Class-2.1.5/src/stack_trace.js +151 -0
  114. data/application/js/vendor/JS.Class-2.1.5/src/state.js +95 -0
  115. data/application/js/vendor/JS.Class-2.1.5/src/stdlib.js +2612 -0
  116. data/application/js/vendor/crypto-2.3.0-crypto.js +160 -0
  117. data/application/js/vendor/crypto-2.3.0-sha1.js +91 -0
  118. data/application/js/vendor/diff_match_patch.js +2153 -0
  119. data/application/js/vendor/jquery-1.4.2.min.js +154 -0
  120. data/application/js/vendor/jquery-1.4.3.min.js +166 -0
  121. data/application/js/vendor/jquery-1.5.1.min.js +16 -0
  122. data/application/js/vendor/jquery-1.5.1rc1.min.js +24 -0
  123. data/application/js/vendor/jquery-1.6.2.min.js +18 -0
  124. data/application/js/vendor/jquery-ui-1.8.6.custom.min.js +265 -0
  125. data/application/js/vendor/jquery-ui-1.8.9.custom.min.js +415 -0
  126. data/application/js/vendor/jquery-ui-1.8.custom.min.js +106 -0
  127. data/application/js/vendor/jquery.hotkeys-0.7.9.js +248 -0
  128. data/application/js/vendor/jquery.hotkeys-0.7.9.min.js +19 -0
  129. data/application/js/vendor/jsdiff.js +169 -0
  130. data/application/js/views/box_view.js +229 -0
  131. data/application/js/views/page_piece_view.js +45 -0
  132. data/application/js/views/page_view.js +238 -0
  133. data/application/js/views/piece_view.js +178 -0
  134. data/application/js/views.js +110 -0
  135. data/application/static/editing-0-noise.png +0 -0
  136. data/application/static/editing-1-noise.png +0 -0
  137. data/application/static/editing-texture-1.png +0 -0
  138. data/application/static/editing-texture.png +0 -0
  139. data/application/static/editing-toolbar-shadow-bottom.png +0 -0
  140. data/application/static/editing-toolbar-shadow-top.png +0 -0
  141. data/application/static/favicon.ico +0 -0
  142. data/application/static/inner-glow.png +0 -0
  143. data/application/static/item-buttons.png +0 -0
  144. data/application/static/location-arrow.png +0 -0
  145. data/application/static/logo-400px-transparent.png +0 -0
  146. data/application/static/missing.png +0 -0
  147. data/application/static/orange-down-arrow.png +0 -0
  148. data/application/static/page-browser-next.png +0 -0
  149. data/application/static/paper-texture-dark.png +0 -0
  150. data/application/static/px.gif +0 -0
  151. data/application/static/select-arrow-root.png +0 -0
  152. data/application/static/select-arrow.png +0 -0
  153. data/application/static/slot-down-arrow.png +0 -0
  154. data/application/static/splash.png +0 -0
  155. data/application/static/spontaneous.png +0 -0
  156. data/application/static/spot.png +0 -0
  157. data/application/static/spot.svg +40 -0
  158. data/application/static/texture.png +0 -0
  159. data/application/views/index.erubis +46 -0
  160. data/application/views/login.erubis +69 -0
  161. data/application/views/schema_modification_error.html.erb +61 -0
  162. data/application/views/unsupported.erubis +23 -0
  163. data/bin/limit-upload +5 -0
  164. data/bin/spot +10 -0
  165. data/bin/unlimit-upload +3 -0
  166. data/config/nginx.conf +60 -0
  167. data/db/migrations/20100610142136_init.rb +66 -0
  168. data/db/migrations/20101130104334_timestamps.rb +44 -0
  169. data/db/migrations/20101202113205_site_publishing_flags.rb +12 -0
  170. data/db/migrations/20101206124543_aliases.rb +16 -0
  171. data/db/migrations/20110201133550_visibility.rb +27 -0
  172. data/db/migrations/20110209152710_users_and_groups.rb +58 -0
  173. data/db/migrations/20110215133910_boxes.rb +25 -0
  174. data/db/migrations/20110521114145_remove_slots_and_entries.rb +21 -0
  175. data/db/migrations/20110604192145_rename_schema_id_columns.rb +22 -0
  176. data/db/migrations/20110805141925_rename_site_to_state.rb +11 -0
  177. data/lib/cutaneous/context_helper.rb +82 -0
  178. data/lib/cutaneous/first_pass_parser.rb +23 -0
  179. data/lib/cutaneous/first_pass_renderer.rb +18 -0
  180. data/lib/cutaneous/parser_core.rb +18 -0
  181. data/lib/cutaneous/preview_context.rb +31 -0
  182. data/lib/cutaneous/preview_renderer.rb +15 -0
  183. data/lib/cutaneous/publish_context.rb +9 -0
  184. data/lib/cutaneous/renderer.rb +122 -0
  185. data/lib/cutaneous/request_context.rb +8 -0
  186. data/lib/cutaneous/second_pass_parser.rb +23 -0
  187. data/lib/cutaneous/second_pass_renderer.rb +18 -0
  188. data/lib/cutaneous.rb +47 -0
  189. data/lib/sequel/plugins/content_table_inheritance.rb +196 -0
  190. data/lib/sequel/plugins/yajl_serialization.rb +154 -0
  191. data/lib/spontaneous/application/feature.rb +9 -0
  192. data/lib/spontaneous/application/plugin.rb +13 -0
  193. data/lib/spontaneous/application.rb +8 -0
  194. data/lib/spontaneous/box.rb +232 -0
  195. data/lib/spontaneous/box_style.rb +64 -0
  196. data/lib/spontaneous/change.rb +107 -0
  197. data/lib/spontaneous/cli/adapter.rb +13 -0
  198. data/lib/spontaneous/cli/base.rb +184 -0
  199. data/lib/spontaneous/cli/console.rb +0 -0
  200. data/lib/spontaneous/cli/media.rb +13 -0
  201. data/lib/spontaneous/cli/server.rb +50 -0
  202. data/lib/spontaneous/cli/site.rb +46 -0
  203. data/lib/spontaneous/cli/sync.rb +42 -0
  204. data/lib/spontaneous/cli/tasks.rb +9 -0
  205. data/lib/spontaneous/cli.rb +83 -0
  206. data/lib/spontaneous/collections/box_set.rb +56 -0
  207. data/lib/spontaneous/collections/change_set.rb +43 -0
  208. data/lib/spontaneous/collections/entry_set.rb +83 -0
  209. data/lib/spontaneous/collections/field_set.rb +53 -0
  210. data/lib/spontaneous/collections/prototype_set.rb +131 -0
  211. data/lib/spontaneous/collections/style_set.rb +13 -0
  212. data/lib/spontaneous/config.rb +156 -0
  213. data/lib/spontaneous/constants.rb +24 -0
  214. data/lib/spontaneous/content.rb +113 -0
  215. data/lib/spontaneous/content_query.rb +17 -0
  216. data/lib/spontaneous/errors.rb +48 -0
  217. data/lib/spontaneous/extensions/array.rb +18 -0
  218. data/lib/spontaneous/extensions/class.rb +17 -0
  219. data/lib/spontaneous/extensions/hash.rb +18 -0
  220. data/lib/spontaneous/extensions/json.rb +26 -0
  221. data/lib/spontaneous/extensions/kernel.rb +7 -0
  222. data/lib/spontaneous/extensions/object.rb +30 -0
  223. data/lib/spontaneous/extensions/object_space.rb +12 -0
  224. data/lib/spontaneous/extensions/string.rb +44 -0
  225. data/lib/spontaneous/facet.rb +47 -0
  226. data/lib/spontaneous/field_types/date_field.rb +12 -0
  227. data/lib/spontaneous/field_types/field.rb +252 -0
  228. data/lib/spontaneous/field_types/image_field.rb +329 -0
  229. data/lib/spontaneous/field_types/markdown_field.rb +37 -0
  230. data/lib/spontaneous/field_types/string_field.rb +14 -0
  231. data/lib/spontaneous/field_types.rb +40 -0
  232. data/lib/spontaneous/generators/page/inline.html.cut +1 -0
  233. data/lib/spontaneous/generators/page/page.html.cut.tt +4 -0
  234. data/lib/spontaneous/generators/page/page.rb.tt +9 -0
  235. data/lib/spontaneous/generators/page.rb +38 -0
  236. data/lib/spontaneous/generators/site/.gitignore +4 -0
  237. data/lib/spontaneous/generators/site/Gemfile.tt +31 -0
  238. data/lib/spontaneous/generators/site/Rakefile.tt +6 -0
  239. data/lib/spontaneous/generators/site/config/back.ru +7 -0
  240. data/lib/spontaneous/generators/site/config/boot.rb +19 -0
  241. data/lib/spontaneous/generators/site/config/database.yml.tt +21 -0
  242. data/lib/spontaneous/generators/site/config/deploy.rb.tt +0 -0
  243. data/lib/spontaneous/generators/site/config/environment.rb.tt +8 -0
  244. data/lib/spontaneous/generators/site/config/environments/development.rb.tt +15 -0
  245. data/lib/spontaneous/generators/site/config/environments/production.rb.tt +5 -0
  246. data/lib/spontaneous/generators/site/config/front.ru +8 -0
  247. data/lib/spontaneous/generators/site/config/user_levels.yml +22 -0
  248. data/lib/spontaneous/generators/site/lib/site.rb.tt +4 -0
  249. data/lib/spontaneous/generators/site/lib/tasks/site.rake.tt +8 -0
  250. data/lib/spontaneous/generators/site/public/css/site.css +0 -0
  251. data/lib/spontaneous/generators/site/public/favicon.ico +0 -0
  252. data/lib/spontaneous/generators/site/public/js/.empty_directory +0 -0
  253. data/lib/spontaneous/generators/site/public/js/site.js +0 -0
  254. data/lib/spontaneous/generators/site/public/robots.txt +0 -0
  255. data/lib/spontaneous/generators/site/schema/.map +1 -0
  256. data/lib/spontaneous/generators/site/schema/page.rb.tt +8 -0
  257. data/lib/spontaneous/generators/site/schema/piece.rb.tt +4 -0
  258. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +13 -0
  259. data/lib/spontaneous/generators/site.rb +77 -0
  260. data/lib/spontaneous/generators.rb +23 -0
  261. data/lib/spontaneous/image_size.rb +117 -0
  262. data/lib/spontaneous/json.rb +33 -0
  263. data/lib/spontaneous/layout.rb +15 -0
  264. data/lib/spontaneous/loader.rb +280 -0
  265. data/lib/spontaneous/logger.rb +369 -0
  266. data/lib/spontaneous/media.rb +84 -0
  267. data/lib/spontaneous/page.rb +92 -0
  268. data/lib/spontaneous/page_controller.rb +18 -0
  269. data/lib/spontaneous/page_piece.rb +77 -0
  270. data/lib/spontaneous/paths.rb +30 -0
  271. data/lib/spontaneous/permissions/access_group.rb +50 -0
  272. data/lib/spontaneous/permissions/access_key.rb +35 -0
  273. data/lib/spontaneous/permissions/user.rb +167 -0
  274. data/lib/spontaneous/permissions/user_level.rb +177 -0
  275. data/lib/spontaneous/permissions.rb +55 -0
  276. data/lib/spontaneous/piece.rb +30 -0
  277. data/lib/spontaneous/plugins/aliases.rb +128 -0
  278. data/lib/spontaneous/plugins/allowed_types.rb +173 -0
  279. data/lib/spontaneous/plugins/application/facets.rb +25 -0
  280. data/lib/spontaneous/plugins/application/paths.rb +137 -0
  281. data/lib/spontaneous/plugins/application/render.rb +29 -0
  282. data/lib/spontaneous/plugins/application/serialisation.rb +16 -0
  283. data/lib/spontaneous/plugins/application/state.rb +86 -0
  284. data/lib/spontaneous/plugins/boxes.rb +84 -0
  285. data/lib/spontaneous/plugins/controllers.rb +52 -0
  286. data/lib/spontaneous/plugins/entries.rb +193 -0
  287. data/lib/spontaneous/plugins/entry.rb +51 -0
  288. data/lib/spontaneous/plugins/fields.rb +103 -0
  289. data/lib/spontaneous/plugins/instance_code.rb +18 -0
  290. data/lib/spontaneous/plugins/layouts.rb +87 -0
  291. data/lib/spontaneous/plugins/media.rb +41 -0
  292. data/lib/spontaneous/plugins/page/formats.rb +67 -0
  293. data/lib/spontaneous/plugins/page/request.rb +89 -0
  294. data/lib/spontaneous/plugins/page_search.rb +64 -0
  295. data/lib/spontaneous/plugins/page_tree.rb +25 -0
  296. data/lib/spontaneous/plugins/paths.rb +125 -0
  297. data/lib/spontaneous/plugins/permissions.rb +63 -0
  298. data/lib/spontaneous/plugins/prototypes.rb +84 -0
  299. data/lib/spontaneous/plugins/publishing.rb +255 -0
  300. data/lib/spontaneous/plugins/render.rb +24 -0
  301. data/lib/spontaneous/plugins/schema_hierarchy.rb +76 -0
  302. data/lib/spontaneous/plugins/schema_id.rb +60 -0
  303. data/lib/spontaneous/plugins/schema_title.rb +33 -0
  304. data/lib/spontaneous/plugins/serialisation.rb +67 -0
  305. data/lib/spontaneous/plugins/site/instance.rb +22 -0
  306. data/lib/spontaneous/plugins/site/map.rb +19 -0
  307. data/lib/spontaneous/plugins/site/publishing.rb +74 -0
  308. data/lib/spontaneous/plugins/site/revisions.rb +28 -0
  309. data/lib/spontaneous/plugins/site/selectors.rb +41 -0
  310. data/lib/spontaneous/plugins/site_map.rb +34 -0
  311. data/lib/spontaneous/plugins/styles.rb +119 -0
  312. data/lib/spontaneous/plugins/supertype.rb +11 -0
  313. data/lib/spontaneous/plugins/visibility.rb +151 -0
  314. data/lib/spontaneous/plugins.rb +20 -0
  315. data/lib/spontaneous/prototypes/box_prototype.rb +168 -0
  316. data/lib/spontaneous/prototypes/field_prototype.rb +112 -0
  317. data/lib/spontaneous/prototypes/layout_prototype.rb +17 -0
  318. data/lib/spontaneous/prototypes/style_prototype.rb +42 -0
  319. data/lib/spontaneous/proxy_object.rb +12 -0
  320. data/lib/spontaneous/publishing/fire_and_forget.rb +57 -0
  321. data/lib/spontaneous/publishing/immediate.rb +197 -0
  322. data/lib/spontaneous/publishing/threaded.rb +25 -0
  323. data/lib/spontaneous/publishing.rb +10 -0
  324. data/lib/spontaneous/rack/around_back.rb +44 -0
  325. data/lib/spontaneous/rack/around_front.rb +29 -0
  326. data/lib/spontaneous/rack/around_preview.rb +26 -0
  327. data/lib/spontaneous/rack/assets.rb +98 -0
  328. data/lib/spontaneous/rack/back.rb +729 -0
  329. data/lib/spontaneous/rack/front.rb +41 -0
  330. data/lib/spontaneous/rack/http.rb +18 -0
  331. data/lib/spontaneous/rack/media.rb +29 -0
  332. data/lib/spontaneous/rack/public.rb +232 -0
  333. data/lib/spontaneous/rack/reloader.rb +42 -0
  334. data/lib/spontaneous/rack/static.rb +25 -0
  335. data/lib/spontaneous/rack.rb +55 -0
  336. data/lib/spontaneous/render/context.rb +100 -0
  337. data/lib/spontaneous/render/development_renderer.rb +14 -0
  338. data/lib/spontaneous/render/engine.rb +19 -0
  339. data/lib/spontaneous/render/format/html.rb +5 -0
  340. data/lib/spontaneous/render/format.rb +70 -0
  341. data/lib/spontaneous/render/preview_renderer.rb +18 -0
  342. data/lib/spontaneous/render/published_renderer.rb +54 -0
  343. data/lib/spontaneous/render/publishing_renderer.rb +13 -0
  344. data/lib/spontaneous/render/renderer.rb +46 -0
  345. data/lib/spontaneous/render.rb +173 -0
  346. data/lib/spontaneous/revision.rb +7 -0
  347. data/lib/spontaneous/schema/schema_modification.rb +260 -0
  348. data/lib/spontaneous/schema/uid.rb +221 -0
  349. data/lib/spontaneous/schema.rb +295 -0
  350. data/lib/spontaneous/server.rb +65 -0
  351. data/lib/spontaneous/site.rb +87 -0
  352. data/lib/spontaneous/state.rb +53 -0
  353. data/lib/spontaneous/style.rb +144 -0
  354. data/lib/spontaneous/tasks/database.rake +9 -0
  355. data/lib/spontaneous/tasks.rb +5 -0
  356. data/lib/spontaneous/version.rb +6 -0
  357. data/lib/spontaneous.rb +179 -0
  358. data/spontaneous.gemspec.tmpl +66 -0
  359. data/test/disabled/test_slots.rb +287 -0
  360. data/test/experimental/test_formats.rb +92 -0
  361. data/test/experimental/test_plugins.rb +64 -0
  362. data/test/fixtures/application/css/test.less +5 -0
  363. data/test/fixtures/application/js/test.js +1 -0
  364. data/test/fixtures/application/static/favicon.ico +1 -0
  365. data/test/fixtures/application/static/test.html +1 -0
  366. data/test/fixtures/application/views/index.erubis +1 -0
  367. data/test/fixtures/back/public/test.html +1 -0
  368. data/test/fixtures/back/templates/layouts/standard.html.cut +1 -0
  369. data/test/fixtures/config/config/environment.rb +4 -0
  370. data/test/fixtures/config/config/environments/development.rb +13 -0
  371. data/test/fixtures/config/config/environments/production.rb +22 -0
  372. data/test/fixtures/config/config/environments/staging.rb +2 -0
  373. data/test/fixtures/example_application/Gemfile +6 -0
  374. data/test/fixtures/example_application/Gemfile.lock +76 -0
  375. data/test/fixtures/example_application/Rakefile +6 -0
  376. data/test/fixtures/example_application/config/back.rb +15 -0
  377. data/test/fixtures/example_application/config/back.ru +8 -0
  378. data/test/fixtures/example_application/config/back.yml +8 -0
  379. data/test/fixtures/example_application/config/boot.rb +16 -0
  380. data/test/fixtures/example_application/config/database.yml +24 -0
  381. data/test/fixtures/example_application/config/environment.rb +4 -0
  382. data/test/fixtures/example_application/config/environments/development.rb +16 -0
  383. data/test/fixtures/example_application/config/environments/production.rb +21 -0
  384. data/test/fixtures/example_application/config/environments/staging.rb +1 -0
  385. data/test/fixtures/example_application/config/front.rb +8 -0
  386. data/test/fixtures/example_application/config/front.ru +8 -0
  387. data/test/fixtures/example_application/config/front.yml +8 -0
  388. data/test/fixtures/example_application/config/schema.yml +48 -0
  389. data/test/fixtures/example_application/config/unicorn.rb +1 -0
  390. data/test/fixtures/example_application/config/user_levels.yml +19 -0
  391. data/test/fixtures/example_application/public/css/test.css +0 -0
  392. data/test/fixtures/example_application/public/favicon.ico +1 -0
  393. data/test/fixtures/example_application/public/js/test.js +0 -0
  394. data/test/fixtures/example_application/public/test.html +1 -0
  395. data/test/fixtures/example_application/schema/client_project.rb +18 -0
  396. data/test/fixtures/example_application/schema/client_projects.rb +8 -0
  397. data/test/fixtures/example_application/schema/home_page.rb +22 -0
  398. data/test/fixtures/example_application/schema/info_page.rb +13 -0
  399. data/test/fixtures/example_application/schema/inline_image.rb +11 -0
  400. data/test/fixtures/example_application/schema/page.rb +4 -0
  401. data/test/fixtures/example_application/schema/piece.rb +3 -0
  402. data/test/fixtures/example_application/schema/project.rb +21 -0
  403. data/test/fixtures/example_application/schema/project_image.rb +18 -0
  404. data/test/fixtures/example_application/schema/projects_page.rb +12 -0
  405. data/test/fixtures/example_application/schema/text.rb +8 -0
  406. data/test/fixtures/example_application/templates/client_project/images.html.cut +1 -0
  407. data/test/fixtures/example_application/templates/client_project.html.cut +4 -0
  408. data/test/fixtures/example_application/templates/client_projects.html.cut +6 -0
  409. data/test/fixtures/example_application/templates/info_page/inline.html.cut +0 -0
  410. data/test/fixtures/example_application/templates/inline_image.html.cut +1 -0
  411. data/test/fixtures/example_application/templates/layouts/home.html.cut +15 -0
  412. data/test/fixtures/example_application/templates/layouts/info.html.cut +3 -0
  413. data/test/fixtures/example_application/templates/layouts/project.html.cut +13 -0
  414. data/test/fixtures/example_application/templates/layouts/projects.html.cut +11 -0
  415. data/test/fixtures/example_application/templates/layouts/standard.html.cut +0 -0
  416. data/test/fixtures/example_application/templates/project/inline.html.cut +5 -0
  417. data/test/fixtures/example_application/templates/project.html.cut +5 -0
  418. data/test/fixtures/example_application/templates/project_image.html.cut +1 -0
  419. data/test/fixtures/example_application/templates/text.html.cut +1 -0
  420. data/test/fixtures/images/rose.greyscale.jpg +0 -0
  421. data/test/fixtures/images/rose.jpg +0 -0
  422. data/test/fixtures/images/size.gif +0 -0
  423. data/test/fixtures/images/size.jpg +0 -0
  424. data/test/fixtures/images/size.png24 +0 -0
  425. data/test/fixtures/images/size.png8 +0 -0
  426. data/test/fixtures/layouts/layouts/custom1.html.cut +1 -0
  427. data/test/fixtures/layouts/layouts/custom1.pdf.cut +0 -0
  428. data/test/fixtures/layouts/layouts/custom1.xml.cut +0 -0
  429. data/test/fixtures/layouts/layouts/custom2.html.cut +1 -0
  430. data/test/fixtures/layouts/layouts/custom3.html.cut +0 -0
  431. data/test/fixtures/layouts/layouts/standard.html.cut +1 -0
  432. data/test/fixtures/media/101/003/rose.jpg +0 -0
  433. data/test/fixtures/permissions/config/user_levels.yml +9 -0
  434. data/test/fixtures/permissions/media/image.jpg +0 -0
  435. data/test/fixtures/plugins/schema_plugin/init.rb +1 -0
  436. data/test/fixtures/plugins/schema_plugin/schema/external.rb +5 -0
  437. data/test/fixtures/plugins/schema_plugin/templates/external.html.cut +1 -0
  438. data/test/fixtures/plugins/schema_plugin/templates/from_plugin.html.cut +0 -0
  439. data/test/fixtures/plugins/schema_plugin/templates/layouts/from_plugin.html.cut +0 -0
  440. data/test/fixtures/public/templates/layouts/default.html.cut +1 -0
  441. data/test/fixtures/public/templates/layouts/default.pdf.cut +1 -0
  442. data/test/fixtures/public/templates/layouts/default.rss.cut +1 -0
  443. data/test/fixtures/public/templates/layouts/dynamic.html.cut +1 -0
  444. data/test/fixtures/public/templates/layouts/standard.html.cut +0 -0
  445. data/test/fixtures/schema/before.yml +24 -0
  446. data/test/fixtures/schema/resolvable.yml +12 -0
  447. data/test/fixtures/schema/schema.yml +7 -0
  448. data/test/fixtures/serialisation/class_hash.yaml.erb +53 -0
  449. data/test/fixtures/serialisation/root_hash.yaml.erb +184 -0
  450. data/test/fixtures/sharding/rose.jpg +0 -0
  451. data/test/fixtures/sharding/xaa +0 -0
  452. data/test/fixtures/sharding/xab +0 -0
  453. data/test/fixtures/sharding/xac +0 -0
  454. data/test/fixtures/sharding/xad +0 -0
  455. data/test/fixtures/sharding/xae +0 -0
  456. data/test/fixtures/sharding/xaf +0 -0
  457. data/test/fixtures/sharding/xag +0 -0
  458. data/test/fixtures/styles/box_a/runny.html.cut +0 -0
  459. data/test/fixtures/styles/box_a.html.cut +1 -0
  460. data/test/fixtures/styles/named2.html.cut +1 -0
  461. data/test/fixtures/styles/orange/apple.html.cut +1 -0
  462. data/test/fixtures/styles/template_class/named1.html.cut +1 -0
  463. data/test/fixtures/styles/template_class/results.html.cut +1 -0
  464. data/test/fixtures/styles/template_class/walky.html.cut +0 -0
  465. data/test/fixtures/styles/template_class.epub.cut +0 -0
  466. data/test/fixtures/styles/template_class.html.cut +1 -0
  467. data/test/fixtures/styles/template_class.pdf.cut +0 -0
  468. data/test/fixtures/styles/template_sub_class1.html.cut +1 -0
  469. data/test/fixtures/templates/aliases/a/a_style.html.cut +0 -0
  470. data/test/fixtures/templates/aliases/a/page.html.cut +0 -0
  471. data/test/fixtures/templates/aliases/a_alias/a_alias_style.html.cut +0 -0
  472. data/test/fixtures/templates/aliases/layouts/b.html.cut +1 -0
  473. data/test/fixtures/templates/aliases/layouts/b_alias.html.cut +1 -0
  474. data/test/fixtures/templates/aliases/layouts/c_alias.html.cut +1 -0
  475. data/test/fixtures/templates/boxes/blank_content/things.html.cut +1 -0
  476. data/test/fixtures/templates/boxes/my_box_class/christy.html.cut +1 -0
  477. data/test/fixtures/templates/boxes/thangs.html.cut +1 -0
  478. data/test/fixtures/templates/boxes/with_template_box.html.cut +1 -0
  479. data/test/fixtures/templates/content/include.html.cut +1 -0
  480. data/test/fixtures/templates/content/include_dir.html.cut +1 -0
  481. data/test/fixtures/templates/content/included.epub.cut +1 -0
  482. data/test/fixtures/templates/content/included.html.cut +1 -0
  483. data/test/fixtures/templates/content/partial/included.html.cut +1 -0
  484. data/test/fixtures/templates/content/preprocess.html.cut +1 -0
  485. data/test/fixtures/templates/content/second.html.cut +1 -0
  486. data/test/fixtures/templates/content/template.epub.cut +1 -0
  487. data/test/fixtures/templates/content/template.html.cut +1 -0
  488. data/test/fixtures/templates/default_style_class.html.cut +1 -0
  489. data/test/fixtures/templates/direct.html.cut +1 -0
  490. data/test/fixtures/templates/extended/grandparent.html.cut +10 -0
  491. data/test/fixtures/templates/extended/main.html.cut +6 -0
  492. data/test/fixtures/templates/extended/parent.html.cut +10 -0
  493. data/test/fixtures/templates/layouts/entries.html.cut +7 -0
  494. data/test/fixtures/templates/layouts/page_style.html.cut +1 -0
  495. data/test/fixtures/templates/layouts/params.html.cut +1 -0
  496. data/test/fixtures/templates/layouts/preview_render.html.cut +2 -0
  497. data/test/fixtures/templates/layouts/standard_page.html.cut +1 -0
  498. data/test/fixtures/templates/layouts/subdir_style.html.cut +1 -0
  499. data/test/fixtures/templates/layouts/template_params.html.cut +1 -0
  500. data/test/fixtures/templates/page_class/inline_style.html.cut +1 -0
  501. data/test/fixtures/templates/preview_render/inline.html.cut +0 -0
  502. data/test/fixtures/templates/publishing/layouts/dynamic.html.cut +1 -0
  503. data/test/fixtures/templates/publishing/layouts/static.html.cut +1 -0
  504. data/test/fixtures/templates/template_class/anonymous_style.html.cut +4 -0
  505. data/test/fixtures/templates/template_class/another_template.html.cut +0 -0
  506. data/test/fixtures/templates/template_class/complex_template.html.cut +6 -0
  507. data/test/fixtures/templates/template_class/complex_template.pdf.cut +6 -0
  508. data/test/fixtures/templates/template_class/default_template_style.html.cut +4 -0
  509. data/test/fixtures/templates/template_class/images_with_template.html.cut +5 -0
  510. data/test/fixtures/templates/template_class/slots_template.html.cut +5 -0
  511. data/test/fixtures/templates/template_class/slots_template.pdf.cut +5 -0
  512. data/test/fixtures/templates/template_class/this_template.epub.cut +1 -0
  513. data/test/fixtures/templates/template_class/this_template.html.cut +1 -0
  514. data/test/fixtures/templates/template_class/this_template.pdf.cut +1 -0
  515. data/test/fixtures/templates/with_default_style_class.html.cut +1 -0
  516. data/test/functional/test_application.rb +176 -0
  517. data/test/functional/test_back.rb +902 -0
  518. data/test/functional/test_front.rb +571 -0
  519. data/test/javascript/test_dom.rb +94 -0
  520. data/test/javascript/test_markdown.rb +97 -0
  521. data/test/slow/test_publishing.rb +987 -0
  522. data/test/slow/test_visibility.rb +250 -0
  523. data/test/support/custom_matchers.rb +77 -0
  524. data/test/support/timing.rb +23 -0
  525. data/test/test_helper.rb +164 -0
  526. data/test/test_javascript.rb +34 -0
  527. data/test/ui/test_page_editing.rb +167 -0
  528. data/test/ui_helper.rb +114 -0
  529. data/test/unit/test_alias.rb +254 -0
  530. data/test/unit/test_authentication.rb +510 -0
  531. data/test/unit/test_boxes.rb +497 -0
  532. data/test/unit/test_config.rb +156 -0
  533. data/test/unit/test_content.rb +221 -0
  534. data/test/unit/test_content_inheritance.rb +103 -0
  535. data/test/unit/test_extensions.rb +14 -0
  536. data/test/unit/test_fields.rb +392 -0
  537. data/test/unit/test_generators.rb +97 -0
  538. data/test/unit/test_image_size.rb +25 -0
  539. data/test/unit/test_images.rb +265 -0
  540. data/test/unit/test_layouts.rb +111 -0
  541. data/test/unit/test_logger.rb +80 -0
  542. data/test/unit/test_media.rb +70 -0
  543. data/test/unit/test_page.rb +244 -0
  544. data/test/unit/test_permissions.rb +834 -0
  545. data/test/unit/test_piece.rb +80 -0
  546. data/test/unit/test_prototype_set.rb +192 -0
  547. data/test/unit/test_prototypes.rb +102 -0
  548. data/test/unit/test_render.rb +359 -0
  549. data/test/unit/test_schema.rb +1009 -0
  550. data/test/unit/test_serialisation.rb +215 -0
  551. data/test/unit/test_site.rb +145 -0
  552. data/test/unit/test_structure.rb +85 -0
  553. data/test/unit/test_styles.rb +417 -0
  554. data/test/unit/test_templates.rb +224 -0
  555. data/test/unit/test_type_hierarchy.rb +28 -0
  556. metadata +1017 -0
@@ -0,0 +1,50 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Permissions
4
+ class AccessGroup < Sequel::Model(:spontaneous_groups)
5
+ many_to_many :members, :class => :'Spontaneous::Permissions::User', :join_table => :spontaneous_groups_users, :left_key => :group_id, :right_key => :user_id
6
+
7
+ def level_for(content)
8
+ if selector.matches(content)
9
+ level
10
+ else
11
+ UserLevel.none
12
+ end
13
+ end
14
+
15
+ def selector
16
+ @selector ||= Spontaneous::ContentQuery.new(access_selector)
17
+ end
18
+
19
+ def level_for(content)
20
+ if selector.matches?(content)
21
+ level
22
+ else
23
+ UserLevel.none
24
+ end
25
+ end
26
+
27
+ def level
28
+ if disabled
29
+ UserLevel.none
30
+ else
31
+ UserLevel[level_name]
32
+ end
33
+ end
34
+
35
+ def level=(level)
36
+ self.level_name = level.to_s
37
+ end
38
+
39
+ def invisible?
40
+ !user_id.blank?
41
+ end
42
+
43
+ def validate
44
+ super
45
+ errors.add(:name, 'is required') if name.blank?
46
+ end
47
+ end
48
+ end
49
+
50
+
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Permissions
4
+ class AccessKey < Sequel::Model(:spontaneous_access_keys)
5
+ plugin :timestamps
6
+ many_to_one :user, :class => :'Spontaneous::Permissions::User'
7
+
8
+ def self.authenticate(key_id)
9
+ if key = self.for_id(key_id)
10
+ key.access!
11
+ return key
12
+ end
13
+ nil
14
+ end
15
+
16
+ def self.valid?(key_id, user)
17
+ return true if (key = self.for_id(key_id)) and key.user == user
18
+ false
19
+ end
20
+
21
+ def self.for_id(key_id)
22
+ self[:key_id => key_id]
23
+ end
24
+
25
+ def before_create
26
+ self.key_id = Spontaneous::Permissions.random_string(44)
27
+ self.last_access_at = Time.now
28
+ super
29
+ end
30
+
31
+ def access!
32
+ self.update(:last_access_at => Time.now)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,167 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Permissions
4
+ class User < Sequel::Model(:spontaneous_users)
5
+ extend Forwardable
6
+
7
+ plugin :timestamps
8
+
9
+ one_to_one :group, :class => :'Spontaneous::Permissions::AccessGroup'
10
+ many_to_many :groups, :class => :'Spontaneous::Permissions::AccessGroup', :join_table => :spontaneous_groups_users
11
+ one_to_many :access_keys, :class => :'Spontaneous::Permissions::AccessKey'
12
+
13
+ set_restricted_columns(:crypted_password)
14
+
15
+ def_delegators :group, :level, :access_selector
16
+
17
+ def self.encrypt_password(clear_password, salt)
18
+ Digest::SHA1.hexdigest("--#{salt}--#{clear_password}--")
19
+ end
20
+
21
+ def self.authenticate(login, clear_password)
22
+ if user = self[:login => login, :disabled => false]
23
+ crypted_password = user.encrypt_password(clear_password)
24
+ if crypted_password == user.crypted_password
25
+ access_key = user.logged_in!
26
+ return access_key
27
+ end
28
+ end
29
+ nil
30
+ end
31
+
32
+ attr_accessor :password, :password_confirmation
33
+
34
+ ##
35
+ # Find the highest access level available from all the groups we
36
+ # belong to
37
+ # TODO: actually match the content against the memberships
38
+ def level_for(content)
39
+ memberships.map { |m| m.level_for(content) }.sort.last
40
+ end
41
+
42
+ def last_access_at
43
+ access_keys.map(&:last_access_at).sort.last
44
+ end
45
+
46
+ def logged_in!
47
+ self.last_login_at = Time.now
48
+ key = AccessKey.new
49
+ self.add_access_key(key)
50
+ self.save
51
+ key
52
+ end
53
+
54
+ def encrypt_password(clear_password)
55
+ self.class.encrypt_password(clear_password, salt)
56
+ end
57
+
58
+ def before_save
59
+ self.salt = Spontaneous::Permissions.random_string(32) if salt.blank?
60
+ self.crypted_password = encrypt_password(password) unless password.blank?
61
+ if self.disabled
62
+ access_keys.each { | key | key.delete }
63
+ end
64
+ super
65
+ end
66
+
67
+ def after_create
68
+ super
69
+ ensure_group!
70
+ end
71
+
72
+ def password=(new_password)
73
+ updating_password!
74
+ @password = new_password
75
+ end
76
+
77
+ def password_confirmation=(new_password)
78
+ updating_password!
79
+ @password_confirmation = new_password
80
+ end
81
+
82
+ def level=(level)
83
+ ensure_group!
84
+ group.level = level
85
+ group.save
86
+ end
87
+
88
+ def raise_on_save_failure
89
+ false
90
+ end
91
+
92
+ def memberships
93
+ groups.push(group)
94
+ end
95
+
96
+ def developer?
97
+ level.developer?
98
+ end
99
+
100
+ def export
101
+ {
102
+ :name => name,
103
+ :email => email,
104
+ :login => login,
105
+ :developer => !!developer?
106
+ }
107
+ end
108
+
109
+ def serialise_http
110
+ Spontaneous.serialise_http(export)
111
+ end
112
+
113
+ protected
114
+
115
+ def validate
116
+ super
117
+ errors.add(:name, 'is required') if name.blank?
118
+ errors.add(:email, 'is required') if email.blank?
119
+ errors.add(:email, 'is invalid') unless email =~ /^[^@]+@.+$/
120
+
121
+ if login.blank?
122
+ errors.add(:login, 'is required')
123
+ else
124
+ errors.add(:login, 'should only contain letters, numbers & underscore') unless login =~ /^[a-zA-Z0-9_]+$/
125
+ errors.add(:login, 'should be at least 3 letters long') if login.length < 3
126
+ end
127
+
128
+ if errors[:login].empty? && new?
129
+ if User[:login => login]
130
+ errors.add(:login, "must be unique, login '#{login}' already exists")
131
+ end
132
+ end
133
+
134
+ if new? || updating_password?
135
+ if password.blank?
136
+ errors.add(:password, 'is required')
137
+ elsif password_confirmation.blank?
138
+ errors.add(:password_confirmation, 'is required')
139
+ else
140
+ if password != password_confirmation
141
+ errors.add(:password_confirmation, 'should match the password')
142
+ else
143
+ if password.length < 6
144
+ errors.add(:password, 'is too short. It should be at least 6 characters')
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+
152
+ def updating_password!
153
+ @_updating_password = true
154
+ end
155
+
156
+ def updating_password?
157
+ @_updating_password
158
+ end
159
+
160
+ def ensure_group!
161
+ if group.nil?
162
+ self.group = AccessGroup.create(:user_id => id, :name => "_#{name}_", :level_name => UserLevel.none.to_s)
163
+ end
164
+ end
165
+ end
166
+ end
167
+
@@ -0,0 +1,177 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'hwia'
4
+ require 'yaml'
5
+
6
+ module Spontaneous::Permissions
7
+ class UserLevel
8
+
9
+ class Root
10
+ private(:initialize)
11
+ def self.>(level); true; end
12
+ def self.>=(level); true; end
13
+ def self.<=>(level); 1; end
14
+ def self.to_s; 'root'; end
15
+ def self.to_sym; :root; end
16
+ def self.can_publish?; true; end
17
+ def self.developer?; true; end
18
+ end
19
+
20
+ class None
21
+ private(:initialize)
22
+ def self.>(level); false; end
23
+ def self.>=(level)
24
+ level.equal?(None)
25
+ end
26
+
27
+ def self.<=>(level); -1; end
28
+ def self.to_s; 'none'; end
29
+ def self.to_sym; :none; end
30
+ def self.can_publish?; false; end
31
+ def self.developer?; false; end
32
+ end
33
+
34
+ class Level
35
+ @@instances = Hash.new
36
+
37
+ def self.[](value, description)
38
+ name = description.delete(:name)
39
+ if @@instances.key?(value.to_i)
40
+ @@instances[value.to_i]
41
+ else
42
+ @@instances[value.to_i] = self.new(name, value.to_i, description)
43
+ end
44
+ end
45
+
46
+ attr_reader :name, :value
47
+ alias_method :to_i, :value
48
+
49
+ def initialize(name, value, permissions)
50
+ @name, @value, @permissions = name.to_sym, value.to_i, permissions
51
+ end
52
+
53
+ def >(level)
54
+ return false if level.equal?(Root)
55
+ return true if level.equal?(None)
56
+ @value > level.to_i
57
+ end
58
+
59
+ def >=(level)
60
+ return false if level.equal?(Root)
61
+ return true if level.equal?(None)
62
+ @value >= level.to_i
63
+ end
64
+
65
+ def <(level)
66
+ return true if level.equal?(Root)
67
+ return false if level.equal?(None)
68
+ @value < level.to_i
69
+ end
70
+
71
+ def <=>(level)
72
+ return -1 if level.equal?(Root)
73
+ return 1 if level.equal?(None)
74
+ @value <=> level.to_i
75
+ end
76
+
77
+ def ==(level)
78
+ return false if level.equal?(Root)
79
+ return false if level.equal?(None)
80
+ return @value == level.to_i
81
+ end
82
+
83
+ def can_publish?
84
+ @permissions[:publish]
85
+ end
86
+
87
+ def developer?
88
+ @permissions[:developer]
89
+ end
90
+
91
+ def to_s
92
+ @name.to_s
93
+ end
94
+
95
+ def to_sym
96
+ @name.to_sym
97
+ end
98
+ end
99
+
100
+ class << self
101
+ def minimum
102
+ get(all[1]) || None
103
+ end
104
+
105
+ def [](level)
106
+ get(level)
107
+ end
108
+
109
+ def get(level)
110
+ store[level]
111
+ end
112
+
113
+ def all(base_level = nil)
114
+ list = store.to_a.sort { |a, b| a[1] <=> b[1] }
115
+ list.reject! { |l| l[1] > get(base_level) } if base_level
116
+ list.map { |l| l[0] }
117
+ end
118
+
119
+ def root
120
+ Root
121
+ end
122
+
123
+ def none
124
+ None
125
+ end
126
+
127
+ def level_file
128
+ @level_file ||= 'config/user_levels.yml'
129
+ end
130
+
131
+ def level_file=(file)
132
+ @level_file = file
133
+ end
134
+
135
+ def reset!
136
+ @initialised = false
137
+ @store = nil
138
+ end
139
+
140
+ def init!
141
+ return if @initialised
142
+ store[:none] = None
143
+ store[:root] = Root
144
+ numeric = 1
145
+ if File.exists?(level_file)
146
+ levels = YAML.load_file(level_file)
147
+ levels.each_with_index do |description, index|
148
+ level = Level[(index+1), description]
149
+ store[level.name] = level
150
+ end
151
+ else
152
+ logger.warn {
153
+ "User level file '#{level_file}' missing, unable to load User Levels"
154
+ }
155
+ end
156
+ @initialised = true
157
+ end
158
+
159
+ def store
160
+ if !@store
161
+ @store = StrHash.new
162
+ init!
163
+ end
164
+ @store
165
+ end
166
+
167
+ def method_missing(method, *args)
168
+ if level = get(method)
169
+ level
170
+ else
171
+ super
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+
@@ -0,0 +1,55 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'base58'
4
+
5
+ module Spontaneous
6
+ module Permissions
7
+
8
+ autoload :UserLevel, "spontaneous/permissions/user_level"
9
+ autoload :User, "spontaneous/permissions/user"
10
+ autoload :AccessGroup, "spontaneous/permissions/access_group"
11
+ autoload :AccessKey, "spontaneous/permissions/access_key"
12
+
13
+ @@active_user = nil
14
+
15
+ class << self
16
+ # Convenience shortcut so we can do Permissions[:root]
17
+ def [](level_name)
18
+ UserLevel[level_name]
19
+ end
20
+
21
+ def root
22
+ UserLevel.root
23
+ end
24
+
25
+ def has_level?(level)
26
+ return true unless active_user
27
+ active_user.level >= level
28
+ end
29
+
30
+ def with_user(user)
31
+ self.active_user = user
32
+ yield if block_given?
33
+ ensure
34
+ self.active_user = nil
35
+ end
36
+
37
+ def active_user
38
+ Thread.current[:_permissions_active_user]
39
+ end
40
+
41
+ def active_user=(user)
42
+ Thread.current[:_permissions_active_user] = user
43
+ end
44
+
45
+ protected(:active_user=)
46
+
47
+ def random_string(length)
48
+ bytes = ((length * Math.log10(58))/(8 * Math.log10(2))).ceil + 2
49
+ string = Base58.encode(OpenSSL::Random.random_bytes(bytes).unpack("h*").first.to_i(16))
50
+ string[0...(length)]
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Spontaneous
5
+ class Piece < Content
6
+ plugin Plugins::Supertype
7
+
8
+ set_inheritance_root
9
+
10
+ def export
11
+ super.merge(export_styles)
12
+ end
13
+
14
+ def export_styles
15
+ h = {
16
+ :style => style_sid.to_s,
17
+ }
18
+ if container
19
+ h.merge!({
20
+ :styles => container.available_styles(self).map { |s| s.schema_id.to_s }
21
+ })
22
+ else
23
+ h.merge!({
24
+ :styles => self.styles.map { |s| s.schema_id.to_s }
25
+ })
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,128 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Spontaneous::Plugins
5
+ module Aliases
6
+
7
+ def self.configure(base)
8
+ base.many_to_one :target, :class => base, :reciprocal => :aliases
9
+ base.one_to_many :aliases, :class => base, :key => :target_id, :reciprocal => :target
10
+ base.add_association_dependencies :aliases => :destroy
11
+ end
12
+
13
+ module ClassMethods
14
+ def alias_of(*class_list)
15
+ @alias_classes = class_list
16
+ extend ClassAliasMethods
17
+ include AliasMethods
18
+ include PageAliasMethods if page?
19
+ end
20
+
21
+ alias_method :aliases, :alias_of
22
+
23
+ def targets
24
+ targets = []
25
+ target_classes.each do |target_class|
26
+ targets += target_class.sti_subclasses_array
27
+ end
28
+ S::Content.filter(sti_key => targets.map { |t| t.to_s }).all
29
+ end
30
+
31
+ def target_classes
32
+ @target_classes ||= @alias_classes.map { |c| c.to_s.constantize }
33
+ end
34
+
35
+ def alias?
36
+ false
37
+ end
38
+ end
39
+
40
+ module InstanceMethods
41
+ def alias_title
42
+ fields[:title].to_s
43
+ end
44
+
45
+ def alias_icon_field
46
+ if field = fields.detect { |f| f.image? }
47
+ field
48
+ else
49
+ nil
50
+ end
51
+ end
52
+ end
53
+
54
+ module ClassAliasMethods
55
+ def alias?
56
+ true
57
+ end
58
+ end
59
+
60
+ # included only in instances that are aliases
61
+ module AliasMethods
62
+ def alias?
63
+ true
64
+ end
65
+
66
+ def field?(field_name)
67
+ super || target.class.field?(field_name)
68
+ end
69
+
70
+ def method_missing(method, *args)
71
+ if target && target.respond_to?(method)
72
+ if block_given?
73
+ target.__send__(method, *args, &Proc.new)
74
+ else
75
+ target.__send__(method, *args)
76
+ end
77
+ else
78
+ super
79
+ end
80
+ end
81
+
82
+
83
+ def find_named_style(style_name)
84
+ super or target.find_named_style(style_name)
85
+ end
86
+
87
+ def style
88
+ if self.class.styles.empty?
89
+ target.resolve_style(style_sid)
90
+ else
91
+ self.resolve_style(self.style_sid) or target.resolve_style(self.style_sid)
92
+ end
93
+ end
94
+
95
+ def styles
96
+ @styles ||= Spontaneous::Collections::PrototypeSet.new(target, :styles)
97
+ end
98
+
99
+ def export
100
+ super.merge(:target => target.shallow_export, :alias_title => target.alias_title, :alias_icon => target.alias_icon_field.export)
101
+ end
102
+ end
103
+
104
+ module PageAliasMethods
105
+ def path
106
+ @_path ||= [parent.path, target.slug].join(S::SLASH)
107
+ end
108
+
109
+ def calculate_path
110
+ ""
111
+ end
112
+
113
+ def layout
114
+ # if this alias class has no layouts defined, then just use the one set on the target
115
+ if self.class.layouts.empty?
116
+ target.resolve_layout(self.style_sid)
117
+ else
118
+ # but if it does have layouts defined, use them
119
+ self.resolve_layout(self.style_sid) or target.resolve_layout(self.style_sid)
120
+ end
121
+ end
122
+
123
+ def find_named_layout(layout_name)
124
+ super or target.find_named_layout(layout_name)
125
+ end
126
+ end
127
+ end
128
+ end