rails_admin_next 1.0.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 +7 -0
- data/Gemfile +46 -0
- data/LICENSE.md +21 -0
- data/README.md +317 -0
- data/Rakefile +25 -0
- data/app/assets/javascripts/rails_admin/custom/ui.js +1 -0
- data/app/assets/stylesheets/rails_admin/framework.css +2375 -0
- data/app/assets/stylesheets/rails_admin/skin.css +472 -0
- data/app/assets/stylesheets/rails_admin/tokens.css +281 -0
- data/app/assets/stylesheets/rails_admin.css +47 -0
- data/app/controllers/rails_admin_next/application_controller.rb +98 -0
- data/app/controllers/rails_admin_next/main_controller.rb +185 -0
- data/app/helpers/rails_admin_next/application_helper.rb +254 -0
- data/app/helpers/rails_admin_next/form_builder.rb +173 -0
- data/app/helpers/rails_admin_next/main_helper.rb +63 -0
- data/app/views/layouts/rails_admin_next/_head.html.erb +29 -0
- data/app/views/layouts/rails_admin_next/_navigation.html.erb +18 -0
- data/app/views/layouts/rails_admin_next/_secondary_navigation.html.erb +27 -0
- data/app/views/layouts/rails_admin_next/_sidebar_navigation.html.erb +6 -0
- data/app/views/layouts/rails_admin_next/application.html.erb +42 -0
- data/app/views/layouts/rails_admin_next/content.html.erb +22 -0
- data/app/views/layouts/rails_admin_next/modal.js.erb +7 -0
- data/app/views/rails_admin_next/main/_dashboard_history.html.erb +46 -0
- data/app/views/rails_admin_next/main/_delete_notice.html.erb +36 -0
- data/app/views/rails_admin_next/main/_form_action_text.html.erb +2 -0
- data/app/views/rails_admin_next/main/_form_boolean.html.erb +15 -0
- data/app/views/rails_admin_next/main/_form_colorpicker.html.erb +6 -0
- data/app/views/rails_admin_next/main/_form_datetime.html.erb +14 -0
- data/app/views/rails_admin_next/main/_form_enumeration.html.erb +26 -0
- data/app/views/rails_admin_next/main/_form_field.html.erb +2 -0
- data/app/views/rails_admin_next/main/_form_file_upload.html.erb +18 -0
- data/app/views/rails_admin_next/main/_form_filtering_multiselect.html.erb +20 -0
- data/app/views/rails_admin_next/main/_form_filtering_select.html.erb +22 -0
- data/app/views/rails_admin_next/main/_form_multiple_file_upload.html.erb +21 -0
- data/app/views/rails_admin_next/main/_form_nested_many.html.erb +20 -0
- data/app/views/rails_admin_next/main/_form_nested_one.html.erb +19 -0
- data/app/views/rails_admin_next/main/_form_polymorphic_association.html.erb +24 -0
- data/app/views/rails_admin_next/main/_form_text.html.erb +2 -0
- data/app/views/rails_admin_next/main/_pagination.html.erb +54 -0
- data/app/views/rails_admin_next/main/_submit_buttons.html.erb +26 -0
- data/app/views/rails_admin_next/main/bulk_delete.html.erb +19 -0
- data/app/views/rails_admin_next/main/dashboard.html.erb +64 -0
- data/app/views/rails_admin_next/main/delete.html.erb +21 -0
- data/app/views/rails_admin_next/main/edit.html.erb +3 -0
- data/app/views/rails_admin_next/main/export.html.erb +149 -0
- data/app/views/rails_admin_next/main/history.html.erb +80 -0
- data/app/views/rails_admin_next/main/index.html.erb +186 -0
- data/app/views/rails_admin_next/main/new.html.erb +3 -0
- data/app/views/rails_admin_next/main/show.html.erb +30 -0
- data/config/brakeman.ignore +145 -0
- data/config/importmap.rails_admin.rb +29 -0
- data/config/initializers/active_record_extensions.rb +21 -0
- data/config/locales/rails_admin_next.en.yml +158 -0
- data/config/routes.rb +14 -0
- data/lib/generators/rails_admin_next/install_generator.rb +39 -0
- data/lib/generators/rails_admin_next/templates/initializer.erb +40 -0
- data/lib/generators/rails_admin_next/utils.rb +21 -0
- data/lib/rails_admin_next/abstract_model.rb +266 -0
- data/lib/rails_admin_next/adapters/active_record/association.rb +130 -0
- data/lib/rails_admin_next/adapters/active_record/object_extension.rb +13 -0
- data/lib/rails_admin_next/adapters/active_record/property.rb +58 -0
- data/lib/rails_admin_next/adapters/active_record.rb +371 -0
- data/lib/rails_admin_next/config/actions/base.rb +160 -0
- data/lib/rails_admin_next/config/actions/bulk_delete.rb +67 -0
- data/lib/rails_admin_next/config/actions/dashboard.rb +62 -0
- data/lib/rails_admin_next/config/actions/delete.rb +58 -0
- data/lib/rails_admin_next/config/actions/edit.rb +56 -0
- data/lib/rails_admin_next/config/actions/export.rb +47 -0
- data/lib/rails_admin_next/config/actions/history_index.rb +40 -0
- data/lib/rails_admin_next/config/actions/history_show.rb +40 -0
- data/lib/rails_admin_next/config/actions/index.rb +108 -0
- data/lib/rails_admin_next/config/actions/new.rb +69 -0
- data/lib/rails_admin_next/config/actions/show.rb +36 -0
- data/lib/rails_admin_next/config/actions/show_in_app.rb +37 -0
- data/lib/rails_admin_next/config/actions.rb +122 -0
- data/lib/rails_admin_next/config/configurable.rb +107 -0
- data/lib/rails_admin_next/config/const_load_suppressor.rb +78 -0
- data/lib/rails_admin_next/config/fields/association.rb +169 -0
- data/lib/rails_admin_next/config/fields/base.rb +391 -0
- data/lib/rails_admin_next/config/fields/collection_association.rb +90 -0
- data/lib/rails_admin_next/config/fields/factories/action_text.rb +14 -0
- data/lib/rails_admin_next/config/fields/factories/active_storage.rb +34 -0
- data/lib/rails_admin_next/config/fields/factories/association.rb +32 -0
- data/lib/rails_admin_next/config/fields/factories/encrypted_password.rb +28 -0
- data/lib/rails_admin_next/config/fields/factories/enum.rb +23 -0
- data/lib/rails_admin_next/config/fields/factories/password.rb +19 -0
- data/lib/rails_admin_next/config/fields/group.rb +77 -0
- data/lib/rails_admin_next/config/fields/singular_association.rb +62 -0
- data/lib/rails_admin_next/config/fields/types/action_text.rb +20 -0
- data/lib/rails_admin_next/config/fields/types/active_record_enum.rb +62 -0
- data/lib/rails_admin_next/config/fields/types/active_storage.rb +70 -0
- data/lib/rails_admin_next/config/fields/types/all.rb +32 -0
- data/lib/rails_admin_next/config/fields/types/belongs_to_association.rb +48 -0
- data/lib/rails_admin_next/config/fields/types/boolean.rb +70 -0
- data/lib/rails_admin_next/config/fields/types/citext.rb +15 -0
- data/lib/rails_admin_next/config/fields/types/color.rb +43 -0
- data/lib/rails_admin_next/config/fields/types/date.rb +38 -0
- data/lib/rails_admin_next/config/fields/types/datetime.rb +79 -0
- data/lib/rails_admin_next/config/fields/types/decimal.rb +23 -0
- data/lib/rails_admin_next/config/fields/types/enum.rb +52 -0
- data/lib/rails_admin_next/config/fields/types/file_upload.rb +87 -0
- data/lib/rails_admin_next/config/fields/types/float.rb +23 -0
- data/lib/rails_admin_next/config/fields/types/has_and_belongs_to_many_association.rb +16 -0
- data/lib/rails_admin_next/config/fields/types/has_many_association.rb +16 -0
- data/lib/rails_admin_next/config/fields/types/has_one_association.rb +35 -0
- data/lib/rails_admin_next/config/fields/types/hidden.rb +31 -0
- data/lib/rails_admin_next/config/fields/types/inet.rb +15 -0
- data/lib/rails_admin_next/config/fields/types/integer.rb +20 -0
- data/lib/rails_admin_next/config/fields/types/json.rb +37 -0
- data/lib/rails_admin_next/config/fields/types/multiple_active_storage.rb +82 -0
- data/lib/rails_admin_next/config/fields/types/multiple_file_upload.rb +134 -0
- data/lib/rails_admin_next/config/fields/types/numeric.rb +24 -0
- data/lib/rails_admin_next/config/fields/types/password.rb +45 -0
- data/lib/rails_admin_next/config/fields/types/polymorphic_association.rb +118 -0
- data/lib/rails_admin_next/config/fields/types/serialized.rb +28 -0
- data/lib/rails_admin_next/config/fields/types/string.rb +50 -0
- data/lib/rails_admin_next/config/fields/types/string_like.rb +25 -0
- data/lib/rails_admin_next/config/fields/types/text.rb +28 -0
- data/lib/rails_admin_next/config/fields/types/time.rb +39 -0
- data/lib/rails_admin_next/config/fields/types/timestamp.rb +16 -0
- data/lib/rails_admin_next/config/fields/types/uuid.rb +15 -0
- data/lib/rails_admin_next/config/fields/types.rb +29 -0
- data/lib/rails_admin_next/config/fields.rb +88 -0
- data/lib/rails_admin_next/config/groupable.rb +20 -0
- data/lib/rails_admin_next/config/has_description.rb +14 -0
- data/lib/rails_admin_next/config/has_fields.rb +144 -0
- data/lib/rails_admin_next/config/has_groups.rb +27 -0
- data/lib/rails_admin_next/config/hideable.rb +30 -0
- data/lib/rails_admin_next/config/inspectable.rb +39 -0
- data/lib/rails_admin_next/config/lazy_model.rb +74 -0
- data/lib/rails_admin_next/config/model.rb +126 -0
- data/lib/rails_admin_next/config/proxyable/proxy.rb +42 -0
- data/lib/rails_admin_next/config/proxyable.rb +26 -0
- data/lib/rails_admin_next/config/sections/base.rb +36 -0
- data/lib/rails_admin_next/config/sections/create.rb +13 -0
- data/lib/rails_admin_next/config/sections/edit.rb +13 -0
- data/lib/rails_admin_next/config/sections/export.rb +13 -0
- data/lib/rails_admin_next/config/sections/list.rb +63 -0
- data/lib/rails_admin_next/config/sections/modal.rb +12 -0
- data/lib/rails_admin_next/config/sections/nested.rb +12 -0
- data/lib/rails_admin_next/config/sections/show.rb +12 -0
- data/lib/rails_admin_next/config/sections/update.rb +12 -0
- data/lib/rails_admin_next/config/sections.rb +39 -0
- data/lib/rails_admin_next/config.rb +436 -0
- data/lib/rails_admin_next/engine.rb +91 -0
- data/lib/rails_admin_next/extension.rb +35 -0
- data/lib/rails_admin_next/extensions/cancancan/authorization_adapter.rb +90 -0
- data/lib/rails_admin_next/extensions/cancancan.rb +5 -0
- data/lib/rails_admin_next/extensions/controller_extension.rb +8 -0
- data/lib/rails_admin_next/extensions/paper_trail/auditing_adapter.rb +192 -0
- data/lib/rails_admin_next/extensions/paper_trail.rb +5 -0
- data/lib/rails_admin_next/extensions/pundit/authorization_adapter.rb +72 -0
- data/lib/rails_admin_next/extensions/pundit.rb +5 -0
- data/lib/rails_admin_next/extensions/url_for_extension.rb +15 -0
- data/lib/rails_admin_next/icons.rb +143 -0
- data/lib/rails_admin_next/support/composite_keys_serializer.rb +15 -0
- data/lib/rails_admin_next/support/csv_converter.rb +100 -0
- data/lib/rails_admin_next/support/hash_helper.rb +31 -0
- data/lib/rails_admin_next/support/paginated_collection.rb +79 -0
- data/lib/rails_admin_next/version.rb +17 -0
- data/lib/rails_admin_next.rb +72 -0
- data/lib/tasks/rails_admin.rake +40 -0
- data/src/rails_admin/application.js +15 -0
- data/src/rails_admin/base.js +12 -0
- data/src/rails_admin/controllers/alert_controller.js +28 -0
- data/src/rails_admin/controllers/collapse_controller.js +16 -0
- data/src/rails_admin/controllers/dropdown_controller.js +110 -0
- data/src/rails_admin/controllers/feedback_controller.js +73 -0
- data/src/rails_admin/controllers/filter_box_controller.js +346 -0
- data/src/rails_admin/controllers/filtering_multiselect_controller.js +386 -0
- data/src/rails_admin/controllers/filtering_select_controller.js +509 -0
- data/src/rails_admin/controllers/index.js +31 -0
- data/src/rails_admin/controllers/modal_controller.js +142 -0
- data/src/rails_admin/controllers/nested_form_controller.js +117 -0
- data/src/rails_admin/controllers/polymorphic_controller.js +26 -0
- data/src/rails_admin/controllers/remote_form_controller.js +173 -0
- data/src/rails_admin/controllers/sidescroll_controller.js +23 -0
- data/src/rails_admin/dom-ready.js +20 -0
- data/src/rails_admin/dom.js +19 -0
- data/src/rails_admin/i18n.js +20 -0
- data/src/rails_admin/icons.js +64 -0
- data/src/rails_admin/interactions.js +221 -0
- data/src/rails_admin/select_query.js +65 -0
- metadata +346 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/lazy_model"
|
|
4
|
+
require "rails_admin_next/config/sections/list"
|
|
5
|
+
require "rails_admin_next/support/composite_keys_serializer"
|
|
6
|
+
require "active_support/core_ext/module/attribute_accessors"
|
|
7
|
+
|
|
8
|
+
module RailsAdminNext
|
|
9
|
+
module Config
|
|
10
|
+
# RailsAdminNext authentication is fully pluggable — set authenticate_with to any proc.
|
|
11
|
+
# Works with Devise, Rodauth, authentication-zero, has_secure_password, or any Warden setup.
|
|
12
|
+
#
|
|
13
|
+
# @see RailsAdminNext::Config.authenticate_with
|
|
14
|
+
# @see RailsAdminNext::Config.authorize_with
|
|
15
|
+
DEFAULT_AUTHENTICATION = proc {}
|
|
16
|
+
|
|
17
|
+
DEFAULT_AUTHORIZE = proc {}
|
|
18
|
+
|
|
19
|
+
DEFAULT_AUDIT = proc {}
|
|
20
|
+
|
|
21
|
+
DEFAULT_CURRENT_USER = proc {}
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# Configuration option to specify which models you want to exclude.
|
|
25
|
+
attr_accessor :excluded_models
|
|
26
|
+
|
|
27
|
+
# Configuration option to specify a allowlist of models you want to RailsAdminNext to work with.
|
|
28
|
+
# The excluded_models list applies against the allowlist as well and further reduces the models
|
|
29
|
+
# RailsAdminNext will use.
|
|
30
|
+
# If included_models is left empty ([]), then RailsAdminNext will automatically use all the models
|
|
31
|
+
# in your application (less any excluded_models you may have specified).
|
|
32
|
+
attr_accessor :included_models
|
|
33
|
+
|
|
34
|
+
# Fields to be hidden in show, create and update views
|
|
35
|
+
attr_reader :default_hidden_fields
|
|
36
|
+
|
|
37
|
+
# Default items per page value used if a model level option has not
|
|
38
|
+
# been configured
|
|
39
|
+
attr_accessor :default_items_per_page
|
|
40
|
+
|
|
41
|
+
# Default association limit
|
|
42
|
+
attr_accessor :default_associated_collection_limit
|
|
43
|
+
|
|
44
|
+
attr_reader :default_search_operator
|
|
45
|
+
|
|
46
|
+
# Configuration option to specify which method names will be searched for
|
|
47
|
+
# to be used as a label for object records. This defaults to [:name, :title]
|
|
48
|
+
attr_accessor :label_methods
|
|
49
|
+
|
|
50
|
+
# hide blank fields in show view if true
|
|
51
|
+
attr_accessor :compact_show_view
|
|
52
|
+
|
|
53
|
+
# Tell browsers whether to use the native HTML5 validations (novalidate form option).
|
|
54
|
+
attr_accessor :browser_validations
|
|
55
|
+
|
|
56
|
+
# Color scheme of the admin UI: :auto (default) follows the OS preference,
|
|
57
|
+
# :light or :dark pins it. Rendered as the layout's <meta name="color-scheme">,
|
|
58
|
+
# which every light-dark() token pair in the engine stylesheets resolves against.
|
|
59
|
+
attr_reader :color_scheme
|
|
60
|
+
|
|
61
|
+
# set parent controller
|
|
62
|
+
attr_reader :parent_controller
|
|
63
|
+
|
|
64
|
+
# Stores model configuration objects in a hash identified by model's class
|
|
65
|
+
# name.
|
|
66
|
+
#
|
|
67
|
+
# @see RailsAdminNext.config
|
|
68
|
+
attr_reader :registry
|
|
69
|
+
|
|
70
|
+
# Bootstrap CSS classes used for Navigation bar
|
|
71
|
+
attr_accessor :navbar_css_classes
|
|
72
|
+
|
|
73
|
+
# show Gravatar in Navigation bar
|
|
74
|
+
attr_accessor :show_gravatar
|
|
75
|
+
|
|
76
|
+
# accepts a hash of static links to be shown below the main navigation
|
|
77
|
+
attr_accessor :navigation_static_links
|
|
78
|
+
attr_accessor :navigation_static_label
|
|
79
|
+
|
|
80
|
+
# For customization of composite keys representation
|
|
81
|
+
attr_accessor :composite_keys_serializer
|
|
82
|
+
|
|
83
|
+
# Setup authentication to be run as a before filter
|
|
84
|
+
# This is run inside the controller instance so you can setup any authentication you need to
|
|
85
|
+
#
|
|
86
|
+
# By default, the authentication will run via warden if available
|
|
87
|
+
# and will run the default.
|
|
88
|
+
#
|
|
89
|
+
# Works with any auth: Devise, Rodauth, authentication-zero, has_secure_password.
|
|
90
|
+
#
|
|
91
|
+
# @example Warden (any setup)
|
|
92
|
+
# RailsAdminNext.config do |config|
|
|
93
|
+
# config.authenticate_with do
|
|
94
|
+
# warden.authenticate! scope: :user
|
|
95
|
+
# end
|
|
96
|
+
# end
|
|
97
|
+
#
|
|
98
|
+
# @example Custom scope
|
|
99
|
+
# RailsAdminNext.config do |config|
|
|
100
|
+
# config.authenticate_with do
|
|
101
|
+
# warden.authenticate! scope: :paranoid
|
|
102
|
+
# end
|
|
103
|
+
# end
|
|
104
|
+
#
|
|
105
|
+
# @see RailsAdminNext::Config::DEFAULT_AUTHENTICATION
|
|
106
|
+
def authenticate_with(&blk)
|
|
107
|
+
@authenticate = blk if blk
|
|
108
|
+
@authenticate || DEFAULT_AUTHENTICATION
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Content Security Policy for the admin. Opt-in: the engine enforces no policy by default.
|
|
112
|
+
#
|
|
113
|
+
# Pass a block receiving an `ActionDispatch::ContentSecurityPolicy`; it is applied per-request
|
|
114
|
+
# to admin responses only. The engine threads a per-request nonce onto every inline tag it
|
|
115
|
+
# emits (the importmap JSON, the import entry point, the index column-width style), so a
|
|
116
|
+
# policy may use `:self` + nonces without breaking the admin's own modules.
|
|
117
|
+
# Pass `report_only: true` to send `Content-Security-Policy-Report-Only` instead of enforcing.
|
|
118
|
+
#
|
|
119
|
+
# NOTE: the admin still renders a few inline `style="…"` attributes (enumerated in
|
|
120
|
+
# docs/security.md), so a `style-src` directive currently needs `:unsafe_inline`.
|
|
121
|
+
#
|
|
122
|
+
# @example Enforce a locked-down policy for the admin
|
|
123
|
+
# RailsAdminNext.config do |config|
|
|
124
|
+
# config.content_security_policy do |policy|
|
|
125
|
+
# policy.default_src :self
|
|
126
|
+
# policy.script_src :self
|
|
127
|
+
# policy.style_src :self, :unsafe_inline
|
|
128
|
+
# policy.img_src :self, :data
|
|
129
|
+
# end
|
|
130
|
+
# end
|
|
131
|
+
#
|
|
132
|
+
# @example Report-only while tuning it
|
|
133
|
+
# RailsAdminNext.config do |config|
|
|
134
|
+
# config.content_security_policy(report_only: true) { |policy| policy.default_src :self }
|
|
135
|
+
# end
|
|
136
|
+
def content_security_policy(report_only: false, &block)
|
|
137
|
+
if block
|
|
138
|
+
@content_security_policy = block
|
|
139
|
+
@content_security_policy_report_only = report_only
|
|
140
|
+
end
|
|
141
|
+
@content_security_policy
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Whether the opt-in CSP is sent as report-only (set via #content_security_policy).
|
|
145
|
+
attr_reader :content_security_policy_report_only
|
|
146
|
+
|
|
147
|
+
# Setup auditing/versioning provider that observe objects lifecycle
|
|
148
|
+
def audit_with(*args, &block)
|
|
149
|
+
extension = args.shift
|
|
150
|
+
if extension
|
|
151
|
+
klass = RailsAdminNext::AUDITING_ADAPTERS[extension]
|
|
152
|
+
klass.setup if klass.respond_to? :setup
|
|
153
|
+
@audit = proc do
|
|
154
|
+
@auditing_adapter = klass.new(*([self] + args).compact, &block)
|
|
155
|
+
end
|
|
156
|
+
elsif block
|
|
157
|
+
@audit = block
|
|
158
|
+
end
|
|
159
|
+
@audit || DEFAULT_AUDIT
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Setup authorization to be run as a before filter
|
|
163
|
+
# This is run inside the controller instance so you can setup any authorization you need to.
|
|
164
|
+
#
|
|
165
|
+
# By default, there is no authorization.
|
|
166
|
+
#
|
|
167
|
+
# @example Custom
|
|
168
|
+
# RailsAdminNext.config do |config|
|
|
169
|
+
# config.authorize_with do
|
|
170
|
+
# redirect_to root_path unless warden.user.is_admin?
|
|
171
|
+
# end
|
|
172
|
+
# end
|
|
173
|
+
#
|
|
174
|
+
# To use an authorization adapter, pass the name of the adapter. For example,
|
|
175
|
+
# to use with CanCanCan[https://github.com/CanCanCommunity/cancancan/], pass it like this.
|
|
176
|
+
#
|
|
177
|
+
# @example CanCanCan
|
|
178
|
+
# RailsAdminNext.config do |config|
|
|
179
|
+
# config.authorize_with :cancancan
|
|
180
|
+
# end
|
|
181
|
+
#
|
|
182
|
+
# See the wiki[https://github.com/railsadminteam/rails_admin/wiki] for more on authorization.
|
|
183
|
+
#
|
|
184
|
+
# @see RailsAdminNext::Config::DEFAULT_AUTHORIZE
|
|
185
|
+
def authorize_with(*args, &block)
|
|
186
|
+
extension = args.shift
|
|
187
|
+
if extension
|
|
188
|
+
klass = RailsAdminNext::AUTHORIZATION_ADAPTERS[extension]
|
|
189
|
+
klass.setup if klass.respond_to? :setup
|
|
190
|
+
@authorize = proc do
|
|
191
|
+
@authorization_adapter = klass.new(*([self] + args).compact, &block)
|
|
192
|
+
end
|
|
193
|
+
elsif block
|
|
194
|
+
@authorize = block
|
|
195
|
+
end
|
|
196
|
+
@authorize || DEFAULT_AUTHORIZE
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Setup configuration using an extension-provided ConfigurationAdapter
|
|
200
|
+
#
|
|
201
|
+
# @example Custom configuration for role-based setup.
|
|
202
|
+
# RailsAdminNext.config do |config|
|
|
203
|
+
# config.configure_with(:custom) do |config|
|
|
204
|
+
# config.models = ['User', 'Comment']
|
|
205
|
+
# config.roles = {
|
|
206
|
+
# 'Admin' => :all,
|
|
207
|
+
# 'User' => ['User']
|
|
208
|
+
# }
|
|
209
|
+
# end
|
|
210
|
+
# end
|
|
211
|
+
def configure_with(extension)
|
|
212
|
+
configuration = RailsAdminNext::CONFIGURATION_ADAPTERS[extension].new
|
|
213
|
+
yield(configuration) if block_given?
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Setup a different method to determine the current user or admin logged in.
|
|
217
|
+
# This is run inside the controller instance and made available as a helper.
|
|
218
|
+
#
|
|
219
|
+
# By default, _request.env["warden"].user_ or _current_user_ will be used (auth-library agnostic).
|
|
220
|
+
#
|
|
221
|
+
# @example Custom
|
|
222
|
+
# RailsAdminNext.config do |config|
|
|
223
|
+
# config.current_user_method do
|
|
224
|
+
# current_admin
|
|
225
|
+
# end
|
|
226
|
+
# end
|
|
227
|
+
#
|
|
228
|
+
# @see RailsAdminNext::Config::DEFAULT_CURRENT_USER
|
|
229
|
+
def current_user_method(&block)
|
|
230
|
+
@current_user = block if block
|
|
231
|
+
@current_user || DEFAULT_CURRENT_USER
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Validate at configuration time so a typo fails with an actionable
|
|
235
|
+
# message instead of a bare KeyError on the first admin page render.
|
|
236
|
+
def color_scheme=(scheme)
|
|
237
|
+
raise ArgumentError.new("color_scheme must be :auto, :light or :dark (got #{scheme.inspect})") unless %i[auto light dark].include?(scheme)
|
|
238
|
+
|
|
239
|
+
@color_scheme = scheme
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def default_search_operator=(operator)
|
|
243
|
+
if %w[default like not_like starts_with ends_with is =].include? operator
|
|
244
|
+
@default_search_operator = operator
|
|
245
|
+
else
|
|
246
|
+
raise ArgumentError.new("Search operator '#{operator}' not supported")
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# pool of all found model names from the whole application
|
|
251
|
+
def models_pool
|
|
252
|
+
(viable_models - excluded_models.collect(&:to_s)).uniq.sort
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# Loads a model configuration instance from the registry or registers
|
|
256
|
+
# a new one if one is yet to be added.
|
|
257
|
+
#
|
|
258
|
+
# First argument can be an instance of requested model, its class object,
|
|
259
|
+
# its class name as a string or symbol or a RailsAdminNext::AbstractModel
|
|
260
|
+
# instance.
|
|
261
|
+
#
|
|
262
|
+
# If a block is given it is evaluated in the context of configuration instance.
|
|
263
|
+
#
|
|
264
|
+
# Returns given model's configuration
|
|
265
|
+
#
|
|
266
|
+
# @see RailsAdminNext::Config.registry
|
|
267
|
+
def model(entity, &block)
|
|
268
|
+
key =
|
|
269
|
+
case entity
|
|
270
|
+
when RailsAdminNext::AbstractModel
|
|
271
|
+
entity.model.try(:name).try :to_sym
|
|
272
|
+
when Class, ConstLoadSuppressor::ConstProxy
|
|
273
|
+
entity.name.to_sym
|
|
274
|
+
when String, Symbol
|
|
275
|
+
entity.to_sym
|
|
276
|
+
else
|
|
277
|
+
entity.class.name.to_sym
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
@registry[key] ||= RailsAdminNext::Config::LazyModel.new(key.to_s)
|
|
281
|
+
@registry[key].add_deferred_block(&block) if block
|
|
282
|
+
@registry[key]
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# The engine ships a single zero-build asset path: browser-native ESM + CSS served by Propshaft
|
|
286
|
+
# and pinned via an engine-owned importmap. The option is vestigial — assignment is deprecated
|
|
287
|
+
# and ignored, kept only so a host's legacy `config.asset_source = :sprockets` doesn't raise.
|
|
288
|
+
def asset_source
|
|
289
|
+
:importmap
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def asset_source=(_)
|
|
293
|
+
RailsAdminNext.deprecator.warn("The asset_source configuration option was removed, RailsAdminNext serves a single importmap + Propshaft asset pipeline now.")
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def default_hidden_fields=(fields)
|
|
297
|
+
if fields.is_a?(Array)
|
|
298
|
+
@default_hidden_fields = {}
|
|
299
|
+
@default_hidden_fields[:edit] = fields
|
|
300
|
+
@default_hidden_fields[:show] = fields
|
|
301
|
+
else
|
|
302
|
+
@default_hidden_fields = fields
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def parent_controller=(name)
|
|
307
|
+
@parent_controller = name
|
|
308
|
+
|
|
309
|
+
if defined?(RailsAdminNext::ApplicationController) || defined?(RailsAdminNext::MainController)
|
|
310
|
+
RailsAdminNext::Config::ConstLoadSuppressor.allowing do
|
|
311
|
+
RailsAdminNext.send(:remove_const, :ApplicationController)
|
|
312
|
+
RailsAdminNext.send(:remove_const, :MainController)
|
|
313
|
+
load RailsAdminNext::Engine.root.join("app/controllers/rails_admin_next/application_controller.rb")
|
|
314
|
+
load RailsAdminNext::Engine.root.join("app/controllers/rails_admin_next/main_controller.rb")
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def total_columns_width=(_)
|
|
320
|
+
RailsAdminNext.deprecator.warn("The total_columns_width configuration option is deprecated and has no effect.")
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def sidescroll=(_)
|
|
324
|
+
RailsAdminNext.deprecator.warn("The sidescroll configuration option was removed, it is always enabled now.")
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# Setup actions to be used.
|
|
328
|
+
def actions(&block)
|
|
329
|
+
return unless block
|
|
330
|
+
|
|
331
|
+
RailsAdminNext::Config::Actions.reset
|
|
332
|
+
RailsAdminNext::Config::Actions.instance_eval(&block)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Returns all model configurations
|
|
336
|
+
#
|
|
337
|
+
# @see RailsAdminNext::Config.registry
|
|
338
|
+
def models
|
|
339
|
+
RailsAdminNext::AbstractModel.all.collect { |m| model(m) }
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Reset all configurations to defaults.
|
|
343
|
+
#
|
|
344
|
+
# @see RailsAdminNext::Config.registry
|
|
345
|
+
def reset
|
|
346
|
+
@compact_show_view = true
|
|
347
|
+
@browser_validations = true
|
|
348
|
+
@color_scheme = :auto
|
|
349
|
+
@authenticate = nil
|
|
350
|
+
@authorize = nil
|
|
351
|
+
@audit = nil
|
|
352
|
+
@current_user = nil
|
|
353
|
+
@default_hidden_fields = {}
|
|
354
|
+
@default_hidden_fields[:base] = [:_type]
|
|
355
|
+
@default_hidden_fields[:edit] = %i[id _id created_at created_on deleted_at updated_at updated_on deleted_on]
|
|
356
|
+
@default_hidden_fields[:show] = %i[id _id created_at created_on deleted_at updated_at updated_on deleted_on]
|
|
357
|
+
@default_items_per_page = 20
|
|
358
|
+
@default_associated_collection_limit = 100
|
|
359
|
+
@default_search_operator = "default"
|
|
360
|
+
@excluded_models = []
|
|
361
|
+
@included_models = []
|
|
362
|
+
@label_methods = %i[name title]
|
|
363
|
+
@registry = {}
|
|
364
|
+
@navbar_css_classes = %w[navbar-dark bg-primary border-bottom]
|
|
365
|
+
@show_gravatar = true
|
|
366
|
+
@navigation_static_links = {}
|
|
367
|
+
@navigation_static_label = nil
|
|
368
|
+
@composite_keys_serializer = RailsAdminNext::Support::CompositeKeysSerializer
|
|
369
|
+
@parent_controller = "::ActionController::Base"
|
|
370
|
+
@content_security_policy = nil
|
|
371
|
+
@content_security_policy_report_only = false
|
|
372
|
+
RailsAdminNext::Config::Actions.reset
|
|
373
|
+
RailsAdminNext::AbstractModel.reset
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Reset a provided model's configuration.
|
|
377
|
+
#
|
|
378
|
+
# @see RailsAdminNext::Config.registry
|
|
379
|
+
def reset_model(model)
|
|
380
|
+
key = model.is_a?(Class) ? model.name.to_sym : model.to_sym
|
|
381
|
+
@registry.delete(key)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Perform reset, then load RailsAdminNext initializer again
|
|
385
|
+
def reload!
|
|
386
|
+
reset
|
|
387
|
+
load RailsAdminNext::Engine.config.initializer_path
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# Get all models that are configured as visible sorted by their weight and label.
|
|
391
|
+
#
|
|
392
|
+
# @see RailsAdminNext::Config::Hideable
|
|
393
|
+
def visible_models(bindings)
|
|
394
|
+
visible_models_with_bindings(bindings).sort do |a, b|
|
|
395
|
+
if (weight_order = a.weight <=> b.weight) == 0
|
|
396
|
+
a.label.casecmp(b.label)
|
|
397
|
+
else
|
|
398
|
+
weight_order
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
private
|
|
404
|
+
|
|
405
|
+
def viable_models
|
|
406
|
+
included_models.collect(&:to_s).presence || begin
|
|
407
|
+
@@system_models ||= # memoization for tests
|
|
408
|
+
([Rails.application] + Rails::Engine.subclasses.collect(&:instance)).flat_map do |app|
|
|
409
|
+
(app.paths["app/models"].to_a + app.config.eager_load_paths).collect do |load_path|
|
|
410
|
+
Dir.glob(app.root.join(load_path)).collect do |load_dir|
|
|
411
|
+
path_prefix = "#{app.root.join(load_dir)}/"
|
|
412
|
+
Dir.glob("#{load_dir}/**/*.rb").collect do |filename|
|
|
413
|
+
# app/models/module/class.rb => module/class.rb => module/class => Module::Class
|
|
414
|
+
filename.delete_prefix(path_prefix).chomp(".rb").camelize
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
end.flatten.reject { |m| m.starts_with?("Concerns::") } # rubocop:disable Style/MultilineBlockChain
|
|
419
|
+
|
|
420
|
+
@@system_models + @registry.keys.collect(&:to_s)
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def visible_models_with_bindings(bindings)
|
|
425
|
+
models.collect { |m| m.with(bindings) }.select do |m|
|
|
426
|
+
m.visible? &&
|
|
427
|
+
RailsAdminNext::Config::Actions.find(:index, bindings.merge(abstract_model: m.abstract_model)).try(:authorized?) &&
|
|
428
|
+
(!m.abstract_model.embedded? || m.abstract_model.cyclic?)
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
# Set default values for configuration options on load
|
|
434
|
+
reset
|
|
435
|
+
end
|
|
436
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "action_cable/engine"
|
|
4
|
+
require "geared_pagination"
|
|
5
|
+
require "rails"
|
|
6
|
+
require "rails_admin_next"
|
|
7
|
+
require "rails_admin_next/extensions/url_for_extension"
|
|
8
|
+
require "rails_admin_next/version"
|
|
9
|
+
require "stimulus-rails"
|
|
10
|
+
require "turbo-rails"
|
|
11
|
+
|
|
12
|
+
module RailsAdminNext
|
|
13
|
+
class Engine < Rails::Engine
|
|
14
|
+
isolate_namespace RailsAdminNext
|
|
15
|
+
|
|
16
|
+
attr_accessor :importmap
|
|
17
|
+
|
|
18
|
+
config.action_dispatch.rescue_responses["RailsAdminNext::ActionNotAllowed"] = :forbidden
|
|
19
|
+
|
|
20
|
+
initializer "RailsAdminNext load UrlForExtension" do
|
|
21
|
+
RailsAdminNext::Engine.routes.singleton_class.prepend(RailsAdminNext::Extensions::UrlForExtension)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
initializer "RailsAdminNext reload config in development" do |app|
|
|
25
|
+
config.initializer_path = app.root.join("config/initializers/rails_admin_next.rb")
|
|
26
|
+
|
|
27
|
+
unless Rails.application.config.cache_classes
|
|
28
|
+
ActiveSupport::Reloader.before_class_unload do
|
|
29
|
+
RailsAdminNext::Config.reload!
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
reloader = app.config.file_watcher.new([config.initializer_path], []) do
|
|
33
|
+
# Do nothing, ActiveSupport::Reloader will trigger class_unload! anyway
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
app.reloaders << reloader
|
|
37
|
+
app.reloader.to_run do
|
|
38
|
+
reloader.execute_if_updated { require_unload_lock! }
|
|
39
|
+
end
|
|
40
|
+
reloader.execute
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
initializer "RailsAdminNext assets", group: :all do |app|
|
|
45
|
+
# Propshaft auto-registers the engine's app/assets (stylesheets + fonts); the browser-native
|
|
46
|
+
# ESM modules live under src/ — a non-conventional asset dir — so push it explicitly.
|
|
47
|
+
app.config.assets.paths << RailsAdminNext::Engine.root.join("src")
|
|
48
|
+
|
|
49
|
+
# The engine draws its OWN importmap (distinct from the host's config/importmap.rb), rendered
|
|
50
|
+
# inline — with the request CSP nonce — by app/views/layouts/rails_admin_next/_head.html.erb.
|
|
51
|
+
# A host that ships config/importmap.rails_admin.rb has it appended last, so it can override
|
|
52
|
+
# the `rails_admin_next` entrypoint pin (to add its own ActiveStorage/locales/custom UI) or add pins.
|
|
53
|
+
self.importmap = Importmap::Map.new.draw(RailsAdminNext::Engine.root.join("config/importmap.rails_admin.rb"))
|
|
54
|
+
host_importmap = app.root.join("config/importmap.rails_admin.rb")
|
|
55
|
+
importmap.draw(host_importmap) if host_importmap.exist?
|
|
56
|
+
|
|
57
|
+
# Invalidate the cached importmap JSON in development when an engine ESM file changes.
|
|
58
|
+
importmap.cache_sweeper(watches: RailsAdminNext::Engine.root.join("src"))
|
|
59
|
+
app.reloader.to_run { RailsAdminNext::Engine.importmap.cache_sweeper.execute_if_updated } unless app.config.cache_classes
|
|
60
|
+
|
|
61
|
+
# SRI/integrity is optional hardening: its value is cross-origin/CDN assets, which
|
|
62
|
+
# self-hosting same-origin already removes. Enable it only when the host opts in via
|
|
63
|
+
# config.assets.integrity_hash_algorithm (requires propshaft >= 1.2).
|
|
64
|
+
importmap.enable_integrity! if app.config.assets.try(:integrity_hash_algorithm).present?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Check for required middlewares, users may forget to use them in Rails API mode
|
|
68
|
+
config.after_initialize do |app|
|
|
69
|
+
has_session_store = app.config.middleware.to_a.any? do |m|
|
|
70
|
+
m.klass.try(:<=, ActionDispatch::Session::AbstractStore) ||
|
|
71
|
+
m.klass.try(:<=, ActionDispatch::Session::AbstractSecureStore) ||
|
|
72
|
+
m.klass.name =~ /^ActionDispatch::Session::/
|
|
73
|
+
end
|
|
74
|
+
loaded = app.config.middleware.to_a.map(&:name)
|
|
75
|
+
required = %w[ActionDispatch::Cookies ActionDispatch::Flash Rack::MethodOverride]
|
|
76
|
+
missing = required - loaded
|
|
77
|
+
unless missing.empty? && has_session_store
|
|
78
|
+
configs = missing.map { |m| "config.middleware.use #{m}" }
|
|
79
|
+
configs << "config.middleware.use #{app.config.session_store.try(:name) || "ActionDispatch::Session::CookieStore"}, #{app.config.session_options}" unless has_session_store
|
|
80
|
+
raise <<~ERROR
|
|
81
|
+
Required middlewares for RailsAdminNext are not added
|
|
82
|
+
To fix this, add
|
|
83
|
+
|
|
84
|
+
#{configs.join("\n ")}
|
|
85
|
+
|
|
86
|
+
to config/application.rb.
|
|
87
|
+
ERROR
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/extensions/controller_extension"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
EXTENSIONS = [] # rubocop:disable Style/MutableConstant
|
|
7
|
+
AUTHORIZATION_ADAPTERS = {} # rubocop:disable Style/MutableConstant
|
|
8
|
+
AUDITING_ADAPTERS = {} # rubocop:disable Style/MutableConstant
|
|
9
|
+
CONFIGURATION_ADAPTERS = {} # rubocop:disable Style/MutableConstant
|
|
10
|
+
|
|
11
|
+
# Extend RailsAdminNext
|
|
12
|
+
#
|
|
13
|
+
# The extension may define various adapters (e.g., for authorization) and
|
|
14
|
+
# register those via the options hash.
|
|
15
|
+
def self.add_extension(extension_key, extension_definition, options = {})
|
|
16
|
+
options.assert_valid_keys(:authorization, :configuration, :auditing)
|
|
17
|
+
|
|
18
|
+
EXTENSIONS << extension_key
|
|
19
|
+
|
|
20
|
+
AUTHORIZATION_ADAPTERS[extension_key] = extension_definition::AuthorizationAdapter if options[:authorization]
|
|
21
|
+
|
|
22
|
+
CONFIGURATION_ADAPTERS[extension_key] = extension_definition::ConfigurationAdapter if options[:configuration]
|
|
23
|
+
|
|
24
|
+
AUDITING_ADAPTERS[extension_key] = extension_definition::AuditingAdapter if options[:auditing]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Setup all extensions for testing
|
|
28
|
+
def self.setup_all_extensions
|
|
29
|
+
(AUTHORIZATION_ADAPTERS.values + AUDITING_ADAPTERS.values).each do |klass|
|
|
30
|
+
klass.setup if klass.respond_to? :setup
|
|
31
|
+
rescue # rubocop:disable Style/RescueStandardError
|
|
32
|
+
# ignore errors
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAdminNext
|
|
4
|
+
module Extensions
|
|
5
|
+
module CanCanCan
|
|
6
|
+
# This adapter is for the CanCanCan[https://github.com/CanCanCommunity/cancancan] authorization library.
|
|
7
|
+
class AuthorizationAdapter
|
|
8
|
+
module ControllerExtension
|
|
9
|
+
def current_ability
|
|
10
|
+
# use _current_user instead of default current_user so it works with
|
|
11
|
+
# whatever current user method is defined with RailsAdminNext
|
|
12
|
+
@current_ability ||= ability_class.new(_current_user)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
include RailsAdminNext::Config::Configurable
|
|
17
|
+
|
|
18
|
+
def self.setup
|
|
19
|
+
RailsAdminNext::Extensions::ControllerExtension.include ControllerExtension
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# See the +authorize_with+ config method for where the initialization happens.
|
|
23
|
+
def initialize(controller, ability = nil, &block)
|
|
24
|
+
@controller = controller
|
|
25
|
+
ability_class { ability } if ability
|
|
26
|
+
instance_eval(&block) if block
|
|
27
|
+
|
|
28
|
+
adapter = self
|
|
29
|
+
ControllerExtension.define_method(:ability_class) do
|
|
30
|
+
adapter.ability_class
|
|
31
|
+
end
|
|
32
|
+
@controller.current_ability.authorize! :access, :rails_admin
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
register_instance_option :ability_class do
|
|
36
|
+
Ability
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# This method is called in every controller action and should raise an exception
|
|
40
|
+
# when the authorization fails. The first argument is the name of the controller
|
|
41
|
+
# action as a symbol (:create, :bulk_delete, etc.). The second argument is the
|
|
42
|
+
# AbstractModel instance that applies. The third argument is the actual model
|
|
43
|
+
# instance if it is available.
|
|
44
|
+
def authorize(action, abstract_model = nil, model_object = nil)
|
|
45
|
+
return unless action
|
|
46
|
+
|
|
47
|
+
action, subject = resolve_action_and_subject(action, abstract_model, model_object)
|
|
48
|
+
@controller.current_ability.authorize!(action, subject)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# This method is called primarily from the view to determine whether the given user
|
|
52
|
+
# has access to perform the action on a given model. It should return true when authorized.
|
|
53
|
+
# This takes the same arguments as +authorize+. The difference is that this will
|
|
54
|
+
# return a boolean whereas +authorize+ will raise an exception when not authorized.
|
|
55
|
+
def authorized?(action, abstract_model = nil, model_object = nil)
|
|
56
|
+
return unless action
|
|
57
|
+
|
|
58
|
+
action, subject = resolve_action_and_subject(action, abstract_model, model_object)
|
|
59
|
+
@controller.current_ability.can?(action, subject)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# This is called when needing to scope a database query. It is called within the list
|
|
63
|
+
# and bulk_delete/destroy actions and should return a scope which limits the records
|
|
64
|
+
# to those which the user can perform the given action on.
|
|
65
|
+
def query(action, abstract_model)
|
|
66
|
+
abstract_model.model.accessible_by(@controller.current_ability, action)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# This is called in the new/create actions to determine the initial attributes for new
|
|
70
|
+
# records. It should return a hash of attributes which match what the user
|
|
71
|
+
# is authorized to create.
|
|
72
|
+
def attributes_for(action, abstract_model)
|
|
73
|
+
@controller.current_ability.attributes_for(action, abstract_model&.model)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def resolve_action_and_subject(action, abstract_model, model_object)
|
|
79
|
+
subject = model_object || abstract_model&.model
|
|
80
|
+
if subject
|
|
81
|
+
[action, subject]
|
|
82
|
+
else
|
|
83
|
+
# For :dashboard compatibility
|
|
84
|
+
[:read, action]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|