pages_core 3.4.2

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 (271) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +29 -0
  3. data/Rakefile +10 -0
  4. data/app/assets/images/pages/admin/description-bg.gif +0 -0
  5. data/app/assets/images/pages/admin/drag-handle.gif +0 -0
  6. data/app/assets/images/pages/admin/drag-icon.png +0 -0
  7. data/app/assets/images/pages/admin/flash-error-bg.gif +0 -0
  8. data/app/assets/images/pages/admin/formelement-bg.gif +0 -0
  9. data/app/assets/images/pages/admin/header-tab-current-bg.gif +0 -0
  10. data/app/assets/images/pages/admin/icon.png +0 -0
  11. data/app/assets/images/pages/admin/image-editor-bg.png +0 -0
  12. data/app/assets/images/pages/admin/list-table-pin-blue.gif +0 -0
  13. data/app/assets/images/pages/admin/list-table-pin-disabled.gif +0 -0
  14. data/app/assets/images/pages/admin/list-table-pin-green.gif +0 -0
  15. data/app/assets/images/pages/admin/list-table-pin-red.gif +0 -0
  16. data/app/assets/images/pages/admin/list-table-pin-yellow.gif +0 -0
  17. data/app/assets/images/pages/admin/list-table-td-bg.gif +0 -0
  18. data/app/assets/images/pages/admin/loading-modal.gif +0 -0
  19. data/app/assets/images/pages/admin/sidebar-bg.gif +0 -0
  20. data/app/assets/images/pages/admin/textarea_controls.gif +0 -0
  21. data/app/assets/images/pages/admin/warning-icon.gif +0 -0
  22. data/app/assets/images/pages/favicon.gif +0 -0
  23. data/app/assets/images/pages/feed-icon-14x14.png +0 -0
  24. data/app/assets/javascripts/pages/admin/controllers/base.js.coffee +4 -0
  25. data/app/assets/javascripts/pages/admin/controllers/pages_controller.js.coffee +139 -0
  26. data/app/assets/javascripts/pages/admin/controllers/users_controller.js.coffee +9 -0
  27. data/app/assets/javascripts/pages/admin/features/content_tabs.js.coffee +47 -0
  28. data/app/assets/javascripts/pages/admin/features/editable_image.js.coffee.erb +122 -0
  29. data/app/assets/javascripts/pages/admin/features/modal.js.coffee +66 -0
  30. data/app/assets/javascripts/pages/admin/features/page_images.js +329 -0
  31. data/app/assets/javascripts/pages/admin/features/rich_text.js.coffee +40 -0
  32. data/app/assets/javascripts/pages/admin/features/tag_editor.js +159 -0
  33. data/app/assets/javascripts/pages/admin/lib/ajax_extensions.js.coffee +17 -0
  34. data/app/assets/javascripts/pages/admin/lib/center_on_screen.js.coffee +21 -0
  35. data/app/assets/javascripts/pages/admin/lib/jrichtextarea.js +57 -0
  36. data/app/assets/javascripts/pages/admin.js.coffee +54 -0
  37. data/app/assets/javascripts/pages/login_form.js.coffee +17 -0
  38. data/app/assets/stylesheets/pages/admin/buttons.css.erb +5 -0
  39. data/app/assets/stylesheets/pages/admin/controllers/artists.css.erb +94 -0
  40. data/app/assets/stylesheets/pages/admin/controllers/files.css.erb +58 -0
  41. data/app/assets/stylesheets/pages/admin/controllers/pages.css.scss.erb +178 -0
  42. data/app/assets/stylesheets/pages/admin/controllers/users.css.erb +3 -0
  43. data/app/assets/stylesheets/pages/admin/editable_image.css.erb +19 -0
  44. data/app/assets/stylesheets/pages/admin/forms.css.scss.erb +73 -0
  45. data/app/assets/stylesheets/pages/admin/header.css.erb +129 -0
  46. data/app/assets/stylesheets/pages/admin/images.css.scss.erb +160 -0
  47. data/app/assets/stylesheets/pages/admin/links.css.erb +34 -0
  48. data/app/assets/stylesheets/pages/admin/list_table.css.erb +56 -0
  49. data/app/assets/stylesheets/pages/admin/login.css.scss.erb +32 -0
  50. data/app/assets/stylesheets/pages/admin/modal.css.erb +14 -0
  51. data/app/assets/stylesheets/pages/admin/pagination.css.scss +22 -0
  52. data/app/assets/stylesheets/pages/admin/print.css.erb +17 -0
  53. data/app/assets/stylesheets/pages/admin/sidebar.css.erb +39 -0
  54. data/app/assets/stylesheets/pages/admin/sortable_images.css.erb +18 -0
  55. data/app/assets/stylesheets/pages/admin/tag_editor.css.scss.erb +48 -0
  56. data/app/assets/stylesheets/pages/admin/textarea.css.erb +55 -0
  57. data/app/assets/stylesheets/pages/admin.css.erb +404 -0
  58. data/app/assets/stylesheets/pages/errors.css +126 -0
  59. data/app/controller_dummies/admin/admin_controller.rb +6 -0
  60. data/app/controller_dummies/application_controller.rb +6 -0
  61. data/app/controller_dummies/frontend_controller.rb +4 -0
  62. data/app/controller_dummies/images_controller.rb +4 -0
  63. data/app/controller_dummies/page_files_controller.rb +4 -0
  64. data/app/controller_dummies/pages_controller.rb +4 -0
  65. data/app/controller_dummies/sitemaps_controller.rb +4 -0
  66. data/app/controllers/admin/categories_controller.rb +57 -0
  67. data/app/controllers/admin/images_controller.rb +48 -0
  68. data/app/controllers/admin/invites_controller.rb +79 -0
  69. data/app/controllers/admin/page_comments_controller.rb +61 -0
  70. data/app/controllers/admin/page_files_controller.rb +81 -0
  71. data/app/controllers/admin/page_images_controller.rb +116 -0
  72. data/app/controllers/admin/pages_controller.rb +179 -0
  73. data/app/controllers/admin/password_resets_controller.rb +83 -0
  74. data/app/controllers/admin/users_controller.rb +102 -0
  75. data/app/controllers/concerns/pages_core/authentication.rb +48 -0
  76. data/app/controllers/concerns/pages_core/domain_based_cache.rb +28 -0
  77. data/app/controllers/concerns/pages_core/exception_handler.rb +114 -0
  78. data/app/controllers/concerns/pages_core/policies_helper.rb +40 -0
  79. data/app/controllers/concerns/pages_core/process_titler.rb +44 -0
  80. data/app/controllers/errors_controller.rb +45 -0
  81. data/app/controllers/pages_core/admin_controller.rb +109 -0
  82. data/app/controllers/pages_core/application_controller.rb +31 -0
  83. data/app/controllers/pages_core/frontend/page_files_controller.rb +42 -0
  84. data/app/controllers/pages_core/frontend/pages_controller.rb +308 -0
  85. data/app/controllers/pages_core/frontend_controller.rb +34 -0
  86. data/app/controllers/pages_core/images_controller.rb +15 -0
  87. data/app/controllers/pages_core/sitemaps_controller.rb +73 -0
  88. data/app/controllers/sessions_controller.rb +38 -0
  89. data/app/formatters/pages_core/html_formatter.rb +86 -0
  90. data/app/helpers/admin/admin_helper.rb +7 -0
  91. data/app/helpers/admin/menu_helper.rb +65 -0
  92. data/app/helpers/admin/pages_helper.rb +74 -0
  93. data/app/helpers/application_helper.rb +5 -0
  94. data/app/helpers/frontend_helper.rb +5 -0
  95. data/app/helpers/pages_core/admin/admin_helper.rb +108 -0
  96. data/app/helpers/pages_core/admin/labelled_field_helper.rb +73 -0
  97. data/app/helpers/pages_core/admin/tag_editor_helper.rb +46 -0
  98. data/app/helpers/pages_core/application_helper.rb +65 -0
  99. data/app/helpers/pages_core/form_builder.rb +187 -0
  100. data/app/helpers/pages_core/frontend_helper.rb +21 -0
  101. data/app/helpers/pages_core/head_tags_helper.rb +270 -0
  102. data/app/helpers/pages_core/images_helper.rb +36 -0
  103. data/app/helpers/pages_core/login_helper.rb +14 -0
  104. data/app/indices/page_file_index.rb +9 -0
  105. data/app/indices/page_index.rb +29 -0
  106. data/app/indices/user_index.rb +11 -0
  107. data/app/jobs/pages_core/autopublish_job.rb +11 -0
  108. data/app/jobs/pages_core/sweep_cache_job.rb +11 -0
  109. data/app/mailers/admin_mailer.rb +46 -0
  110. data/app/models/autopublisher.rb +33 -0
  111. data/app/models/category.rb +23 -0
  112. data/app/models/concerns/pages_core/has_roles.rb +25 -0
  113. data/app/models/concerns/pages_core/humanizable_param.rb +17 -0
  114. data/app/models/concerns/pages_core/page_tree.rb +85 -0
  115. data/app/models/concerns/pages_core/searchable_page.rb +33 -0
  116. data/app/models/concerns/pages_core/sweepable.rb +23 -0
  117. data/app/models/concerns/pages_core/taggable.rb +46 -0
  118. data/app/models/concerns/pages_core/templateable.rb +85 -0
  119. data/app/models/image.rb +23 -0
  120. data/app/models/invite.rb +33 -0
  121. data/app/models/invite_role.rb +11 -0
  122. data/app/models/localization.rb +27 -0
  123. data/app/models/page.rb +281 -0
  124. data/app/models/page_builder.rb +61 -0
  125. data/app/models/page_comment.rb +18 -0
  126. data/app/models/page_file.rb +74 -0
  127. data/app/models/page_image.rb +62 -0
  128. data/app/models/password_reset_token.rb +38 -0
  129. data/app/models/role.rb +51 -0
  130. data/app/models/tag.rb +64 -0
  131. data/app/models/tagging.rb +22 -0
  132. data/app/models/user.rb +131 -0
  133. data/app/policies/invite_policy.rb +29 -0
  134. data/app/policies/page_file_policy.rb +25 -0
  135. data/app/policies/page_image_policy.rb +25 -0
  136. data/app/policies/page_policy.rb +33 -0
  137. data/app/policies/policy.rb +64 -0
  138. data/app/policies/user_policy.rb +49 -0
  139. data/app/serializers/admin/image_serializer.rb +10 -0
  140. data/app/serializers/admin/page_image_serializer.rb +6 -0
  141. data/app/serializers/page_image_serializer.rb +38 -0
  142. data/app/serializers/page_serializer.rb +21 -0
  143. data/app/views/admin/invites/new.html.erb +16 -0
  144. data/app/views/admin/invites/show.html.erb +25 -0
  145. data/app/views/admin/pages/_edit_comments.html.erb +21 -0
  146. data/app/views/admin/pages/_edit_content.html.erb +10 -0
  147. data/app/views/admin/pages/_edit_images.html.erb +84 -0
  148. data/app/views/admin/pages/_edit_metadata.html.erb +24 -0
  149. data/app/views/admin/pages/_edit_options.html.erb +72 -0
  150. data/app/views/admin/pages/_pagelisting.html.erb +63 -0
  151. data/app/views/admin/pages/edit.html.erb +161 -0
  152. data/app/views/admin/pages/index.html.erb +67 -0
  153. data/app/views/admin/pages/new.html.erb +48 -0
  154. data/app/views/admin/pages/news.html.erb +69 -0
  155. data/app/views/admin/password_resets/show.html.erb +24 -0
  156. data/app/views/admin/users/_access_control.html.erb +14 -0
  157. data/app/views/admin/users/_list.html.erb +62 -0
  158. data/app/views/admin/users/_login_form.html.erb +47 -0
  159. data/app/views/admin/users/deactivated.html.erb +12 -0
  160. data/app/views/admin/users/edit.html.erb +54 -0
  161. data/app/views/admin/users/index.html.erb +27 -0
  162. data/app/views/admin/users/login.html.erb +15 -0
  163. data/app/views/admin/users/new.html.erb +23 -0
  164. data/app/views/admin/users/new_password.html.erb +19 -0
  165. data/app/views/admin/users/show.html.erb +64 -0
  166. data/app/views/admin_mailer/comment_notification.text.erb +7 -0
  167. data/app/views/admin_mailer/error_report.html.erb +70 -0
  168. data/app/views/admin_mailer/invite.text.erb +9 -0
  169. data/app/views/admin_mailer/password_reset.text.erb +13 -0
  170. data/app/views/errors/403.html.erb +6 -0
  171. data/app/views/errors/404.html.erb +11 -0
  172. data/app/views/errors/405.html.erb +4 -0
  173. data/app/views/errors/500.html.erb +19 -0
  174. data/app/views/errors/500_critical.html.erb +7 -0
  175. data/app/views/errors/_generic_help.html.erb +21 -0
  176. data/app/views/errors/report.html.erb +4 -0
  177. data/app/views/feeds/pages.rss.builder +39 -0
  178. data/app/views/layouts/admin/_analytics.html.erb +18 -0
  179. data/app/views/layouts/admin/_header.html.erb +37 -0
  180. data/app/views/layouts/admin.html.erb +79 -0
  181. data/app/views/layouts/errors.html.erb +23 -0
  182. data/app/views/sitemaps/show.xml.builder +9 -0
  183. data/config/locales/en.yml +6 -0
  184. data/config/removed_migrations.yml +60 -0
  185. data/config/routes.rb +127 -0
  186. data/db/migrate/20111219033112_create_pages_tables.rb +281 -0
  187. data/db/migrate/20120627033112_rename_textbits.rb +19 -0
  188. data/db/migrate/20121010055412_drop_removed_tables.rb +83 -0
  189. data/db/migrate/20130130053932_add_queue_to_delayed_jobs.rb +11 -0
  190. data/db/migrate/20130303053932_remove_filter_from_localizations.rb +11 -0
  191. data/db/migrate/20130303160632_remove_imagesets.rb +24 -0
  192. data/db/migrate/20130303161732_remove_sms_subscribers.rb +16 -0
  193. data/db/migrate/20130823133208_update_page_redirect_to.rb +25 -0
  194. data/db/migrate/20140203183900_create_roles.rb +63 -0
  195. data/db/migrate/20140414150500_change_locale_names.rb +13 -0
  196. data/db/migrate/20140515130100_remove_sphinx_deltas.rb +15 -0
  197. data/db/migrate/20140604142100_remove_openid_url.rb +9 -0
  198. data/db/migrate/20140920231700_convert_images_to_dis.rb +79 -0
  199. data/db/migrate/20140922124600_convert_page_files_to_dis.rb +50 -0
  200. data/db/migrate/20141004003100_create_password_reset_tokens.rb +10 -0
  201. data/db/migrate/20141006181300_remove_user_cruft.rb +11 -0
  202. data/db/migrate/20141007173000_create_invites.rb +16 -0
  203. data/db/migrate/20150204130800_update_delayed_job_table.rb +9 -0
  204. data/db/migrate/20150401131300_localize_images.rb +39 -0
  205. data/db/migrate/20150520174300_add_meta_image_to_page.rb +5 -0
  206. data/db/migrate/20150904164200_add_pinned_to_tags.rb +5 -0
  207. data/lib/pages_core/admin_menu_item.rb +22 -0
  208. data/lib/pages_core/archive_finder.rb +75 -0
  209. data/lib/pages_core/cache_sweeper.rb +112 -0
  210. data/lib/pages_core/configuration/base.rb +85 -0
  211. data/lib/pages_core/configuration/pages.rb +23 -0
  212. data/lib/pages_core/configuration.rb +9 -0
  213. data/lib/pages_core/engine.rb +27 -0
  214. data/lib/pages_core/extensions/hash_extensions.rb +23 -0
  215. data/lib/pages_core/extensions/string_extensions.rb +17 -0
  216. data/lib/pages_core/extensions.rb +4 -0
  217. data/lib/pages_core/localizable/active_record_extension.rb +41 -0
  218. data/lib/pages_core/localizable/class_methods.rb +51 -0
  219. data/lib/pages_core/localizable/configuration.rb +50 -0
  220. data/lib/pages_core/localizable/instance_methods.rb +130 -0
  221. data/lib/pages_core/localizable/localizer.rb +72 -0
  222. data/lib/pages_core/localizable/scope_extension.rb +22 -0
  223. data/lib/pages_core/localizable.rb +49 -0
  224. data/lib/pages_core/pages_plugin.rb +14 -0
  225. data/lib/pages_core/paginates.rb +102 -0
  226. data/lib/pages_core/plugin.rb +118 -0
  227. data/lib/pages_core/templates/block_configuration.rb +17 -0
  228. data/lib/pages_core/templates/configuration.rb +81 -0
  229. data/lib/pages_core/templates/configuration_handler.rb +62 -0
  230. data/lib/pages_core/templates/configuration_proxy.rb +28 -0
  231. data/lib/pages_core/templates/controller_actions.rb +32 -0
  232. data/lib/pages_core/templates/template_configuration.rb +198 -0
  233. data/lib/pages_core/templates.rb +53 -0
  234. data/lib/pages_core/version.rb +5 -0
  235. data/lib/pages_core.rb +89 -0
  236. data/lib/rails/generators/pages_core/frontend/frontend_generator.rb +68 -0
  237. data/lib/rails/generators/pages_core/frontend/templates/application.css.scss.erb +3 -0
  238. data/lib/rails/generators/pages_core/frontend/templates/application.js.erb +16 -0
  239. data/lib/rails/generators/pages_core/frontend/templates/base.css.scss.erb +3 -0
  240. data/lib/rails/generators/pages_core/frontend/templates/breakpoints.css.scss.erb +24 -0
  241. data/lib/rails/generators/pages_core/frontend/templates/hidpi.css.scss.erb +8 -0
  242. data/lib/rails/generators/pages_core/frontend/templates/layout.html.erb +15 -0
  243. data/lib/rails/generators/pages_core/frontend/templates/normalize.css.erb +425 -0
  244. data/lib/rails/generators/pages_core/install/install_generator.rb +135 -0
  245. data/lib/rails/generators/pages_core/install/templates/active_job_initializer.rb +1 -0
  246. data/lib/rails/generators/pages_core/install/templates/application_controller.rb +11 -0
  247. data/lib/rails/generators/pages_core/install/templates/application_helper.rb +5 -0
  248. data/lib/rails/generators/pages_core/install/templates/cache_sweeper_initializer.rb +11 -0
  249. data/lib/rails/generators/pages_core/install/templates/default_page_template.html.erb +5 -0
  250. data/lib/rails/generators/pages_core/install/templates/delayed_job +7 -0
  251. data/lib/rails/generators/pages_core/install/templates/delayed_job_initializer.rb +3 -0
  252. data/lib/rails/generators/pages_core/install/templates/frontend_controller.rb +6 -0
  253. data/lib/rails/generators/pages_core/install/templates/frontend_helper.rb +5 -0
  254. data/lib/rails/generators/pages_core/install/templates/gitignore.erb +25 -0
  255. data/lib/rails/generators/pages_core/install/templates/page_templates_initializer.rb +67 -0
  256. data/lib/rails/generators/pages_core/install/templates/pages_controller.rb +4 -0
  257. data/lib/rails/generators/pages_core/install/templates/pages_initializer.rb +45 -0
  258. data/lib/rails/generators/pages_core/install/templates/thinking_sphinx.yml +12 -0
  259. data/lib/rails/generators/pages_core/rspec/rspec_generator.rb +34 -0
  260. data/lib/rails/generators/pages_core/rspec/templates/factories.rb +9 -0
  261. data/lib/rails/generators/pages_core/rspec/templates/mailer_macros.rb +9 -0
  262. data/lib/rails/generators/pages_core/rspec/templates/spec_helper.rb +51 -0
  263. data/lib/tasks/db.rake +96 -0
  264. data/lib/tasks/pages/assets.rake +65 -0
  265. data/lib/tasks/pages/cache.rake +16 -0
  266. data/lib/tasks/pages/update.rake +19 -0
  267. data/lib/tasks/pages.rake +76 -0
  268. data/template.rb +19 -0
  269. data/vendor/assets/javascripts/jquery.dimscreen.js +77 -0
  270. data/vendor/assets/javascripts/jquery.fieldselection.js +59 -0
  271. metadata +690 -0
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ class PageImage < ActiveRecord::Base
4
+ belongs_to :page
5
+ belongs_to_image :image
6
+
7
+ validates_presence_of :page_id
8
+
9
+ accepts_nested_attributes_for :image
10
+ validates_associated :image
11
+
12
+ acts_as_list scope: :page
13
+
14
+ localizable
15
+
16
+ validate do |page_image|
17
+ if page_image.page && page_image.page.page_images.count < 1
18
+ page_image.primary = true
19
+ end
20
+ end
21
+
22
+ after_save do |page_image|
23
+ if page_image.primary_changed?
24
+
25
+ # Make sure only one PageImage can be the primary,
26
+ # then update image_id on the page.
27
+ if page_image.primary?
28
+ PageImage.where
29
+ page_image.page
30
+ .page_images
31
+ .where("id != ?", page_image.id)
32
+ .update_all(primary: false)
33
+ page_image.page.update(image_id: page_image.image_id)
34
+
35
+ # Clear image_id on the page if primary is toggled off
36
+ else
37
+ page_image.page.update(image_id: nil)
38
+ end
39
+ end
40
+ end
41
+
42
+ after_destroy do |page_image|
43
+ page_image.page.update(image_id: nil) if page_image.primary?
44
+ end
45
+
46
+ class << self
47
+ def cleanup!
48
+ all.each do |page_image|
49
+ page_image.destroy unless page_image.image
50
+ end
51
+ end
52
+ end
53
+
54
+ def image
55
+ super.localize!(locale)
56
+ end
57
+
58
+ def to_json(options = {})
59
+ options = { include: [:image] }.merge(options)
60
+ super(options)
61
+ end
62
+ end
@@ -0,0 +1,38 @@
1
+ class PasswordResetToken < ActiveRecord::Base
2
+ belongs_to :user
3
+ before_create :ensure_token
4
+ before_create :ensure_expiration
5
+
6
+ validates :user_id, presence: true
7
+
8
+ scope :active, -> { where("expires_at >= ?", Time.now) }
9
+ scope :expired, -> { where("expires_at < ?", Time.now) }
10
+
11
+ class << self
12
+ def default_expiration
13
+ 24.hours
14
+ end
15
+
16
+ def expire!
17
+ expired.delete_all
18
+ end
19
+
20
+ def find_by_token(token)
21
+ active.where(token: token).first
22
+ end
23
+ end
24
+
25
+ def expired?
26
+ expires_at < Time.now
27
+ end
28
+
29
+ private
30
+
31
+ def ensure_expiration
32
+ self.expires_at ||= Time.now + self.class.default_expiration
33
+ end
34
+
35
+ def ensure_token
36
+ self.token ||= SecureRandom.hex(32)
37
+ end
38
+ end
@@ -0,0 +1,51 @@
1
+ class Role < ActiveRecord::Base
2
+ belongs_to :user
3
+ validates :name,
4
+ presence: true,
5
+ uniqueness: { scope: :user_id },
6
+ inclusion: { in: proc { Role.roles.map(&:name) } }
7
+
8
+ class << self
9
+ def define(name, description, default = false)
10
+ if roles.map(&:name).include?(name.to_s)
11
+ fail ArgumentError, "Tried to define role :#{role}, " \
12
+ "but a role by that name already exists"
13
+ else
14
+ roles << OpenStruct.new(
15
+ name: name.to_s,
16
+ description: description,
17
+ default: default
18
+ )
19
+ end
20
+ end
21
+
22
+ def roles
23
+ @roles ||= default_roles
24
+ end
25
+
26
+ def names
27
+ all.map(&:name)
28
+ end
29
+
30
+ protected
31
+
32
+ def default_roles
33
+ [
34
+ OpenStruct.new(
35
+ name: "users", description: "Can manage users", default: false
36
+ ),
37
+ OpenStruct.new(
38
+ name: "pages", description: "Can manage pages", default: true
39
+ )
40
+ ]
41
+ end
42
+ end
43
+
44
+ def name=(new_name)
45
+ super(new_name.to_s)
46
+ end
47
+
48
+ def to_s
49
+ name.humanize
50
+ end
51
+ end
data/app/models/tag.rb ADDED
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ class Tag < ActiveRecord::Base
4
+ include PagesCore::HumanizableParam
5
+ has_many :taggings
6
+
7
+ scope :pinned, -> { where(pinned: true) }
8
+ scope :sorted, -> { order("pinned DESC, name ASC") }
9
+
10
+ class << self
11
+ def tags_and_suggestions_for(taggable, options = {})
12
+ options = default_options.merge(options)
13
+ tags = (taggable.tags.sorted + pinned.sorted).uniq
14
+ if tags.count < options[:limit]
15
+ suggested = suggestions(tags, options)
16
+ tags = tags.to_a + suggested[0...(options[:limit] - tags.length)]
17
+ end
18
+ tags
19
+ end
20
+
21
+ def parse(*tags)
22
+ Array(tags).flatten
23
+ .map { |tag| tag.is_a?(Tag) ? tag.name : tag }
24
+ .map { |tag| tag.split(",") }
25
+ .flatten
26
+ .map(&:strip)
27
+ end
28
+
29
+ private
30
+
31
+ def suggestions(tags, options = {})
32
+ Tag.joins(:taggings)
33
+ .select("`tags`.*, COUNT(`tags`.id) AS counter")
34
+ .group("`tags`.id")
35
+ .order("counter DESC")
36
+ .limit(options[:limit])
37
+ .reject { |t| tags.include?(t) }
38
+ end
39
+
40
+ def default_options
41
+ { limit: 100 }
42
+ end
43
+ end
44
+
45
+ def tagged
46
+ @tagged ||= taggings.collect(&:taggable)
47
+ end
48
+
49
+ def on(taggable)
50
+ taggings.create(taggable: taggable)
51
+ end
52
+
53
+ def ==(other)
54
+ super || name == other.to_s
55
+ end
56
+
57
+ def to_param
58
+ humanized_param(name)
59
+ end
60
+
61
+ def to_s
62
+ name
63
+ end
64
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ class Tagging < ActiveRecord::Base
4
+ belongs_to :tag
5
+ belongs_to :taggable, polymorphic: true
6
+
7
+ validates_presence_of :taggable_id, :taggable_type
8
+ validates :tag_id,
9
+ presence: true,
10
+ uniqueness: { scope: [:taggable_type, :taggable_id] }
11
+
12
+ def self.tagged_class(taggable)
13
+ ActiveRecord::Base.send(
14
+ :class_of_active_record_descendant,
15
+ taggable.class
16
+ ).to_s
17
+ end
18
+
19
+ def self.find_taggable(tagged_class, tagged_id)
20
+ tagged_class.constantize.find(tagged_id)
21
+ end
22
+ end
@@ -0,0 +1,131 @@
1
+ # encoding: utf-8
2
+
3
+ class User < ActiveRecord::Base
4
+ include PagesCore::HasRoles
5
+
6
+ attr_accessor :password, :confirm_password
7
+
8
+ belongs_to :creator, class_name: "User", foreign_key: "created_by"
9
+ has_many :created_users, class_name: "User", foreign_key: "created_by"
10
+ has_many :pages
11
+ has_many :password_reset_tokens, dependent: :destroy
12
+ has_many :roles, dependent: :destroy
13
+ has_many :invites, dependent: :destroy
14
+ belongs_to_image :image, foreign_key: :image_id
15
+
16
+ serialize :persistent_data
17
+
18
+ validates :username,
19
+ presence: true,
20
+ uniqueness: { case_sensitive: false }
21
+
22
+ validates :name,
23
+ presence: true
24
+
25
+ validates :email,
26
+ presence: true,
27
+ format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i },
28
+ uniqueness: { case_sensitive: false }
29
+
30
+ validates :password, presence: true, on: :create
31
+ validates :password, length: { minimum: 8 }, allow_blank: true
32
+
33
+ validate :confirm_password_must_match
34
+
35
+ before_validation :ensure_username
36
+ before_validation :hash_password
37
+ before_create :ensure_first_user_has_all_roles
38
+
39
+ after_save ThinkingSphinx::RealTime.callback_for(:user)
40
+
41
+ scope :by_name, -> { order("name ASC") }
42
+ scope :activated, -> { by_name.includes(:roles).where(activated: true) }
43
+ scope :deactivated, -> { by_name.includes(:roles).where(activated: false) }
44
+
45
+ class << self
46
+ def authenticate(email, password:)
47
+ user = User.find_by_username_or_email(email)
48
+ user if user.try { |u| u.authenticate!(password) }
49
+ end
50
+
51
+ # Finds a user by either username or email address.
52
+ def find_by_username_or_email(string)
53
+ where(username: string.to_s).first ||
54
+ where(email: string.to_s).first
55
+ end
56
+ end
57
+
58
+ def authenticate!(password)
59
+ if can_login? && valid_password?(password)
60
+ rehash_password!(password) if password_needs_rehash?
61
+ true
62
+ else
63
+ false
64
+ end
65
+ end
66
+
67
+ def can_login?
68
+ self.activated?
69
+ end
70
+
71
+ def mark_active!
72
+ return if last_login_at && last_login_at > 10.minutes.ago
73
+ update_columns(last_login_at: Time.now)
74
+ end
75
+
76
+ def name_and_email
77
+ "#{name} <#{email}>"
78
+ end
79
+
80
+ def online?
81
+ (last_login_at && last_login_at > 15.minutes.ago) ? true : false
82
+ end
83
+
84
+ def realname
85
+ name
86
+ end
87
+
88
+ private
89
+
90
+ def confirm_password_must_match
91
+ return if password.blank? || password == confirm_password
92
+ errors.add(:confirm_password, "does not match")
93
+ end
94
+
95
+ def encrypt_password(password)
96
+ BCrypt::Password.create(password)
97
+ end
98
+
99
+ def ensure_username
100
+ self.username ||= email
101
+ end
102
+
103
+ def ensure_first_user_has_all_roles
104
+ return if User.any?
105
+ self.activated = true
106
+ Role.roles.each do |role|
107
+ roles.new(name: role.name)
108
+ end
109
+ end
110
+
111
+ def hash_password
112
+ self.hashed_password = encrypt_password(password) unless password.blank?
113
+ end
114
+
115
+ def password_needs_rehash?
116
+ hashed_password.length <= 40
117
+ end
118
+
119
+ def rehash_password!(password)
120
+ update(hashed_password: encrypt_password(password))
121
+ end
122
+
123
+ def valid_password?(password)
124
+ if hashed_password.length <= 40
125
+ return true if hashed_password == Digest::SHA1.hexdigest(password)
126
+ else
127
+ return true if BCrypt::Password.new(hashed_password) == password
128
+ end
129
+ false
130
+ end
131
+ end
@@ -0,0 +1,29 @@
1
+ class InvitePolicy < Policy
2
+ def index?
3
+ true
4
+ end
5
+
6
+ def reorder?
7
+ user.role?(:users)
8
+ end
9
+
10
+ def new?
11
+ user.role?(:users)
12
+ end
13
+
14
+ def show?
15
+ true
16
+ end
17
+
18
+ def edit?
19
+ user.role?(:users)
20
+ end
21
+
22
+ def accept?
23
+ true
24
+ end
25
+
26
+ def policies?
27
+ user.role?(:users)
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ class PageFilePolicy < Policy
2
+ module Collection
3
+ def index?
4
+ true
5
+ end
6
+
7
+ def reorder?
8
+ user.role?(:pages)
9
+ end
10
+
11
+ def new?
12
+ user.role?(:pages)
13
+ end
14
+ end
15
+
16
+ module Member
17
+ def show?
18
+ true
19
+ end
20
+
21
+ def edit?
22
+ user.role?(:pages)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ class PageImagePolicy < Policy
2
+ module Collection
3
+ def index?
4
+ true
5
+ end
6
+
7
+ def reorder?
8
+ user.role?(:pages)
9
+ end
10
+
11
+ def new?
12
+ user.role?(:pages)
13
+ end
14
+ end
15
+
16
+ module Member
17
+ def show?
18
+ true
19
+ end
20
+
21
+ def edit?
22
+ user.role?(:pages)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ class PagePolicy < Policy
2
+ module Collection
3
+ def index?
4
+ true
5
+ end
6
+
7
+ def news?
8
+ true
9
+ end
10
+
11
+ def new?
12
+ user.role?(:pages)
13
+ end
14
+
15
+ def new_news?
16
+ create?
17
+ end
18
+
19
+ def reorder_pages?
20
+ create?
21
+ end
22
+ end
23
+
24
+ module Member
25
+ def show?
26
+ true
27
+ end
28
+
29
+ def edit?
30
+ user.role?(:pages)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,64 @@
1
+ class Policy
2
+ module DefaultPolicy
3
+ def index
4
+ false
5
+ end
6
+
7
+ def new?
8
+ false
9
+ end
10
+
11
+ def create?
12
+ new?
13
+ end
14
+
15
+ def show?
16
+ false
17
+ end
18
+
19
+ def edit?
20
+ false
21
+ end
22
+
23
+ def update?
24
+ edit?
25
+ end
26
+
27
+ def destroy?
28
+ edit?
29
+ end
30
+ end
31
+
32
+ include DefaultPolicy
33
+
34
+ attr_reader :user, :record
35
+
36
+ def initialize(user, record = nil)
37
+ @user = user
38
+ @record = record
39
+ end
40
+
41
+ class << self
42
+ def for(user, object)
43
+ if object.is_a?(Class)
44
+ "#{object}Policy".constantize.collection(user)
45
+ else
46
+ "#{object.class}Policy".constantize.member(user, object)
47
+ end
48
+ end
49
+
50
+ def collection(user)
51
+ policy = new(user)
52
+ const_defined?(:Collection) &&
53
+ policy.extend(const_get(:Collection))
54
+ policy
55
+ end
56
+
57
+ def member(user, record)
58
+ policy = new(user, record)
59
+ const_defined?(:Member) &&
60
+ policy.extend(const_get(:Member))
61
+ policy
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,49 @@
1
+ class UserPolicy < Policy
2
+ module Collection
3
+ def index?
4
+ true
5
+ end
6
+
7
+ def deactivated?
8
+ index?
9
+ end
10
+
11
+ def new?
12
+ (!User.any?) || user.role?(:users)
13
+ end
14
+
15
+ def create?
16
+ new?
17
+ end
18
+
19
+ def manage?
20
+ new?
21
+ end
22
+ end
23
+
24
+ module Member
25
+ def edit?
26
+ user == record || user.role?(:users)
27
+ end
28
+
29
+ def show?
30
+ edit?
31
+ end
32
+
33
+ def delete_image?
34
+ edit?
35
+ end
36
+
37
+ def policies?
38
+ user.role?(:users)
39
+ end
40
+
41
+ def destroy?
42
+ user.role?(:users)
43
+ end
44
+ end
45
+
46
+ def change_password?
47
+ user == record
48
+ end
49
+ end
@@ -0,0 +1,10 @@
1
+ module Admin
2
+ class ImageSerializer < ActiveModel::Serializer
3
+ attributes(
4
+ :id, :filename, :content_type, :content_hash, :content_length,
5
+ :colorspace, :real_width, :real_height, :crop_width, :crop_height,
6
+ :crop_start_x, :crop_start_y, :crop_gravity_x, :crop_gravity_y,
7
+ :alternative, :caption, :created_at, :updated_at
8
+ )
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module Admin
2
+ class PageImageSerializer < ActiveModel::Serializer
3
+ attributes :id, :page_id, :image_id, :position, :primary
4
+ has_one :image
5
+ end
6
+ end
@@ -0,0 +1,38 @@
1
+ class PageImageSerializer < ActiveModel::Serializer
2
+ include DynamicImage::Helper
3
+ attributes :id, :image_id, :primary, :filename
4
+ attributes :alternative, :caption, :created_at, :url
5
+
6
+ def name
7
+ object.image.name
8
+ end
9
+
10
+ def alternative
11
+ object.image.alternative
12
+ end
13
+
14
+ def caption
15
+ object.image.caption
16
+ end
17
+
18
+ def filename
19
+ object.image.filename
20
+ end
21
+
22
+ def size
23
+ object.image.crop_size
24
+ end
25
+
26
+ def created_at
27
+ object.image.created_at
28
+ end
29
+
30
+ def url
31
+ dynamic_image_path(
32
+ object.image,
33
+ size: "2000x2000",
34
+ crop: false,
35
+ upscale: false
36
+ )
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ class PageSerializer < ActiveModel::Serializer
2
+ attributes :id, :param, :parent_page_id, :locale
3
+ attributes(*PagesCore::Templates::TemplateConfiguration.all_blocks)
4
+ attributes :published_at, :pinned
5
+
6
+ has_one :image
7
+ has_many :images
8
+ has_many :pages
9
+
10
+ def param
11
+ object.to_param
12
+ end
13
+
14
+ def image
15
+ object.page_images.where(primary: true).try(:first)
16
+ end
17
+
18
+ def images
19
+ object.page_images
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ <%
2
+ self.page_title = "New invite"
3
+ self.page_description = "New invite"
4
+ %>
5
+
6
+ <% content_for(:sidebar) do %>
7
+ &nbsp;
8
+ <% end %>
9
+
10
+ <%= form_for [:admin, @invite], builder: PagesCore::FormBuilder do |f| %>
11
+ <%= f.labelled_text_field :email %>
12
+ <%= render partial: "admin/users/access_control", locals: { user: @user, f: f } %>
13
+ <button type="submit">
14
+ Send invite
15
+ </button>
16
+ <% end %>