plutonium 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (346) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.ruby-version +1 -0
  4. data/.standard.yml +4 -0
  5. data/.vscode/extensions.json +15 -0
  6. data/.vscode/launch.json +7 -0
  7. data/.vscode/settings.json +35 -0
  8. data/CHANGELOG.md +5 -0
  9. data/LICENSE.txt +21 -0
  10. data/README copy.md +84 -0
  11. data/README.md +67 -0
  12. data/Rakefile +8 -0
  13. data/app/views/layouts/resource.html.erb +43 -0
  14. data/app/views/resource/_color_modes.html.erb +55 -0
  15. data/app/views/resource/_details.html.erb +6 -0
  16. data/app/views/resource/_empty_card.html.erb +12 -0
  17. data/app/views/resource/_flash.html.erb +9 -0
  18. data/app/views/resource/_form.html.erb +32 -0
  19. data/app/views/resource/_header.html.erb +8 -0
  20. data/app/views/resource/_interactive_resource_action_form.html.erb +67 -0
  21. data/app/views/resource/_messages.html.erb +1 -0
  22. data/app/views/resource/_metric_card.html.erb +16 -0
  23. data/app/views/resource/_nav_user.html.erb +4 -0
  24. data/app/views/resource/_pagination.html.erb +6 -0
  25. data/app/views/resource/_pagy_pagination.html.erb +15 -0
  26. data/app/views/resource/_resource.html.erb +1 -0
  27. data/app/views/resource/_resource.rabl +5 -0
  28. data/app/views/resource/_sidebar.html.erb +11 -0
  29. data/app/views/resource/_sidebar_menu.html.erb +1 -0
  30. data/app/views/resource/_tab_menu.html.erb +13 -0
  31. data/app/views/resource/_table.html.erb +78 -0
  32. data/app/views/resource/_table_actions.html.erb +15 -0
  33. data/app/views/resource/_toast.html.erb +26 -0
  34. data/app/views/resource/_toolbar.html.erb +22 -0
  35. data/app/views/resource/_toolbar_actions.html.erb +16 -0
  36. data/app/views/resource/_toolbar_breadcrumbs.html.erb +32 -0
  37. data/app/views/resource/_toolbar_search_input.erb +27 -0
  38. data/app/views/resource/edit.html.erb +10 -0
  39. data/app/views/resource/errors.rabl +3 -0
  40. data/app/views/resource/index.html.erb +19 -0
  41. data/app/views/resource/index.rabl +3 -0
  42. data/app/views/resource/interactive_resource_collection_action.html.erb +11 -0
  43. data/app/views/resource/interactive_resource_record_action.html.erb +11 -0
  44. data/app/views/resource/interactive_resource_recordless_action.html.erb +11 -0
  45. data/app/views/resource/new.html.erb +11 -0
  46. data/app/views/resource/readme.md +16 -0
  47. data/app/views/resource/show.html.erb +14 -0
  48. data/app/views/resource/show.rabl +3 -0
  49. data/brakeman.ignore +51 -0
  50. data/lib/active_model/validations/array_validator.rb +74 -0
  51. data/lib/active_model/validations/attached_validator.rb +17 -0
  52. data/lib/active_model/validations/url_validator.rb +51 -0
  53. data/lib/generators/pu/core/install/install_generator.rb +43 -0
  54. data/lib/generators/pu/core/install/templates/.keep +0 -0
  55. data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +2 -0
  56. data/lib/generators/pu/core/install/templates/app/interactions/resource_interaction.rb.tt +2 -0
  57. data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +5 -0
  58. data/lib/generators/pu/core/install/templates/app/policies/resource_policy.rb.tt +2 -0
  59. data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +2 -0
  60. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +2 -0
  61. data/lib/generators/pu/core/install/templates/config/packages.rb +3 -0
  62. data/lib/generators/pu/gem/pagy/pagy_generator.rb +25 -0
  63. data/lib/generators/pu/gem/pagy/templates/.keep +0 -0
  64. data/lib/generators/pu/gem/pagy/templates/config/initializers/pagy.rb +4 -0
  65. data/lib/generators/pu/gem/rabl/rabl_generator.rb +25 -0
  66. data/lib/generators/pu/gem/rabl/templates/.keep +0 -0
  67. data/lib/generators/pu/gem/rabl/templates/config/initializers/rabl.rb +60 -0
  68. data/lib/generators/pu/gem/simple_form/simple_form_generator.rb +25 -0
  69. data/lib/generators/pu/gem/simple_form/templates/.keep +0 -0
  70. data/lib/generators/pu/gen/pug/pug_generator.rb +43 -0
  71. data/lib/generators/pu/gen/pug/templates/pug.rb.tt +23 -0
  72. data/lib/generators/pu/pkg/app/app_generator.rb +60 -0
  73. data/lib/generators/pu/pkg/app/templates/app/controllers/resource_controller.rb.tt +26 -0
  74. data/lib/generators/pu/pkg/app/templates/app/interactions/resource_interaction.rb.tt +4 -0
  75. data/lib/generators/pu/pkg/app/templates/app/policies/resource_policy.rb.tt +4 -0
  76. data/lib/generators/pu/pkg/app/templates/app/presenters/resource_presenter.rb.tt +4 -0
  77. data/lib/generators/pu/pkg/app/templates/config/routes.rb.tt +17 -0
  78. data/lib/generators/pu/pkg/app/templates/lib/engine.rb.tt +14 -0
  79. data/lib/generators/pu/pkg/feature/feature_generator.rb +44 -0
  80. data/lib/generators/pu/pkg/feature/templates/.keep +0 -0
  81. data/lib/generators/pu/pkg/feature/templates/app/controllers/resource_controller.rb.tt +7 -0
  82. data/lib/generators/pu/pkg/feature/templates/app/interactions/resource_interaction.rb.tt +4 -0
  83. data/lib/generators/pu/pkg/feature/templates/app/models/resource_record.rb.tt +5 -0
  84. data/lib/generators/pu/pkg/feature/templates/app/policies/resource_policy.rb.tt +4 -0
  85. data/lib/generators/pu/pkg/feature/templates/app/presenters/resource_presenter.rb.tt +4 -0
  86. data/lib/generators/pu/pkg/feature/templates/lib/engine.rb.tt +8 -0
  87. data/lib/generators/pu/resource/conn/conn_generator.rb +54 -0
  88. data/lib/generators/pu/resource/conn/templates/.keep +0 -0
  89. data/lib/generators/pu/resource/conn/templates/app/controllers/resource_controller.rb.tt +3 -0
  90. data/lib/generators/pu/resource/conn/templates/app/policies/resource_policy.rb.tt +3 -0
  91. data/lib/generators/pu/resource/conn/templates/app/presenters/resource_presenter.rb.tt +3 -0
  92. data/lib/generators/pu/resource/model/USAGE +113 -0
  93. data/lib/generators/pu/resource/model/model_generator.rb +163 -0
  94. data/lib/generators/pu/resource/model/templates/controller.rb.tt +5 -0
  95. data/lib/generators/pu/resource/model/templates/create_table_migration.rb.tt +26 -0
  96. data/lib/generators/pu/resource/model/templates/model.rb.tt +53 -0
  97. data/lib/generators/pu/resource/model/templates/module.rb.tt +7 -0
  98. data/lib/generators/pu/resource/model/templates/policy.rb.tt +4 -0
  99. data/lib/generators/pu/resource/model/templates/presenter.rb.tt +4 -0
  100. data/lib/generators/pu/resource/scaffold/scaffold_generator.rb +219 -0
  101. data/lib/generators/pu/resource/scaffold/templates/app/controllers/admin_resources/resource_controller.rb.tt +7 -0
  102. data/lib/generators/pu/resource/scaffold/templates/app/controllers/entity_resources/resource_controller.rb.tt +7 -0
  103. data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/admin/resource_policy.rb.tt +22 -0
  104. data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/entity/resource_policy.rb.tt +22 -0
  105. data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/resource_policy.rb.tt +13 -0
  106. data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/admin_presenter.rb.tt +7 -0
  107. data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/entity_presenter.rb.tt +7 -0
  108. data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/presenter.rb.tt +23 -0
  109. data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.html.erb.tt +3 -0
  110. data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.rabl +7 -0
  111. data/lib/generators/pu/rodauth/account_generator.rb +120 -0
  112. data/lib/generators/pu/rodauth/concerns/account_selector.rb +22 -0
  113. data/lib/generators/pu/rodauth/concerns/configuration.rb +211 -0
  114. data/lib/generators/pu/rodauth/concerns/feature_selector.rb +125 -0
  115. data/lib/generators/pu/rodauth/install_generator.rb +69 -0
  116. data/lib/generators/pu/rodauth/migration/active_record/account_expiration.erb +8 -0
  117. data/lib/generators/pu/rodauth/migration/active_record/active_sessions.erb +7 -0
  118. data/lib/generators/pu/rodauth/migration/active_record/audit_logging.erb +16 -0
  119. data/lib/generators/pu/rodauth/migration/active_record/base.erb +22 -0
  120. data/lib/generators/pu/rodauth/migration/active_record/disallow_password_reuse.erb +5 -0
  121. data/lib/generators/pu/rodauth/migration/active_record/email_auth.erb +8 -0
  122. data/lib/generators/pu/rodauth/migration/active_record/jwt_refresh.erb +7 -0
  123. data/lib/generators/pu/rodauth/migration/active_record/lockout.erb +13 -0
  124. data/lib/generators/pu/rodauth/migration/active_record/otp.erb +8 -0
  125. data/lib/generators/pu/rodauth/migration/active_record/password_expiration.erb +6 -0
  126. data/lib/generators/pu/rodauth/migration/active_record/recovery_codes.erb +6 -0
  127. data/lib/generators/pu/rodauth/migration/active_record/remember.erb +7 -0
  128. data/lib/generators/pu/rodauth/migration/active_record/reset_password.erb +8 -0
  129. data/lib/generators/pu/rodauth/migration/active_record/separate_passwords.erb +5 -0
  130. data/lib/generators/pu/rodauth/migration/active_record/single_session.erb +6 -0
  131. data/lib/generators/pu/rodauth/migration/active_record/sms_codes.erb +9 -0
  132. data/lib/generators/pu/rodauth/migration/active_record/verify_account.erb +8 -0
  133. data/lib/generators/pu/rodauth/migration/active_record/verify_login_change.erb +8 -0
  134. data/lib/generators/pu/rodauth/migration/active_record/webauthn.erb +13 -0
  135. data/lib/generators/pu/rodauth/migration/sequel/account_expiration.erb +7 -0
  136. data/lib/generators/pu/rodauth/migration/sequel/active_sessions.erb +8 -0
  137. data/lib/generators/pu/rodauth/migration/sequel/audit_logging.erb +17 -0
  138. data/lib/generators/pu/rodauth/migration/sequel/base.erb +25 -0
  139. data/lib/generators/pu/rodauth/migration/sequel/disallow_password_reuse.erb +6 -0
  140. data/lib/generators/pu/rodauth/migration/sequel/email_auth.erb +7 -0
  141. data/lib/generators/pu/rodauth/migration/sequel/jwt_refresh.erb +8 -0
  142. data/lib/generators/pu/rodauth/migration/sequel/lockout.erb +11 -0
  143. data/lib/generators/pu/rodauth/migration/sequel/otp.erb +7 -0
  144. data/lib/generators/pu/rodauth/migration/sequel/password_expiration.erb +5 -0
  145. data/lib/generators/pu/rodauth/migration/sequel/recovery_codes.erb +6 -0
  146. data/lib/generators/pu/rodauth/migration/sequel/remember.erb +6 -0
  147. data/lib/generators/pu/rodauth/migration/sequel/reset_password.erb +7 -0
  148. data/lib/generators/pu/rodauth/migration/sequel/separate_passwords.erb +6 -0
  149. data/lib/generators/pu/rodauth/migration/sequel/single_session.erb +5 -0
  150. data/lib/generators/pu/rodauth/migration/sequel/sms_codes.erb +8 -0
  151. data/lib/generators/pu/rodauth/migration/sequel/verify_account.erb +7 -0
  152. data/lib/generators/pu/rodauth/migration/sequel/verify_login_change.erb +7 -0
  153. data/lib/generators/pu/rodauth/migration/sequel/webauthn.erb +13 -0
  154. data/lib/generators/pu/rodauth/migration_generator.rb +190 -0
  155. data/lib/generators/pu/rodauth/templates/INSTRUCTIONS +52 -0
  156. data/lib/generators/pu/rodauth/templates/app/controllers/plugin_controller.rb.tt +6 -0
  157. data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +3 -0
  158. data/lib/generators/pu/rodauth/templates/app/mailers/account_mailer.rb.tt +4 -0
  159. data/lib/generators/pu/rodauth/templates/app/mailers/rodauth_mailer.rb.tt +62 -0
  160. data/lib/generators/pu/rodauth/templates/app/misc/account_rodauth_plugin.rb.tt +255 -0
  161. data/lib/generators/pu/rodauth/templates/app/misc/rodauth_app.rb.tt +24 -0
  162. data/lib/generators/pu/rodauth/templates/app/misc/rodauth_plugin.rb.tt +234 -0
  163. data/lib/generators/pu/rodauth/templates/app/models/account.rb.tt +40 -0
  164. data/lib/generators/pu/rodauth/templates/app/views/rodauth/_email_auth_request_form.html.erb +7 -0
  165. data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form.html.erb +26 -0
  166. data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form_footer.html.erb +9 -0
  167. data/lib/generators/pu/rodauth/templates/app/views/rodauth/add_recovery_codes.html.erb +6 -0
  168. data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_login.html.erb +27 -0
  169. data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_password.html.erb +27 -0
  170. data/lib/generators/pu/rodauth/templates/app/views/rodauth/close_account.html.erb +13 -0
  171. data/lib/generators/pu/rodauth/templates/app/views/rodauth/confirm_password.html.erb +11 -0
  172. data/lib/generators/pu/rodauth/templates/app/views/rodauth/create_account.html.erb +35 -0
  173. data/lib/generators/pu/rodauth/templates/app/views/rodauth/email_auth.html.erb +5 -0
  174. data/lib/generators/pu/rodauth/templates/app/views/rodauth/login.html.erb +4 -0
  175. data/lib/generators/pu/rodauth/templates/app/views/rodauth/logout.html.erb +14 -0
  176. data/lib/generators/pu/rodauth/templates/app/views/rodauth/multi_phase_login.html.erb +3 -0
  177. data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_auth.html.erb +15 -0
  178. data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_disable.html.erb +13 -0
  179. data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_setup.html.erb +41 -0
  180. data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_auth.html.erb +11 -0
  181. data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_codes.html.erb +13 -0
  182. data/lib/generators/pu/rodauth/templates/app/views/rodauth/remember.html.erb +22 -0
  183. data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password.html.erb +19 -0
  184. data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password_request.html.erb +17 -0
  185. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_auth.html.erb +15 -0
  186. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_confirm.html.erb +15 -0
  187. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_disable.html.erb +13 -0
  188. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_request.html.erb +5 -0
  189. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_setup.html.erb +23 -0
  190. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_email_auth_request_form.html.erb +5 -0
  191. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form.html.erb +24 -0
  192. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form_footer.html.erb +7 -0
  193. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/add_recovery_codes.html.erb +16 -0
  194. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_login.html.erb +25 -0
  195. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_password.html.erb +25 -0
  196. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/close_account.html.erb +11 -0
  197. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/confirm_password.html.erb +19 -0
  198. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/create_account.html.erb +33 -0
  199. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/email_auth.html.erb +3 -0
  200. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/login.html.erb +5 -0
  201. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/logout.html.erb +10 -0
  202. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/multi_phase_login.html.erb +5 -0
  203. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_auth.html.erb +9 -0
  204. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_disable.html.erb +11 -0
  205. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_setup.html.erb +32 -0
  206. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_auth.html.erb +9 -0
  207. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_codes.html.erb +11 -0
  208. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/remember.html.erb +18 -0
  209. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password.html.erb +17 -0
  210. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password_request.html.erb +17 -0
  211. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_auth.html.erb +9 -0
  212. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_confirm.html.erb +9 -0
  213. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_disable.html.erb +11 -0
  214. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_request.html.erb +3 -0
  215. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_setup.html.erb +17 -0
  216. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_auth.html.erb +5 -0
  217. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_disable.html.erb +11 -0
  218. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_manage.html.erb +26 -0
  219. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account.html.erb +15 -0
  220. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account_request.html.erb +9 -0
  221. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account.html.erb +19 -0
  222. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account_resend.html.erb +17 -0
  223. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_login_change.html.erb +3 -0
  224. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_auth.html.erb +13 -0
  225. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_autofill.html.erb +10 -0
  226. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_remove.html.erb +21 -0
  227. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_setup.html.erb +21 -0
  228. data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_auth.html.erb +5 -0
  229. data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_disable.html.erb +13 -0
  230. data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_manage.html.erb +22 -0
  231. data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account.html.erb +15 -0
  232. data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account_request.html.erb +9 -0
  233. data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account.html.erb +21 -0
  234. data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account_resend.html.erb +17 -0
  235. data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_login_change.html.erb +5 -0
  236. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_auth.html.erb +15 -0
  237. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_autofill.html.erb +10 -0
  238. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_remove.html.erb +23 -0
  239. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_setup.html.erb +23 -0
  240. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/email_auth.text.erb +5 -0
  241. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/password_changed.text.erb +2 -0
  242. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password.text.erb +5 -0
  243. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password_notify.text.erb +2 -0
  244. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb +5 -0
  245. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_account.text.erb +4 -0
  246. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_login_change.text.erb +10 -0
  247. data/lib/generators/pu/rodauth/templates/config/initializers/rodauth.rb.tt +3 -0
  248. data/lib/generators/pu/rodauth/templates/db/migrate/create_rodauth.rb.tt +13 -0
  249. data/lib/generators/pu/rodauth/views_generator.rb +125 -0
  250. data/lib/plutonium/auth/public_access.rb +17 -0
  251. data/lib/plutonium/auth/rodauth.rb +35 -0
  252. data/lib/plutonium/auth.rb +12 -0
  253. data/lib/plutonium/config.rb +11 -0
  254. data/lib/plutonium/core/.DS_Store +0 -0
  255. data/lib/plutonium/core/action.rb +46 -0
  256. data/lib/plutonium/core/actions/basic_action.rb +16 -0
  257. data/lib/plutonium/core/actions/collection.rb +33 -0
  258. data/lib/plutonium/core/actions/destroy_action.rb +21 -0
  259. data/lib/plutonium/core/actions/edit_action.rb +19 -0
  260. data/lib/plutonium/core/actions/interactive_action.rb +64 -0
  261. data/lib/plutonium/core/actions/new_action.rb +18 -0
  262. data/lib/plutonium/core/actions/show_action.rb +17 -0
  263. data/lib/plutonium/core/actions.rb +17 -0
  264. data/lib/plutonium/core/app_controller.rb +121 -0
  265. data/lib/plutonium/core/autodiscovery/discoverer.rb +15 -0
  266. data/lib/plutonium/core/autodiscovery/input_discoverer.rb +33 -0
  267. data/lib/plutonium/core/autodiscovery/renderer_discoverer.rb +33 -0
  268. data/lib/plutonium/core/autodiscovery.rb +13 -0
  269. data/lib/plutonium/core/controllers/authorizable.rb +56 -0
  270. data/lib/plutonium/core/controllers/bootable.rb +44 -0
  271. data/lib/plutonium/core/controllers/crud_actions.rb +128 -0
  272. data/lib/plutonium/core/controllers/entity_scoping.rb +69 -0
  273. data/lib/plutonium/core/controllers/interactive_actions.rb +210 -0
  274. data/lib/plutonium/core/controllers/presentable.rb +59 -0
  275. data/lib/plutonium/core/controllers.rb +16 -0
  276. data/lib/plutonium/core/definers/action_definer.rb +25 -0
  277. data/lib/plutonium/core/definers/field_definer.rb +19 -0
  278. data/lib/plutonium/core/definers/input_definer.rb +37 -0
  279. data/lib/plutonium/core/definers/renderer_definer.rb +35 -0
  280. data/lib/plutonium/core/definers.rb +14 -0
  281. data/lib/plutonium/core/fields/inputs/association_input.rb +26 -0
  282. data/lib/plutonium/core/fields/inputs/basic_input.rb +42 -0
  283. data/lib/plutonium/core/fields/inputs/belongs_to_input.rb +15 -0
  284. data/lib/plutonium/core/fields/inputs/factory.rb +58 -0
  285. data/lib/plutonium/core/fields/inputs/has_many_input.rb +15 -0
  286. data/lib/plutonium/core/fields/inputs/noop_input.rb +19 -0
  287. data/lib/plutonium/core/fields/inputs.rb +18 -0
  288. data/lib/plutonium/core/fields/renderers/association_renderer.rb +25 -0
  289. data/lib/plutonium/core/fields/renderers/basic_renderer.rb +27 -0
  290. data/lib/plutonium/core/fields/renderers/factory.rb +52 -0
  291. data/lib/plutonium/core/fields/renderers.rb +15 -0
  292. data/lib/plutonium/core/fields.rb +12 -0
  293. data/lib/plutonium/core/ui/collection.rb +14 -0
  294. data/lib/plutonium/core/ui/detail.rb +11 -0
  295. data/lib/plutonium/core/ui/form.rb +11 -0
  296. data/lib/plutonium/core/ui.rb +13 -0
  297. data/lib/plutonium/core.rb +16 -0
  298. data/lib/plutonium/helpers/action_buttons_helper.rb +32 -0
  299. data/lib/plutonium/helpers/application_helper.rb +22 -0
  300. data/lib/plutonium/helpers/attachment_helper.rb +62 -0
  301. data/lib/plutonium/helpers/content_helper.rb +66 -0
  302. data/lib/plutonium/helpers/display_helper.rb +83 -0
  303. data/lib/plutonium/helpers/form_helper.rb +24 -0
  304. data/lib/plutonium/helpers/menu_helper.rb +69 -0
  305. data/lib/plutonium/helpers/pagination_helper.rb +9 -0
  306. data/lib/plutonium/helpers/turbo_helper.rb +13 -0
  307. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +9 -0
  308. data/lib/plutonium/helpers.rb +31 -0
  309. data/lib/plutonium/initializers/TODO +2 -0
  310. data/lib/plutonium/initializers/pagy.rb +5 -0
  311. data/lib/plutonium/initializers/patches.rb +2 -0
  312. data/lib/plutonium/initializers/rabl.rb +60 -0
  313. data/lib/plutonium/initializers/simple_form.rb +405 -0
  314. data/lib/plutonium/lib/after_commit.rb +34 -0
  315. data/lib/plutonium/lib/bit_flags.rb +36 -0
  316. data/lib/plutonium/packaging/app.rb +125 -0
  317. data/lib/plutonium/packaging/feature.rb +18 -0
  318. data/lib/plutonium/packaging/package.rb +22 -0
  319. data/lib/plutonium/packaging.rb +9 -0
  320. data/lib/plutonium/policy/initializer.rb +22 -0
  321. data/lib/plutonium/policy/scope.rb +19 -0
  322. data/lib/plutonium/policy.rb +8 -0
  323. data/lib/plutonium/preserved__/field.rb +65 -0
  324. data/lib/plutonium/preserved__/input.rb +93 -0
  325. data/lib/plutonium/reactor/core.rb +61 -0
  326. data/lib/plutonium/reactor/resource_context.rb +15 -0
  327. data/lib/plutonium/reactor/resource_controller.rb +108 -0
  328. data/lib/plutonium/reactor/resource_interaction.rb +8 -0
  329. data/lib/plutonium/reactor/resource_policy.rb +105 -0
  330. data/lib/plutonium/reactor/resource_presenter.rb +42 -0
  331. data/lib/plutonium/reactor/resource_record.rb +123 -0
  332. data/lib/plutonium/reactor.rb +13 -0
  333. data/lib/plutonium/refinements/parameter_refinements.rb +26 -0
  334. data/lib/plutonium/simple_form_components/attachment_component.rb +77 -0
  335. data/lib/plutonium/simple_form_components/input_group_component.rb +14 -0
  336. data/lib/plutonium/version.rb +3 -0
  337. data/lib/plutonium.rb +31 -0
  338. data/plutonium.gemspec +47 -0
  339. data/public/.keep +0 -0
  340. data/public/plutonium-assets/application.css +24280 -0
  341. data/public/plutonium-assets/application.js +31420 -0
  342. data/public/plutonium-assets/fonts/bootstrap-icons.woff +0 -0
  343. data/public/plutonium-assets/fonts/bootstrap-icons.woff2 +0 -0
  344. data/public/plutonium-assets/logo.png +0 -0
  345. data/sig/plutonium.rbs +4 -0
  346. metadata +519 -0
