open-loam 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -8
- data/LICENSE +1 -1
- data/README.md +24 -24
- data/app/jobs/{loam → open_loam}/custom_field_reindex_job.rb +6 -6
- data/app/jobs/{loam → open_loam}/event_delivery_job.rb +8 -8
- data/app/jobs/{loam → open_loam}/event_redelivery_sweep_job.rb +4 -4
- data/app/jobs/{loam → open_loam}/webhook_delivery_job.rb +7 -7
- data/app/models/{loam → open_loam}/api_token.rb +7 -7
- data/app/models/{loam → open_loam}/audit_record.rb +3 -3
- data/app/models/{loam → open_loam}/auth_attempt.rb +5 -5
- data/app/models/{loam → open_loam}/business_rule.rb +10 -10
- data/app/models/{loam → open_loam}/business_rule_run.rb +5 -5
- data/app/models/{loam → open_loam}/comment.rb +9 -9
- data/app/models/{loam → open_loam}/config.rb +7 -7
- data/app/models/{loam → open_loam}/custom_field_value.rb +5 -5
- data/app/models/{loam → open_loam}/dashboard_widget.rb +5 -5
- data/app/models/open_loam/dictionary.rb +20 -0
- data/app/models/{loam → open_loam}/dictionary_entry.rb +7 -7
- data/app/models/{loam → open_loam}/event_delivery.rb +4 -4
- data/app/models/{loam → open_loam}/field_definition.rb +8 -8
- data/app/models/{loam → open_loam}/inbound_webhook_delivery.rb +4 -4
- data/app/models/{loam → open_loam}/inbound_webhook_source.rb +13 -13
- data/app/models/{loam → open_loam}/membership.rb +6 -6
- data/app/models/{loam → open_loam}/mfa_credential.rb +8 -8
- data/app/models/{loam → open_loam}/notification.rb +10 -10
- data/app/models/{loam → open_loam}/pending_action.rb +23 -23
- data/app/models/{loam → open_loam}/perspective.rb +5 -5
- data/app/models/{loam → open_loam}/progress_job.rb +7 -7
- data/app/models/{loam → open_loam}/record_lock.rb +5 -5
- data/app/models/{loam → open_loam}/scheduled_job.rb +7 -7
- data/app/models/open_loam/search_token.rb +9 -0
- data/app/models/{loam → open_loam}/sso_identity.rb +4 -4
- data/app/models/{loam → open_loam}/sso_provider.rb +8 -8
- data/app/models/open_loam/tenant.rb +20 -0
- data/app/models/{loam → open_loam}/translation.rb +5 -5
- data/app/models/{loam → open_loam}/webhook_endpoint.rb +6 -6
- data/app/views/{loam → open_loam}/attachments/_attachments.html.erb +1 -1
- data/app/views/{loam → open_loam}/comments/_comments.html.erb +1 -1
- data/app/views/{loam → open_loam}/custom_fields/_fields.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/entity/entity_generator.rb +9 -9
- data/lib/generators/{loam → open_loam}/entity/templates/api_controller.rb +1 -1
- data/lib/generators/{loam → open_loam}/entity/templates/controller.rb +21 -21
- data/lib/generators/{loam → open_loam}/entity/templates/entity_test.rb +12 -12
- data/lib/generators/{loam → open_loam}/entity/templates/migration.rb +5 -5
- data/lib/generators/{loam → open_loam}/entity/templates/model.rb +10 -10
- data/lib/generators/{loam → open_loam}/entity/templates/policy.rb +1 -1
- data/lib/generators/{loam → open_loam}/entity/templates/views/_form.html.erb +4 -4
- data/lib/generators/{loam → open_loam}/entity/templates/views/deleted.html.erb +7 -7
- data/lib/generators/open_loam/entity/templates/views/edit.html.erb +3 -0
- data/lib/generators/open_loam/entity/templates/views/index.html.erb +90 -0
- data/lib/generators/open_loam/entity/templates/views/new.html.erb +3 -0
- data/lib/generators/open_loam/entity/templates/views/show.html.erb +36 -0
- data/lib/generators/{loam → open_loam}/install/install_generator.rb +47 -47
- data/lib/generators/open_loam/install/templates/AGENTS.md +341 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_controller.rb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/api_docs_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/api_tokens_controller.rb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/base_controller.rb +38 -38
- data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_form.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/comments_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/admin/configs_controller.rb +9 -9
- data/lib/generators/open_loam/install/templates/admin/dashboard_controller.rb +10 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_form.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/dictionary_entries_controller.rb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/events_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/features_controller.rb +9 -9
- data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_new.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/history_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/history_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/imports_controller.rb +12 -12
- data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_controller.rb +6 -6
- data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_new.html.erb +2 -2
- data/lib/generators/open_loam/install/templates/admin/layout.html.erb +76 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_controller.rb +6 -6
- data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_controller.rb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_controller.rb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/overrides_index.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_controller.rb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/perspectives_index.html.erb +1 -1
- data/lib/generators/open_loam/install/templates/admin/progress_jobs_controller.rb +19 -0
- data/lib/generators/{loam → open_loam}/install/templates/admin/progress_jobs_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/record_locks_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_form.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/search_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_controller.rb +32 -32
- data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_controller.rb +6 -6
- data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_form.html.erb +2 -2
- data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_controller.rb +5 -5
- data/lib/generators/{loam → open_loam}/install/templates/admin/sudo_new.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin/translations_controller.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/admin/translations_index.html.erb +3 -3
- data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_index.html.erb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/admin.css +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/api_base_controller.rb +15 -15
- data/lib/generators/{loam → open_loam}/install/templates/guardrails_test.rb +17 -17
- data/lib/generators/{loam → open_loam}/install/templates/import_job.rb +7 -7
- data/lib/generators/{loam → open_loam}/install/templates/inbound_webhooks_controller.rb +4 -4
- data/lib/generators/{loam → open_loam}/install/templates/initializer.rb +74 -74
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_api_tokens.rb +15 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_audit_records.rb +14 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_auth_attempts.rb → open_loam/install/templates/migrations/create_open_loam_auth_attempts.rb} +3 -3
- data/lib/generators/{loam/install/templates/migrations/create_loam_business_rules.rb → open_loam/install/templates/migrations/create_open_loam_business_rules.rb} +10 -10
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_comments.rb +13 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_configs.rb → open_loam/install/templates/migrations/create_open_loam_configs.rb} +7 -7
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_custom_field_values.rb +19 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dashboard_widgets.rb +12 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_dictionaries.rb +11 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_dictionary_entries.rb → open_loam/install/templates/migrations/create_open_loam_dictionary_entries.rb} +6 -6
- data/lib/generators/{loam/install/templates/migrations/create_loam_event_deliveries.rb → open_loam/install/templates/migrations/create_open_loam_event_deliveries.rb} +5 -5
- data/lib/generators/{loam/install/templates/migrations/create_loam_field_definitions.rb → open_loam/install/templates/migrations/create_open_loam_field_definitions.rb} +4 -4
- data/lib/generators/{loam/install/templates/migrations/create_loam_inbound_webhooks.rb → open_loam/install/templates/migrations/create_open_loam_inbound_webhooks.rb} +9 -9
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_memberships.rb +11 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_mfa_credentials.rb → open_loam/install/templates/migrations/create_open_loam_mfa_credentials.rb} +4 -4
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_notifications.rb +15 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_pending_actions.rb → open_loam/install/templates/migrations/create_open_loam_pending_actions.rb} +9 -9
- data/lib/generators/{loam/install/templates/migrations/create_loam_perspectives.rb → open_loam/install/templates/migrations/create_open_loam_perspectives.rb} +5 -5
- data/lib/generators/{loam/install/templates/migrations/create_loam_progress_jobs.rb → open_loam/install/templates/migrations/create_open_loam_progress_jobs.rb} +5 -5
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_record_locks.rb +16 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_scheduled_jobs.rb → open_loam/install/templates/migrations/create_open_loam_scheduled_jobs.rb} +5 -5
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_search_tokens.rb +18 -0
- data/lib/generators/{loam/install/templates/migrations/create_loam_sso_providers.rb → open_loam/install/templates/migrations/create_open_loam_sso_providers.rb} +12 -12
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_tenants.rb +9 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_translations.rb +15 -0
- data/lib/generators/open_loam/install/templates/migrations/create_open_loam_webhook_endpoints.rb +13 -0
- data/lib/generators/{loam → open_loam}/install/templates/migrations/create_users.rb +1 -1
- data/lib/generators/{loam → open_loam}/install/templates/user.rb +5 -5
- data/lib/generators/{loam → open_loam}/primary_key_options.rb +23 -23
- data/lib/open-loam.rb +2 -2
- data/lib/{loam → open_loam}/attachable.rb +4 -4
- data/lib/{loam → open_loam}/auditable.rb +23 -23
- data/lib/{loam → open_loam}/auth_throttle.rb +10 -10
- data/lib/{loam → open_loam}/base32.rb +1 -1
- data/lib/{loam → open_loam}/bulk.rb +7 -7
- data/lib/{loam → open_loam}/business_rules/actions.rb +7 -7
- data/lib/{loam → open_loam}/business_rules/condition.rb +5 -5
- data/lib/{loam → open_loam}/business_rules.rb +19 -19
- data/lib/{loam → open_loam}/commentable.rb +6 -6
- data/lib/{loam → open_loam}/configs.rb +19 -19
- data/lib/{loam → open_loam}/cron.rb +2 -2
- data/lib/{loam → open_loam}/csv.rb +2 -2
- data/lib/{loam → open_loam}/current.rb +5 -5
- data/lib/{loam → open_loam}/custom_field_index.rb +23 -23
- data/lib/{loam → open_loam}/custom_fields.rb +17 -17
- data/lib/{loam → open_loam}/dashboard.rb +5 -5
- data/lib/{loam → open_loam}/dictionaries.rb +12 -12
- data/lib/{loam → open_loam}/durable_events.rb +19 -19
- data/lib/{loam → open_loam}/encryptable.rb +33 -33
- data/lib/{loam → open_loam}/encryption/cipher.rb +3 -3
- data/lib/{loam → open_loam}/encryption/key_provider.rb +3 -3
- data/lib/{loam → open_loam}/encryption.rb +11 -11
- data/lib/open_loam/engine.rb +57 -0
- data/lib/{loam → open_loam}/enrichers.rb +5 -5
- data/lib/{loam → open_loam}/errors.rb +10 -10
- data/lib/{loam → open_loam}/eval.rb +2 -2
- data/lib/{loam → open_loam}/event_stream.rb +14 -14
- data/lib/{loam → open_loam}/eventful.rb +12 -12
- data/lib/{loam → open_loam}/events.rb +5 -5
- data/lib/{loam → open_loam}/export.rb +8 -8
- data/lib/{loam → open_loam}/features.rb +15 -15
- data/lib/{loam → open_loam}/generated_key.rb +6 -6
- data/lib/{loam → open_loam}/import.rb +12 -12
- data/lib/{loam → open_loam}/inbound_webhooks.rb +7 -7
- data/lib/{loam → open_loam}/lifecycle.rb +25 -25
- data/lib/{loam/locales/loam.en.yml → open_loam/locales/open_loam.en.yml} +5 -5
- data/lib/{loam → open_loam}/mcp/server.rb +9 -9
- data/lib/{loam → open_loam}/mcp.rb +21 -21
- data/lib/{loam → open_loam}/notifications.rb +5 -5
- data/lib/{loam → open_loam}/open_api.rb +16 -16
- data/lib/{loam → open_loam}/overrides.rb +10 -10
- data/lib/{loam → open_loam}/pending_actions.rb +9 -9
- data/lib/{loam → open_loam}/permissions.rb +8 -8
- data/lib/{loam → open_loam}/perspectives.rb +9 -9
- data/lib/{loam → open_loam}/policy.rb +6 -6
- data/lib/{loam → open_loam}/progress.rb +6 -6
- data/lib/{loam → open_loam}/record_locks.rb +9 -9
- data/lib/{loam → open_loam}/scheduler.rb +20 -20
- data/lib/{loam → open_loam}/search/driver.rb +3 -3
- data/lib/{loam → open_loam}/search/like_driver.rb +5 -5
- data/lib/{loam → open_loam}/search/token_driver.rb +15 -15
- data/lib/{loam → open_loam}/search.rb +5 -5
- data/lib/{loam → open_loam}/searchable.rb +22 -22
- data/lib/{loam → open_loam}/soft_deletable.rb +10 -10
- data/lib/{loam → open_loam}/sso/claims.rb +1 -1
- data/lib/{loam → open_loam}/sso/fake_provider.rb +1 -1
- data/lib/{loam → open_loam}/sso/http_client.rb +3 -3
- data/lib/{loam → open_loam}/sso/oidc_provider.rb +2 -2
- data/lib/{loam → open_loam}/sso.rb +17 -17
- data/lib/{loam → open_loam}/telemetry.rb +6 -6
- data/lib/{loam → open_loam}/tenant_record.rb +10 -10
- data/lib/{loam → open_loam}/test_helpers.rb +4 -4
- data/lib/{loam → open_loam}/totp.rb +3 -3
- data/lib/{loam → open_loam}/translatable.rb +24 -24
- data/lib/{loam → open_loam}/undo.rb +11 -11
- data/lib/open_loam/version.rb +3 -0
- data/lib/{loam → open_loam}/webhooks.rb +4 -4
- data/lib/{loam → open_loam}/widgets.rb +9 -9
- data/lib/{loam → open_loam}/workflow.rb +45 -45
- data/lib/open_loam.rb +122 -0
- data/lib/tasks/{loam.rake → open_loam.rake} +43 -43
- data/lib/tasks/{loam_eval.rake → open_loam_eval.rake} +7 -7
- data/lib/tasks/open_loam_mcp.rake +20 -0
- metadata +242 -242
- data/app/models/loam/dictionary.rb +0 -20
- data/app/models/loam/search_token.rb +0 -9
- data/app/models/loam/tenant.rb +0 -20
- data/lib/generators/loam/entity/templates/views/edit.html.erb +0 -3
- data/lib/generators/loam/entity/templates/views/index.html.erb +0 -90
- data/lib/generators/loam/entity/templates/views/new.html.erb +0 -3
- data/lib/generators/loam/entity/templates/views/show.html.erb +0 -36
- data/lib/generators/loam/install/templates/AGENTS.md +0 -341
- data/lib/generators/loam/install/templates/admin/dashboard_controller.rb +0 -10
- data/lib/generators/loam/install/templates/admin/layout.html.erb +0 -76
- data/lib/generators/loam/install/templates/admin/progress_jobs_controller.rb +0 -19
- data/lib/generators/loam/install/templates/migrations/create_loam_api_tokens.rb +0 -15
- data/lib/generators/loam/install/templates/migrations/create_loam_audit_records.rb +0 -14
- data/lib/generators/loam/install/templates/migrations/create_loam_comments.rb +0 -13
- data/lib/generators/loam/install/templates/migrations/create_loam_custom_field_values.rb +0 -19
- data/lib/generators/loam/install/templates/migrations/create_loam_dashboard_widgets.rb +0 -12
- data/lib/generators/loam/install/templates/migrations/create_loam_dictionaries.rb +0 -11
- data/lib/generators/loam/install/templates/migrations/create_loam_memberships.rb +0 -11
- data/lib/generators/loam/install/templates/migrations/create_loam_notifications.rb +0 -15
- data/lib/generators/loam/install/templates/migrations/create_loam_record_locks.rb +0 -16
- data/lib/generators/loam/install/templates/migrations/create_loam_search_tokens.rb +0 -18
- data/lib/generators/loam/install/templates/migrations/create_loam_tenants.rb +0 -9
- data/lib/generators/loam/install/templates/migrations/create_loam_translations.rb +0 -15
- data/lib/generators/loam/install/templates/migrations/create_loam_webhook_endpoints.rb +0 -13
- data/lib/loam/engine.rb +0 -57
- data/lib/loam/version.rb +0 -3
- data/lib/loam.rb +0 -122
- data/lib/tasks/loam_mcp.rake +0 -20
- /data/lib/generators/{loam → open_loam}/install/templates/admin/api_tokens_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/business_rules_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/configs_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/dictionaries_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/features_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_preview.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/imports_summary.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/inbound_webhook_sources_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_activated.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/mfa_show.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/notifications_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/pagination.rb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/pending_actions_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/scheduled_jobs_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/search_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_mfa_challenge.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sessions_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_edit.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_index.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/sso_providers_new.html.erb +0 -0
- /data/lib/generators/{loam → open_loam}/install/templates/admin/webhook_endpoints_new.html.erb +0 -0
|
@@ -4,22 +4,22 @@ module Admin
|
|
|
4
4
|
|
|
5
5
|
layout "admin"
|
|
6
6
|
|
|
7
|
-
before_action :
|
|
7
|
+
before_action :set_open_loam_context
|
|
8
8
|
before_action :set_locale
|
|
9
9
|
|
|
10
|
-
rescue_from
|
|
10
|
+
rescue_from OpenLoam::NotAuthorizedError do
|
|
11
11
|
render plain: "403 Forbidden — your role does not permit this action.", status: :forbidden
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# A disabled feature is "not here" for this tenant, so it 404s — unlike a
|
|
15
15
|
# policy refusal (403), which is "you may not". Capability vs. person.
|
|
16
|
-
rescue_from
|
|
16
|
+
rescue_from OpenLoam::FeatureDisabledError do
|
|
17
17
|
render plain: "404 Not Found — this feature is not enabled for your tenant.", status: :not_found
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# A business rule (or any code) can veto a workflow transition from
|
|
21
|
-
# `
|
|
22
|
-
rescue_from
|
|
21
|
+
# `open_loam_perform_transition!`. Surface it as a clean 422, never a 500.
|
|
22
|
+
rescue_from OpenLoam::TransitionVetoedError do |error|
|
|
23
23
|
render plain: "422 — #{error.message}", status: :unprocessable_entity
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -41,49 +41,49 @@ module Admin
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
# Locale is request state like the tenant: from the switcher (param),
|
|
44
|
-
# remembered in the session, defaulting to
|
|
45
|
-
# translations (
|
|
44
|
+
# remembered in the session, defaulting to OpenLoam.default_locale. Content
|
|
45
|
+
# translations (OpenLoam::Translatable) overlay onto it.
|
|
46
46
|
def set_locale
|
|
47
|
-
session[:locale] = params[:locale] if params[:locale].present? &&
|
|
48
|
-
|
|
47
|
+
session[:locale] = params[:locale] if params[:locale].present? && OpenLoam.locales.include?(params[:locale])
|
|
48
|
+
OpenLoam::Current.locale = session[:locale] || OpenLoam.default_locale
|
|
49
49
|
# Drive Rails i18n (UI strings) off the same choice, so the switcher moves
|
|
50
50
|
# both the chrome and the content — but only to a locale that actually has
|
|
51
51
|
# translations, so an unlisted locale keeps English UI (data still overlays).
|
|
52
|
-
chosen =
|
|
52
|
+
chosen = OpenLoam::Current.locale.to_s
|
|
53
53
|
I18n.locale = chosen if I18n.available_locales.map(&:to_s).include?(chosen)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
def current_locale =
|
|
56
|
+
def current_locale = OpenLoam::Current.locale
|
|
57
57
|
|
|
58
|
-
def current_tenant =
|
|
59
|
-
def current_actor =
|
|
58
|
+
def current_tenant = OpenLoam::Current.tenant
|
|
59
|
+
def current_actor = OpenLoam::Current.actor
|
|
60
60
|
|
|
61
|
-
# Establishes
|
|
61
|
+
# Establishes OpenLoam::Current from the session, then proves the actor is
|
|
62
62
|
# allowed to be here.
|
|
63
63
|
#
|
|
64
|
-
# The order is load-bearing.
|
|
64
|
+
# The order is load-bearing. OpenLoam::Membership is itself tenant-scoped, so
|
|
65
65
|
# "is this actor a member?" is a question you can only ask from inside a
|
|
66
|
-
# tenant — the tenant has to be in
|
|
67
|
-
#
|
|
66
|
+
# tenant — the tenant has to be in OpenLoam::Current first, or the check raises
|
|
67
|
+
# OpenLoam::MissingTenantError instead of answering. The `&&` chain below
|
|
68
68
|
# guarantees that: membership is only consulted once both are set.
|
|
69
69
|
#
|
|
70
70
|
# If anything fails, BOTH halves of the context are cleared before the
|
|
71
71
|
# redirect, so a half-established context can never leak into the next
|
|
72
72
|
# request or into a job enqueued from it.
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
def set_open_loam_context
|
|
74
|
+
OpenLoam::Current.tenant = OpenLoam::Tenant.find_by(id: session[:tenant_id])
|
|
75
|
+
OpenLoam::Current.actor = User.find_by(id: session[:user_id])
|
|
76
76
|
|
|
77
77
|
return if current_tenant && current_actor && member_of_current_tenant?
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
OpenLoam::Current.reset
|
|
80
80
|
redirect_to new_admin_session_path
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
# Scoped to the current tenant by
|
|
83
|
+
# Scoped to the current tenant by OpenLoam::TenantRecord, which is the whole
|
|
84
84
|
# point: a membership in some other tenant is not membership here.
|
|
85
85
|
def member_of_current_tenant?
|
|
86
|
-
|
|
86
|
+
OpenLoam::Membership.exists?(user_id: current_actor.id)
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
# Drives the bell in the admin layout. One COUNT per admin page render,
|
|
@@ -91,54 +91,54 @@ module Admin
|
|
|
91
91
|
def unread_notification_count
|
|
92
92
|
return 0 unless current_actor
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
OpenLoam::Notification.unread.where(user_id: current_actor.id).count
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# Staged changes awaiting review, for the "Approvals (N)" nav badge.
|
|
98
98
|
def pending_approval_count
|
|
99
99
|
return 0 unless current_tenant
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
OpenLoam::PendingAction.pending.count
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
def policy_for(record)
|
|
105
|
-
|
|
105
|
+
OpenLoam::Policy.for(record)
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def authorize!(policy, action)
|
|
109
|
-
raise
|
|
109
|
+
raise OpenLoam::NotAuthorizedError unless policy.public_send(action)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
# For admin screens with no per-record policy (e.g. field definitions,
|
|
113
113
|
# which apply to a whole entity_type rather than one record).
|
|
114
114
|
def current_role
|
|
115
|
-
|
|
115
|
+
OpenLoam::Membership.find_by(user_id: current_actor&.id)&.role&.to_sym
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
def require_role!(*roles)
|
|
119
|
-
raise
|
|
119
|
+
raise OpenLoam::NotAuthorizedError unless roles.include?(current_role)
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
-
# Feature-string permission gate (
|
|
122
|
+
# Feature-string permission gate (OpenLoam::Permissions) — a finer capability
|
|
123
123
|
# check than require_role!. `can?` is a helper_method so views hide UI a role
|
|
124
124
|
# lacks; require_permission! enforces it (403) server-side.
|
|
125
125
|
def can?(permission)
|
|
126
|
-
|
|
126
|
+
OpenLoam.can?(permission)
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def require_permission!(permission)
|
|
130
|
-
raise
|
|
130
|
+
raise OpenLoam::NotAuthorizedError unless OpenLoam.can?(permission)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
# Feature guards. These gate a CAPABILITY (is the feature on for this
|
|
134
134
|
# tenant), orthogonal to require_role! / policies, which gate a PERSON.
|
|
135
135
|
# `feature_on?` is a helper_method, so views can hide UI a flag turns off.
|
|
136
136
|
def feature_on?(name)
|
|
137
|
-
|
|
137
|
+
OpenLoam::Features.on?(name)
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
def require_feature!(name)
|
|
141
|
-
raise
|
|
141
|
+
raise OpenLoam::FeatureDisabledError unless OpenLoam::Features.on?(name)
|
|
142
142
|
end
|
|
143
143
|
|
|
144
144
|
# Optimistic-locking conflict handling: someone saved this record between the
|
|
@@ -146,13 +146,13 @@ module Admin
|
|
|
146
146
|
# StaleObjectError). Build a field-level diff of what the user tried to write
|
|
147
147
|
# vs the current saved values, then RELOAD to fresh data so the retry carries
|
|
148
148
|
# the new lock_version — never a 500, never a silent clobber. lock_version is
|
|
149
|
-
# the guarantee; the advisory
|
|
149
|
+
# the guarantee; the advisory OpenLoam::RecordLock is only a courtesy warning.
|
|
150
150
|
#
|
|
151
151
|
# Encrypted fields are compared and shown via the reader (decrypted); the raw
|
|
152
152
|
# column is ciphertext that never matches (random IV), so a byte compare would
|
|
153
153
|
# be a false conflict every time.
|
|
154
154
|
def stale_conflict!(record, fields)
|
|
155
|
-
encrypted = record.class.respond_to?(:
|
|
155
|
+
encrypted = record.class.respond_to?(:open_loam_encrypted_attributes) ? record.class.open_loam_encrypted_attributes.map(&:to_s) : []
|
|
156
156
|
attempted = fields.map(&:to_s).index_with { |field| conflict_value(record, field, encrypted) }
|
|
157
157
|
|
|
158
158
|
record.reload
|
|
@@ -199,12 +199,12 @@ module Admin
|
|
|
199
199
|
submitted = Array(params.dig(record.model_name.param_key, :files)).reject(&:blank?)
|
|
200
200
|
return if submitted.empty?
|
|
201
201
|
|
|
202
|
-
raise
|
|
202
|
+
raise OpenLoam::NotAuthorizedError unless policy.update?
|
|
203
203
|
|
|
204
204
|
record.files.attach(submitted)
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
# Runtime custom fields (see
|
|
207
|
+
# Runtime custom fields (see OpenLoam::CustomFields) go through the same
|
|
208
208
|
# field-level enforcement as real columns: only a writable definition's
|
|
209
209
|
# value is ever assigned.
|
|
210
210
|
def assign_custom_fields!(record, params, policy)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Managing business rules (
|
|
2
|
+
# Managing business rules (OpenLoam::BusinessRule) — manager-only, since a rule can
|
|
3
3
|
# notify, emit events, and set fields across the tenant. The condition and
|
|
4
4
|
# actions are edited as JSON for the prototype (a visual builder is a future
|
|
5
5
|
# increment). The recent execution log shows WHY rules fired.
|
|
@@ -9,21 +9,21 @@ module Admin
|
|
|
9
9
|
|
|
10
10
|
rescue_from JSON::ParserError do |error|
|
|
11
11
|
flash.now[:alert] = "Condition and actions must be valid JSON: #{error.message}"
|
|
12
|
-
@rule ||=
|
|
12
|
+
@rule ||= OpenLoam::BusinessRule.new
|
|
13
13
|
render(@rule.persisted? ? :edit : :new, status: :unprocessable_entity)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def index
|
|
17
|
-
@rules =
|
|
18
|
-
@recent_runs =
|
|
17
|
+
@rules = OpenLoam::BusinessRule.by_priority
|
|
18
|
+
@recent_runs = OpenLoam::BusinessRuleRun.recent.limit(20)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def new
|
|
22
|
-
@rule =
|
|
22
|
+
@rule = OpenLoam::BusinessRule.new(active: true, condition: {}, actions: [])
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def create
|
|
26
|
-
@rule =
|
|
26
|
+
@rule = OpenLoam::BusinessRule.new(rule_params)
|
|
27
27
|
if @rule.save
|
|
28
28
|
redirect_to admin_business_rules_path, notice: "Rule created."
|
|
29
29
|
else
|
|
@@ -49,7 +49,7 @@ module Admin
|
|
|
49
49
|
private
|
|
50
50
|
|
|
51
51
|
def set_rule
|
|
52
|
-
@rule =
|
|
52
|
+
@rule = OpenLoam::BusinessRule.find(params[:id])
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
# Parse the JSON textareas here; a malformed value raises JSON::ParserError,
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
<p style="color:#b00"><%%= @error || flash[:alert] %></p>
|
|
3
3
|
<%% end %>
|
|
4
4
|
|
|
5
|
-
<%# The model is namespaced (
|
|
6
|
-
would be
|
|
5
|
+
<%# The model is namespaced (OpenLoam::BusinessRule), so an inferred URL/param-scope
|
|
6
|
+
would be admin_open_loam_business_rule_path / open_loam_business_rule[...]. Pin both to
|
|
7
7
|
the un-namespaced route and the "business_rule" key the controller permits. %>
|
|
8
8
|
<%%= form_with model: @rule, scope: :business_rule,
|
|
9
9
|
url: (@rule.persisted? ? admin_business_rule_path(@rule) : admin_business_rules_path) do |f| %>
|
|
@@ -14,7 +14,7 @@ module Admin
|
|
|
14
14
|
# discussion too.
|
|
15
15
|
authorize!(policy_for(record), :read?)
|
|
16
16
|
|
|
17
|
-
comment = record.
|
|
17
|
+
comment = record.open_loam_comments.new(body: params[:body], author: current_actor)
|
|
18
18
|
flash[:alert] = comment.errors.full_messages.to_sentence unless comment.save
|
|
19
19
|
|
|
20
20
|
redirect_back fallback_location: [ :admin, record ]
|
|
@@ -24,13 +24,13 @@ module Admin
|
|
|
24
24
|
|
|
25
25
|
# The type arrives from the browser, so it is never constantized blindly.
|
|
26
26
|
# `safe_constantize` returns nil for anything that is not a real constant,
|
|
27
|
-
# and the class then has to prove it is a
|
|
27
|
+
# and the class then has to prove it is a OpenLoam entity that opted into
|
|
28
28
|
# comments — the allowlist is the contract, not a hand-kept list of names.
|
|
29
29
|
def commentable
|
|
30
30
|
klass = params[:commentable_type].to_s.safe_constantize
|
|
31
31
|
|
|
32
|
-
unless klass.is_a?(Class) && klass <
|
|
33
|
-
raise
|
|
32
|
+
unless klass.is_a?(Class) && klass < OpenLoam::TenantRecord && klass.include?(OpenLoam::Commentable)
|
|
33
|
+
raise OpenLoam::NotAuthorizedError, "#{params[:commentable_type].inspect} is not a commentable OpenLoam entity"
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
klass.find(params[:commentable_id])
|
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Per-tenant settings (
|
|
2
|
+
# Per-tenant settings (OpenLoam::Configs). Structural, not per-record, so it is
|
|
3
3
|
# gated on the manager role rather than an entity policy — settings are
|
|
4
|
-
# privileged. Everything routes through
|
|
4
|
+
# privileged. Everything routes through OpenLoam::Configs, never OpenLoam::Config
|
|
5
5
|
# directly, so the cross-level resolution stays in vetted gem code.
|
|
6
6
|
class ConfigsController < BaseController
|
|
7
7
|
before_action { require_role!(:manager) }
|
|
8
8
|
|
|
9
9
|
def index
|
|
10
|
-
# Feature flags share the
|
|
10
|
+
# Feature flags share the open_loam_configs store but have their own screen
|
|
11
11
|
# (/admin/features), so hide their reserved-prefix keys from Settings.
|
|
12
|
-
keys =
|
|
12
|
+
keys = OpenLoam::Configs.defined_keys.reject { |key| key.start_with?(OpenLoam::Features::PREFIX) }
|
|
13
13
|
@settings = keys.map do |key|
|
|
14
|
-
{ key: key, value:
|
|
14
|
+
{ key: key, value: OpenLoam::Configs.get(key), overridden: OpenLoam::Configs.overridden?(key) }
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def edit
|
|
19
19
|
@key = params[:key]
|
|
20
|
-
@value =
|
|
21
|
-
@overridden =
|
|
20
|
+
@value = OpenLoam::Configs.get(@key)
|
|
21
|
+
@overridden = OpenLoam::Configs.overridden?(@key)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def update
|
|
25
|
-
|
|
25
|
+
OpenLoam::Configs.set(params[:key], coerce(params[:value]))
|
|
26
26
|
redirect_to admin_configs_path, notice: "#{params[:key]} set for this tenant."
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def reset
|
|
30
|
-
|
|
30
|
+
OpenLoam::Configs.reset(params[:key])
|
|
31
31
|
redirect_to admin_configs_path, notice: "#{params[:key]} reset to the default."
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class DashboardController < BaseController
|
|
3
|
+
def index
|
|
4
|
+
# Configurable, role-visible widgets (OpenLoam::Dashboard) — a raising widget
|
|
5
|
+
# is isolated into an error tile, never breaking the page. Register your
|
|
6
|
+
# own with OpenLoam::Widgets.register; arrange them under Dashboard settings.
|
|
7
|
+
@widgets = OpenLoam::Dashboard.for(actor: current_actor, role: current_role)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
data/lib/generators/{loam → open_loam}/install/templates/admin/dashboard_widgets_controller.rb
RENAMED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Dashboard settings (
|
|
2
|
+
# Dashboard settings (OpenLoam::DashboardWidget) — manager-only. Choose which
|
|
3
3
|
# registered widgets appear and in what order for this tenant.
|
|
4
4
|
class DashboardWidgetsController < BaseController
|
|
5
5
|
before_action { require_role!(:manager) }
|
|
6
6
|
|
|
7
7
|
def index
|
|
8
|
-
@registered =
|
|
9
|
-
@config =
|
|
8
|
+
@registered = OpenLoam::Widgets.registered
|
|
9
|
+
@config = OpenLoam::DashboardWidget.all.index_by(&:widget_key)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def update
|
|
13
|
-
|
|
13
|
+
OpenLoam::Widgets.keys.each do |key|
|
|
14
14
|
attrs = params.dig(:widgets, key) || {}
|
|
15
|
-
row =
|
|
15
|
+
row = OpenLoam::DashboardWidget.find_or_initialize_by(widget_key: key)
|
|
16
16
|
row.active = attrs[:active] == "1"
|
|
17
17
|
row.position = attrs[:position].to_i
|
|
18
18
|
row.save!
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Managed lookup lists (
|
|
2
|
+
# Managed lookup lists (OpenLoam::Dictionary) — manager-only. The index lists a
|
|
3
3
|
# tenant's dictionaries; the edit screen curates a dictionary's entries
|
|
4
4
|
# (Admin::DictionaryEntriesController). Tenant-scoped by the model's default
|
|
5
5
|
# scope, so a manager only ever sees their own tenant's lists.
|
|
@@ -8,15 +8,15 @@ module Admin
|
|
|
8
8
|
before_action :set_dictionary, only: %i[edit update destroy]
|
|
9
9
|
|
|
10
10
|
def index
|
|
11
|
-
@dictionaries =
|
|
11
|
+
@dictionaries = OpenLoam::Dictionary.order(:key)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def new
|
|
15
|
-
@dictionary =
|
|
15
|
+
@dictionary = OpenLoam::Dictionary.new
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def create
|
|
19
|
-
@dictionary =
|
|
19
|
+
@dictionary = OpenLoam::Dictionary.new(dictionary_params)
|
|
20
20
|
if @dictionary.save
|
|
21
21
|
redirect_to edit_admin_dictionary_path(@dictionary), notice: "Dictionary created — add its entries below."
|
|
22
22
|
else
|
|
@@ -45,7 +45,7 @@ module Admin
|
|
|
45
45
|
private
|
|
46
46
|
|
|
47
47
|
def set_dictionary
|
|
48
|
-
@dictionary =
|
|
48
|
+
@dictionary = OpenLoam::Dictionary.find(params[:id])
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def dictionary_params
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%%#
|
|
1
|
+
<%%# OpenLoam::Dictionary is namespaced, so pin the URL + param scope. %>
|
|
2
2
|
<%%= form_with model: @dictionary, scope: :dictionary,
|
|
3
3
|
url: (@dictionary.persisted? ? admin_dictionary_path(@dictionary) : admin_dictionaries_path) do |f| %>
|
|
4
4
|
<%% if @dictionary.errors.any? %>
|
data/lib/generators/{loam → open_loam}/install/templates/admin/dictionary_entries_controller.rb
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Entries of a
|
|
2
|
+
# Entries of a OpenLoam::Dictionary — manager-only, nested under a dictionary.
|
|
3
3
|
# Add / edit (value, label, color, icon, position, default, active) / delete;
|
|
4
4
|
# reordering is by editing `position`.
|
|
5
5
|
class DictionaryEntriesController < BaseController
|
|
@@ -33,7 +33,7 @@ module Admin
|
|
|
33
33
|
private
|
|
34
34
|
|
|
35
35
|
def set_dictionary
|
|
36
|
-
@dictionary =
|
|
36
|
+
@dictionary = OpenLoam::Dictionary.find(params[:dictionary_id])
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def set_entry
|
data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_controller.rb
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Durable event deliveries (
|
|
2
|
+
# Durable event deliveries (OpenLoam::EventDelivery) — the dead-letter view.
|
|
3
3
|
# Manager-only. Lists deliveries parked as `dead` (handler removed, or retries
|
|
4
4
|
# exhausted) and lets an operator requeue one after fixing the handler. Pending
|
|
5
5
|
# deliveries drain on their own; a small sample is shown for visibility.
|
|
@@ -7,16 +7,16 @@ module Admin
|
|
|
7
7
|
before_action { require_role!(:manager) }
|
|
8
8
|
|
|
9
9
|
def index
|
|
10
|
-
@dead =
|
|
11
|
-
@pending =
|
|
10
|
+
@dead = OpenLoam::EventDelivery.dead.order(updated_at: :desc).limit(200)
|
|
11
|
+
@pending = OpenLoam::EventDelivery.pending.order(Arel.sql("next_attempt_at IS NULL DESC, next_attempt_at ASC")).limit(50)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# Re-arm one delivery: back to pending with a clean slate, and nudge a job.
|
|
15
15
|
# The sweep would eventually pick it up anyway; this is the "try now" button.
|
|
16
16
|
def redeliver
|
|
17
|
-
delivery =
|
|
17
|
+
delivery = OpenLoam::EventDelivery.find(params[:id])
|
|
18
18
|
delivery.update!(status: "pending", attempts: 0, next_attempt_at: nil, last_error: nil)
|
|
19
|
-
|
|
19
|
+
OpenLoam::EventDeliveryJob.perform_later(delivery.tenant_id, delivery.id)
|
|
20
20
|
redirect_to admin_event_deliveries_path, notice: "Delivery requeued."
|
|
21
21
|
end
|
|
22
22
|
end
|
data/lib/generators/{loam → open_loam}/install/templates/admin/event_deliveries_index.html.erb
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<h1>Event deliveries</h1>
|
|
2
2
|
|
|
3
|
-
<p>Durable subscribers (<code>
|
|
3
|
+
<p>Durable subscribers (<code>OpenLoam::DurableEvents</code>). Delivery is at-least-once
|
|
4
4
|
with retry; a delivery that exhausts its retries — or whose subscriber was removed —
|
|
5
5
|
is parked here as <strong>dead</strong> for you to fix and requeue.</p>
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Server-Sent Events: a per-tenant push stream (
|
|
2
|
+
# Server-Sent Events: a per-tenant push stream (OpenLoam::EventStream) so the admin
|
|
3
3
|
# updates live instead of polling. Authentication runs in the normal
|
|
4
|
-
# before_action chain (
|
|
4
|
+
# before_action chain (set_open_loam_context) BEFORE any stream write — so an
|
|
5
5
|
# unauthenticated request redirects to login the ordinary way, since no headers
|
|
6
6
|
# have been committed yet. Once the loop starts writing, the response is
|
|
7
7
|
# committed and there is no going back; that ordering is the whole safety of a
|
|
@@ -20,7 +20,7 @@ module Admin
|
|
|
20
20
|
# Subscribe as the FIRST thing in the begin whose ensure unsubscribes: a
|
|
21
21
|
# leaked AS::Notifications subscriber would fire on every future event in
|
|
22
22
|
# the process, holding this dead stream's queue forever.
|
|
23
|
-
handle =
|
|
23
|
+
handle = OpenLoam::EventStream.broadcaster.subscribe(tenant: current_tenant, actor: current_actor) do |sse|
|
|
24
24
|
queue << sse
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -34,9 +34,9 @@ module Admin
|
|
|
34
34
|
rescue IOError, ActionController::Live::ClientDisconnected
|
|
35
35
|
# The client went away — nothing to do but clean up in `ensure`.
|
|
36
36
|
ensure
|
|
37
|
-
|
|
37
|
+
OpenLoam::EventStream.broadcaster.unsubscribe(handle)
|
|
38
38
|
response.stream.close
|
|
39
|
-
|
|
39
|
+
OpenLoam::Current.reset
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
end
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Feature flags (
|
|
3
|
-
# like Settings. Everything routes through
|
|
2
|
+
# Feature flags (OpenLoam::Features). Structural and privileged, so manager-only,
|
|
3
|
+
# like Settings. Everything routes through OpenLoam::Features; the admin toggles
|
|
4
4
|
# the CURRENT tenant's override, and Reset drops it back to the declared /
|
|
5
5
|
# global state. Global (app-wide) flips are a deploy concern, not this screen.
|
|
6
6
|
class FeaturesController < BaseController
|
|
7
7
|
before_action { require_role!(:manager) }
|
|
8
8
|
|
|
9
9
|
def index
|
|
10
|
-
@flags =
|
|
10
|
+
@flags = OpenLoam::Features.declared.map do |name|
|
|
11
11
|
{
|
|
12
12
|
name: name,
|
|
13
|
-
on:
|
|
14
|
-
overridden:
|
|
15
|
-
description:
|
|
13
|
+
on: OpenLoam::Features.on?(name),
|
|
14
|
+
overridden: OpenLoam::Features.overridden?(name),
|
|
15
|
+
description: OpenLoam::Features.description(name)
|
|
16
16
|
}
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def enable
|
|
21
|
-
|
|
21
|
+
OpenLoam::Features.enable(params[:name])
|
|
22
22
|
redirect_to admin_features_path, notice: "#{params[:name]} enabled for this tenant."
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def disable
|
|
26
|
-
|
|
26
|
+
OpenLoam::Features.disable(params[:name])
|
|
27
27
|
redirect_to admin_features_path, notice: "#{params[:name]} disabled for this tenant."
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def reset
|
|
31
|
-
|
|
31
|
+
OpenLoam::Features.reset(params[:name])
|
|
32
32
|
redirect_to admin_features_path, notice: "#{params[:name]} reset to the default."
|
|
33
33
|
end
|
|
34
34
|
end
|
data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_controller.rb
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# Manages
|
|
2
|
+
# Manages OpenLoam::FieldDefinition records: the "migration-free field" screen.
|
|
3
3
|
# Structural, not per-entity — gated on the manager role rather than a
|
|
4
4
|
# generated entity policy, since a field definition applies to a whole
|
|
5
5
|
# entity_type, not one record.
|
|
@@ -9,16 +9,16 @@ module Admin
|
|
|
9
9
|
|
|
10
10
|
def index
|
|
11
11
|
@entity_type = params[:entity_type]
|
|
12
|
-
@records =
|
|
12
|
+
@records = OpenLoam::FieldDefinition.order(:entity_type, :name)
|
|
13
13
|
@records = @records.where(entity_type: @entity_type) if @entity_type.present?
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def new
|
|
17
|
-
@record =
|
|
17
|
+
@record = OpenLoam::FieldDefinition.new(entity_type: params[:entity_type])
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def create
|
|
21
|
-
@record =
|
|
21
|
+
@record = OpenLoam::FieldDefinition.new(permitted_params)
|
|
22
22
|
@record.writable_roles = parse_roles(params.dig(:field_definition, :writable_roles))
|
|
23
23
|
@record.readable_roles = parse_roles(params.dig(:field_definition, :readable_roles))
|
|
24
24
|
|
|
@@ -38,7 +38,7 @@ module Admin
|
|
|
38
38
|
private
|
|
39
39
|
|
|
40
40
|
def set_record
|
|
41
|
-
@record =
|
|
41
|
+
@record = OpenLoam::FieldDefinition.find(params[:id])
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def permitted_params
|
data/lib/generators/{loam → open_loam}/install/templates/admin/field_definitions_new.html.erb
RENAMED
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
</p>
|
|
20
20
|
<p>
|
|
21
21
|
<%%= f.label :field_type %><br>
|
|
22
|
-
<%%= f.select :field_type,
|
|
22
|
+
<%%= f.select :field_type, OpenLoam::FieldDefinition::FIELD_TYPES %>
|
|
23
23
|
</p>
|
|
24
24
|
<p>
|
|
25
25
|
<%%= f.label :dictionary_key, "Dictionary key (only for a 'dictionary' field type)" %><br>
|
|
26
|
-
<%%= f.select :dictionary_key,
|
|
26
|
+
<%%= f.select :dictionary_key, OpenLoam::Dictionary.order(:key).pluck(:key), include_blank: true %>
|
|
27
27
|
</p>
|
|
28
28
|
<p>
|
|
29
29
|
<%%= f.label :writable_roles, "Writable by (comma-separated roles, blank = any member)" %><br>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module Admin
|
|
2
|
-
# A record's change history (
|
|
2
|
+
# A record's change history (OpenLoam::AuditRecord) with one-click Undo (L-704).
|
|
3
3
|
# Undo applies the inverse of a change and records ITSELF as an audit, so
|
|
4
4
|
# undoing an "undo" entry is redo — no separate redo action. Reading needs read
|
|
5
5
|
# on the record; undoing needs update (the same gate as editing it).
|
|
@@ -8,17 +8,17 @@ module Admin
|
|
|
8
8
|
|
|
9
9
|
def index
|
|
10
10
|
authorize!(policy_for(@record), :read?)
|
|
11
|
-
@audits =
|
|
11
|
+
@audits = OpenLoam::AuditRecord
|
|
12
12
|
.where(auditable_type: @record.class.name, auditable_id: @record.id)
|
|
13
13
|
.order(id: :desc).limit(100)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def undo
|
|
17
17
|
authorize!(policy_for(@record), :update?)
|
|
18
|
-
audit =
|
|
19
|
-
|
|
18
|
+
audit = OpenLoam::AuditRecord.find(params[:id])
|
|
19
|
+
OpenLoam::Undo.undo(audit, policy: policy_for(@record))
|
|
20
20
|
redirect_to admin_history_path(type: @record.class.name, record_id: @record.id), notice: "Change undone."
|
|
21
|
-
rescue
|
|
21
|
+
rescue OpenLoam::Undo::NotUndoableError => error
|
|
22
22
|
redirect_to admin_history_path(type: @record.class.name, record_id: @record.id), alert: error.message
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -26,10 +26,10 @@ module Admin
|
|
|
26
26
|
|
|
27
27
|
# The target record, looked up through its OWN default scope (tenancy holds;
|
|
28
28
|
# a soft-deleted row is still reachable to restore). The type is whitelisted
|
|
29
|
-
# to a
|
|
29
|
+
# to a OpenLoam::TenantRecord — never a bare constantize of a param.
|
|
30
30
|
def set_target
|
|
31
31
|
klass = params[:type].to_s.safe_constantize
|
|
32
|
-
raise
|
|
32
|
+
raise OpenLoam::NotAuthorizedError unless klass.is_a?(Class) && klass < OpenLoam::TenantRecord
|
|
33
33
|
|
|
34
34
|
scope = klass.respond_to?(:with_deleted) ? klass.with_deleted : klass.all
|
|
35
35
|
@record = scope.find(params[:record_id])
|
|
@@ -24,7 +24,7 @@ never reverted here.</p>
|
|
|
24
24
|
<%% end %>
|
|
25
25
|
</td>
|
|
26
26
|
<td>
|
|
27
|
-
<%% if
|
|
27
|
+
<%% if OpenLoam::Undo.undoable?(audit) %>
|
|
28
28
|
<%%= button_to "Undo", admin_undo_history_path(id: audit.id, type: @record.class.name, record_id: @record.id),
|
|
29
29
|
form: { style: "display:inline" } %>
|
|
30
30
|
<%% end %>
|