activeadmin_mcp 0.0.4 → 0.1.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/README.md +280 -32
- data/app/controllers/activeadmin_mcp/mcp_controller.rb +0 -2
- data/app/models/activeadmin_mcp/api_token.rb +0 -2
- data/config/routes.rb +0 -2
- data/lib/activeadmin_mcp/action_catalog.rb +64 -0
- data/lib/activeadmin_mcp/action_definition.rb +183 -0
- data/lib/activeadmin_mcp/action_params.rb +78 -0
- data/lib/activeadmin_mcp/action_runner.rb +163 -0
- data/lib/activeadmin_mcp/action_schema.rb +66 -0
- data/lib/activeadmin_mcp/active_admin_ext.rb +39 -0
- data/lib/activeadmin_mcp/authorization.rb +0 -2
- data/lib/activeadmin_mcp/configuration.rb +0 -2
- data/lib/activeadmin_mcp/controller_dispatcher.rb +138 -0
- data/lib/activeadmin_mcp/engine.rb +6 -2
- data/lib/activeadmin_mcp/form_description.rb +149 -0
- data/lib/activeadmin_mcp/form_field_collector.rb +68 -15
- data/lib/activeadmin_mcp/record_writer.rb +161 -0
- data/lib/activeadmin_mcp/request_handler.rb +149 -38
- data/lib/activeadmin_mcp/resource_registry.rb +0 -2
- data/lib/activeadmin_mcp/version.rb +1 -3
- data/lib/activeadmin_mcp.rb +9 -3
- data/lib/generators/activeadmin_mcp/install/install_generator.rb +0 -2
- data/lib/generators/activeadmin_mcp/install/templates/initializer.rb +5 -2
- data/lib/generators/activeadmin_mcp/install/templates/mcp_api_tokens.rb +0 -2
- data/lib/generators/activeadmin_mcp/install/templates/migration.rb.erb +0 -2
- metadata +18 -10
- data/lib/activeadmin_mcp/record_updater.rb +0 -108
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ActiveadminMcp
|
|
4
|
-
# Updates a single ActiveAdmin-managed record, enforcing the same three gates
|
|
5
|
-
# the admin UI would: the resource must expose the update action, the current
|
|
6
|
-
# user must be authorized, and only fields the admin form permits are written.
|
|
7
|
-
class RecordUpdater
|
|
8
|
-
UPDATE = :update
|
|
9
|
-
|
|
10
|
-
# Raised internally when the resource's permitted params cannot be resolved.
|
|
11
|
-
class PermitError < StandardError; end
|
|
12
|
-
|
|
13
|
-
def initialize(resource:, current_user:)
|
|
14
|
-
@resource = resource
|
|
15
|
-
@current_user = current_user
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def call(id:, attributes:)
|
|
19
|
-
config = @resource[:config]
|
|
20
|
-
|
|
21
|
-
return error("Resource is not editable: #{@resource[:name]}") unless editable?(config)
|
|
22
|
-
|
|
23
|
-
record = @resource[:model].find_by(id: id)
|
|
24
|
-
return error("Record not found: #{@resource[:name]}##{id}") unless record
|
|
25
|
-
|
|
26
|
-
unless authorized?(config, record)
|
|
27
|
-
return error("Not authorized to update #{@resource[:name]}##{id}")
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
begin
|
|
31
|
-
permitted = permitted_attributes(config, attributes)
|
|
32
|
-
rescue PermitError => e
|
|
33
|
-
return error(e.message)
|
|
34
|
-
end
|
|
35
|
-
return error("No permitted attributes to update") if permitted.empty?
|
|
36
|
-
|
|
37
|
-
if record.update(permitted)
|
|
38
|
-
{
|
|
39
|
-
resource: @resource[:name],
|
|
40
|
-
id: record.id,
|
|
41
|
-
updated: permitted.keys,
|
|
42
|
-
record: record.as_json,
|
|
43
|
-
}
|
|
44
|
-
else
|
|
45
|
-
error("Validation failed", details: record.errors.full_messages)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
private
|
|
50
|
-
|
|
51
|
-
def editable?(config)
|
|
52
|
-
config.defined_actions.include?(UPDATE)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def authorized?(config, record)
|
|
56
|
-
Authorization.for(config, @current_user).authorized?(UPDATE, record)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Resolves the fields we may write, accepting exactly what the admin form
|
|
60
|
-
# accepts. Prefers the resource's own `permit_params` (via the controller's
|
|
61
|
-
# compiled permitted_params); when a resource declares its writable fields
|
|
62
|
-
# through a `form do ... end` block instead — as ActiveAdmin's default
|
|
63
|
-
# permitted_params then returns nil — derives them from the form inputs.
|
|
64
|
-
# Fails closed if neither can be resolved.
|
|
65
|
-
def permitted_attributes(config, attributes)
|
|
66
|
-
from_permit_params(config, attributes) ||
|
|
67
|
-
from_form(config, attributes) ||
|
|
68
|
-
raise(PermitError, "Could not determine permitted attributes: #{@resource[:name]}")
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def from_permit_params(config, attributes)
|
|
72
|
-
param_key = config.param_key.to_sym
|
|
73
|
-
controller = config.controller.new
|
|
74
|
-
return nil unless controller.respond_to?(:permitted_params, true)
|
|
75
|
-
|
|
76
|
-
controller.params = ActionController::Parameters.new(param_key => attributes)
|
|
77
|
-
permitted = controller.send(:permitted_params)
|
|
78
|
-
scoped = permitted && permitted[param_key]
|
|
79
|
-
scoped ? scoped.to_h.symbolize_keys : nil
|
|
80
|
-
rescue StandardError
|
|
81
|
-
nil
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def from_form(config, attributes)
|
|
85
|
-
fields = form_fields(config)
|
|
86
|
-
return nil if fields.empty?
|
|
87
|
-
|
|
88
|
-
ActionController::Parameters.new(attributes).permit(*fields).to_h.symbolize_keys
|
|
89
|
-
rescue StandardError
|
|
90
|
-
nil
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def form_fields(config)
|
|
94
|
-
return [] unless config.respond_to?(:page_presenters)
|
|
95
|
-
|
|
96
|
-
block = config.page_presenters[:form]&.block
|
|
97
|
-
return [] unless block
|
|
98
|
-
|
|
99
|
-
FormFieldCollector.new.collect(&block)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def error(message, details: nil)
|
|
103
|
-
result = { error: message }
|
|
104
|
-
result[:details] = details if details
|
|
105
|
-
result
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|