permission_forge 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1138 -0
- data/LICENSE.txt +21 -0
- data/README.md +356 -0
- data/app/controllers/concerns/permission_forge/acting_admin.rb +17 -0
- data/app/controllers/concerns/permission_forge/api/crud_actions.rb +84 -0
- data/app/controllers/concerns/permission_forge/api/nested_resource_lookup.rb +18 -0
- data/app/controllers/concerns/permission_forge/api/pagination.rb +50 -0
- data/app/controllers/concerns/permission_forge/api/response_renderer.rb +65 -0
- data/app/controllers/concerns/permission_forge/api/serializer_resolver.rb +30 -0
- data/app/controllers/concerns/permission_forge/api_authentication.rb +40 -0
- data/app/controllers/concerns/permission_forge/assignment_authorization.rb +97 -0
- data/app/controllers/concerns/permission_forge/audit_log_gate.rb +55 -0
- data/app/controllers/concerns/permission_forge/basic_authentication.rb +77 -0
- data/app/controllers/concerns/permission_forge/cache_confirmation.rb +32 -0
- data/app/controllers/concerns/permission_forge/forgery_protection.rb +29 -0
- data/app/controllers/concerns/permission_forge/html_format.rb +40 -0
- data/app/controllers/concerns/permission_forge/param_shapes.rb +87 -0
- data/app/controllers/concerns/permission_forge/tenant_required.rb +42 -0
- data/app/controllers/permission_forge/api/audit_events_controller.rb +33 -0
- data/app/controllers/permission_forge/api/base_controller.rb +220 -0
- data/app/controllers/permission_forge/api/dashboard_controller.rb +30 -0
- data/app/controllers/permission_forge/api/permission_set_group_users_controller.rb +51 -0
- data/app/controllers/permission_forge/api/permission_set_groups_controller.rb +71 -0
- data/app/controllers/permission_forge/api/permission_set_rules_controller.rb +37 -0
- data/app/controllers/permission_forge/api/permission_set_users_controller.rb +105 -0
- data/app/controllers/permission_forge/api/permission_sets_controller.rb +87 -0
- data/app/controllers/permission_forge/api/resource_actions_controller.rb +58 -0
- data/app/controllers/permission_forge/api/resource_fields_controller.rb +30 -0
- data/app/controllers/permission_forge/api/resources_controller.rb +56 -0
- data/app/controllers/permission_forge/application_controller.rb +198 -0
- data/app/controllers/permission_forge/assets_controller.rb +97 -0
- data/app/controllers/permission_forge/assignments_controller.rb +266 -0
- data/app/controllers/permission_forge/audit_events_controller.rb +94 -0
- data/app/controllers/permission_forge/bulk_assignments_controller.rb +108 -0
- data/app/controllers/permission_forge/field_lookups_controller.rb +38 -0
- data/app/controllers/permission_forge/home_controller.rb +24 -0
- data/app/controllers/permission_forge/maintenance_controller.rb +13 -0
- data/app/controllers/permission_forge/people_controller.rb +190 -0
- data/app/controllers/permission_forge/permission_set_editor.rb +71 -0
- data/app/controllers/permission_forge/permission_set_group_users_controller.rb +57 -0
- data/app/controllers/permission_forge/permission_set_groups_controller.rb +111 -0
- data/app/controllers/permission_forge/permission_set_rules_controller.rb +97 -0
- data/app/controllers/permission_forge/permission_sets_controller.rb +227 -0
- data/app/controllers/permission_forge/preferences_controller.rb +26 -0
- data/app/controllers/permission_forge/resource_actions_controller.rb +106 -0
- data/app/controllers/permission_forge/resource_fields_controller.rb +129 -0
- data/app/controllers/permission_forge/resources_controller.rb +189 -0
- data/app/controllers/permission_forge/settings_controller.rb +33 -0
- data/app/frontend/permission_forge/brand/apple-touch-icon.png +0 -0
- data/app/frontend/permission_forge/brand/chevron.svg +1 -0
- data/app/frontend/permission_forge/brand/favicon.ico +0 -0
- data/app/frontend/permission_forge/brand/favicon.svg +1 -0
- data/app/frontend/permission_forge/brand/logo-horizontal-dark.svg +1 -0
- data/app/frontend/permission_forge/brand/logo-horizontal-light.svg +1 -0
- data/app/frontend/permission_forge/brand/mark-small.svg +1 -0
- data/app/frontend/permission_forge/brand/mark.svg +1 -0
- data/app/frontend/permission_forge/pf_admin.css +766 -0
- data/app/frontend/permission_forge/pf_admin.js +482 -0
- data/app/helpers/permission_forge/application_helper.rb +167 -0
- data/app/helpers/permission_forge/audit_helper.rb +230 -0
- data/app/helpers/permission_forge/audit_sentences_helper.rb +84 -0
- data/app/helpers/permission_forge/badges_helper.rb +134 -0
- data/app/helpers/permission_forge/changes_helper.rb +117 -0
- data/app/helpers/permission_forge/people_helper.rb +118 -0
- data/app/helpers/permission_forge/sentences_helper.rb +175 -0
- data/app/helpers/permission_forge/settings_helper.rb +152 -0
- data/app/helpers/permission_forge/ui_helper.rb +184 -0
- data/app/models/permission_forge/audit_event.rb +159 -0
- data/app/models/permission_forge/permission_set.rb +100 -0
- data/app/models/permission_forge/permission_set_group.rb +83 -0
- data/app/models/permission_forge/permission_set_group_user.rb +43 -0
- data/app/models/permission_forge/permission_set_rule.rb +99 -0
- data/app/models/permission_forge/permission_set_user.rb +158 -0
- data/app/models/permission_forge/resource.rb +100 -0
- data/app/models/permission_forge/resource_action.rb +58 -0
- data/app/models/permission_forge/resource_field.rb +69 -0
- data/app/views/layouts/permission_forge/application.html.erb +30 -0
- data/app/views/layouts/permission_forge/fragment.html.erb +2 -0
- data/app/views/permission_forge/assignments/_person_options.html.erb +26 -0
- data/app/views/permission_forge/assignments/confirm_destroy.html.erb +24 -0
- data/app/views/permission_forge/assignments/new.html.erb +99 -0
- data/app/views/permission_forge/audit_events/index.html.erb +161 -0
- data/app/views/permission_forge/audit_events/show.html.erb +146 -0
- data/app/views/permission_forge/bulk_assignments/confirm_revoke.html.erb +21 -0
- data/app/views/permission_forge/bulk_assignments/new.html.erb +69 -0
- data/app/views/permission_forge/field_lookups/show.html.erb +32 -0
- data/app/views/permission_forge/home/_audit_card.html.erb +19 -0
- data/app/views/permission_forge/home/_ending_card.html.erb +32 -0
- data/app/views/permission_forge/home/_expired_card.html.erb +34 -0
- data/app/views/permission_forge/home/_privacy_card.html.erb +67 -0
- data/app/views/permission_forge/home/_rules_card.html.erb +23 -0
- data/app/views/permission_forge/home/_stale_card.html.erb +39 -0
- data/app/views/permission_forge/home/_tidy_card.html.erb +18 -0
- data/app/views/permission_forge/home/index.html.erb +69 -0
- data/app/views/permission_forge/people/_access_tab.html.erb +58 -0
- data/app/views/permission_forge/people/_audit_tab.html.erb +93 -0
- data/app/views/permission_forge/people/_effective_field_source.html.erb +11 -0
- data/app/views/permission_forge/people/_effective_tab.html.erb +118 -0
- data/app/views/permission_forge/people/_effective_why.html.erb +48 -0
- data/app/views/permission_forge/people/_why_item.html.erb +19 -0
- data/app/views/permission_forge/people/confirm_remove_all.html.erb +27 -0
- data/app/views/permission_forge/people/consent_preview.html.erb +39 -0
- data/app/views/permission_forge/people/erasure_preview.html.erb +28 -0
- data/app/views/permission_forge/people/index.html.erb +78 -0
- data/app/views/permission_forge/people/show.html.erb +54 -0
- data/app/views/permission_forge/permission_set_groups/confirm_destroy.html.erb +12 -0
- data/app/views/permission_forge/permission_set_groups/index.html.erb +55 -0
- data/app/views/permission_forge/permission_set_groups/show.html.erb +100 -0
- data/app/views/permission_forge/permission_set_rules/_builder.html.erb +145 -0
- data/app/views/permission_forge/permission_set_rules/_value_input.html.erb +42 -0
- data/app/views/permission_forge/permission_set_rules/confirm_destroy.html.erb +13 -0
- data/app/views/permission_forge/permission_set_rules/edit.html.erb +3 -0
- data/app/views/permission_forge/permission_set_rules/new.html.erb +3 -0
- data/app/views/permission_forge/permission_sets/_assignments_tab.html.erb +74 -0
- data/app/views/permission_forge/permission_sets/_audit_tab.html.erb +80 -0
- data/app/views/permission_forge/permission_sets/_conditions_tab.html.erb +83 -0
- data/app/views/permission_forge/permission_sets/_header.html.erb +36 -0
- data/app/views/permission_forge/permission_sets/_records_summary.html.erb +16 -0
- data/app/views/permission_forge/permission_sets/_resource_summary.html.erb +11 -0
- data/app/views/permission_forge/permission_sets/_resources_tab.html.erb +49 -0
- data/app/views/permission_forge/permission_sets/confirm_destroy.html.erb +23 -0
- data/app/views/permission_forge/permission_sets/confirm_switch_mode.html.erb +15 -0
- data/app/views/permission_forge/permission_sets/index.html.erb +83 -0
- data/app/views/permission_forge/permission_sets/new.html.erb +63 -0
- data/app/views/permission_forge/permission_sets/review.html.erb +26 -0
- data/app/views/permission_forge/permission_sets/show.html.erb +50 -0
- data/app/views/permission_forge/resource_actions/_across_sets.html.erb +24 -0
- data/app/views/permission_forge/resource_actions/_add_select.html.erb +12 -0
- data/app/views/permission_forge/resource_actions/_effect.html.erb +25 -0
- data/app/views/permission_forge/resource_actions/_endpoints.html.erb +16 -0
- data/app/views/permission_forge/resource_actions/_form.html.erb +44 -0
- data/app/views/permission_forge/resource_actions/_managed_note.html.erb +11 -0
- data/app/views/permission_forge/resource_actions/confirm_destroy.html.erb +13 -0
- data/app/views/permission_forge/resource_actions/new.html.erb +31 -0
- data/app/views/permission_forge/resource_actions/show.html.erb +39 -0
- data/app/views/permission_forge/resource_fields/_explain.html.erb +24 -0
- data/app/views/permission_forge/resource_fields/show.html.erb +186 -0
- data/app/views/permission_forge/resources/_actions_tab.html.erb +88 -0
- data/app/views/permission_forge/resources/_fields_tab.html.erb +89 -0
- data/app/views/permission_forge/resources/_rules_tab.html.erb +55 -0
- data/app/views/permission_forge/resources/_sync.html.erb +57 -0
- data/app/views/permission_forge/resources/confirm_destroy.html.erb +17 -0
- data/app/views/permission_forge/resources/new.html.erb +57 -0
- data/app/views/permission_forge/resources/show.html.erb +117 -0
- data/app/views/permission_forge/settings/_ladder.html.erb +15 -0
- data/app/views/permission_forge/settings/_row.html.erb +38 -0
- data/app/views/permission_forge/settings/show.html.erb +67 -0
- data/app/views/permission_forge/shared/_across_sets.html.erb +31 -0
- data/app/views/permission_forge/shared/_audit_events.html.erb +36 -0
- data/app/views/permission_forge/shared/_audit_footer.html.erb +16 -0
- data/app/views/permission_forge/shared/_audit_off_note.html.erb +15 -0
- data/app/views/permission_forge/shared/_audit_pagination.html.erb +19 -0
- data/app/views/permission_forge/shared/_audit_refused_note.html.erb +7 -0
- data/app/views/permission_forge/shared/_audit_timeline.html.erb +29 -0
- data/app/views/permission_forge/shared/_crud_cell.html.erb +18 -0
- data/app/views/permission_forge/shared/_dialog_frame.html.erb +11 -0
- data/app/views/permission_forge/shared/_expiry_picker.html.erb +27 -0
- data/app/views/permission_forge/shared/_head_extra.html.erb +3 -0
- data/app/views/permission_forge/shared/_help_banner.html.erb +10 -0
- data/app/views/permission_forge/shared/_level_control.html.erb +18 -0
- data/app/views/permission_forge/shared/_mode_banners.html.erb +22 -0
- data/app/views/permission_forge/shared/_nav.html.erb +12 -0
- data/app/views/permission_forge/shared/_preferences.html.erb +24 -0
- data/app/views/permission_forge/shared/_reason_field.html.erb +20 -0
- data/app/views/permission_forge/shared/_savebar.html.erb +13 -0
- data/app/views/permission_forge/shared/_sheet_frame.html.erb +22 -0
- data/app/views/permission_forge/shared/_sidebar.html.erb +18 -0
- data/app/views/permission_forge/shared/_tech_details.html.erb +20 -0
- data/app/views/permission_forge/shared/_toasts.html.erb +27 -0
- data/app/views/permission_forge/shared/_topbar.html.erb +15 -0
- data/app/views/permission_forge/shared/_user_select.html.erb +16 -0
- data/app/views/permission_forge/shared/audit_refused.html.erb +7 -0
- data/config/locales/permission_forge.en.yml +2115 -0
- data/config/locales/permission_forge.mk.yml +2166 -0
- data/config/locales/permission_forge.sq.yml +2164 -0
- data/config/routes.rb +143 -0
- data/lib/generators/permission_forge/install/install_generator.rb +105 -0
- data/lib/generators/permission_forge/install/templates/initializer.rb.tt +148 -0
- data/lib/generators/permission_forge/install/templates/migration.rb.tt +198 -0
- data/lib/generators/permission_forge/rls/rls_generator.rb +57 -0
- data/lib/generators/permission_forge/rls/templates/enable_permission_forge_rls.rb.tt +15 -0
- data/lib/generators/permission_forge/upgrade/templates/add_admin_ui_columns.rb.tt +8 -0
- data/lib/generators/permission_forge/upgrade/templates/add_audit_events.rb.tt +98 -0
- data/lib/generators/permission_forge/upgrade/templates/add_resource_fields_unique_index.rb.tt +69 -0
- data/lib/generators/permission_forge/upgrade/upgrade_generator.rb +66 -0
- data/lib/permission_forge/admin/action_across_sets.rb +76 -0
- data/lib/permission_forge/admin/action_rows.rb +156 -0
- data/lib/permission_forge/admin/attention_items.rb +207 -0
- data/lib/permission_forge/admin/audit_event_detail.rb +75 -0
- data/lib/permission_forge/admin/audit_log.rb +193 -0
- data/lib/permission_forge/admin/audit_log_days.rb +41 -0
- data/lib/permission_forge/admin/audit_lookups.rb +105 -0
- data/lib/permission_forge/admin/audit_name_history.rb +85 -0
- data/lib/permission_forge/admin/audit_trail.rb +169 -0
- data/lib/permission_forge/admin/bulk_people_matcher.rb +109 -0
- data/lib/permission_forge/admin/change_set.rb +123 -0
- data/lib/permission_forge/admin/change_set_parts/actions.rb +27 -0
- data/lib/permission_forge/admin/change_set_parts/base.rb +58 -0
- data/lib/permission_forge/admin/change_set_parts/context.rb +50 -0
- data/lib/permission_forge/admin/change_set_parts/field_edit.rb +67 -0
- data/lib/permission_forge/admin/change_set_parts/field_levels.rb +71 -0
- data/lib/permission_forge/admin/change_set_parts/new_actions.rb +91 -0
- data/lib/permission_forge/admin/change_set_parts/new_fields.rb +63 -0
- data/lib/permission_forge/admin/change_set_parts/resource_edit.rb +55 -0
- data/lib/permission_forge/admin/change_set_parts/resource_flags.rb +19 -0
- data/lib/permission_forge/admin/change_set_parts/set_attrs.rb +45 -0
- data/lib/permission_forge/admin/change_set_parts/values.rb +20 -0
- data/lib/permission_forge/admin/column_fields.rb +48 -0
- data/lib/permission_forge/admin/conditions_form.rb +78 -0
- data/lib/permission_forge/admin/controller_catalog.rb +166 -0
- data/lib/permission_forge/admin/csv.rb +41 -0
- data/lib/permission_forge/admin/editable_lock.rb +157 -0
- data/lib/permission_forge/admin/effective_access.rb +158 -0
- data/lib/permission_forge/admin/effective_fields.rb +176 -0
- data/lib/permission_forge/admin/expiry_presets.rb +51 -0
- data/lib/permission_forge/admin/exports/document.rb +89 -0
- data/lib/permission_forge/admin/exports/events.rb +51 -0
- data/lib/permission_forge/admin/exports/holdings.rb +118 -0
- data/lib/permission_forge/admin/exports.rb +37 -0
- data/lib/permission_forge/admin/field_across_sets.rb +51 -0
- data/lib/permission_forge/admin/field_detail.rb +112 -0
- data/lib/permission_forge/admin/field_level.rb +74 -0
- data/lib/permission_forge/admin/field_rows.rb +137 -0
- data/lib/permission_forge/admin/last_changes.rb +94 -0
- data/lib/permission_forge/admin/model_catalog.rb +216 -0
- data/lib/permission_forge/admin/people_candidates.rb +108 -0
- data/lib/permission_forge/admin/people_directory.rb +158 -0
- data/lib/permission_forge/admin/permission_set_factory.rb +48 -0
- data/lib/permission_forge/admin/person_label.rb +95 -0
- data/lib/permission_forge/admin/record_id.rb +19 -0
- data/lib/permission_forge/admin/rule_builder.rb +58 -0
- data/lib/permission_forge/admin/rule_form.rb +175 -0
- data/lib/permission_forge/admin/rule_form_input.rb +74 -0
- data/lib/permission_forge/admin/sensitive_columns.rb +68 -0
- data/lib/permission_forge/admin/settings_catalog.rb +261 -0
- data/lib/permission_forge/admin/settings_values.rb +130 -0
- data/lib/permission_forge/api/serializers/audit_event_serializer.rb +27 -0
- data/lib/permission_forge/api/serializers/base_serializer.rb +36 -0
- data/lib/permission_forge/api/serializers/permission_set_group_serializer.rb +12 -0
- data/lib/permission_forge/api/serializers/permission_set_group_user_serializer.rb +11 -0
- data/lib/permission_forge/api/serializers/permission_set_rule_serializer.rb +25 -0
- data/lib/permission_forge/api/serializers/permission_set_serializer.rb +13 -0
- data/lib/permission_forge/api/serializers/permission_set_user_serializer.rb +11 -0
- data/lib/permission_forge/api/serializers/resource_action_serializer.rb +13 -0
- data/lib/permission_forge/api/serializers/resource_field_serializer.rb +14 -0
- data/lib/permission_forge/api/serializers/resource_serializer.rb +15 -0
- data/lib/permission_forge/audit/actor.rb +144 -0
- data/lib/permission_forge/audit/actor_resolver.rb +103 -0
- data/lib/permission_forge/audit/audited_views.rb +208 -0
- data/lib/permission_forge/audit/boot_warnings.rb +58 -0
- data/lib/permission_forge/audit/column_values.rb +56 -0
- data/lib/permission_forge/audit/context.rb +98 -0
- data/lib/permission_forge/audit/detached.rb +62 -0
- data/lib/permission_forge/audit/event_catalog.rb +110 -0
- data/lib/permission_forge/audit/event_query.rb +192 -0
- data/lib/permission_forge/audit/failure.rb +47 -0
- data/lib/permission_forge/audit/field_access.rb +186 -0
- data/lib/permission_forge/audit/gate.rb +167 -0
- data/lib/permission_forge/audit/job_context.rb +32 -0
- data/lib/permission_forge/audit/log_access.rb +36 -0
- data/lib/permission_forge/audit/recorder.rb +168 -0
- data/lib/permission_forge/audit/refusals.rb +61 -0
- data/lib/permission_forge/audit/request_context.rb +152 -0
- data/lib/permission_forge/audit/runtime.rb +178 -0
- data/lib/permission_forge/audit/runtime_emission.rb +135 -0
- data/lib/permission_forge/audit/settings_observer.rb +70 -0
- data/lib/permission_forge/audit/source.rb +54 -0
- data/lib/permission_forge/audit/subscribers/base.rb +69 -0
- data/lib/permission_forge/audit/subscribers/legacy_hooks.rb +97 -0
- data/lib/permission_forge/audit/subscribers/log.rb +45 -0
- data/lib/permission_forge/audit/subscribers.rb +58 -0
- data/lib/permission_forge/audit.rb +302 -0
- data/lib/permission_forge/boot_checks.rb +184 -0
- data/lib/permission_forge/cache/backlog.rb +142 -0
- data/lib/permission_forge/cache/base.rb +200 -0
- data/lib/permission_forge/cache/bulk_invalidation.rb +131 -0
- data/lib/permission_forge/cache/failure.rb +171 -0
- data/lib/permission_forge/cache/handled_errors.rb +82 -0
- data/lib/permission_forge/cache/holder_invalidation.rb +85 -0
- data/lib/permission_forge/cache/invalidation.rb +180 -0
- data/lib/permission_forge/cache/memory_cache.rb +77 -0
- data/lib/permission_forge/cache/null_cache.rb +40 -0
- data/lib/permission_forge/cache/rails_cache.rb +231 -0
- data/lib/permission_forge/cache/rebuild.rb +149 -0
- data/lib/permission_forge/cache/settlement.rb +63 -0
- data/lib/permission_forge/cache/user_keys.rb +206 -0
- data/lib/permission_forge/cache/variant_removal.rb +55 -0
- data/lib/permission_forge/cache/withheld_notice.rb +60 -0
- data/lib/permission_forge/concerns/audited_collection.rb +34 -0
- data/lib/permission_forge/concerns/auto_permission_scoping.rb +158 -0
- data/lib/permission_forge/concerns/controller_action_guard.rb +106 -0
- data/lib/permission_forge/concerns/field_mask_checker.rb +45 -0
- data/lib/permission_forge/concerns/has_active_scope.rb +12 -0
- data/lib/permission_forge/concerns/has_audit_trail.rb +59 -0
- data/lib/permission_forge/concerns/has_permission_set_users.rb +115 -0
- data/lib/permission_forge/concerns/has_tenant_scoping.rb +86 -0
- data/lib/permission_forge/concerns/has_uuid.rb +24 -0
- data/lib/permission_forge/concerns/invalidates_in_batch.rb +207 -0
- data/lib/permission_forge/concerns/invalidates_managed_actions.rb +80 -0
- data/lib/permission_forge/concerns/masked_attributes/alias_access.rb +280 -0
- data/lib/permission_forge/concerns/masked_attributes/store_access.rb +100 -0
- data/lib/permission_forge/concerns/masked_attributes/validation_reads.rb +153 -0
- data/lib/permission_forge/concerns/masked_attributes/virtual_readers.rb +242 -0
- data/lib/permission_forge/concerns/masked_attributes.rb +576 -0
- data/lib/permission_forge/concerns/permission_cache_accessor.rb +416 -0
- data/lib/permission_forge/concerns/permission_scoped_findable.rb +337 -0
- data/lib/permission_forge/concerns/permissioned_user.rb +78 -0
- data/lib/permission_forge/concerns/permissions_memo.rb +160 -0
- data/lib/permission_forge/concerns/permissions_per_context.rb +288 -0
- data/lib/permission_forge/concerns/permissions_regenerator.rb +43 -0
- data/lib/permission_forge/concerns/records_audit_events.rb +286 -0
- data/lib/permission_forge/concerns/resource_permission_checker.rb +116 -0
- data/lib/permission_forge/concerns/validates_column_lengths.rb +69 -0
- data/lib/permission_forge/concerns/validates_dependency.rb +54 -0
- data/lib/permission_forge/conditional_sets.rb +361 -0
- data/lib/permission_forge/configuration/admin_ui_settings.rb +108 -0
- data/lib/permission_forge/configuration/audit_settings.rb +184 -0
- data/lib/permission_forge/configuration/cache_settings.rb +76 -0
- data/lib/permission_forge/configuration/controller_action_settings.rb +112 -0
- data/lib/permission_forge/configuration/gdpr_settings.rb +70 -0
- data/lib/permission_forge/configuration/masked_attributes_settings.rb +83 -0
- data/lib/permission_forge/configuration/permits_attributes_settings.rb +26 -0
- data/lib/permission_forge/configuration/presets.rb +139 -0
- data/lib/permission_forge/configuration/query_scoping_settings.rb +107 -0
- data/lib/permission_forge/configuration/strategy_values.rb +57 -0
- data/lib/permission_forge/configuration/virtual_attributes_settings.rb +65 -0
- data/lib/permission_forge/configuration.rb +624 -0
- data/lib/permission_forge/controller_actions/authorizer.rb +171 -0
- data/lib/permission_forge/controller_actions/managed_index.rb +213 -0
- data/lib/permission_forge/controller_actions/mapping.rb +167 -0
- data/lib/permission_forge/controller_actions.rb +122 -0
- data/lib/permission_forge/deprecation.rb +86 -0
- data/lib/permission_forge/engine.rb +113 -0
- data/lib/permission_forge/execution_state.rb +318 -0
- data/lib/permission_forge/invalidation_batch.rb +206 -0
- data/lib/permission_forge/masked_models.rb +226 -0
- data/lib/permission_forge/masking_sync.rb +271 -0
- data/lib/permission_forge/model_bindings.rb +90 -0
- data/lib/permission_forge/open_transaction.rb +303 -0
- data/lib/permission_forge/operators/constants.rb +41 -0
- data/lib/permission_forge/operators/registry.rb +300 -0
- data/lib/permission_forge/operators/rule_column.rb +120 -0
- data/lib/permission_forge/operators/validations.rb +111 -0
- data/lib/permission_forge/operators/value_casters/number.rb +68 -0
- data/lib/permission_forge/operators/value_casters/temporal.rb +69 -0
- data/lib/permission_forge/operators/value_casters.rb +80 -0
- data/lib/permission_forge/operators/value_typing.rb +115 -0
- data/lib/permission_forge/query_scoping_warnings.rb +68 -0
- data/lib/permission_forge/rake_audit.rb +65 -0
- data/lib/permission_forge/resource_chain.rb +190 -0
- data/lib/permission_forge/rls.rb +209 -0
- data/lib/permission_forge/services/attribute_access_guard.rb +138 -0
- data/lib/permission_forge/services/audit_event_purger.rb +150 -0
- data/lib/permission_forge/services/bulk_permission_set_assignment.rb +108 -0
- data/lib/permission_forge/services/concerns/across_tenants.rb +69 -0
- data/lib/permission_forge/services/concerns/audited_operation.rb +43 -0
- data/lib/permission_forge/services/concerns/clonable.rb +29 -0
- data/lib/permission_forge/services/consent_withdrawal_handler.rb +135 -0
- data/lib/permission_forge/services/dashboard_stats.rb +43 -0
- data/lib/permission_forge/services/data_subject_erasure.rb +306 -0
- data/lib/permission_forge/services/expired_assignment_cleaner.rb +152 -0
- data/lib/permission_forge/services/extra_field_defaults.rb +71 -0
- data/lib/permission_forge/services/field_permission_merger.rb +83 -0
- data/lib/permission_forge/services/filters_response_attributes.rb +144 -0
- data/lib/permission_forge/services/gdpr_field_auditor/text_report.rb +63 -0
- data/lib/permission_forge/services/gdpr_field_auditor.rb +223 -0
- data/lib/permission_forge/services/host_key_guard.rb +110 -0
- data/lib/permission_forge/services/mask_value.rb +93 -0
- data/lib/permission_forge/services/permission_cache_clearer.rb +174 -0
- data/lib/permission_forge/services/permission_hash_builder.rb +305 -0
- data/lib/permission_forge/services/permission_rule_applier.rb +192 -0
- data/lib/permission_forge/services/permission_set_cloner.rb +89 -0
- data/lib/permission_forge/services/permission_set_condition_evaluator.rb +102 -0
- data/lib/permission_forge/services/permission_set_group_cloner.rb +52 -0
- data/lib/permission_forge/services/permits_attributes/nested_records.rb +106 -0
- data/lib/permission_forge/services/permits_attributes.rb +270 -0
- data/lib/permission_forge/services/resource_field_generator.rb +93 -0
- data/lib/permission_forge/services/resource_with_fields_builder.rb +47 -0
- data/lib/permission_forge/services/rls_operator_sql.rb +131 -0
- data/lib/permission_forge/services/rls_policy_generator.rb +365 -0
- data/lib/permission_forge/services/security_audit/action_check.rb +157 -0
- data/lib/permission_forge/services/security_audit/assignment_check.rb +120 -0
- data/lib/permission_forge/services/security_audit/audit_trail_check.rb +166 -0
- data/lib/permission_forge/services/security_audit/base_check.rb +57 -0
- data/lib/permission_forge/services/security_audit/config_check.rb +212 -0
- data/lib/permission_forge/services/security_audit/integrity_check.rb +105 -0
- data/lib/permission_forge/services/security_audit/personal_data_check.rb +79 -0
- data/lib/permission_forge/services/security_audit/privilege_check.rb +67 -0
- data/lib/permission_forge/services/security_audit/rule_check.rb +141 -0
- data/lib/permission_forge/services/security_audit/text_report.rb +46 -0
- data/lib/permission_forge/services/security_audit/user_model_check.rb +67 -0
- data/lib/permission_forge/services/security_audit.rb +75 -0
- data/lib/permission_forge/services/stale_assignment_auditor.rb +68 -0
- data/lib/permission_forge/services/unscoped_query_detector.rb +132 -0
- data/lib/permission_forge/version.rb +3 -0
- data/lib/permission_forge/virtual_fields/discovery.rb +65 -0
- data/lib/permission_forge/virtual_fields.rb +102 -0
- data/lib/permission_forge.rb +464 -0
- data/lib/tasks/permission_forge.rake +31 -0
- data/lib/tasks/permission_forge_audit_events.rake +28 -0
- data/lib/tasks/permission_forge_cache.rake +26 -0
- data/lib/tasks/permission_forge_expiration.rake +30 -0
- data/lib/tasks/permission_forge_gdpr.rake +69 -0
- data/lib/tasks/permission_forge_rls.rake +38 -0
- metadata +515 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PermissionForge
|
|
4
|
+
class Configuration
|
|
5
|
+
# `config.preset`: a named set of values for the options that decide
|
|
6
|
+
# whether something fails open, applied as a layer of defaults under
|
|
7
|
+
# the settings the host makes itself.
|
|
8
|
+
#
|
|
9
|
+
# :compat (default) — the library defaults, as every version had them
|
|
10
|
+
# :strict — every fail-open default of the README's
|
|
11
|
+
# "Production hardening checklist" closed, and the
|
|
12
|
+
# settings that are already closed kept so
|
|
13
|
+
#
|
|
14
|
+
# A setting made explicitly always wins, before or after `preset =`, in
|
|
15
|
+
# the same configure block or a later one: the preset only fills the
|
|
16
|
+
# options nobody set. A String is taken as its Symbol; anything else
|
|
17
|
+
# raises ConfigurationError. SecurityAudit reports the preset and, under
|
|
18
|
+
# :strict, every option set looser than the preset.
|
|
19
|
+
#
|
|
20
|
+
# The options that need host code to close (an authenticated
|
|
21
|
+
# base_controller_class, admin_assignment_authorization,
|
|
22
|
+
# audit_log_authorization, a request_context_resolver, user_active_check)
|
|
23
|
+
# are not in a preset. Nor is masked_attributes_nil_user_strategy
|
|
24
|
+
# (OPT_IN): :hide makes jobs and mailers that read masked models with no
|
|
25
|
+
# user see hidden values, a cost each app must choose; it stays :bypass
|
|
26
|
+
# under every preset.
|
|
27
|
+
#
|
|
28
|
+
# @api public
|
|
29
|
+
module Presets
|
|
30
|
+
# The library defaults of every option a preset decides: what
|
|
31
|
+
# Configuration.new starts with (a test pins the two together).
|
|
32
|
+
COMPAT = {
|
|
33
|
+
# fail open by default (the checklist)
|
|
34
|
+
nil_user_strategy: :bypass,
|
|
35
|
+
response_filter_nil_user_strategy: :bypass,
|
|
36
|
+
auto_query_scoping: :off,
|
|
37
|
+
unconfigured_action_strategy: :allow,
|
|
38
|
+
action_guard_nil_user_strategy: nil,
|
|
39
|
+
conditional_sets_strict_mode: false,
|
|
40
|
+
mask_virtual_attributes: false,
|
|
41
|
+
extra_fields_default_access: :grant,
|
|
42
|
+
cache_backend: :memory,
|
|
43
|
+
# closed by default
|
|
44
|
+
api_require_authorization: true,
|
|
45
|
+
admin_tenantless_access: :deny,
|
|
46
|
+
nested_attributes_parent_fallback: false,
|
|
47
|
+
unconfigured_field_strategy: :block
|
|
48
|
+
}.freeze
|
|
49
|
+
|
|
50
|
+
STRICT = COMPAT.merge(
|
|
51
|
+
nil_user_strategy: :deny,
|
|
52
|
+
response_filter_nil_user_strategy: :block,
|
|
53
|
+
auto_query_scoping: :filter_only,
|
|
54
|
+
unconfigured_action_strategy: :block,
|
|
55
|
+
action_guard_nil_user_strategy: :deny,
|
|
56
|
+
conditional_sets_strict_mode: true,
|
|
57
|
+
mask_virtual_attributes: :auto,
|
|
58
|
+
extra_fields_default_access: :unconfigured,
|
|
59
|
+
cache_backend: :rails_cache
|
|
60
|
+
).freeze
|
|
61
|
+
|
|
62
|
+
PRESETS = { compat: COMPAT, strict: STRICT }.freeze
|
|
63
|
+
|
|
64
|
+
# Fail-open defaults of the hardening checklist that no preset closes:
|
|
65
|
+
# an explicit choice with a documented cost.
|
|
66
|
+
OPT_IN = %i[masked_attributes_nil_user_strategy].freeze
|
|
67
|
+
OPTIONS = COMPAT.keys.freeze
|
|
68
|
+
|
|
69
|
+
# When an option counts as closed with a value other than the :strict
|
|
70
|
+
# one: receives (value, configuration).
|
|
71
|
+
ALSO_CLOSED = {
|
|
72
|
+
nil_user_strategy: ->(value, _config) { value == :raise },
|
|
73
|
+
# nil follows nil_user_strategy
|
|
74
|
+
action_guard_nil_user_strategy: ->(_value, config) { !config.action_guard_nil_user_bypass? },
|
|
75
|
+
mask_virtual_attributes: ->(value, _config) { [true, 'auto'].include?(value) },
|
|
76
|
+
# no cache at all, or a shared store the host built
|
|
77
|
+
cache_backend: ->(value, _config) { value == :null || value.is_a?(ActiveSupport::Cache::Store) }
|
|
78
|
+
}.freeze
|
|
79
|
+
|
|
80
|
+
# Each writer of an option a preset decides marks the option as set by
|
|
81
|
+
# the host (after the value passed validation).
|
|
82
|
+
OPTIONS.each do |option|
|
|
83
|
+
define_method(:"#{option}=") do |value|
|
|
84
|
+
super(value)
|
|
85
|
+
@explicit_options << option
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @return [Symbol] :compat or :strict
|
|
90
|
+
attr_reader :preset
|
|
91
|
+
|
|
92
|
+
# @raise [PermissionForge::ConfigurationError] for anything but :strict
|
|
93
|
+
# or :compat (or its String)
|
|
94
|
+
def preset=(value)
|
|
95
|
+
name = StrategyValues.as_symbol(value)
|
|
96
|
+
unless PRESETS.key?(name)
|
|
97
|
+
raise PermissionForge::ConfigurationError,
|
|
98
|
+
"preset must be one of #{PRESETS.keys.map(&:inspect).join(', ')} (or its String); got #{value.inspect}"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
backend = @cache_backend
|
|
102
|
+
@preset = name
|
|
103
|
+
PRESETS.fetch(name).each do |option, preset_value|
|
|
104
|
+
instance_variable_set(:"@#{option}", preset_value) unless @explicit_options.include?(option)
|
|
105
|
+
end
|
|
106
|
+
# A store built from the old backend (preset set outside configure,
|
|
107
|
+
# which rebuilds it anyway) is rebuilt.
|
|
108
|
+
reset_cache_store! if @cache_store && !backend.equal?(@cache_backend)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @param option [Symbol]
|
|
112
|
+
# @return [Boolean] whether the host set the option itself (not the preset)
|
|
113
|
+
def explicitly_set?(option)
|
|
114
|
+
@explicit_options.include?(option.to_sym)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# The options whose value is looser than the :strict preset's — under
|
|
118
|
+
# :strict, the ones the host overrode.
|
|
119
|
+
#
|
|
120
|
+
# @return [Hash{Symbol => Object}] option => current value
|
|
121
|
+
def options_looser_than_strict
|
|
122
|
+
STRICT.each_with_object({}) do |(option, strict_value), looser|
|
|
123
|
+
value = public_send(option)
|
|
124
|
+
value = value.to_sym if value.is_a?(String) # 'block' is :block, as the strategy writers take it
|
|
125
|
+
next if value == strict_value || ALSO_CLOSED[option]&.call(value, self)
|
|
126
|
+
|
|
127
|
+
looser[option] = value
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def set_preset_defaults
|
|
134
|
+
@preset = :compat
|
|
135
|
+
@explicit_options = Set.new
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PermissionForge
|
|
4
|
+
class Configuration
|
|
5
|
+
# Query-scoping configuration (the three defense levels) extracted for SRP.
|
|
6
|
+
#
|
|
7
|
+
# Level 1 — ENFORCE: auto_query_scoping applies filter-type row rules to
|
|
8
|
+
# every relation built on a protected model.
|
|
9
|
+
# Level 2 — DETECT: unscoped_query_detection reports queries on protected
|
|
10
|
+
# tables that bypassed a permission-scoped path.
|
|
11
|
+
# Level 3 — DATABASE: database_row_level_security enables Postgres RLS
|
|
12
|
+
# session-variable plumbing (policies via the
|
|
13
|
+
# permission_forge:rls generator + rls:sync rake task).
|
|
14
|
+
#
|
|
15
|
+
# All options default OFF — behavior is unchanged unless a level is enabled.
|
|
16
|
+
#
|
|
17
|
+
# @api public
|
|
18
|
+
module QueryScopingSettings
|
|
19
|
+
AUTO_QUERY_SCOPING_VALUES = %i[off filter_only].freeze
|
|
20
|
+
UNSCOPED_QUERY_DETECTION_VALUES = %i[off log raise].freeze
|
|
21
|
+
|
|
22
|
+
# Level 1 — ENFORCE.
|
|
23
|
+
# :off — (default) only find_by/find_by!/permission_scoped apply rules
|
|
24
|
+
# :filter_only — a default_scope applies the current user's FILTER-type rules
|
|
25
|
+
# to every relation (where/all/find/first/count/pluck and
|
|
26
|
+
# association traversal). Join-type rules are NOT auto-applied
|
|
27
|
+
# and still require permission_scoped (a boot warning fires
|
|
28
|
+
# when join rules exist while this is enabled).
|
|
29
|
+
# Notes: view_all/modify_all bypasses auto-scoping (parity with find_by);
|
|
30
|
+
# nil current_user follows nil_user_strategy (:bypass -> unscoped,
|
|
31
|
+
# :deny/:raise -> none — fail closed, never raising from inside a scope);
|
|
32
|
+
# denied rows are silently filtered (find -> RecordNotFound).
|
|
33
|
+
# Unknown values raise ConfigurationError at assignment (see below).
|
|
34
|
+
attr_reader :auto_query_scoping
|
|
35
|
+
|
|
36
|
+
# Level 2 — DETECT.
|
|
37
|
+
# :off — (default) no detection
|
|
38
|
+
# :log — Rails.logger.warn for each unscoped query on a protected table
|
|
39
|
+
# :raise — raise PermissionForge::UnscopedQueryError instead (CI guard)
|
|
40
|
+
# Detection only activates in environments listed in
|
|
41
|
+
# unscoped_query_detection_environments. Queries carrying the pf_scoped
|
|
42
|
+
# annotation (permission_scoped, auto-scoping, gem internals) are never
|
|
43
|
+
# flagged; INSERTs and schema queries are ignored.
|
|
44
|
+
attr_reader :unscoped_query_detection
|
|
45
|
+
|
|
46
|
+
# Environments (strings) where unscoped_query_detection is active.
|
|
47
|
+
# Default: %w[development test]. Adding 'production' is allowed but a
|
|
48
|
+
# boot warning fires when :raise is configured for production.
|
|
49
|
+
attr_accessor :unscoped_query_detection_environments
|
|
50
|
+
|
|
51
|
+
# Level 3 — DATABASE (Postgres only). When true, PermissionForge::RLS
|
|
52
|
+
# helpers set/clear the session variable used by generated policies.
|
|
53
|
+
# Policies themselves are installed via `rails generate permission_forge:rls`
|
|
54
|
+
# and kept in sync with `rake permission_forge:rls:sync`.
|
|
55
|
+
attr_accessor :database_row_level_security
|
|
56
|
+
|
|
57
|
+
# Postgres session variable (set via SET LOCAL) that generated policies
|
|
58
|
+
# read through current_setting(..., true). Must contain a dot (Postgres
|
|
59
|
+
# requires namespaced custom settings).
|
|
60
|
+
attr_accessor :rls_session_variable
|
|
61
|
+
|
|
62
|
+
def auto_query_scoping=(value)
|
|
63
|
+
@auto_query_scoping = normalize_scoping_value(
|
|
64
|
+
value, AUTO_QUERY_SCOPING_VALUES, 'auto_query_scoping'
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def unscoped_query_detection=(value)
|
|
69
|
+
@unscoped_query_detection = normalize_scoping_value(
|
|
70
|
+
value, UNSCOPED_QUERY_DETECTION_VALUES, 'unscoped_query_detection'
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def auto_query_scoping_enabled?
|
|
75
|
+
@auto_query_scoping == :filter_only
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def unscoped_query_detection_active?
|
|
79
|
+
return false if @unscoped_query_detection == :off
|
|
80
|
+
return false unless defined?(Rails) && Rails.respond_to?(:env)
|
|
81
|
+
|
|
82
|
+
@unscoped_query_detection_environments.include?(Rails.env.to_s)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def set_query_scoping_defaults
|
|
88
|
+
@auto_query_scoping = :off
|
|
89
|
+
@unscoped_query_detection = :off
|
|
90
|
+
@unscoped_query_detection_environments = %w[development test]
|
|
91
|
+
@database_row_level_security = false
|
|
92
|
+
@rls_session_variable = 'permission_forge.user_id'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Fail closed on typos: an unknown value must never silently enable a
|
|
96
|
+
# weaker mode than the dev intended, so we raise at assignment time
|
|
97
|
+
# (initializer) rather than guessing at query time.
|
|
98
|
+
def normalize_scoping_value(value, allowed, option)
|
|
99
|
+
sym = value.to_sym
|
|
100
|
+
return sym if allowed.include?(sym)
|
|
101
|
+
|
|
102
|
+
raise PermissionForge::ConfigurationError,
|
|
103
|
+
"Invalid #{option}: #{value.inspect}. Allowed: #{allowed.map(&:inspect).join(', ')}"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PermissionForge
|
|
4
|
+
class Configuration
|
|
5
|
+
# The strategy options that decide whether something is allowed. Each
|
|
6
|
+
# writer takes a Symbol from its list, or that Symbol's String
|
|
7
|
+
# ('block' is :block), and raises ConfigurationError for anything else,
|
|
8
|
+
# at assignment time (the initializer). Before, a String was compared
|
|
9
|
+
# with a Symbol and read as an unknown value: for some options that
|
|
10
|
+
# failed open ('block' for response_filter_nil_user_strategy was
|
|
11
|
+
# :bypass). Prepended, so it wraps the plain writers declared in
|
|
12
|
+
# Configuration and its sub-settings.
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
module StrategyValues
|
|
16
|
+
ALLOWED = {
|
|
17
|
+
nil_user_strategy: %i[bypass raise deny],
|
|
18
|
+
response_filter_nil_user_strategy: %i[bypass block],
|
|
19
|
+
masked_write_protection: %i[skip raise off],
|
|
20
|
+
masked_attributes_nil_user_strategy: %i[bypass hide],
|
|
21
|
+
action_guard_nil_user_strategy: %i[bypass deny raise],
|
|
22
|
+
admin_tenantless_access: %i[deny allow],
|
|
23
|
+
unconfigured_action_strategy: %i[allow block],
|
|
24
|
+
extra_fields_default_access: %i[grant unconfigured]
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
# nil or blank means "follow nil_user_strategy".
|
|
28
|
+
BLANK_ALLOWED = %i[action_guard_nil_user_strategy].freeze
|
|
29
|
+
|
|
30
|
+
ALLOWED.each_key do |option|
|
|
31
|
+
define_method(:"#{option}=") do |value|
|
|
32
|
+
super(StrategyValues.strategy(option, value))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @return [Symbol, nil]
|
|
37
|
+
# @raise [PermissionForge::ConfigurationError] for a value not in ALLOWED[option]
|
|
38
|
+
def self.strategy(option, value)
|
|
39
|
+
blank_allowed = BLANK_ALLOWED.include?(option)
|
|
40
|
+
return nil if blank_allowed && value.to_s.strip.empty?
|
|
41
|
+
|
|
42
|
+
allowed = ALLOWED.fetch(option)
|
|
43
|
+
symbol = as_symbol(value)
|
|
44
|
+
return symbol if allowed.include?(symbol)
|
|
45
|
+
|
|
46
|
+
raise PermissionForge::ConfigurationError,
|
|
47
|
+
"#{option} must be one of #{allowed.map(&:inspect).join(', ')} (or its String)" \
|
|
48
|
+
"#{' or nil' if blank_allowed}; got #{value.inspect}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# A Symbol as is, a String as its Symbol, anything else nil.
|
|
52
|
+
def self.as_symbol(value)
|
|
53
|
+
value.to_s.to_sym if value.is_a?(String) || value.is_a?(Symbol)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PermissionForge
|
|
4
|
+
class Configuration
|
|
5
|
+
# Options for virtual (non-column) fields: names a model declares through
|
|
6
|
+
# `extra_fields_method`, plus names the admin can discover.
|
|
7
|
+
#
|
|
8
|
+
# @api public
|
|
9
|
+
module VirtualAttributesSettings
|
|
10
|
+
EXTRA_FIELDS_DEFAULT_ACCESS = %i[grant unconfigured].freeze
|
|
11
|
+
|
|
12
|
+
# What a declared virtual field gets when no ResourceField row configures it:
|
|
13
|
+
#
|
|
14
|
+
# :grant — readable and editable, unmasked (default, backward-compatible)
|
|
15
|
+
# :unconfigured — no implicit entry; the field follows unconfigured_field_strategy
|
|
16
|
+
# until an admin gives it a level (fail closed with :block)
|
|
17
|
+
#
|
|
18
|
+
# A String is taken as its Symbol; any other value raises
|
|
19
|
+
# ConfigurationError (StrategyValues).
|
|
20
|
+
attr_accessor :extra_fields_default_access
|
|
21
|
+
|
|
22
|
+
# When true, the admin also lists attribute-API attributes and
|
|
23
|
+
# store_accessor keys as virtual fields. Discovered names never get
|
|
24
|
+
# implicit access — they stay unconfigured until an admin sets a level.
|
|
25
|
+
# Default: false.
|
|
26
|
+
attr_accessor :virtual_field_discovery
|
|
27
|
+
|
|
28
|
+
# Model-level masking of virtual readers (methods, store accessors,
|
|
29
|
+
# attribute-API attributes), on top of the column masking MaskedAttributes
|
|
30
|
+
# already does. Off by default: the model's own callbacks and validations
|
|
31
|
+
# then see the masked value too (see pf_without_virtual_masking).
|
|
32
|
+
#
|
|
33
|
+
# false / nil — off; virtual fields are enforced only by
|
|
34
|
+
# PermitsAttributes and FiltersResponseAttributes (default)
|
|
35
|
+
# :auto / true — every model that has MaskedAttributes
|
|
36
|
+
# ['Customer', 'Order'] — only these models
|
|
37
|
+
attr_accessor :mask_virtual_attributes
|
|
38
|
+
|
|
39
|
+
# Sets this group's defaults; called from Configuration#initialize.
|
|
40
|
+
# @return [void]
|
|
41
|
+
# @api private
|
|
42
|
+
def set_virtual_attributes_defaults
|
|
43
|
+
@extra_fields_default_access = :grant
|
|
44
|
+
@virtual_field_discovery = false
|
|
45
|
+
@mask_virtual_attributes = false
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [Boolean] whether declared virtual fields get the implicit
|
|
49
|
+
# read + edit entry. Only the exact :grant value grants.
|
|
50
|
+
def grant_extra_fields_by_default?
|
|
51
|
+
extra_fields_default_access.to_s == 'grant'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @param model_name [String, Symbol, Class]
|
|
55
|
+
# @return [Boolean] whether virtual readers of this model are masked.
|
|
56
|
+
def mask_virtual_attributes_for?(model_name)
|
|
57
|
+
setting = mask_virtual_attributes
|
|
58
|
+
return false if [false, nil].include?(setting)
|
|
59
|
+
return setting.map(&:to_s).include?(model_name.to_s) if setting.is_a?(Array)
|
|
60
|
+
|
|
61
|
+
[true, :auto, 'auto'].include?(setting)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|