cortex 0.1.1

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 (342) hide show
  1. checksums.yaml +7 -0
  2. data/.babelrc +18 -0
  3. data/.codeclimate.yml +43 -0
  4. data/.csslintrc +2 -0
  5. data/.editorconfig +9 -0
  6. data/.eslintignore +1 -0
  7. data/.eslintrc.yml +277 -0
  8. data/.github/PULL_REQUEST_TEMPLATE.md +47 -0
  9. data/.gitignore +82 -0
  10. data/.npmignore +34 -0
  11. data/.postcssrc.yml +3 -0
  12. data/.rspec +3 -0
  13. data/.rubocop.yml +1156 -0
  14. data/CODE_OF_CONDUCT.md +74 -0
  15. data/CONTRIBUTING.md +58 -0
  16. data/Gemfile +101 -0
  17. data/Gemfile.lock +604 -0
  18. data/Guardfile +23 -0
  19. data/LICENSE.md +201 -0
  20. data/README.md +239 -0
  21. data/Rakefile +22 -0
  22. data/app/assets/config/cortex_manifest.js +4 -0
  23. data/app/assets/fonts/cortex/Montserrat-Light.otf +0 -0
  24. data/app/assets/fonts/cortex/Montserrat-Medium.otf +0 -0
  25. data/app/assets/fonts/cortex/Montserrat-Regular.otf +0 -0
  26. data/app/assets/fonts/cortex/Montserrat-SemiBold.otf +0 -0
  27. data/app/assets/images/cortex/favicon.ico +0 -0
  28. data/app/assets/images/cortex/icons/add.svg +59 -0
  29. data/app/assets/images/cortex/icons/blog.png +0 -0
  30. data/app/assets/images/cortex/icons/media.png +0 -0
  31. data/app/assets/images/cortex/logo.svg +43 -0
  32. data/app/assets/javascripts/cortex/application.js +17 -0
  33. data/app/assets/javascripts/cortex/authentication.js +6 -0
  34. data/app/assets/javascripts/cortex/base.js +6 -0
  35. data/app/assets/javascripts/cortex/datepicker_init.js +29 -0
  36. data/app/assets/javascripts/cortex/flash.js +7 -0
  37. data/app/assets/javascripts/cortex/form.js +6 -0
  38. data/app/assets/javascripts/cortex/media_dialogs.js +40 -0
  39. data/app/assets/javascripts/cortex/quick_links.js +13 -0
  40. data/app/assets/stylesheets/cortex/application.scss +34 -0
  41. data/app/assets/stylesheets/cortex/authentication.scss +34 -0
  42. data/app/assets/stylesheets/cortex/base.scss +4 -0
  43. data/app/assets/stylesheets/cortex/bootstrap-namespaced.scss +57 -0
  44. data/app/assets/stylesheets/cortex/components/card.scss +9 -0
  45. data/app/assets/stylesheets/cortex/components/dialog.scss +67 -0
  46. data/app/assets/stylesheets/cortex/components/flash.scss +60 -0
  47. data/app/assets/stylesheets/cortex/components/form.scss +45 -0
  48. data/app/assets/stylesheets/cortex/components/header.scss +53 -0
  49. data/app/assets/stylesheets/cortex/components/index.scss +28 -0
  50. data/app/assets/stylesheets/cortex/components/jumbo-button.scss +41 -0
  51. data/app/assets/stylesheets/cortex/components/loaders.scss +76 -0
  52. data/app/assets/stylesheets/cortex/components/notes.scss +26 -0
  53. data/app/assets/stylesheets/cortex/components/sidebar.scss +120 -0
  54. data/app/assets/stylesheets/cortex/components/table.scss +7 -0
  55. data/app/assets/stylesheets/cortex/components/tenant-switcher.scss +209 -0
  56. data/app/assets/stylesheets/cortex/components/ui.scss +119 -0
  57. data/app/assets/stylesheets/cortex/demo.scss +140 -0
  58. data/app/assets/stylesheets/cortex/directives/aspect-ratio.scss +9 -0
  59. data/app/assets/stylesheets/cortex/helpers.scss +1701 -0
  60. data/app/assets/stylesheets/cortex/layout.scss +21 -0
  61. data/app/assets/stylesheets/cortex/material-icons.scss +13 -0
  62. data/app/assets/stylesheets/cortex/variables/_colors.scss +46 -0
  63. data/app/assets/stylesheets/cortex/variables/_material-overrides.scss +1 -0
  64. data/app/assets/stylesheets/cortex/variables/_typography.scss +114 -0
  65. data/app/cells/cortex/application_cell.rb +8 -0
  66. data/app/cells/cortex/content_type/nav.haml +5 -0
  67. data/app/cells/cortex/content_type_cell.rb +10 -0
  68. data/app/cells/cortex/field_cell.rb +35 -0
  69. data/app/cells/cortex/index/content_item/column.haml +4 -0
  70. data/app/cells/cortex/index/content_item_cell.rb +37 -0
  71. data/app/cells/cortex/index/index.haml +5 -0
  72. data/app/cells/cortex/index/table_body.haml +11 -0
  73. data/app/cells/cortex/index/table_headers.haml +5 -0
  74. data/app/cells/cortex/index_cell.rb +53 -0
  75. data/app/cells/cortex/wizard/column/show.haml +10 -0
  76. data/app/cells/cortex/wizard/column_cell.rb +21 -0
  77. data/app/cells/cortex/wizard/field/show.haml +30 -0
  78. data/app/cells/cortex/wizard/field_cell.rb +29 -0
  79. data/app/cells/cortex/wizard/plugin/show.haml +1 -0
  80. data/app/cells/cortex/wizard/plugin_cell.rb +28 -0
  81. data/app/cells/cortex/wizard/show.haml +1 -0
  82. data/app/cells/cortex/wizard/step/show.haml +2 -0
  83. data/app/cells/cortex/wizard/step_cell.rb +17 -0
  84. data/app/cells/cortex/wizard_cell.rb +15 -0
  85. data/app/containers/cortex/transaction_container.rb +23 -0
  86. data/app/controllers/concerns/cortex/decoratable.rb +16 -0
  87. data/app/controllers/cortex/admin_controller.rb +7 -0
  88. data/app/controllers/cortex/application_controller.rb +19 -0
  89. data/app/controllers/cortex/authentication/passwords_controller.rb +3 -0
  90. data/app/controllers/cortex/authentication/sessions_controller.rb +3 -0
  91. data/app/controllers/cortex/content_items_controller.rb +75 -0
  92. data/app/controllers/cortex/content_types_controller.rb +19 -0
  93. data/app/controllers/cortex/dashboards_controller.rb +7 -0
  94. data/app/controllers/cortex/graphql_controller.rb +40 -0
  95. data/app/controllers/cortex/tenants_controller.rb +12 -0
  96. data/app/devise/cortex/authentication_failure.rb +12 -0
  97. data/app/graphql/cortex/cortex_schema.rb +8 -0
  98. data/app/graphql/cortex/interfaces/.keep +0 -0
  99. data/app/graphql/cortex/mutations/.keep +0 -0
  100. data/app/graphql/cortex/types/content_item_type.rb +31 -0
  101. data/app/graphql/cortex/types/content_type_type.rb +23 -0
  102. data/app/graphql/cortex/types/contract_type.rb +10 -0
  103. data/app/graphql/cortex/types/date_time_type.rb +8 -0
  104. data/app/graphql/cortex/types/field_item_type.rb +15 -0
  105. data/app/graphql/cortex/types/field_type.rb +18 -0
  106. data/app/graphql/cortex/types/mutation_type.rb +5 -0
  107. data/app/graphql/cortex/types/query_type.rb +45 -0
  108. data/app/graphql/cortex/types/tenant_type.rb +19 -0
  109. data/app/graphql/cortex/types/user_type.rb +20 -0
  110. data/app/helpers/cortex/application_helper.rb +75 -0
  111. data/app/helpers/cortex/cells/association_helper.rb +25 -0
  112. data/app/helpers/cortex/content_item_helper.rb +106 -0
  113. data/app/helpers/cortex/dashboard_helper.rb +19 -0
  114. data/app/helpers/cortex/popup_helper.rb +27 -0
  115. data/app/jobs/cortex/application_job.rb +4 -0
  116. data/app/mailers/cortex/application_mailer.rb +6 -0
  117. data/app/mailers/cortex/password_reset_mailer.rb +13 -0
  118. data/app/models/concerns/cortex/belongs_to_tenant.rb +13 -0
  119. data/app/models/concerns/cortex/has_firstname_lastname.rb +11 -0
  120. data/app/models/concerns/cortex/has_gravatar.rb +18 -0
  121. data/app/models/concerns/cortex/searchable.rb +11 -0
  122. data/app/models/concerns/cortex/searchable_content_item.rb +31 -0
  123. data/app/models/concerns/cortex/searchable_content_item_for_content_type.rb +52 -0
  124. data/app/models/concerns/cortex/searchable_content_type.rb +11 -0
  125. data/app/models/cortex/application_record.rb +17 -0
  126. data/app/models/cortex/content_item.rb +71 -0
  127. data/app/models/cortex/content_type.rb +27 -0
  128. data/app/models/cortex/contentable_decorator.rb +8 -0
  129. data/app/models/cortex/contract.rb +12 -0
  130. data/app/models/cortex/decorator.rb +13 -0
  131. data/app/models/cortex/field.rb +36 -0
  132. data/app/models/cortex/field_item.rb +54 -0
  133. data/app/models/cortex/field_type.rb +44 -0
  134. data/app/models/cortex/permission.rb +11 -0
  135. data/app/models/cortex/role.rb +12 -0
  136. data/app/models/cortex/tenant.rb +41 -0
  137. data/app/models/cortex/user.rb +77 -0
  138. data/app/operations/cortex/database_transact_operation.rb +17 -0
  139. data/app/operations/cortex/execute_content_item_state_change_operation.rb +16 -0
  140. data/app/operations/cortex/parse_content_item_field_items_operation.rb +18 -0
  141. data/app/operations/cortex/persist_content_item_operation.rb +12 -0
  142. data/app/policies/cortex/application_policy.rb +55 -0
  143. data/app/policies/cortex/content_item_policy.rb +49 -0
  144. data/app/policies/cortex/content_type_policy.rb +38 -0
  145. data/app/transactions/concerns/cortex/content_itemable.rb +15 -0
  146. data/app/transactions/concerns/cortex/field_item_transactor.rb +28 -0
  147. data/app/transactions/concerns/cortex/widget_parsable.rb +19 -0
  148. data/app/transactions/cortex/application_transaction.rb +5 -0
  149. data/app/transactions/cortex/create_content_item_transaction.rb +35 -0
  150. data/app/transactions/cortex/get_content_item_transaction.rb +4 -0
  151. data/app/transactions/cortex/get_content_items_for_content_type_transaction.rb +34 -0
  152. data/app/transactions/cortex/get_publish_state_transaction.rb +28 -0
  153. data/app/transactions/cortex/new_field_item_transaction.rb +16 -0
  154. data/app/transactions/cortex/update_content_item_transaction.rb +45 -0
  155. data/app/transactions/cortex/update_field_item_transaction.rb +23 -0
  156. data/app/types/cortex/application_types.rb +21 -0
  157. data/app/types/cortex/content_item_transaction_type.rb +10 -0
  158. data/app/types/cortex/core_types.rb +5 -0
  159. data/app/types/cortex/transaction_type.rb +5 -0
  160. data/app/views/cortex/authentication/passwords/new.html.haml +13 -0
  161. data/app/views/cortex/authentication/sessions/new.html.haml +20 -0
  162. data/app/views/cortex/authentication/shared/_links.html.haml +19 -0
  163. data/app/views/cortex/content_items/_form.html.haml +13 -0
  164. data/app/views/cortex/content_items/_grid.html.haml +1 -0
  165. data/app/views/cortex/content_items/edit.html.haml +2 -0
  166. data/app/views/cortex/content_items/index.html.haml +4 -0
  167. data/app/views/cortex/content_items/new.html.haml +2 -0
  168. data/app/views/cortex/content_types/index.html.haml +2 -0
  169. data/app/views/cortex/content_types/new.html.haml +0 -0
  170. data/app/views/cortex/dashboards/index.html.haml +6 -0
  171. data/app/views/cortex/graphql/ide.haml +1 -0
  172. data/app/views/cortex/partials/_breadcrumb.html.haml +2 -0
  173. data/app/views/cortex/partials/_cortex_redux_state.html.haml +1 -0
  174. data/app/views/cortex/partials/_flash.html.haml +25 -0
  175. data/app/views/cortex/partials/_media_dialogs.html.haml +13 -0
  176. data/app/views/cortex/partials/_navigation.html.haml +15 -0
  177. data/app/views/cortex/partials/_notes.html.haml +17 -0
  178. data/app/views/cortex/partials/_quick_links.html.haml +22 -0
  179. data/app/views/cortex/partials/_sidebar.html.haml +7 -0
  180. data/app/views/cortex/partials/_topbar.html.haml +5 -0
  181. data/app/views/cortex/partials/_user_control.html.haml +7 -0
  182. data/app/views/cortex/partials/authentication/_header.html.haml +4 -0
  183. data/app/views/cortex/partials/trackers/_google_analytics.html.haml +10 -0
  184. data/app/views/cortex/partials/trackers/_qualtrics.html.haml +10 -0
  185. data/app/views/cortex/password_reset_mailer/send_password_reset.html.erb +5 -0
  186. data/app/views/cortex/password_reset_mailer/send_password_reset.text.erb +5 -0
  187. data/app/views/layouts/cortex/application.html.haml +30 -0
  188. data/app/views/layouts/cortex/devise.html.haml +19 -0
  189. data/app/views/layouts/cortex/mailer.html.erb +13 -0
  190. data/app/views/layouts/cortex/mailer.text.erb +1 -0
  191. data/bin/rails +25 -0
  192. data/config/config.yml +22 -0
  193. data/config/initializers/devise.rb +35 -0
  194. data/config/initializers/elasticsearch.rb +3 -0
  195. data/config/initializers/filter_parameter_logging.rb +4 -0
  196. data/config/initializers/flipper.rb +16 -0
  197. data/config/initializers/graphiql.rb +51 -0
  198. data/config/initializers/inflections.rb +16 -0
  199. data/config/initializers/load_config.rb +16 -0
  200. data/config/initializers/mime_types.rb +5 -0
  201. data/config/initializers/plugins.rb +17 -0
  202. data/config/initializers/react_on_rails.rb +15 -0
  203. data/config/initializers/rolify.rb +9 -0
  204. data/config/initializers/tag_parsers.rb +5 -0
  205. data/config/locales/devise.en.yml +64 -0
  206. data/config/routes.rb +41 -0
  207. data/cortex.gemspec +84 -0
  208. data/db/migrate/0_enable_pgcrypto_extension.rb +5 -0
  209. data/db/migrate/10_create_fields.rb +15 -0
  210. data/db/migrate/11_create_content_items.rb +14 -0
  211. data/db/migrate/12_create_field_items.rb +12 -0
  212. data/db/migrate/13_create_field_types.rb +5 -0
  213. data/db/migrate/1_create_users.rb +14 -0
  214. data/db/migrate/2_create_tenants.rb +26 -0
  215. data/db/migrate/3_add_devise_to_users.rb +49 -0
  216. data/db/migrate/4_create_roles.rb +15 -0
  217. data/db/migrate/5_create_permissions.rb +16 -0
  218. data/db/migrate/6_create_flipper_tables.rb +20 -0
  219. data/db/migrate/7_create_contracts.rb +11 -0
  220. data/db/migrate/8_create_decorators.rb +21 -0
  221. data/db/migrate/9_create_content_types.rb +17 -0
  222. data/db/seeds.rb +40 -0
  223. data/db/seeds.yml +33 -0
  224. data/lib/assets/.keep +0 -0
  225. data/lib/breadcrumbs/title_builder.rb +12 -0
  226. data/lib/cortex.rb +4 -0
  227. data/lib/cortex/engine.rb +41 -0
  228. data/lib/cortex/version.rb +3 -0
  229. data/lib/helpers/utility_helper.rb +7 -0
  230. data/lib/tasks/cortex_tasks.rake +13 -0
  231. data/lib/tasks/elasticsearch_tasks.rake +1 -0
  232. data/node_package/.babelrc +26 -0
  233. data/node_package/src/components/side_bar/environment_flag.jsx +21 -0
  234. data/node_package/src/components/side_bar/tenant_list.jsx +65 -0
  235. data/node_package/src/components/wizard/column.jsx +29 -0
  236. data/node_package/src/components/wizard/field.jsx +22 -0
  237. data/node_package/src/components/wizard/step.jsx +20 -0
  238. data/node_package/src/constants/tenant_switcher.jsx +17 -0
  239. data/node_package/src/constants/type_constants.jsx +12 -0
  240. data/node_package/src/constants/wizard.jsx +9 -0
  241. data/node_package/src/containers/layout.jsx +33 -0
  242. data/node_package/src/containers/tenant_switcher_container.jsx +115 -0
  243. data/node_package/src/containers/wizard_container.jsx +28 -0
  244. data/node_package/src/elements/loaders.jsx +7 -0
  245. data/node_package/src/helpers/formatting.jsx +5 -0
  246. data/node_package/src/helpers/tenant_ancestry.jsx +14 -0
  247. data/node_package/src/helpers/tenant_lookup.jsx +23 -0
  248. data/node_package/src/index.jsx +21 -0
  249. data/node_package/src/reducers/index.jsx +13 -0
  250. data/node_package/src/reducers/rails_context_reducer.jsx +5 -0
  251. data/node_package/src/reducers/tenant_switcher_reducer.jsx +74 -0
  252. data/node_package/src/reducers/wizard_reducer.jsx +32 -0
  253. data/node_package/src/services/rails_api_service.jsx +13 -0
  254. data/node_package/src/store/store.jsx +15 -0
  255. data/package.json +66 -0
  256. data/spec/dummy/Rakefile +7 -0
  257. data/spec/dummy/app/assets/config/manifest.js +4 -0
  258. data/spec/dummy/app/assets/javascripts/application.js +2 -0
  259. data/spec/dummy/app/assets/stylesheets/application.scss +2 -0
  260. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  261. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  262. data/spec/dummy/app/javascript/packs/application.js +8 -0
  263. data/spec/dummy/app/javascript/packs/cortex.jsx +1 -0
  264. data/spec/dummy/app/jobs/application_job.rb +2 -0
  265. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  266. data/spec/dummy/app/views/layouts/application.html.haml +11 -0
  267. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  268. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  269. data/spec/dummy/bin/bundle +105 -0
  270. data/spec/dummy/bin/rails +4 -0
  271. data/spec/dummy/bin/rake +4 -0
  272. data/spec/dummy/bin/rspec +17 -0
  273. data/spec/dummy/bin/setup +38 -0
  274. data/spec/dummy/bin/update +29 -0
  275. data/spec/dummy/bin/webpack +29 -0
  276. data/spec/dummy/bin/webpack-dev-server +29 -0
  277. data/spec/dummy/bin/yarn +11 -0
  278. data/spec/dummy/config.ru +7 -0
  279. data/spec/dummy/config/apollo_engine_proxy.yml +23 -0
  280. data/spec/dummy/config/application.rb +21 -0
  281. data/spec/dummy/config/boot.rb +11 -0
  282. data/spec/dummy/config/cable.yml +9 -0
  283. data/spec/dummy/config/config.yml +22 -0
  284. data/spec/dummy/config/database.yml +22 -0
  285. data/spec/dummy/config/environment.rb +5 -0
  286. data/spec/dummy/config/environments/development.rb +74 -0
  287. data/spec/dummy/config/environments/production.rb +103 -0
  288. data/spec/dummy/config/environments/staging.rb +103 -0
  289. data/spec/dummy/config/environments/test.rb +65 -0
  290. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
  291. data/spec/dummy/config/initializers/assets.rb +14 -0
  292. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  293. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  294. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  295. data/spec/dummy/config/initializers/inflections.rb +16 -0
  296. data/spec/dummy/config/initializers/load_config.rb +9 -0
  297. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  298. data/spec/dummy/config/initializers/react_on_rails.rb +41 -0
  299. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  300. data/spec/dummy/config/initializers/sentry.rb +6 -0
  301. data/spec/dummy/config/initializers/session_store.rb +7 -0
  302. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  303. data/spec/dummy/config/locales/en.yml +8 -0
  304. data/spec/dummy/config/newrelic.yml +224 -0
  305. data/spec/dummy/config/puma.rb +47 -0
  306. data/spec/dummy/config/routes.rb +5 -0
  307. data/spec/dummy/config/secrets.yml +32 -0
  308. data/spec/dummy/config/sidekiq.yml +9 -0
  309. data/spec/dummy/config/webpack/development.js +3 -0
  310. data/spec/dummy/config/webpack/environment.js +3 -0
  311. data/spec/dummy/config/webpack/production.js +3 -0
  312. data/spec/dummy/config/webpack/test.js +3 -0
  313. data/spec/dummy/config/webpacker.yml +66 -0
  314. data/spec/dummy/db/migrate/20180118233001_enable_pgcrypto_extension.cortex.rb +6 -0
  315. data/spec/dummy/db/migrate/20180118233002_create_users.cortex.rb +15 -0
  316. data/spec/dummy/db/migrate/20180118233003_create_tenants.cortex.rb +27 -0
  317. data/spec/dummy/db/migrate/20180118233004_add_devise_to_users.cortex.rb +50 -0
  318. data/spec/dummy/db/migrate/20180118233005_create_roles.cortex.rb +16 -0
  319. data/spec/dummy/db/migrate/20180118233006_create_permissions.cortex.rb +17 -0
  320. data/spec/dummy/db/migrate/20180118233007_create_flipper_tables.cortex.rb +21 -0
  321. data/spec/dummy/db/migrate/20180118233008_create_contracts.cortex.rb +12 -0
  322. data/spec/dummy/db/migrate/20180118233009_create_decorators.cortex.rb +22 -0
  323. data/spec/dummy/db/migrate/20180118233010_create_content_types.cortex.rb +18 -0
  324. data/spec/dummy/db/migrate/20180118233011_create_fields.cortex.rb +16 -0
  325. data/spec/dummy/db/migrate/20180118233012_create_content_items.cortex.rb +15 -0
  326. data/spec/dummy/db/migrate/20180118233013_create_field_items.cortex.rb +13 -0
  327. data/spec/dummy/db/migrate/20180118233014_create_field_types.cortex.rb +6 -0
  328. data/spec/dummy/db/schema.rb +258 -0
  329. data/spec/dummy/db/seeds.rb +1 -0
  330. data/spec/dummy/lib/tasks/content_types_tasks.rake +31 -0
  331. data/spec/dummy/lib/tasks/employer/blog_tasks.rake +345 -0
  332. data/spec/dummy/package.json +28 -0
  333. data/spec/dummy/public/404.html +67 -0
  334. data/spec/dummy/public/422.html +67 -0
  335. data/spec/dummy/public/500.html +66 -0
  336. data/spec/dummy/public/robots.txt +5 -0
  337. data/spec/dummy/spec/javascripts/support/jasmine.yml +50 -0
  338. data/spec/dummy/yarn.lock +6615 -0
  339. data/spec/rails_helper.rb +57 -0
  340. data/spec/spec_helper.rb +96 -0
  341. data/yarn.lock +6032 -0
  342. metadata +1061 -0