@@ -0,0 +1,5 @@
1
+ Someone has requested a login link for the account with this email
2
+ address. If you did not request a login link, please ignore this
3
+ message. If you requested a login link, please go to
4
+ <%= @rodauth.email_auth_email_link %>
5
+ to login to this account.
@@ -0,0 +1,2 @@
1
+ Someone (hopefully you) has changed the password for the account
2
+ associated to this email address.
@@ -0,0 +1,5 @@
1
+ Someone has requested a password reset for the account with this email
2
+ address. If you did not request a password reset, please ignore this
3
+ message. If you requested a password reset, please go to
4
+ <%= @rodauth.reset_password_email_link %>
5
+ to reset the password for the account.
@@ -0,0 +1,2 @@
1
+ Someone (hopefully you) has reset the password for the account
2
+ associated to this email address.
@@ -0,0 +1,5 @@
1
+ Someone has requested that the account with this email be unlocked.
2
+ If you did not request the unlocking of this account, please ignore this
3
+ message. If you requested the unlocking of this account, please go to
4
+ <%= @rodauth.unlock_account_email_link %>
5
+ to unlock this account.
@@ -0,0 +1,4 @@
1
+ Someone has created an account with this email address. If you did not create
2
+ this account, please ignore this message. If you created this account, please go to
3
+ <%= @rodauth.verify_account_email_link %>
4
+ to verify the account.
@@ -0,0 +1,10 @@
1
+ Someone with an account has requested their login be changed to this email address:
2
+
3
+ Old email: <%= @account.email %>
4
+
5
+ New email: <%= @new_email %>
6
+
7
+ If you did not request this login change, please ignore this message. If you
8
+ requested this login change, please go to
9
+ <%= @rodauth.verify_login_change_email_link %>
10
+ to verify the login change.
@@ -0,0 +1,3 @@
1
+ Rodauth::Rails.configure do |config|
2
+ config.app = "RodauthApp"
3
+ end
@@ -0,0 +1,13 @@
1
+ <% if defined?(::ActiveRecord::Railtie) -%>
2
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
3
+ def change
4
+ <%= migration_content -%>
5
+ end
6
+ end
7
+ <% else -%>
8
+ Sequel.migration do
9
+ change do
10
+ <%= migration_content -%>
11
+ end
12
+ end
13
+ <% end -%>
@@ -0,0 +1,125 @@
1
+ return unless defined?(Rodauth::Rails)
2
+
3
+ require "rails/generators/base"
4
+
5
+ require "#{__dir__}/concerns/configuration"
6
+
7
+ module Pu
8
+ module Rodauth
9
+ class ViewsGenerator < ::Rails::Generators::Base
10
+ include Concerns::Configuration
11
+
12
+ source_root "#{__dir__}/templates"
13
+ # namespace "rodauth:views"
14
+
15
+ desc "Generate views for selected features\n\n" \
16
+ "Supported Features\n" \
17
+ "=========================================\n" \
18
+ "#{VIEW_CONFIG.keys.sort.map(&:to_s).join "\n"}\n\n\n\n"
19
+
20
+ argument :plugin_name, type: :string, optional: true,
21
+ desc: "[CONFIG] Name of the configured rodauth app. Leave blank to use the primary account."
22
+
23
+ class_option :features, required: true, type: :array,
24
+ desc: "Rodauth features to generate views for (login, create_account, reset_password, verify_account etc.)"
25
+
26
+ class_option :all, aliases: "-a", type: :boolean,
27
+ desc: "Generates views for all Rodauth features",
28
+ default: false
29
+
30
+ class_option :css, type: :string, enum: %w[bootstrap tailwind tailwindcss],
31
+ desc: "CSS framework to generate views for",
32
+ default: "bootstrap"
33
+
34
+ def validate_selected_features
35
+ if selected_features.empty?
36
+ say "No view features specified!", :yellow
37
+ exit(1)
38
+ elsif (selected_features - view_config.keys).any?
39
+ say "No available view template for feature(s): #{(selected_features - view_config.keys).join(", ")}", :red
40
+ exit(1)
41
+ end
42
+ end
43
+
44
+ def create_views
45
+ views.each do |view|
46
+ copy_file view_location(view), "app/views/#{directory}/#{view}.html.erb" do |content|
47
+ content = content.gsub("rodauth.", "rodauth(:#{configuration_name}).") if configuration_name
48
+ content = content.gsub("rodauth/", "#{directory}/")
49
+ content = form_helpers_compatibility(content) if ActionView.version < Gem::Version.new("5.1")
50
+ content
51
+ end
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def features
58
+ options[:features]
59
+ end
60
+
61
+ def views
62
+ selected_features.flat_map { |feature| view_config.fetch(feature) }
63
+ end
64
+
65
+ def selected_features
66
+ if options[:all]
67
+ view_config.keys
68
+ elsif features
69
+ features.map(&:to_sym)
70
+ else
71
+ rodauth_configuration.features & view_config.keys
72
+ end
73
+ end
74
+
75
+ def directory
76
+ if controller.abstract?
77
+ raise Error, "no controller configured for configuration: #{configuration_name.inspect}"
78
+ end
79
+
80
+ controller.controller_path
81
+ end
82
+
83
+ def controller
84
+ rodauth_configuration.allocate.rails_controller
85
+ end
86
+
87
+ def rodauth_configuration
88
+ require "rodauth-rails" # this requires the project to include the package
89
+
90
+ ::Rodauth::Rails.app.rodauth!(configuration_name&.to_sym)
91
+ rescue ArgumentError => e
92
+ say "An error occurred generating views for " \
93
+ "#{configuration_name.present? ? "'#{configuration_name}'" : "primary"} account:\n\n#{e}", :red
94
+ exit(1)
95
+ end
96
+
97
+ def configuration_name
98
+ plugin_name
99
+ end
100
+
101
+ # We need to use the *_tag helpers on versions lower than Rails 5.1.
102
+ def form_helpers_compatibility(content)
103
+ content
104
+ .gsub(/form_with url: (.+) do \|form\|/, 'form_tag \1 do')
105
+ .gsub(/form\.(label|submit)/, '\1_tag')
106
+ .gsub(/form\.(email|password|text|telephone|hidden)_field (\S+), value:/, '\1_field_tag \2,')
107
+ .gsub(/form\.radio_button (\S+), (\S+),/, 'radio_button_tag \1, \2, false,')
108
+ .gsub(/form\.check_box (\S+), (.+) /, 'check_box_tag \1, "t", false, \2 ')
109
+ end
110
+
111
+ def view_location(view)
112
+ if tailwind?
113
+ "app/views/rodauth/tailwind/#{view}.html.erb"
114
+ else
115
+ "app/views/rodauth/#{view}.html.erb"
116
+ end
117
+ end
118
+
119
+ def tailwind?
120
+ ::Rails.application.config.generators.options[:rails][:template_engine] == :tailwindcss ||
121
+ options[:css]&.downcase&.start_with?("tailwind")
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,17 @@
1
+ module Plutonium
2
+ module Auth
3
+ module PublicAccess
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ helper_method :current_user
8
+ end
9
+
10
+ private
11
+
12
+ def current_user
13
+ "Guest"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ module Plutonium
2
+ module Auth
3
+ module Rodauth
4
+ def self.for(name)
5
+ mod = Module.new
6
+ mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ helper_method :current_user
11
+ helper_method :logout_url
12
+ end
13
+
14
+ private
15
+
16
+ def rodauth(name = :#{name})
17
+ super(name)
18
+ end
19
+
20
+ def current_user
21
+ rodauth.rails_account
22
+ end
23
+
24
+ def logout_url
25
+ rodauth.logout_path
26
+ end
27
+
28
+ define_singleton_method(:to_s) { "Plutonium::Auth::Rodauth(:#{name})" }
29
+ define_singleton_method(:inspect) { "Plutonium::Auth::Rodautht(:#{name})" }
30
+ RUBY
31
+ mod
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ module Plutonium
2
+ module Auth
3
+ extend ActiveSupport::Autoload
4
+
5
+ def self.rodauth(name)
6
+ Rodauth.for(name)
7
+ end
8
+
9
+ autoload :Rodauth
10
+ autoload :PublicAccess
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ require "active_support"
2
+
3
+ module Plutonium
4
+ module Config
5
+ mattr_accessor :reload_files
6
+ @@reload_files = defined?(Rails.env) && Rails.env.local?
7
+
8
+ mattr_accessor :cache_discovery
9
+ @@cache_discovery = defined?(Rails.env) && !Rails.env.development?
10
+ end
11
+ end
Binary file
@@ -0,0 +1,46 @@
1
+ module Plutonium
2
+ module Core
3
+ class Action
4
+ RouteOptions = Data.define :action, :method, :options do
5
+ def initialize(action: nil, method: :get, options: {})
6
+ super
7
+ end
8
+ end
9
+
10
+ attr_reader :name, :label, :icon, :route_options, :confirmation, :turbo_frame, :action_class
11
+
12
+ def initialize(name, label: nil, icon: nil, action_class: nil,
13
+ confirmation: nil,
14
+ route_options: nil, turbo_frame: nil,
15
+ collection_action: false, collection_record_action: false, record_action: false, bulk_action: false)
16
+ @name = name
17
+ @icon = icon
18
+ @label = label || name.to_s.humanize
19
+ @route_options = route_options || RouteOptions.new
20
+ @turbo_frame = turbo_frame
21
+ @action_class = action_class
22
+ @confirmation = confirmation
23
+ @collection_action = collection_action
24
+ @collection_record_action = collection_record_action
25
+ @record_action = record_action
26
+ @bulk_action = bulk_action
27
+ end
28
+
29
+ def collection_action?
30
+ @collection_action
31
+ end
32
+
33
+ def collection_record_action?
34
+ @collection_record_action
35
+ end
36
+
37
+ def record_action?
38
+ @record_action
39
+ end
40
+
41
+ def bulk_action?
42
+ @bulk_action
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ class BasicAction < Plutonium::Core::Action
5
+ def initialize(*args, **kwargs)
6
+ kwargs.reverse_merge! action_options
7
+ super(*args, **kwargs)
8
+ end
9
+
10
+ private
11
+
12
+ def action_options = {}
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ class Collection
5
+ delegate_missing_to :@collection
6
+
7
+ def initialize(collection = {})
8
+ @collection = collection
9
+ end
10
+
11
+ def permitted_for(policy)
12
+ Collection.new(@collection.select { |name, action| policy.send :"#{action.name}?" })
13
+ end
14
+
15
+ def collection_actions
16
+ Collection.new(@collection.select { |name, action| action.collection_action? })
17
+ end
18
+
19
+ def collection_record_actions
20
+ Collection.new(@collection.select { |name, action| action.collection_record_action? })
21
+ end
22
+
23
+ def record_actions
24
+ Collection.new(@collection.select { |name, action| action.record_action? })
25
+ end
26
+
27
+ def bulk_actions
28
+ Collection.new(@collection.select { |name, action| action.bulk_action? })
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ class DestroyAction < BasicAction
5
+ private
6
+
7
+ def action_options
8
+ {
9
+ icon: "trash",
10
+ route_options: Plutonium::Core::Action::RouteOptions.new(method: :delete),
11
+ action_class: "danger",
12
+ confirmation: "Are you sure?",
13
+ turbo_frame: "_top",
14
+ collection_record_action: true,
15
+ record_action: true
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ class EditAction < BasicAction
5
+ private
6
+
7
+ def action_options
8
+ {
9
+ icon: "pencil",
10
+ route_options: Plutonium::Core::Action::RouteOptions.new(action: :edit),
11
+ action_class: "warning",
12
+ collection_record_action: true,
13
+ record_action: true
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,64 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ class InteractiveAction < Plutonium::Core::Action
5
+ include Plutonium::Core::Definers::InputDefiner
6
+
7
+ Context = Data.define :resource_class
8
+
9
+ attr_reader :interaction, :inline, :inputs
10
+
11
+ def initialize(name, *args, interaction:, **kwargs)
12
+ set_interaction interaction
13
+
14
+ kwargs[:route_options] ||= build_route_options name
15
+ kwargs.reverse_merge! action_options
16
+ super(name, *args, **kwargs)
17
+ end
18
+
19
+ def confirmation
20
+ super || (inline ? "#{label}?" : nil)
21
+ end
22
+
23
+ private
24
+
25
+ def resource_class = interaction
26
+
27
+ def action_options
28
+ {
29
+ # TODO: move these into config
30
+ collection_action: [:interactive_resource_collection_action,
31
+ :interactive_resource_recordless_action].include?(action_type),
32
+ collection_record_action: action_type == :interactive_resource_record_action,
33
+ record_action: action_type == :interactive_resource_record_action,
34
+ bulk_action: action_type == :interactive_resource_collection_action
35
+ }
36
+ end
37
+
38
+ def set_interaction(interaction)
39
+ @interaction = interaction
40
+ @inputs = defined_inputs_for(interaction.filters.keys - [:resource, :resources])
41
+ @inline = @inputs.blank? unless inline == false
42
+ end
43
+
44
+ def build_route_options(name)
45
+ method = inline ? :post : :get
46
+ action = action_type
47
+ options = {interactive_action: name}
48
+
49
+ RouteOptions.new action:, method:, options:
50
+ end
51
+
52
+ def action_type
53
+ if interaction.filters.key? :resource
54
+ :interactive_resource_record_action
55
+ elsif interaction.filters.key? :resources
56
+ :interactive_resource_collection_action
57
+ else
58
+ :interactive_resource_recordless_action
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,18 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ class NewAction < BasicAction
5
+ private
6
+
7
+ def action_options
8
+ {
9
+ icon: "plus-lg",
10
+ route_options: Plutonium::Core::Action::RouteOptions.new(action: :new),
11
+ action_class: "primary",
12
+ collection_action: true
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ class ShowAction < BasicAction
5
+ private
6
+
7
+ def action_options
8
+ {
9
+ icon: "box-arrow-up-right",
10
+ action_class: "primary",
11
+ collection_record_action: true
12
+ }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Plutonium
2
+ module Core
3
+ module Actions
4
+ extend ActiveSupport::Autoload
5
+
6
+ eager_autoload do
7
+ autoload :BasicAction
8
+ autoload :Collection
9
+ autoload :NewAction
10
+ autoload :DestroyAction
11
+ autoload :EditAction
12
+ autoload :InteractiveAction
13
+ autoload :ShowAction
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,121 @@
1
+ module Plutonium
2
+ module Core
3
+ module AppController
4
+ extend ActiveSupport::Concern
5
+ include Plutonium::Core::Controllers::EntityScoping
6
+
7
+ included do
8
+ helper_method :current_parent
9
+ helper_method :adapt_route_args
10
+ end
11
+
12
+ private
13
+
14
+ def resource_presenter(resource_class)
15
+ presenter_class = "#{current_package}::#{resource_class}Presenter".constantize
16
+ presenter_class.new resource_context
17
+ end
18
+
19
+ def policy_namespace(scope)
20
+ [current_package.to_s.underscore.to_sym, scope]
21
+ end
22
+
23
+ # Menu Builder
24
+ def build_namespace_node(namespaces, resource, parent)
25
+ current = namespaces.shift
26
+ if namespaces.size.zero?
27
+ parent[current.pluralize] = url_for(adapt_route_args(resource, use_parent: false))
28
+ else
29
+ parent[current] = {}
30
+ build_namespace_node(namespaces, resource, parent[current])
31
+ end
32
+ # parent.sort!
33
+ end
34
+
35
+ def build_namespace_tree(resources)
36
+ root = {}
37
+ resources.each do |resource|
38
+ namespaces = resource.name.split("::")
39
+ build_namespace_node(namespaces, resource, root)
40
+ end
41
+ root
42
+ end
43
+
44
+ def build_sidebar_menu
45
+ build_namespace_tree(current_engine.resource_register)
46
+ end
47
+
48
+ # Menu Builder
49
+
50
+ def current_parent
51
+ return unless parent_route_param.present?
52
+
53
+ @current_parent ||= begin
54
+ parent_route_key = parent_route_param.to_s.gsub(/_id$/, "").to_sym
55
+ parent_class = current_engine.registered_resource_route_key_lookup[parent_route_key]
56
+ parent_scope = parent_class.from_path_param(params[parent_route_param])
57
+ parent_scope = parent_scope.associated_with(current_scoped_entity) if scoped_to_entity?
58
+ parent_scope.first!
59
+ end
60
+ end
61
+
62
+ def parent_route_param
63
+ @parent_route_param ||= request.path_parameters.keys.reverse.find { |key| /_id$/.match? key }
64
+ end
65
+
66
+ #
67
+ # Returns the attribute on the resource if there is a current parent and the resource has a belongs to association to it
68
+ #
69
+ def parent_input_param
70
+ return unless current_parent.present?
71
+
72
+ resource_class.reflect_on_all_associations(:belongs_to).find { |assoc| assoc.klass == current_parent.class }&.name&.to_sym
73
+ end
74
+
75
+ #
76
+ # Returns a dynamic list of args to be used with `url_for` which considers the route namespace and nesting.
77
+ # The current entity and parent record (for nested routes) are inserted appropriately, ensuring that generated urls
78
+ # obey the current routing.
79
+ #
80
+ # e.g. of route helpers that will be invoked given the output of this method
81
+ #
82
+ # - when invoked in a root route (/acme/dashboard/users)
83
+ #
84
+ # `adapt_route_args User` => `entity_users_*`
85
+ # `adapt_route_args @user` => `entity_user_*`
86
+ # `adapt_route_args @user, action: :edit` => `edit_entity_user_*`
87
+ # `adapt_route_args @user, Post => `entity_user_posts_*`
88
+ #
89
+ # - when invoked in a nested route (/acme/dashboard/users/1/post/1)
90
+ #
91
+ # `adapt_route_args Post` => `entity_user_posts_*`
92
+ # `adapt_route_args @post` => `entity_user_post_*`
93
+ # `adapt_route_args @post, action: :edit` => `edit_entity_user_post_*`
94
+ #
95
+ # @param [Class, ApplicationRecord] *args arguments you would normally pass to `url_for`
96
+ # @param [Symbol] action optional action to invoke e.g. :new, :edit
97
+ #
98
+ # @return [Array[Class, ApplicationRecord, Symbol]] args to pass to `url_for`
99
+ #
100
+ def adapt_route_args(*args, action: nil, use_parent: true, **kwargs)
101
+ # If the last item is a class and the action is :new e.g. `adapt_route_args User, action: :new`,
102
+ # it must be converted into a symbol to generate the appropriate helper i.e `new_user_*`
103
+ # to match the url helper generated by `resources :users`
104
+ resource = args.pop
105
+ resource = resource.model_name.singular_route_key.to_sym if action == :new && resource.is_a?(Class)
106
+ args.push resource
107
+
108
+ parent = use_parent ? current_parent : nil
109
+
110
+ base_args = if scoped_to_entity?
111
+ [action, current_scoped_entity.becomes(scoped_entity_class), parent]
112
+ else
113
+ [action, parent]
114
+ end
115
+
116
+ # rails compacts this list. no need to handle nils
117
+ base_args + args + [**kwargs]
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,15 @@
1
+ module Plutonium
2
+ module Core
3
+ module Autodiscovery
4
+ module Discoverer
5
+ extend ActiveSupport::Concern
6
+
7
+ private
8
+
9
+ def resource_class
10
+ raise NotImplementedError, "#{self.class}#resource_class"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end