plutonium 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.standard.yml +4 -0
- data/.vscode/extensions.json +15 -0
- data/.vscode/launch.json +7 -0
- data/.vscode/settings.json +35 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README copy.md +84 -0
- data/README.md +67 -0
- data/Rakefile +8 -0
- data/app/views/layouts/resource.html.erb +43 -0
- data/app/views/resource/_color_modes.html.erb +55 -0
- data/app/views/resource/_details.html.erb +6 -0
- data/app/views/resource/_empty_card.html.erb +12 -0
- data/app/views/resource/_flash.html.erb +9 -0
- data/app/views/resource/_form.html.erb +32 -0
- data/app/views/resource/_header.html.erb +8 -0
- data/app/views/resource/_interactive_resource_action_form.html.erb +67 -0
- data/app/views/resource/_messages.html.erb +1 -0
- data/app/views/resource/_metric_card.html.erb +16 -0
- data/app/views/resource/_nav_user.html.erb +4 -0
- data/app/views/resource/_pagination.html.erb +6 -0
- data/app/views/resource/_pagy_pagination.html.erb +15 -0
- data/app/views/resource/_resource.html.erb +1 -0
- data/app/views/resource/_resource.rabl +5 -0
- data/app/views/resource/_sidebar.html.erb +11 -0
- data/app/views/resource/_sidebar_menu.html.erb +1 -0
- data/app/views/resource/_tab_menu.html.erb +13 -0
- data/app/views/resource/_table.html.erb +78 -0
- data/app/views/resource/_table_actions.html.erb +15 -0
- data/app/views/resource/_toast.html.erb +26 -0
- data/app/views/resource/_toolbar.html.erb +22 -0
- data/app/views/resource/_toolbar_actions.html.erb +16 -0
- data/app/views/resource/_toolbar_breadcrumbs.html.erb +32 -0
- data/app/views/resource/_toolbar_search_input.erb +27 -0
- data/app/views/resource/edit.html.erb +10 -0
- data/app/views/resource/errors.rabl +3 -0
- data/app/views/resource/index.html.erb +19 -0
- data/app/views/resource/index.rabl +3 -0
- data/app/views/resource/interactive_resource_collection_action.html.erb +11 -0
- data/app/views/resource/interactive_resource_record_action.html.erb +11 -0
- data/app/views/resource/interactive_resource_recordless_action.html.erb +11 -0
- data/app/views/resource/new.html.erb +11 -0
- data/app/views/resource/readme.md +16 -0
- data/app/views/resource/show.html.erb +14 -0
- data/app/views/resource/show.rabl +3 -0
- data/brakeman.ignore +51 -0
- data/lib/active_model/validations/array_validator.rb +74 -0
- data/lib/active_model/validations/attached_validator.rb +17 -0
- data/lib/active_model/validations/url_validator.rb +51 -0
- data/lib/generators/pu/core/install/install_generator.rb +43 -0
- data/lib/generators/pu/core/install/templates/.keep +0 -0
- data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/interactions/resource_interaction.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +5 -0
- data/lib/generators/pu/core/install/templates/app/policies/resource_policy.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +2 -0
- data/lib/generators/pu/core/install/templates/config/packages.rb +3 -0
- data/lib/generators/pu/gem/pagy/pagy_generator.rb +25 -0
- data/lib/generators/pu/gem/pagy/templates/.keep +0 -0
- data/lib/generators/pu/gem/pagy/templates/config/initializers/pagy.rb +4 -0
- data/lib/generators/pu/gem/rabl/rabl_generator.rb +25 -0
- data/lib/generators/pu/gem/rabl/templates/.keep +0 -0
- data/lib/generators/pu/gem/rabl/templates/config/initializers/rabl.rb +60 -0
- data/lib/generators/pu/gem/simple_form/simple_form_generator.rb +25 -0
- data/lib/generators/pu/gem/simple_form/templates/.keep +0 -0
- data/lib/generators/pu/gen/pug/pug_generator.rb +43 -0
- data/lib/generators/pu/gen/pug/templates/pug.rb.tt +23 -0
- data/lib/generators/pu/pkg/app/app_generator.rb +60 -0
- data/lib/generators/pu/pkg/app/templates/app/controllers/resource_controller.rb.tt +26 -0
- data/lib/generators/pu/pkg/app/templates/app/interactions/resource_interaction.rb.tt +4 -0
- data/lib/generators/pu/pkg/app/templates/app/policies/resource_policy.rb.tt +4 -0
- data/lib/generators/pu/pkg/app/templates/app/presenters/resource_presenter.rb.tt +4 -0
- data/lib/generators/pu/pkg/app/templates/config/routes.rb.tt +17 -0
- data/lib/generators/pu/pkg/app/templates/lib/engine.rb.tt +14 -0
- data/lib/generators/pu/pkg/feature/feature_generator.rb +44 -0
- data/lib/generators/pu/pkg/feature/templates/.keep +0 -0
- data/lib/generators/pu/pkg/feature/templates/app/controllers/resource_controller.rb.tt +7 -0
- data/lib/generators/pu/pkg/feature/templates/app/interactions/resource_interaction.rb.tt +4 -0
- data/lib/generators/pu/pkg/feature/templates/app/models/resource_record.rb.tt +5 -0
- data/lib/generators/pu/pkg/feature/templates/app/policies/resource_policy.rb.tt +4 -0
- data/lib/generators/pu/pkg/feature/templates/app/presenters/resource_presenter.rb.tt +4 -0
- data/lib/generators/pu/pkg/feature/templates/lib/engine.rb.tt +8 -0
- data/lib/generators/pu/resource/conn/conn_generator.rb +54 -0
- data/lib/generators/pu/resource/conn/templates/.keep +0 -0
- data/lib/generators/pu/resource/conn/templates/app/controllers/resource_controller.rb.tt +3 -0
- data/lib/generators/pu/resource/conn/templates/app/policies/resource_policy.rb.tt +3 -0
- data/lib/generators/pu/resource/conn/templates/app/presenters/resource_presenter.rb.tt +3 -0
- data/lib/generators/pu/resource/model/USAGE +113 -0
- data/lib/generators/pu/resource/model/model_generator.rb +163 -0
- data/lib/generators/pu/resource/model/templates/controller.rb.tt +5 -0
- data/lib/generators/pu/resource/model/templates/create_table_migration.rb.tt +26 -0
- data/lib/generators/pu/resource/model/templates/model.rb.tt +53 -0
- data/lib/generators/pu/resource/model/templates/module.rb.tt +7 -0
- data/lib/generators/pu/resource/model/templates/policy.rb.tt +4 -0
- data/lib/generators/pu/resource/model/templates/presenter.rb.tt +4 -0
- data/lib/generators/pu/resource/scaffold/scaffold_generator.rb +219 -0
- data/lib/generators/pu/resource/scaffold/templates/app/controllers/admin_resources/resource_controller.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/controllers/entity_resources/resource_controller.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/admin/resource_policy.rb.tt +22 -0
- data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/entity/resource_policy.rb.tt +22 -0
- data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/resource_policy.rb.tt +13 -0
- data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/admin_presenter.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/entity_presenter.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/presenter.rb.tt +23 -0
- data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.html.erb.tt +3 -0
- data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.rabl +7 -0
- data/lib/generators/pu/rodauth/account_generator.rb +120 -0
- data/lib/generators/pu/rodauth/concerns/account_selector.rb +22 -0
- data/lib/generators/pu/rodauth/concerns/configuration.rb +211 -0
- data/lib/generators/pu/rodauth/concerns/feature_selector.rb +125 -0
- data/lib/generators/pu/rodauth/install_generator.rb +69 -0
- data/lib/generators/pu/rodauth/migration/active_record/account_expiration.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/active_sessions.erb +7 -0
- data/lib/generators/pu/rodauth/migration/active_record/audit_logging.erb +16 -0
- data/lib/generators/pu/rodauth/migration/active_record/base.erb +22 -0
- data/lib/generators/pu/rodauth/migration/active_record/disallow_password_reuse.erb +5 -0
- data/lib/generators/pu/rodauth/migration/active_record/email_auth.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/jwt_refresh.erb +7 -0
- data/lib/generators/pu/rodauth/migration/active_record/lockout.erb +13 -0
- data/lib/generators/pu/rodauth/migration/active_record/otp.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/password_expiration.erb +6 -0
- data/lib/generators/pu/rodauth/migration/active_record/recovery_codes.erb +6 -0
- data/lib/generators/pu/rodauth/migration/active_record/remember.erb +7 -0
- data/lib/generators/pu/rodauth/migration/active_record/reset_password.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/separate_passwords.erb +5 -0
- data/lib/generators/pu/rodauth/migration/active_record/single_session.erb +6 -0
- data/lib/generators/pu/rodauth/migration/active_record/sms_codes.erb +9 -0
- data/lib/generators/pu/rodauth/migration/active_record/verify_account.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/verify_login_change.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/webauthn.erb +13 -0
- data/lib/generators/pu/rodauth/migration/sequel/account_expiration.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/active_sessions.erb +8 -0
- data/lib/generators/pu/rodauth/migration/sequel/audit_logging.erb +17 -0
- data/lib/generators/pu/rodauth/migration/sequel/base.erb +25 -0
- data/lib/generators/pu/rodauth/migration/sequel/disallow_password_reuse.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/email_auth.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/jwt_refresh.erb +8 -0
- data/lib/generators/pu/rodauth/migration/sequel/lockout.erb +11 -0
- data/lib/generators/pu/rodauth/migration/sequel/otp.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/password_expiration.erb +5 -0
- data/lib/generators/pu/rodauth/migration/sequel/recovery_codes.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/remember.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/reset_password.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/separate_passwords.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/single_session.erb +5 -0
- data/lib/generators/pu/rodauth/migration/sequel/sms_codes.erb +8 -0
- data/lib/generators/pu/rodauth/migration/sequel/verify_account.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/verify_login_change.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/webauthn.erb +13 -0
- data/lib/generators/pu/rodauth/migration_generator.rb +190 -0
- data/lib/generators/pu/rodauth/templates/INSTRUCTIONS +52 -0
- data/lib/generators/pu/rodauth/templates/app/controllers/plugin_controller.rb.tt +6 -0
- data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +3 -0
- data/lib/generators/pu/rodauth/templates/app/mailers/account_mailer.rb.tt +4 -0
- data/lib/generators/pu/rodauth/templates/app/mailers/rodauth_mailer.rb.tt +62 -0
- data/lib/generators/pu/rodauth/templates/app/misc/account_rodauth_plugin.rb.tt +255 -0
- data/lib/generators/pu/rodauth/templates/app/misc/rodauth_app.rb.tt +24 -0
- data/lib/generators/pu/rodauth/templates/app/misc/rodauth_plugin.rb.tt +234 -0
- data/lib/generators/pu/rodauth/templates/app/models/account.rb.tt +40 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/_email_auth_request_form.html.erb +7 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form.html.erb +26 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form_footer.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/add_recovery_codes.html.erb +6 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_login.html.erb +27 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_password.html.erb +27 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/close_account.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/confirm_password.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/create_account.html.erb +35 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/email_auth.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/login.html.erb +4 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/logout.html.erb +14 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/multi_phase_login.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_auth.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_disable.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_setup.html.erb +41 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_auth.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_codes.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/remember.html.erb +22 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password.html.erb +19 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password_request.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_auth.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_confirm.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_disable.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_request.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_setup.html.erb +23 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_email_auth_request_form.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form.html.erb +24 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form_footer.html.erb +7 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/add_recovery_codes.html.erb +16 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_login.html.erb +25 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_password.html.erb +25 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/close_account.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/confirm_password.html.erb +19 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/create_account.html.erb +33 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/email_auth.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/login.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/logout.html.erb +10 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/multi_phase_login.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_auth.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_disable.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_setup.html.erb +32 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_auth.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_codes.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/remember.html.erb +18 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password_request.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_auth.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_confirm.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_disable.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_request.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_setup.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_auth.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_disable.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_manage.html.erb +26 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account_request.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account.html.erb +19 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account_resend.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_login_change.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_auth.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_autofill.html.erb +10 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_remove.html.erb +21 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_setup.html.erb +21 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_auth.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_disable.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_manage.html.erb +22 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account_request.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account.html.erb +21 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account_resend.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_login_change.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_auth.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_autofill.html.erb +10 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_remove.html.erb +23 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_setup.html.erb +23 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/email_auth.text.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/password_changed.text.erb +2 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password.text.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password_notify.text.erb +2 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_account.text.erb +4 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_login_change.text.erb +10 -0
- data/lib/generators/pu/rodauth/templates/config/initializers/rodauth.rb.tt +3 -0
- data/lib/generators/pu/rodauth/templates/db/migrate/create_rodauth.rb.tt +13 -0
- data/lib/generators/pu/rodauth/views_generator.rb +125 -0
- data/lib/plutonium/auth/public_access.rb +17 -0
- data/lib/plutonium/auth/rodauth.rb +35 -0
- data/lib/plutonium/auth.rb +12 -0
- data/lib/plutonium/config.rb +11 -0
- data/lib/plutonium/core/.DS_Store +0 -0
- data/lib/plutonium/core/action.rb +46 -0
- data/lib/plutonium/core/actions/basic_action.rb +16 -0
- data/lib/plutonium/core/actions/collection.rb +33 -0
- data/lib/plutonium/core/actions/destroy_action.rb +21 -0
- data/lib/plutonium/core/actions/edit_action.rb +19 -0
- data/lib/plutonium/core/actions/interactive_action.rb +64 -0
- data/lib/plutonium/core/actions/new_action.rb +18 -0
- data/lib/plutonium/core/actions/show_action.rb +17 -0
- data/lib/plutonium/core/actions.rb +17 -0
- data/lib/plutonium/core/app_controller.rb +121 -0
- data/lib/plutonium/core/autodiscovery/discoverer.rb +15 -0
- data/lib/plutonium/core/autodiscovery/input_discoverer.rb +33 -0
- data/lib/plutonium/core/autodiscovery/renderer_discoverer.rb +33 -0
- data/lib/plutonium/core/autodiscovery.rb +13 -0
- data/lib/plutonium/core/controllers/authorizable.rb +56 -0
- data/lib/plutonium/core/controllers/bootable.rb +44 -0
- data/lib/plutonium/core/controllers/crud_actions.rb +128 -0
- data/lib/plutonium/core/controllers/entity_scoping.rb +69 -0
- data/lib/plutonium/core/controllers/interactive_actions.rb +210 -0
- data/lib/plutonium/core/controllers/presentable.rb +59 -0
- data/lib/plutonium/core/controllers.rb +16 -0
- data/lib/plutonium/core/definers/action_definer.rb +25 -0
- data/lib/plutonium/core/definers/field_definer.rb +19 -0
- data/lib/plutonium/core/definers/input_definer.rb +37 -0
- data/lib/plutonium/core/definers/renderer_definer.rb +35 -0
- data/lib/plutonium/core/definers.rb +14 -0
- data/lib/plutonium/core/fields/inputs/association_input.rb +26 -0
- data/lib/plutonium/core/fields/inputs/basic_input.rb +42 -0
- data/lib/plutonium/core/fields/inputs/belongs_to_input.rb +15 -0
- data/lib/plutonium/core/fields/inputs/factory.rb +58 -0
- data/lib/plutonium/core/fields/inputs/has_many_input.rb +15 -0
- data/lib/plutonium/core/fields/inputs/noop_input.rb +19 -0
- data/lib/plutonium/core/fields/inputs.rb +18 -0
- data/lib/plutonium/core/fields/renderers/association_renderer.rb +25 -0
- data/lib/plutonium/core/fields/renderers/basic_renderer.rb +27 -0
- data/lib/plutonium/core/fields/renderers/factory.rb +52 -0
- data/lib/plutonium/core/fields/renderers.rb +15 -0
- data/lib/plutonium/core/fields.rb +12 -0
- data/lib/plutonium/core/ui/collection.rb +14 -0
- data/lib/plutonium/core/ui/detail.rb +11 -0
- data/lib/plutonium/core/ui/form.rb +11 -0
- data/lib/plutonium/core/ui.rb +13 -0
- data/lib/plutonium/core.rb +16 -0
- data/lib/plutonium/helpers/action_buttons_helper.rb +32 -0
- data/lib/plutonium/helpers/application_helper.rb +22 -0
- data/lib/plutonium/helpers/attachment_helper.rb +62 -0
- data/lib/plutonium/helpers/content_helper.rb +66 -0
- data/lib/plutonium/helpers/display_helper.rb +83 -0
- data/lib/plutonium/helpers/form_helper.rb +24 -0
- data/lib/plutonium/helpers/menu_helper.rb +69 -0
- data/lib/plutonium/helpers/pagination_helper.rb +9 -0
- data/lib/plutonium/helpers/turbo_helper.rb +13 -0
- data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +9 -0
- data/lib/plutonium/helpers.rb +31 -0
- data/lib/plutonium/initializers/TODO +2 -0
- data/lib/plutonium/initializers/pagy.rb +5 -0
- data/lib/plutonium/initializers/patches.rb +2 -0
- data/lib/plutonium/initializers/rabl.rb +60 -0
- data/lib/plutonium/initializers/simple_form.rb +405 -0
- data/lib/plutonium/lib/after_commit.rb +34 -0
- data/lib/plutonium/lib/bit_flags.rb +36 -0
- data/lib/plutonium/packaging/app.rb +125 -0
- data/lib/plutonium/packaging/feature.rb +18 -0
- data/lib/plutonium/packaging/package.rb +22 -0
- data/lib/plutonium/packaging.rb +9 -0
- data/lib/plutonium/policy/initializer.rb +22 -0
- data/lib/plutonium/policy/scope.rb +19 -0
- data/lib/plutonium/policy.rb +8 -0
- data/lib/plutonium/preserved__/field.rb +65 -0
- data/lib/plutonium/preserved__/input.rb +93 -0
- data/lib/plutonium/reactor/core.rb +61 -0
- data/lib/plutonium/reactor/resource_context.rb +15 -0
- data/lib/plutonium/reactor/resource_controller.rb +108 -0
- data/lib/plutonium/reactor/resource_interaction.rb +8 -0
- data/lib/plutonium/reactor/resource_policy.rb +105 -0
- data/lib/plutonium/reactor/resource_presenter.rb +42 -0
- data/lib/plutonium/reactor/resource_record.rb +123 -0
- data/lib/plutonium/reactor.rb +13 -0
- data/lib/plutonium/refinements/parameter_refinements.rb +26 -0
- data/lib/plutonium/simple_form_components/attachment_component.rb +77 -0
- data/lib/plutonium/simple_form_components/input_group_component.rb +14 -0
- data/lib/plutonium/version.rb +3 -0
- data/lib/plutonium.rb +31 -0
- data/plutonium.gemspec +47 -0
- data/public/.keep +0 -0
- data/public/plutonium-assets/application.css +24280 -0
- data/public/plutonium-assets/application.js +31420 -0
- data/public/plutonium-assets/fonts/bootstrap-icons.woff +0 -0
- data/public/plutonium-assets/fonts/bootstrap-icons.woff2 +0 -0
- data/public/plutonium-assets/logo.png +0 -0
- data/sig/plutonium.rbs +4 -0
- metadata +519 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
return unless defined?(Rodauth::Rails)
|
2
|
+
|
3
|
+
require "rails/generators/base"
|
4
|
+
require "securerandom"
|
5
|
+
|
6
|
+
require "#{__dir__}/concerns/configuration"
|
7
|
+
require "#{__dir__}/concerns/account_selector"
|
8
|
+
require "#{__dir__}/concerns/feature_selector"
|
9
|
+
|
10
|
+
module Pu
|
11
|
+
module Rodauth
|
12
|
+
class AccountGenerator < ::Rails::Generators::Base
|
13
|
+
include Concerns::AccountSelector
|
14
|
+
include Concerns::FeatureSelector
|
15
|
+
|
16
|
+
source_root "#{__dir__}/templates"
|
17
|
+
|
18
|
+
desc "Generate a rodauth-rails account.\n\n" \
|
19
|
+
"Configures a basic set of features as well as migrations, a model, mailer and views."
|
20
|
+
|
21
|
+
def install_dependencies
|
22
|
+
Bundler.with_unbundled_env do
|
23
|
+
run "bundle add jwt" if jwt? || jwt_refresh?
|
24
|
+
run "bundle add rotp" if otp?
|
25
|
+
run "bundle add rqrcode" if otp?
|
26
|
+
run "bundle add webauthn" if webauthn? || webauthn_autofill?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_rodauth_app
|
31
|
+
template "app/misc/account_rodauth_plugin.rb", "app/misc/#{table_prefix}_rodauth_plugin.rb"
|
32
|
+
end
|
33
|
+
|
34
|
+
def configure_rodauth_plugin
|
35
|
+
in_root do
|
36
|
+
plugin_name = indent(
|
37
|
+
"configure ::#{table_prefix.classify}RodauthPlugin#{", :#{table_prefix}" unless primary?}\n", 2
|
38
|
+
)
|
39
|
+
gsub_file "app/misc/rodauth_app.rb", /.*# configure RodauthMain\n/, ""
|
40
|
+
insert_into_file "app/misc/rodauth_app.rb", plugin_name, after: "# auth configuration\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def configure_rodauth_plugin_load_route
|
45
|
+
in_root do
|
46
|
+
route_config = indent("r.rodauth#{"(:#{table_prefix})" unless primary?}\n", 4)
|
47
|
+
gsub_file "app/misc/rodauth_app.rb", /.*# r\.rodauth\n/, ""
|
48
|
+
insert_into_file "app/misc/rodauth_app.rb", route_config, after: "# auth route configuration\n"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def configure_rodauth_plugin_load_memory
|
53
|
+
in_root do
|
54
|
+
plugin_config = indent(
|
55
|
+
"rodauth#{"(:#{table_prefix})" unless primary?}.load_memory # autologin remembered #{table}\n", 4
|
56
|
+
)
|
57
|
+
gsub_file "app/misc/rodauth_app.rb", /.*# rodauth\.load_memory.*\n/, ""
|
58
|
+
|
59
|
+
if remember?
|
60
|
+
insert_into_file "app/misc/rodauth_app.rb", plugin_config, after: "# plugin route configuration\n"
|
61
|
+
else
|
62
|
+
gsub_file "app/misc/rodauth_app.rb", plugin_config, ""
|
63
|
+
in_root do
|
64
|
+
unless File.read("app/misc/rodauth_app.rb").match?(/.*\.load_memory # autologin/)
|
65
|
+
insert_into_file "app/misc/rodauth_app.rb", indent("# rodauth.load_memory # autologin remembered users\n", 4),
|
66
|
+
after: "# plugin route configuration\n"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_rodauth_controller
|
74
|
+
dest = "app/controllers/rodauth/#{table_prefix}_controller.rb"
|
75
|
+
template "app/controllers/plugin_controller.rb", dest
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_rodauth_migration
|
79
|
+
return if selected_migration_features.empty?
|
80
|
+
|
81
|
+
invoke "pu:rodauth:migration", [table], features: selected_migration_features,
|
82
|
+
name: kitchen_sink? ? "rodauth_kitchen_sink" : nil,
|
83
|
+
migration_name: options[:migration_name],
|
84
|
+
force: options[:force],
|
85
|
+
skip: options[:skip]
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_account_model
|
89
|
+
return unless base?
|
90
|
+
|
91
|
+
template "app/models/account.rb", "app/models/#{table_prefix}.rb"
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_mailer
|
95
|
+
return unless mails?
|
96
|
+
|
97
|
+
template "app/mailers/rodauth_mailer.rb", "app/mailers/rodauth_mailer.rb"
|
98
|
+
template "app/mailers/account_mailer.rb", "app/mailers/rodauth/#{table_prefix}_mailer.rb"
|
99
|
+
directory "app/views/rodauth_mailer", "app/views/rodauth/#{table_prefix}_mailer"
|
100
|
+
end
|
101
|
+
|
102
|
+
def create_views
|
103
|
+
return if only_json? || selected_view_features.empty?
|
104
|
+
|
105
|
+
account_name = primary? ? nil : table_prefix
|
106
|
+
# Use generate here because invoke spawns in the same process
|
107
|
+
# Unfortunately, during the generation process, some new files are created which are not currently loaded,
|
108
|
+
# causing an error when it attempts to load the rodauth config.
|
109
|
+
# Generate spawns a separate process which loads the new files and ensures it works correctly
|
110
|
+
generate "pu:rodauth:views", account_name, "--features", *selected_view_features
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def only_json?
|
116
|
+
::Rails.application.config.api_only || !::Rails.application.config.session_store || options[:api_only]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Pu
|
2
|
+
module Rodauth
|
3
|
+
module Concerns
|
4
|
+
module AccountSelector
|
5
|
+
def self.included(base)
|
6
|
+
base.send :argument, :account_name, type: :string, desc: "name of the account model. "
|
7
|
+
base.send :class_option, :migration_name, type: :string, desc: "[CONFIG] name of the generated migration file"
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def table
|
13
|
+
@table ||= account_name.underscore.pluralize
|
14
|
+
end
|
15
|
+
|
16
|
+
def table_prefix
|
17
|
+
@table_prefix ||= account_name.underscore.singularize
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
module Pu
|
2
|
+
module Rodauth
|
3
|
+
module Concerns
|
4
|
+
module Configuration
|
5
|
+
# Configuration map for the supported plugins
|
6
|
+
# key: plugin name
|
7
|
+
# value: hash that can contain the following keys
|
8
|
+
# feature(bool) => enabled in the account plugin when selected. default: true.
|
9
|
+
# default(bool) => enable this plugin by default
|
10
|
+
# desc(string) => description for this plugin to be displayed in the cli help notes
|
11
|
+
# migrations(Hash) => map of table override setter to table name.
|
12
|
+
# table name can contain the format strings: %{plural} and %{singluar}
|
13
|
+
# views(array) => a list of views to generate
|
14
|
+
CONFIGURATION = {
|
15
|
+
base: {
|
16
|
+
default: true,
|
17
|
+
feature: false,
|
18
|
+
desc: "[CONFIG] create account table and model",
|
19
|
+
migrations: {
|
20
|
+
accounts_table: "%<plural>s"
|
21
|
+
}
|
22
|
+
},
|
23
|
+
two_factor_base: {
|
24
|
+
default: true,
|
25
|
+
feature: false,
|
26
|
+
desc: "[CONFIG] setup dependencies for 2fa",
|
27
|
+
views: %w[two_factor_manage two_factor_auth two_factor_disable]
|
28
|
+
},
|
29
|
+
separate_passwords: {
|
30
|
+
feature: false,
|
31
|
+
desc: "[CONFIG] use a separate table for password hashes",
|
32
|
+
migrations: {
|
33
|
+
password_hash_table: "%<singular>s_password_hashes"
|
34
|
+
}
|
35
|
+
},
|
36
|
+
login: {
|
37
|
+
default: true,
|
38
|
+
views: %w[_login_form _login_form_footer login multi_phase_login]
|
39
|
+
},
|
40
|
+
remember: {
|
41
|
+
default: true,
|
42
|
+
views: %w[remember],
|
43
|
+
migrations: {
|
44
|
+
remember_table: "%<singular>s_remember_keys"
|
45
|
+
}
|
46
|
+
},
|
47
|
+
logout: {
|
48
|
+
default: true,
|
49
|
+
views: %w[logout]
|
50
|
+
},
|
51
|
+
create_account: {
|
52
|
+
default: true,
|
53
|
+
views: %w[create_account]
|
54
|
+
},
|
55
|
+
verify_account: {
|
56
|
+
default: true,
|
57
|
+
views: %w[verify_account_resend verify_account],
|
58
|
+
migrations: {
|
59
|
+
verify_account_table: "%<singular>s_verification_keys"
|
60
|
+
}
|
61
|
+
},
|
62
|
+
verify_account_grace_period: {default: true},
|
63
|
+
close_account: {
|
64
|
+
views: %w[close_account]
|
65
|
+
},
|
66
|
+
reset_password: {
|
67
|
+
default: true,
|
68
|
+
views: %w[reset_password_request reset_password],
|
69
|
+
migrations: {
|
70
|
+
reset_password_table: "%<singular>s_password_reset_keys"
|
71
|
+
}
|
72
|
+
},
|
73
|
+
reset_password_notify: {default: true},
|
74
|
+
change_login: {
|
75
|
+
default: true,
|
76
|
+
views: %w[change_login]
|
77
|
+
},
|
78
|
+
verify_login_change: {
|
79
|
+
default: true,
|
80
|
+
views: %w[verify_login_change],
|
81
|
+
migrations: {
|
82
|
+
verify_login_change_table: "%<singular>s_login_change_keys"
|
83
|
+
}
|
84
|
+
},
|
85
|
+
change_password: {
|
86
|
+
default: true,
|
87
|
+
views: %w[change_password]
|
88
|
+
},
|
89
|
+
change_password_notify: {
|
90
|
+
default: true
|
91
|
+
},
|
92
|
+
email_auth: {
|
93
|
+
views: %w[_email_auth_request_form email_auth],
|
94
|
+
migrations: {
|
95
|
+
email_auth_table: "%<singular>s_email_auth_keys"
|
96
|
+
}
|
97
|
+
},
|
98
|
+
otp: {
|
99
|
+
views: %w[otp_setup otp_auth otp_disable],
|
100
|
+
migrations: {
|
101
|
+
otp_keys_table: "%<singular>s_otp_keys"
|
102
|
+
}
|
103
|
+
},
|
104
|
+
sms_codes: {
|
105
|
+
views: %w[sms_setup sms_confirm sms_auth sms_request sms_disable],
|
106
|
+
migrations: {
|
107
|
+
sms_codes_table: "%<singular>s_sms_codes"
|
108
|
+
}
|
109
|
+
},
|
110
|
+
recovery_codes: {
|
111
|
+
views: %w[recovery_codes add_recovery_codes recovery_auth],
|
112
|
+
migrations: {
|
113
|
+
recovery_codes_table: "%<singular>s_recovery_codes"
|
114
|
+
}
|
115
|
+
},
|
116
|
+
webauthn: {
|
117
|
+
views: %w[webauthn_setup webauthn_auth webauthn_remove],
|
118
|
+
migrations: {
|
119
|
+
webauthn_keys_table: "%<singular>s_webauthn_keys",
|
120
|
+
webauthn_user_ids_table: "%<singular>s_webauthn_user_ids",
|
121
|
+
webauthn_keys_account_id_column: "%<singular>s_id"
|
122
|
+
}
|
123
|
+
},
|
124
|
+
webauthn_autofill: {
|
125
|
+
views: %w[webauthn_autofill]
|
126
|
+
},
|
127
|
+
lockout: {
|
128
|
+
views: %w[unlock_account_request unlock_account],
|
129
|
+
migrations: {
|
130
|
+
account_login_failures_table: "%<singular>s_login_failures",
|
131
|
+
account_lockouts_table: "%<singular>s_lockouts"
|
132
|
+
}
|
133
|
+
},
|
134
|
+
active_sessions: {
|
135
|
+
migrations: {
|
136
|
+
active_sessions_table: "%<singular>s_active_session_keys",
|
137
|
+
active_sessions_account_id_column: "%<singular>s_id"
|
138
|
+
}
|
139
|
+
},
|
140
|
+
account_expiration: {
|
141
|
+
migrations: {
|
142
|
+
account_activity_table: "%<singular>s_activity_times"
|
143
|
+
}
|
144
|
+
},
|
145
|
+
password_expiration: {
|
146
|
+
migrations: {
|
147
|
+
password_expiration_table: "%<singular>s_password_change_times"
|
148
|
+
}
|
149
|
+
},
|
150
|
+
single_session: {
|
151
|
+
migrations: {
|
152
|
+
single_session_table: "%<singular>s_session_keys"
|
153
|
+
}
|
154
|
+
},
|
155
|
+
audit_logging: {
|
156
|
+
migrations: {
|
157
|
+
audit_logging_table: "%<singular>s_authentication_audit_logs",
|
158
|
+
audit_logging_account_id_column: "%<singular>s_id"
|
159
|
+
}
|
160
|
+
},
|
161
|
+
disallow_password_reuse: {
|
162
|
+
migrations: {
|
163
|
+
previous_password_hash_table: "%<singular>s_previous_password_hashes",
|
164
|
+
previous_password_account_id_column: "%<singular>s_id"
|
165
|
+
}
|
166
|
+
},
|
167
|
+
jwt_refresh: {
|
168
|
+
migrations: {
|
169
|
+
jwt_refresh_token_table: "%<singular>s_jwt_refresh_keys",
|
170
|
+
jwt_refresh_token_account_id_column: "%<singular>s_id"
|
171
|
+
}
|
172
|
+
},
|
173
|
+
jwt: {},
|
174
|
+
json: {},
|
175
|
+
internal_request: {default: true}
|
176
|
+
}.freeze
|
177
|
+
|
178
|
+
FEATURE_CONFIG = CONFIGURATION.select { |_k, v| v[:feature] != false }
|
179
|
+
.freeze
|
180
|
+
|
181
|
+
MIGRATION_CONFIG = CONFIGURATION.select { |_k, v| v[:migrations] }
|
182
|
+
.map { |k, v| [k, v[:migrations]] }
|
183
|
+
.to_h
|
184
|
+
.freeze
|
185
|
+
|
186
|
+
VIEW_CONFIG = CONFIGURATION.select { |_k, v| v[:views] }
|
187
|
+
.map { |k, v| [k, v[:views]] }
|
188
|
+
.to_h
|
189
|
+
.freeze
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
def configuration
|
194
|
+
CONFIGURATION
|
195
|
+
end
|
196
|
+
|
197
|
+
def feature_config
|
198
|
+
FEATURE_CONFIG
|
199
|
+
end
|
200
|
+
|
201
|
+
def migration_config
|
202
|
+
MIGRATION_CONFIG
|
203
|
+
end
|
204
|
+
|
205
|
+
def view_config
|
206
|
+
VIEW_CONFIG
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Pu
|
2
|
+
module Rodauth
|
3
|
+
module Concerns
|
4
|
+
module FeatureSelector
|
5
|
+
def self.included(base)
|
6
|
+
base.send :include, Configuration
|
7
|
+
|
8
|
+
base.send :class_option, :primary, type: :boolean,
|
9
|
+
desc: "[CONFIG] generated account is primary"
|
10
|
+
base.send :class_option, :argon2, type: :boolean, default: false,
|
11
|
+
desc: "[CONFIG] use Argon2 for password hashing"
|
12
|
+
base.send :class_option, :mails, type: :boolean, default: true, desc: "[CONFIG] setup mails"
|
13
|
+
base.send :class_option, :api_only, type: :boolean, default: false,
|
14
|
+
desc: "[CONFIG] configure only json api support"
|
15
|
+
|
16
|
+
config_features = {}
|
17
|
+
base::CONFIGURATION.sort.each do |feature, opts|
|
18
|
+
feature = feature.to_sym
|
19
|
+
modifier = "[*]" if opts[:default]
|
20
|
+
default_description = "[FEATURE]#{modifier} #{feature}"
|
21
|
+
description = opts[:desc] || default_description
|
22
|
+
|
23
|
+
base.define_method :"#{feature}?" do
|
24
|
+
feature_selected?(feature)
|
25
|
+
end
|
26
|
+
|
27
|
+
if opts[:feature] != false
|
28
|
+
base.send :class_option, feature, type: :boolean, desc: description
|
29
|
+
else
|
30
|
+
config_features[feature] = description
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
config_features.each do |feature, description|
|
35
|
+
base.send :class_option, feature, type: :boolean, desc: description
|
36
|
+
end
|
37
|
+
|
38
|
+
base.send :class_option, :kitchen_sink, type: :boolean, default: false,
|
39
|
+
desc: "[CONFIG] enable all supported features"
|
40
|
+
base.send :class_option, :defaults, type: :boolean, default: true,
|
41
|
+
desc: "[CONFIG] enable default features (indicated with [*])"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def feature_selected?(feature)
|
47
|
+
return true if kitchen_sink?
|
48
|
+
|
49
|
+
# base is special. so long as it is not explicitly disabled, always allow it through
|
50
|
+
return true if feature == :base && options[:base] != false
|
51
|
+
|
52
|
+
feature_options = configuration[feature]
|
53
|
+
case feature
|
54
|
+
when :json, :jwt
|
55
|
+
return true if only_json?
|
56
|
+
when :remember
|
57
|
+
return false if only_json?
|
58
|
+
end
|
59
|
+
|
60
|
+
return feature_options[:default] if defaults? && options[feature].nil?
|
61
|
+
|
62
|
+
options[feature]
|
63
|
+
end
|
64
|
+
|
65
|
+
# Creates a hash of options to pass down options to an invoked sub generator
|
66
|
+
def invoke_options
|
67
|
+
# These are custom options we want to track.
|
68
|
+
extra_options = %i[primary argon2 mails kitchen_sink defaults]
|
69
|
+
# Append them to all the available options from our configuration
|
70
|
+
valid_options = configuration.keys.map(&:to_sym).concat extra_options
|
71
|
+
# Index map the list with the selection value
|
72
|
+
opts = valid_options.map { |opt| [opt, send(:"#{opt}?")] }.to_h.compact
|
73
|
+
# True only options. We don't care if they are false.
|
74
|
+
%i[api_only force skip pretend quiet].each do |key|
|
75
|
+
next unless options[key]
|
76
|
+
|
77
|
+
opts[key] = options[key]
|
78
|
+
end
|
79
|
+
|
80
|
+
opts
|
81
|
+
end
|
82
|
+
|
83
|
+
def all_selected
|
84
|
+
@all_selected ||= configuration.keys.select { |feature| send(:"#{feature}?") }
|
85
|
+
end
|
86
|
+
|
87
|
+
def selected_features
|
88
|
+
@selected_features ||= (all_selected & feature_config.keys)
|
89
|
+
end
|
90
|
+
|
91
|
+
def selected_migration_features
|
92
|
+
@selected_migration_features ||= (all_selected & migration_config.keys).map(&:to_s)
|
93
|
+
end
|
94
|
+
|
95
|
+
def selected_view_features
|
96
|
+
@selected_view_features ||= (all_selected & view_config.keys).map(&:to_s)
|
97
|
+
end
|
98
|
+
|
99
|
+
def primary?
|
100
|
+
options[:primary]
|
101
|
+
end
|
102
|
+
|
103
|
+
def argon2?
|
104
|
+
options[:argon2]
|
105
|
+
end
|
106
|
+
|
107
|
+
def mails?
|
108
|
+
defined?(ActionMailer) && options[:mails]
|
109
|
+
end
|
110
|
+
|
111
|
+
def only_json?
|
112
|
+
::Rails.application.config.api_only || !::Rails.application.config.session_store || options[:api_only]
|
113
|
+
end
|
114
|
+
|
115
|
+
def kitchen_sink?
|
116
|
+
options[:kitchen_sink]
|
117
|
+
end
|
118
|
+
|
119
|
+
def defaults?
|
120
|
+
options[:defaults]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "rails/generators/base"
|
2
|
+
require "securerandom"
|
3
|
+
|
4
|
+
module Pu
|
5
|
+
module Rodauth
|
6
|
+
class InstallGenerator < ::Rails::Generators::Base
|
7
|
+
SEQUEL_ADAPTERS = {
|
8
|
+
"postgresql" => (RUBY_ENGINE == "jruby") ? "postgresql" : "postgres",
|
9
|
+
"mysql2" => (RUBY_ENGINE == "jruby") ? "mysql" : "mysql2",
|
10
|
+
"sqlite3" => "sqlite",
|
11
|
+
"oracle_enhanced" => "oracle",
|
12
|
+
"sqlserver" => (RUBY_ENGINE == "jruby") ? "mssql" : "tinytds"
|
13
|
+
}
|
14
|
+
|
15
|
+
source_root "#{__dir__}/templates"
|
16
|
+
|
17
|
+
desc "Install rodauth-rails"
|
18
|
+
|
19
|
+
def add_rodauth
|
20
|
+
Bundler.with_unbundled_env do
|
21
|
+
run "bundle add bcrypt"
|
22
|
+
run "bundle add rodauth-rails"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_rodauth_initializer
|
27
|
+
template "config/initializers/rodauth.rb"
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_rodauth_controller
|
31
|
+
template "app/controllers/rodauth_controller.rb"
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_rodauth_app
|
35
|
+
template "app/misc/rodauth_app.rb"
|
36
|
+
template "app/misc/rodauth_plugin.rb"
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_dev_config
|
40
|
+
insert_into_file "config/environments/development.rb",
|
41
|
+
"\n config.action_mailer.default_url_options = { host: '127.0.0.1', port: ENV.fetch('PORT', 3000) }\n",
|
42
|
+
before: /^end/
|
43
|
+
end
|
44
|
+
|
45
|
+
def show_instructions
|
46
|
+
readme "INSTRUCTIONS" if behavior == :invoke
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def sequel_activerecord_integration?
|
52
|
+
defined?(ActiveRecord::Railtie) &&
|
53
|
+
(!defined?(Sequel) || Sequel::DATABASES.empty?)
|
54
|
+
end
|
55
|
+
|
56
|
+
def sequel_adapter
|
57
|
+
SEQUEL_ADAPTERS[activerecord_adapter] || activerecord_adapter
|
58
|
+
end
|
59
|
+
|
60
|
+
def activerecord_adapter
|
61
|
+
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
62
|
+
ActiveRecord::Base.connection_db_config.adapter
|
63
|
+
else
|
64
|
+
ActiveRecord::Base.connection_config.fetch(:adapter)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the account expiration feature
|
2
|
+
create_table :<%= table_prefix %>_activity_times, id: false do |t|
|
3
|
+
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
|
+
t.datetime :last_activity_at, null: false
|
6
|
+
t.datetime :last_login_at, null: false
|
7
|
+
t.datetime :expired_at
|
8
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the active sessions feature
|
2
|
+
create_table :<%= table_prefix %>_active_session_keys, primary_key: [:<%= table_prefix %>_id, :session_id] do |t|
|
3
|
+
t.references :<%= table_prefix %>, foreign_key: true<%= primary_key_type(:type) %>
|
4
|
+
t.string :session_id
|
5
|
+
t.datetime :created_at, null: false, default: -> { "<%= current_timestamp %>" }
|
6
|
+
t.datetime :last_use, null: false, default: -> { "<%= current_timestamp %>" }
|
7
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Used by the audit logging feature
|
2
|
+
create_table :<%= table_prefix %>_authentication_audit_logs<%= primary_key_type %> do |t|
|
3
|
+
t.references :<%= table_prefix %>, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
+
t.datetime :at, null: false, default: -> { "<%= current_timestamp %>" }
|
5
|
+
t.text :message, null: false
|
6
|
+
<% case activerecord_adapter -%>
|
7
|
+
<% when "postgresql" -%>
|
8
|
+
t.jsonb :metadata
|
9
|
+
<% when "sqlite3", "mysql2", "trilogy" -%>
|
10
|
+
t.json :metadata
|
11
|
+
<% else -%>
|
12
|
+
t.string :metadata
|
13
|
+
<% end -%>
|
14
|
+
t.index [:<%= table_prefix %>_id, :at], name: "audit_<%= table_prefix %>_at_idx"
|
15
|
+
t.index :at, name: "audit_at_idx"
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<% if activerecord_adapter == "postgresql" -%>
|
2
|
+
enable_extension "citext"
|
3
|
+
|
4
|
+
<% end -%>
|
5
|
+
create_table :<%= table_prefix.pluralize %><%= primary_key_type %> do |t|
|
6
|
+
t.integer :status, null: false, default: 1
|
7
|
+
<% case activerecord_adapter -%>
|
8
|
+
<% when "postgresql" -%>
|
9
|
+
t.citext :email, null: false
|
10
|
+
<% else -%>
|
11
|
+
t.string :email, null: false
|
12
|
+
<% end -%>
|
13
|
+
<% case activerecord_adapter -%>
|
14
|
+
<% when "postgresql", "sqlite3" -%>
|
15
|
+
t.index :email, unique: true, where: "status IN (1, 2)"
|
16
|
+
<% else -%>
|
17
|
+
t.index :email, unique: true
|
18
|
+
<% end -%>
|
19
|
+
<% unless separate_passwords? -%>
|
20
|
+
t.string :password_hash
|
21
|
+
<% end -%>
|
22
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the email auth feature
|
2
|
+
create_table :<%= table_prefix %>_email_auth_keys, id: false do |t|
|
3
|
+
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
|
+
t.string :key, null: false
|
6
|
+
t.datetime :deadline, null: false
|
7
|
+
t.datetime :email_last_sent, null: false, default: -> { "<%= current_timestamp %>" }
|
8
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the jwt refresh feature
|
2
|
+
create_table :<%= table_prefix %>_jwt_refresh_keys<%= primary_key_type %> do |t|
|
3
|
+
t.references :<%= table_prefix %>, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :deadline, null: false
|
6
|
+
t.index :<%= table_prefix %>_id, name: "<%= table_prefix %>_jwt_rk_<%= table_prefix %>_id_idx"
|
7
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Used by the lockout feature
|
2
|
+
create_table :<%= table_prefix %>_login_failures, id: false do |t|
|
3
|
+
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
|
+
t.integer :number, null: false, default: 1
|
6
|
+
end
|
7
|
+
create_table :<%= table_prefix %>_lockouts, id: false do |t|
|
8
|
+
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
9
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
10
|
+
t.string :key, null: false
|
11
|
+
t.datetime :deadline, null: false
|
12
|
+
t.datetime :email_last_sent
|
13
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the otp feature
|
2
|
+
create_table :<%= table_prefix %>_otp_keys, id: false do |t|
|
3
|
+
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
|
+
t.string :key, null: false
|
6
|
+
t.integer :num_failures, null: false, default: 0
|
7
|
+
t.datetime :last_use, null: false, default: -> { "<%= current_timestamp %>" }
|
8
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Used by the password expiration feature
|
2
|
+
create_table :<%= table_prefix %>_password_change_times, id: false do |t|
|
3
|
+
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
|
+
t.datetime :changed_at, null: false, default: -> { "<%= current_timestamp %>" }
|
6
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the remember me feature
|
2
|
+
create_table :<%= table_prefix %>_remember_keys, id: false do |t|
|
3
|
+
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
|
+
t.string :key, null: false
|
6
|
+
t.datetime :deadline, null: false
|
7
|
+
end
|