@@ -0,0 +1,12 @@
1
+ module Cortex
2
+ class Role < Cortex::ApplicationRecord
3
+ scopify
4
+
5
+ has_and_belongs_to_many :users
6
+ has_and_belongs_to_many :permissions
7
+
8
+ validates :resource_type,
9
+ :inclusion => { :in => Rolify.resource_types },
10
+ :allow_nil => true
11
+ end
12
+ end
@@ -0,0 +1,41 @@
1
+ module Cortex
2
+ class Tenant < Cortex::ApplicationRecord
3
+ acts_as_nested_set
4
+
5
+ has_many :content_items
6
+ has_many :content_types
7
+ has_many :contracts
8
+ has_many :decorators
9
+ has_and_belongs_to_many :users
10
+ belongs_to :owner, class_name: 'User'
11
+ has_many :users, foreign_key: :active_tenant_id, class_name: 'User'
12
+
13
+ validates_presence_of :name
14
+ validates_associated :owner
15
+
16
+ validates_uniqueness_of :name,
17
+ :name_id
18
+
19
+ alias_method :organization, :root
20
+
21
+ def is_organization?
22
+ root?
23
+ end
24
+
25
+ def has_children?
26
+ !leaf?
27
+ end
28
+
29
+ def all_up_organization_for(klass)
30
+ self_and_ancestors.flat_map do |tenant|
31
+ tenant.public_send(klass.name.demodulize.underscore.pluralize).all
32
+ end
33
+ end
34
+
35
+ def search_up_organization_for(klass, attribute, value)
36
+ all_up_organization_for(klass).select do |record|
37
+ record[attribute] == value
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,77 @@
1
+ require 'digest/md5'
2
+
3
+ module Cortex
4
+ class User < Cortex::ApplicationRecord
5
+ include HasGravatar
6
+ include HasFirstnameLastname
7
+
8
+ # Include default devise modules. Others available are:
9
+ # :confirmable, :lockable, :timeoutable and :omniauthable
10
+ devise :database_authenticatable, :rememberable, :trackable, :validatable, :recoverable
11
+ rolify role_join_table_name: :roles_users # rolify doesn't obey lexical order for join table names
12
+
13
+ has_and_belongs_to_many :tenants
14
+ belongs_to :active_tenant, class_name: 'Tenant', optional: true
15
+ has_many :content_items
16
+
17
+ validates_presence_of :email, :firstname, :lastname
18
+
19
+ before_destroy :prevent_consumed_deletion
20
+
21
+ def active_tenant
22
+ super || tenants.order(:name).first
23
+ end
24
+
25
+ def referenced?
26
+ [ContentItem].find do |resource|
27
+ true if resource.where(user: self).count > 0
28
+ end
29
+ end
30
+
31
+ def anonymous?
32
+ self.id == nil
33
+ end
34
+
35
+ def has_permission?(resource, permission)
36
+ return true if self.is_superadmin?
37
+
38
+ resource_class = resource.class
39
+ allowed_perms = allowed_permissions(resource_class, permission)
40
+
41
+ if resource_class == Cortex::ContentType
42
+ allowed_perms.select { |perm| perm.resource_id == resource.id }.any?
43
+ else
44
+ allowed_perms.any?
45
+ end
46
+ end
47
+
48
+ def gravatar
49
+ "//www.gravatar.com/avatar/#{Digest::MD5.hexdigest email}"
50
+ end
51
+
52
+ def tenants_with_children
53
+ tenants.flat_map(&:self_and_descendants)
54
+ end
55
+
56
+ private
57
+
58
+ def allowed_permissions(resource_class, permission)
59
+ permissions.select { |perm| perm.resource_type == resource_class.to_s && perm.name == permission }
60
+ end
61
+
62
+ def prevent_consumed_deletion
63
+ raise Cortex::Exceptions::ResourceConsumed if referenced?
64
+ end
65
+
66
+ class << self
67
+ def authenticate(username, password)
68
+ user = User.find_by_email(username)
69
+ user && user.valid_password?(password) ? user : nil
70
+ end
71
+
72
+ def anonymous
73
+ User.new
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ module Cortex
2
+ DatabaseTransactOperation = -> (input, &block) {
3
+ extend Dry::Monads::Result::Mixin
4
+
5
+ result = nil
6
+
7
+ begin
8
+ ActiveRecord::Base.transaction do
9
+ result = block.(Success(input))
10
+ raise ActiveRecord::Rollback if result.failure?
11
+ result
12
+ end
13
+ rescue ActiveRecord::Rollback
14
+ result
15
+ end
16
+ }
17
+ end
@@ -0,0 +1,16 @@
1
+ require 'dry/transaction/operation'
2
+
3
+ module Cortex
4
+ class ExecuteContentItemStateChangeOperation
5
+ include Dry::Transaction::Operation
6
+
7
+ def call(input, state:)
8
+ if state && input.can_transition?(state)
9
+ state_method = "#{state}!"
10
+ input.send(state_method)
11
+ end
12
+
13
+ Success(input)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'dry/transaction/operation'
2
+
3
+ module Cortex
4
+ class ParseContentItemFieldItemsOperation
5
+ include Dry::Transaction::Operation
6
+ include Cortex::WidgetParsable
7
+
8
+ def call(input)
9
+ input.field_items.each do |field_item|
10
+ if field_item.field.metadata && field_item.field.metadata['parse_widgets']
11
+ parse_widgets!(field_item)
12
+ end
13
+ end
14
+
15
+ Success(input)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ require 'dry/transaction/operation'
2
+
3
+ module Cortex
4
+ class PersistContentItemOperation
5
+ include Dry::Transaction::Operation
6
+
7
+ def call(input)
8
+ input.save!
9
+ Success(input)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,55 @@
1
+ module Cortex
2
+ class ApplicationPolicy
3
+ attr_reader :user, :record
4
+
5
+ def initialize(user, record)
6
+ @user = user
7
+ @record = record
8
+ end
9
+
10
+ def index?
11
+ false
12
+ end
13
+
14
+ def show?
15
+ scope.where(:id => record.id).exists?
16
+ end
17
+
18
+ def create?
19
+ false
20
+ end
21
+
22
+ def new?
23
+ create?
24
+ end
25
+
26
+ def update?
27
+ false
28
+ end
29
+
30
+ def edit?
31
+ update?
32
+ end
33
+
34
+ def destroy?
35
+ false
36
+ end
37
+
38
+ def scope
39
+ Pundit.policy_scope!(user, record.class)
40
+ end
41
+
42
+ class Scope
43
+ attr_reader :user, :scope
44
+
45
+ def initialize(user, scope)
46
+ @user = user
47
+ @scope = scope
48
+ end
49
+
50
+ def resolve
51
+ scope
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,49 @@
1
+ module Cortex
2
+ class ContentItemPolicy
3
+ attr_reader :user, :content_item
4
+
5
+ def initialize(user, content_item)
6
+ @user = user
7
+ @content_item = content_item
8
+ @content_type = @content_item.content_type
9
+ end
10
+
11
+ def index?
12
+ has_permission?("Index")
13
+ end
14
+
15
+ def show?
16
+ has_permission?("Show")
17
+ end
18
+
19
+ def create?
20
+ has_permission?("Create")
21
+ end
22
+
23
+ def new?
24
+ has_permission?("New")
25
+ end
26
+
27
+ def update?
28
+ has_permission?("Update")
29
+ end
30
+
31
+ def edit?
32
+ has_permission?("Edit")
33
+ end
34
+
35
+ def destroy?
36
+ has_permission?("Destroy")
37
+ end
38
+
39
+ def can_publish?
40
+ has_permission?("Publish")
41
+ end
42
+
43
+ private
44
+
45
+ def has_permission?(permission)
46
+ @user.has_permission?(@content_type, permission)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,38 @@
1
+ module Cortex
2
+ class ContentTypePolicy
3
+ attr_reader :user, :content_type
4
+
5
+ def initialize(user, content_type)
6
+ @user = user
7
+ @content_type = content_type
8
+ end
9
+
10
+ def index?
11
+ @user.is_superadmin?
12
+ end
13
+
14
+ def show?
15
+ @user.is_superadmin?
16
+ end
17
+
18
+ def create?
19
+ @user.is_superadmin?
20
+ end
21
+
22
+ def new?
23
+ create?
24
+ end
25
+
26
+ def update?
27
+ @user.is_superadmin?
28
+ end
29
+
30
+ def edit?
31
+ update?
32
+ end
33
+
34
+ def destroy?
35
+ @user.is_superadmin?
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ module Cortex
2
+ module ContentItemable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def field_items_attributes(content_item_params)
7
+ content_item_params['field_items_attributes']
8
+ end
9
+
10
+ def last_updated_by(current_user)
11
+ { updated_by: current_user }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ module Cortex
2
+ module FieldItemTransactor
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # TODO: DRY all this up
7
+ def plugin_new_transaction_klass(field_item)
8
+ "new_#{field_type_name(field_item)}_field_item_transaction".classify.safe_constantize
9
+ end
10
+
11
+ def plugin_update_transaction_klass(field_item)
12
+ "update_#{field_type_name(field_item)}_field_item_transaction".classify.safe_constantize
13
+ end
14
+
15
+ def field_type_name(field_item)
16
+ field_item.field.field_type.chomp '_field_type'
17
+ end
18
+
19
+ def transact_new(field_item)
20
+ plugin_new_transaction_klass(field_item)&.new&.call(field_item)&.value!
21
+ end
22
+
23
+ def transact_update(field_item)
24
+ plugin_update_transaction_klass(field_item)&.new&.call(field_item)&.value!
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ module Cortex
2
+ module WidgetParsable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def parse_widgets!(field_item)
7
+ Cortex.tag_parsers.each do |tag_parser|
8
+ parser_module = tag_parser.constantize
9
+ field_item.data['text'] = parser_module.parse(field_item.data['text'])
10
+ end
11
+ end
12
+
13
+ def widget_parsers_as_json
14
+ # TODO: iterate through, provide JSON of Widget parser for frontend
15
+ {}.to_json
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Cortex
2
+ class ApplicationTransaction
3
+ include Dry::Transaction
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ module Cortex
2
+ class CreateContentItemTransaction < Cortex::ApplicationTransaction
3
+ include Dry::Transaction(container: Cortex::TransactionContainer)
4
+ include Cortex::ContentItemable
5
+
6
+ around :database_transact, with: "cortex.database_transact"
7
+ step :init
8
+ step :process
9
+ step :parse_content_item_field_items, with: "cortex.parse_content_item_field_items"
10
+ step :persist_content_item, with: "cortex.persist_content_item"
11
+ step :execute_content_item_state_change, with: "cortex.execute_content_item_state_change"
12
+
13
+ def init(input)
14
+ Success(ContentItemTransactionType.new(input))
15
+ end
16
+
17
+ def process(input)
18
+ if input.content_item
19
+ content_item = input.content_item
20
+ else
21
+ content_item = ContentItem.new
22
+ field_items_attributes(input.content_item_params).each do |_key, field_item_attributes|
23
+ field_item_attributes.delete('id')
24
+ content_item.field_items << NewFieldItemTransaction.new.call(field_item_attributes).value!
25
+ end
26
+
27
+ content_item.attributes = input.content_item_params.except('field_items_attributes')
28
+ end
29
+
30
+ content_item.tenant = input.current_user.active_tenant # TODO: In future, grab from form/route, rather than current_user + perform authorization checks
31
+
32
+ Success(content_item)
33
+ end
34
+ end
35
+ end