marty 2.3.15 → 2.4.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/Gemfile.lock +2 -2
- data/app/components/marty/api_auth_view.rb +27 -4
- data/app/components/marty/api_config_view.rb +27 -4
- data/app/components/marty/extras/layout.rb +4 -7
- data/app/components/marty/form.rb +8 -0
- data/app/components/marty/grid.rb +45 -19
- data/app/components/marty/main_auth_app.rb +12 -11
- data/app/controllers/marty/rpc_controller.rb +63 -150
- data/app/models/marty/api_auth.rb +86 -14
- data/app/models/marty/api_config.rb +11 -6
- data/app/models/marty/delorean_rule.rb +3 -2
- data/config/routes.rb +1 -1
- data/db/migrate/501_add_api_class_to_marty_api_config.rb +6 -0
- data/db/migrate/502_add_parameters_to_marty_api_auth.rb +5 -0
- data/lib/marty/util.rb +0 -15
- data/lib/marty/version.rb +1 -1
- data/other/marty/api/base.rb +207 -0
- data/other/marty/diagnostic/aws/ec2_instance.rb +12 -87
- data/other/marty/diagnostic/environment_variables.rb +1 -1
- data/spec/controllers/job_controller_spec.rb +1 -1
- data/spec/dummy/app/components/gemini/xyz_rule_view.rb +1 -0
- data/spec/dummy/config/application.rb +1 -0
- data/spec/features/enum_spec.rb +35 -100
- data/spec/features/log_view_spec.rb +5 -5
- data/spec/features/rule_spec.rb +30 -30
- data/spec/features/user_view_spec.rb +0 -2
- data/spec/lib/logger_spec.rb +1 -1
- data/spec/models/api_auth_spec.rb +33 -12
- data/spec/models/event_spec.rb +1 -1
- data/spec/models/promise_spec.rb +1 -1
- data/spec/models/user_spec.rb +6 -6
- data/spec/spec_helper.rb +69 -9
- data/spec/support/{shared_connection_db_helpers.rb → clean_db_helpers.rb} +2 -2
- data/spec/support/delayed_job_helpers.rb +1 -1
- data/spec/support/{users.rb → integration_helpers.rb} +9 -11
- data/spec/support/{setup.rb → spec_setup.rb} +6 -19
- data/spec/support/user_helpers.rb +12 -0
- metadata +10 -21
- data/spec/dummy/app/assets/client/application.css +0 -13
- data/spec/dummy/app/assets/client/application.js +0 -15
- data/spec/support/chromedriver.rb +0 -41
- data/spec/support/components/netzke_combobox.rb +0 -57
- data/spec/support/components/netzke_grid.rb +0 -356
- data/spec/support/custom_matchers.rb +0 -18
- data/spec/support/custom_selectors.rb +0 -49
- data/spec/support/download_helper.rb +0 -52
- data/spec/support/helper.rb +0 -20
- data/spec/support/netzke.rb +0 -306
- data/spec/support/performance_helper.rb +0 -26
- data/spec/support/post_run_logger.rb +0 -32
- data/spec/support/shared_connection.rb +0 -31
- data/spec/support/structure_compare.rb +0 -62
- data/spec/support/suite.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d6215dc0386a1fa52611c23d576350432d8dc8867f72dec1a7865717182e9e5
|
4
|
+
data.tar.gz: 66fe4f011556128fe04d5b897f653db57eb6032c4ef3f440ab363c105f0052ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bde7326c5b29b7561371316e43207ded0b9d5b4246b5eb6948aa711eef74fc7e5fbed0fdf5758b61e7eb1549f0109ada0bcfed3910f86dc4e0cf4eeff128153
|
7
|
+
data.tar.gz: 4b2a99929bb2f8fcf4bd75a3b719c3c689dc3cd5e6e04726ea6e6fd07e900bcce821aaec76071d9befd33f604e9a3d4c3884bb0d0051a64669a5dd5c80ccfdd7
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
marty (2.
|
4
|
+
marty (2.4.0)
|
5
5
|
aws-sigv4 (~> 1.0, >= 1.0.2)
|
6
6
|
axlsx (= 3.0.0pre)
|
7
7
|
coderay
|
@@ -106,7 +106,7 @@ GEM
|
|
106
106
|
i18n (0.9.5)
|
107
107
|
concurrent-ruby (~> 1.0)
|
108
108
|
io-like (0.3.0)
|
109
|
-
json-schema (2.8.
|
109
|
+
json-schema (2.8.0)
|
110
110
|
addressable (>= 2.4)
|
111
111
|
loofah (2.2.2)
|
112
112
|
crass (~> 1.0.2)
|
@@ -7,14 +7,37 @@ class Marty::ApiAuthView < Marty::McflyGridPanel
|
|
7
7
|
def configure(c)
|
8
8
|
super
|
9
9
|
|
10
|
-
c.title
|
11
|
-
c.
|
12
|
-
c.
|
10
|
+
c.title = I18n.t('api_auth', default: "API Authorization")
|
11
|
+
c.editing = :in_form
|
12
|
+
c.pagination = :pagination
|
13
|
+
c.model = "Marty::ApiAuth"
|
14
|
+
c.attributes = [:aws, :entity_name, :api_key, :script_name]
|
13
15
|
c.store_config.merge!({sorters: [{property: :app_name, direction: 'ASC'}]})
|
14
16
|
end
|
15
17
|
|
16
|
-
attribute :
|
18
|
+
attribute :aws do |c|
|
19
|
+
c.width = 60
|
20
|
+
c.read_only = true
|
21
|
+
c.text = "AWS"
|
22
|
+
c.type = :boolean
|
23
|
+
c.getter = lambda do |r|
|
24
|
+
!!r.parameters['aws_api_key']
|
25
|
+
end
|
26
|
+
c.sorting_scope = get_json_sorter('parameters', 'aws_api_key')
|
27
|
+
c.filterable = true
|
28
|
+
c.filter_with = lambda do |rel, value, op|
|
29
|
+
rel.where("parameters->>'aws_api_key' IS #{value ? 'NOT' : ''} NULL")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
attribute :entity_name do |c|
|
17
34
|
c.flex = 1
|
35
|
+
c.text = "Entity Name"
|
36
|
+
c.getter = lambda do |r|
|
37
|
+
aws = !!r.parameters['aws_api_key']
|
38
|
+
entity = r.entity
|
39
|
+
entity ? entity.name : (aws ? nil : r.app_name)
|
40
|
+
end
|
18
41
|
end
|
19
42
|
|
20
43
|
attribute :api_key do |c|
|
@@ -12,6 +12,7 @@ class Marty::ApiConfigView < Marty::Grid
|
|
12
12
|
:script,
|
13
13
|
:node,
|
14
14
|
:attr,
|
15
|
+
:api_class,
|
15
16
|
:logged,
|
16
17
|
:input_validated,
|
17
18
|
:output_validated,
|
@@ -19,15 +20,33 @@ class Marty::ApiConfigView < Marty::Grid
|
|
19
20
|
:created_at,
|
20
21
|
:updated_at,
|
21
22
|
]
|
22
|
-
c.paging = :
|
23
|
+
c.paging = :pagination
|
23
24
|
c.editing = :in_form
|
24
25
|
c.store_config.merge!(
|
25
26
|
sorters: [{ property: :script, direction: :ASC},
|
26
|
-
{ property: :node,
|
27
|
-
{ property: :attr,
|
27
|
+
{ property: :node, direction: :ASC},
|
28
|
+
{ property: :attr, direction: :ASC},
|
29
|
+
{ property: :api_class, direction: :ASC},
|
28
30
|
])
|
29
31
|
@model = c.model
|
30
32
|
end
|
33
|
+
|
34
|
+
attribute :api_class do |c|
|
35
|
+
editor_config = {
|
36
|
+
trigger_action: :all,
|
37
|
+
xtype: :combo,
|
38
|
+
store: Marty::Api::Base.class_list,
|
39
|
+
forceSelection: true,
|
40
|
+
}
|
41
|
+
c.merge!(
|
42
|
+
column_config: { editor: editor_config },
|
43
|
+
field_config: editor_config,
|
44
|
+
type: :string,
|
45
|
+
)
|
46
|
+
c.width = 200
|
47
|
+
c.label = "API Class"
|
48
|
+
end
|
49
|
+
|
31
50
|
attribute :script do |c|
|
32
51
|
editor_config = {
|
33
52
|
trigger_action: :all,
|
@@ -43,34 +62,38 @@ class Marty::ApiConfigView < Marty::Grid
|
|
43
62
|
)
|
44
63
|
c.width = 150
|
45
64
|
end
|
65
|
+
|
46
66
|
[:node, :attr].each do |a|
|
47
67
|
attribute a do |c|
|
48
68
|
c.width = 150
|
49
69
|
c.setter = lambda { |r, v| r.send("#{a}=", v.blank? ? nil : v) }
|
50
70
|
end
|
51
71
|
end
|
72
|
+
|
52
73
|
[:logged, :input_validated, :output_validated, :strict_validate].each do
|
53
74
|
|a|
|
54
75
|
attribute a do |c|
|
55
76
|
c.width = 110
|
56
77
|
end
|
57
78
|
end
|
79
|
+
|
58
80
|
[:created_at, :updated_at].each do |a|
|
59
81
|
attribute a do |c|
|
60
82
|
c.read_only = true
|
61
83
|
end
|
62
84
|
end
|
85
|
+
|
63
86
|
def default_form_items
|
64
87
|
[
|
65
88
|
:script,
|
66
89
|
:node,
|
67
90
|
:attr,
|
91
|
+
:api_class,
|
68
92
|
:logged,
|
69
93
|
:input_validated,
|
70
94
|
:output_validated,
|
71
95
|
:strict_validate,
|
72
96
|
]
|
73
97
|
end
|
74
|
-
|
75
98
|
end
|
76
99
|
ApiConfigView = Marty::ApiConfigView
|
@@ -73,8 +73,7 @@ module Layout
|
|
73
73
|
######################################################################
|
74
74
|
# PG ENUM field handling
|
75
75
|
|
76
|
-
def enum_column(c, class_or_array
|
77
|
-
col ||= c.name.demodulize.tableize.singularize
|
76
|
+
def enum_column(c, class_or_array)
|
78
77
|
vals = class_or_array.is_a?(Array) ? class_or_array : class_or_array::VALUES
|
79
78
|
editor_config = {
|
80
79
|
trigger_action: :all,
|
@@ -92,7 +91,6 @@ module Layout
|
|
92
91
|
field_config: editor_config,
|
93
92
|
type: :string,
|
94
93
|
setter: enum_setter(c.name),
|
95
|
-
sorting_scope: get_sorter(col)
|
96
94
|
)
|
97
95
|
end
|
98
96
|
|
@@ -114,10 +112,6 @@ module Layout
|
|
114
112
|
lambda {|r, v| r.send("#{name}=", v.blank? || v == '---' ? nil : v)}
|
115
113
|
end
|
116
114
|
|
117
|
-
def get_sorter(col)
|
118
|
-
lambda {|rel, dir| rel.order("#{col}::text #{dir.to_s}")}
|
119
|
-
end
|
120
|
-
|
121
115
|
######################################################################
|
122
116
|
# employ lots of hakery to implement NULLable boolean field in
|
123
117
|
# Netzke 8.x.
|
@@ -203,4 +197,7 @@ module Layout
|
|
203
197
|
c.align = 'right'
|
204
198
|
end
|
205
199
|
|
200
|
+
def tooltip s1, s2
|
201
|
+
"<span data-qtip=\"#{s2}\">#{s1}</span>"
|
202
|
+
end
|
206
203
|
end; end; end
|
@@ -13,6 +13,28 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
13
13
|
end
|
14
14
|
|
15
15
|
client_class do |c|
|
16
|
+
c.get_component = l(<<-JS)
|
17
|
+
function(name) {
|
18
|
+
return Ext.getCmp(name);
|
19
|
+
}
|
20
|
+
JS
|
21
|
+
|
22
|
+
c.find_component = l(<<-JS)
|
23
|
+
function(name) {
|
24
|
+
return Ext.ComponentQuery.query(`[name=${name}]`)[0];
|
25
|
+
}
|
26
|
+
JS
|
27
|
+
|
28
|
+
c.toggle_component_actions = l(<<-JS)
|
29
|
+
function(prefix, flag) {
|
30
|
+
for (var key in this.actions) {
|
31
|
+
if (key.substring(0, prefix.length) == prefix) {
|
32
|
+
this.actions[key].setDisabled(flag);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
JS
|
37
|
+
|
16
38
|
c.init_component = l(<<-JS)
|
17
39
|
function() {
|
18
40
|
this.dockedItems = this.dockedItems || [];
|
@@ -48,8 +70,7 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
48
70
|
var me = this;
|
49
71
|
|
50
72
|
var children = me.serverConfig.child_components || [];
|
51
|
-
me.
|
52
|
-
'selectionchange',
|
73
|
+
me.onSelectionChange(
|
53
74
|
function(m) {
|
54
75
|
var has_sel = m.hasSelection();
|
55
76
|
|
@@ -66,18 +87,15 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
66
87
|
}
|
67
88
|
|
68
89
|
me.serverConfig.selected = rid;
|
69
|
-
|
70
|
-
for (var key in me.actions) {
|
71
|
-
// hacky -- assumes our functions start with "do"
|
72
|
-
if (key.substring(0, 2) == "do") {
|
73
|
-
me.actions[key].setDisabled(!has_sel);
|
74
|
-
}
|
75
|
-
}
|
90
|
+
me.toggleComponentActions('do', !has_sel);
|
76
91
|
|
77
92
|
for (var child of children) {
|
78
|
-
var comp = me.
|
93
|
+
var comp = me.getComponent(child)
|
79
94
|
if (comp) {
|
80
95
|
comp.serverConfig.parent_id = rid;
|
96
|
+
if (comp.toggleComponentActions) {
|
97
|
+
comp.toggleComponentActions('parent', !has_sel);
|
98
|
+
}
|
81
99
|
if (comp.reload) { comp.reload() }
|
82
100
|
}
|
83
101
|
}
|
@@ -88,7 +106,7 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
88
106
|
for (var event of ['update', 'netzkerefresh']) {
|
89
107
|
store.on(event, function() {
|
90
108
|
for (var link of linked) {
|
91
|
-
var comp = me.
|
109
|
+
var comp = me.findComponent(link);
|
92
110
|
if (comp && comp.reload) { comp.reload() }
|
93
111
|
}
|
94
112
|
}, this);
|
@@ -96,6 +114,15 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
96
114
|
}
|
97
115
|
JS
|
98
116
|
|
117
|
+
c.on_selection_change = l(<<-JS)
|
118
|
+
function(f) {
|
119
|
+
var me = this;
|
120
|
+
me.getSelectionModel().on('selectionchange', function(m) {
|
121
|
+
f(m);
|
122
|
+
});
|
123
|
+
}
|
124
|
+
JS
|
125
|
+
|
99
126
|
c.do_view_in_form = l(<<-JS)
|
100
127
|
function(record){
|
101
128
|
this.netzkeLoadComponent("view_window", {
|
@@ -123,7 +150,7 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
123
150
|
var children = me.serverConfig.child_components || [];
|
124
151
|
this.store.reload();
|
125
152
|
for (child of children) {
|
126
|
-
var comp = me.
|
153
|
+
var comp = me.getComponent(child);
|
127
154
|
if (comp && comp.reload) { comp.reload() }
|
128
155
|
}
|
129
156
|
}
|
@@ -134,13 +161,6 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
134
161
|
this.filters.clearFilters();
|
135
162
|
}
|
136
163
|
JS
|
137
|
-
|
138
|
-
c.netzkeGetComponentFromParent = l(<<-JS)
|
139
|
-
function(component_path) {
|
140
|
-
return this.netzkeGetParentComponent().netzkeGetComponent(component_path);
|
141
|
-
}
|
142
|
-
JS
|
143
|
-
|
144
164
|
end
|
145
165
|
|
146
166
|
######################################################################
|
@@ -168,6 +188,12 @@ class Marty::Grid < ::Netzke::Grid::Base
|
|
168
188
|
false
|
169
189
|
end
|
170
190
|
|
191
|
+
action :clear_filters do |a|
|
192
|
+
a.text = "X"
|
193
|
+
a.tooltip = "Clear filters"
|
194
|
+
a.handler = :clear_filters
|
195
|
+
end
|
196
|
+
|
171
197
|
def get_json_sorter(json_col, field)
|
172
198
|
lambda do |r, dir|
|
173
199
|
r.order("#{json_col} ->> '#{field}' " + dir.to_s)
|
@@ -58,7 +58,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
58
58
|
[
|
59
59
|
{
|
60
60
|
text: 'API Management',
|
61
|
-
icon_cls: "fa fa-
|
61
|
+
icon_cls: "fa fa-fighter-jet glyph",
|
62
62
|
disabled: !self.class.has_admin_perm?,
|
63
63
|
menu: [
|
64
64
|
:api_auth_view,
|
@@ -215,17 +215,19 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
215
215
|
end
|
216
216
|
|
217
217
|
action :api_config_view do |a|
|
218
|
-
a.text
|
219
|
-
a.
|
220
|
-
a.
|
221
|
-
a.
|
218
|
+
a.text = 'API Config Management'
|
219
|
+
a.tooltip = 'Manage API behavior and settings'
|
220
|
+
a.handler = :netzke_load_component_by_action
|
221
|
+
a.icon_cls = "fa fa-sliders-h glyph"
|
222
|
+
a.disabled = !self.class.has_admin_perm?
|
222
223
|
end
|
223
224
|
|
224
225
|
action :api_log_view do |a|
|
225
|
-
a.text
|
226
|
-
a.
|
227
|
-
a.
|
228
|
-
a.
|
226
|
+
a.text = 'API Log View'
|
227
|
+
a.tooltip = 'View API logs'
|
228
|
+
a.handler = :netzke_load_component_by_action
|
229
|
+
a.icon_cls = "fa fa-pencil-alt glyph"
|
230
|
+
a.disabled = !self.class.has_admin_perm?
|
229
231
|
end
|
230
232
|
|
231
233
|
action :data_grid_view do |a|
|
@@ -285,7 +287,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
285
287
|
a.disabled = !self.class.has_admin_perm?
|
286
288
|
end
|
287
289
|
|
288
|
-
|
290
|
+
######################################################################
|
289
291
|
|
290
292
|
def bg_command(param)
|
291
293
|
e, root, p = ENV['RAILS_ENV'], Rails.root, Marty::Config["RUBY_PATH"]
|
@@ -480,7 +482,6 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
480
482
|
});
|
481
483
|
}
|
482
484
|
JS
|
483
|
-
|
484
485
|
end
|
485
486
|
|
486
487
|
action :select_posting do |a|
|
@@ -1,63 +1,53 @@
|
|
1
1
|
class Marty::RpcController < ActionController::Base
|
2
2
|
def evaluate
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
params["background"],
|
10
|
-
)
|
11
|
-
respond_to do |format|
|
12
|
-
format.json { send_data res.to_json }
|
13
|
-
format.csv {
|
14
|
-
# SEMI-HACKY: strip outer list if there's only one element.
|
15
|
-
res = res[0] if res.is_a?(Array) && res.length==1
|
16
|
-
send_data Marty::DataExporter.to_csv(res)
|
17
|
-
}
|
18
|
-
end
|
19
|
-
end
|
3
|
+
massaged_params = massage_params(params)
|
4
|
+
api_config = Marty::ApiConfig.lookup(*massaged_params.values_at(
|
5
|
+
:script,
|
6
|
+
:node,
|
7
|
+
:attr)
|
8
|
+
) || {}
|
20
9
|
|
21
|
-
|
22
|
-
|
23
|
-
def get_schema(tag, sname, node, attr)
|
24
|
-
begin
|
25
|
-
Marty::ScriptSet.new(tag).get_engine(sname+'Schemas').
|
26
|
-
evaluate(node, attr, {})
|
27
|
-
rescue => e
|
28
|
-
use_message = e.message == 'No such script' ?
|
29
|
-
'Schema not defined' : 'Problem with schema: ' + e.message
|
30
|
-
raise "Schema error for #{sname}/#{node} attrs=#{attr}: #{use_message}"
|
31
|
-
end
|
32
|
-
end
|
10
|
+
api = api_config.present? ? api_config[:api_class].constantize :
|
11
|
+
Marty::Api::Base
|
33
12
|
|
34
|
-
|
35
|
-
|
36
|
-
return msg unless m
|
37
|
-
"disallowed parameter '#{m[1]}' of type #{m[2]} was received"
|
38
|
-
end
|
13
|
+
api.respond_to(self) do
|
14
|
+
next massaged_params if massaged_params.include?(:error)
|
39
15
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
16
|
+
auth = api.is_authorized?(massaged_params)
|
17
|
+
next {error: "Permission denied"} unless auth
|
18
|
+
|
19
|
+
start_time = Time.zone.now
|
20
|
+
|
21
|
+
api_params = api.process_params(massaged_params)
|
22
|
+
api.before_evaluate(api_params)
|
23
|
+
result = api.evaluate(api_params.deep_dup, request, api_config.deep_dup)
|
24
|
+
api.after_evaluate(api_params.deep_dup, result)
|
25
|
+
|
26
|
+
log_params = {start_time: start_time, auth: auth}
|
27
|
+
api.log(result, api_params + log_params, request) if
|
28
|
+
api_config[:logged]
|
29
|
+
|
30
|
+
result
|
53
31
|
end
|
54
32
|
end
|
55
33
|
|
56
|
-
|
57
|
-
|
58
|
-
|
34
|
+
private
|
35
|
+
|
36
|
+
def massage_params request_params
|
37
|
+
sname,
|
38
|
+
tag,
|
39
|
+
node,
|
40
|
+
attr,
|
41
|
+
params,
|
42
|
+
api_key,
|
43
|
+
background = request_params.values_at(:script,
|
44
|
+
:tag,
|
45
|
+
:node,
|
46
|
+
:attrs,
|
47
|
+
:params,
|
48
|
+
:api_key,
|
49
|
+
:background)
|
59
50
|
|
60
|
-
def do_eval(sname, tag, node, attr, params, api_key, background)
|
61
51
|
# FIXME: small patch to allow for single attr array
|
62
52
|
attr = ActiveSupport::JSON.decode(attr) rescue attr
|
63
53
|
|
@@ -66,116 +56,39 @@ class Marty::RpcController < ActionController::Base
|
|
66
56
|
|
67
57
|
# if attr is a single attr array, remember to return as an array
|
68
58
|
if attr.is_a? Array
|
69
|
-
attr
|
59
|
+
attr = attr[0]
|
70
60
|
ret_arr = true
|
71
61
|
end
|
72
62
|
|
73
|
-
start_time = Time.zone.now
|
74
63
|
return {error: "Malformed attrs"} unless attr =~ /\A[a-z][a-zA-Z0-9_]*\z/
|
75
|
-
return {error: "Bad params"} unless params.is_a?(String)
|
76
64
|
|
77
65
|
begin
|
78
|
-
|
79
|
-
|
66
|
+
case params
|
67
|
+
when String
|
68
|
+
params = ActiveSupport::JSON.decode(params)
|
69
|
+
when ActionController::Parameters
|
70
|
+
params.permit!
|
71
|
+
params = JSON.parse(params.to_h.to_json)
|
72
|
+
when nil
|
73
|
+
params = {}
|
74
|
+
else
|
75
|
+
return {error: "Bad params"}
|
76
|
+
end
|
80
77
|
rescue JSON::ParserError => e
|
81
78
|
return {error: "Malformed params"}
|
82
79
|
end
|
83
80
|
|
84
81
|
return {error: "Malformed params"} unless params.is_a?(Hash)
|
85
|
-
need_log,
|
86
|
-
need_input_validate,
|
87
|
-
need_output_validate,
|
88
|
-
need_strict_validate = Marty::ApiConfig.lookup(sname, node, attr)
|
89
|
-
opt = {validate_schema: true,
|
90
|
-
errors_as_objects: true,
|
91
|
-
version: Marty::JsonSchema::RAW_URI }
|
92
|
-
to_append = {"\$schema" => Marty::JsonSchema::RAW_URI}
|
93
|
-
validation_error = nil
|
94
|
-
|
95
|
-
if need_input_validate
|
96
|
-
begin
|
97
|
-
schema = get_schema(tag, sname, node, attr)
|
98
|
-
rescue => e
|
99
|
-
return {error: e.message}
|
100
|
-
end
|
101
|
-
begin
|
102
|
-
er = JSON::Validator.
|
103
|
-
fully_validate(schema.merge(to_append), params, opt)
|
104
|
-
rescue NameError
|
105
|
-
return {error: "Unrecognized PgEnum for attribute #{attr}"}
|
106
|
-
rescue => ex
|
107
|
-
return {error: "#{attr}: #{ex.message}"}
|
108
|
-
end
|
109
|
-
validation_error = get_errors(er) if er.size > 0
|
110
|
-
end
|
111
|
-
return {error: "Error(s) validating: #{validation_error}"} if
|
112
|
-
validation_error
|
113
|
-
|
114
|
-
auth = Marty::ApiAuth.authorized?(sname, api_key)
|
115
|
-
return {error: "Permission denied" } unless auth
|
116
82
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
begin
|
129
|
-
if background
|
130
|
-
result = engine.background_eval(node, params, attr)
|
131
|
-
return retval = {"job_id" => result.__promise__.id}
|
132
|
-
end
|
133
|
-
|
134
|
-
res = engine.evaluate(node, attr, params)
|
135
|
-
|
136
|
-
if need_output_validate && !(res.is_a?(Hash) && res['error'])
|
137
|
-
begin
|
138
|
-
schema = get_schema(tag, sname, node, attr + '_')
|
139
|
-
rescue => e
|
140
|
-
return {error: e.message}
|
141
|
-
end
|
142
|
-
|
143
|
-
begin
|
144
|
-
er = JSON::Validator.fully_validate(schema.merge(to_append), res, opt)
|
145
|
-
rescue NameError
|
146
|
-
return {error: "Unrecognized PgEnum for attribute #{attr}"}
|
147
|
-
rescue => ex
|
148
|
-
return {error: "#{attr}: #{ex.message}"}
|
149
|
-
end
|
150
|
-
|
151
|
-
if er.size > 0
|
152
|
-
errors = er.map{|e| e[:message]}
|
153
|
-
Marty::Logger.error("API #{sname}:#{node}.#{attr}",
|
154
|
-
{error: errors, data: res})
|
155
|
-
res = need_strict_validate ? {error: "Error(s) validating: #{errors}",
|
156
|
-
data: res} : res
|
157
|
-
end
|
158
|
-
end
|
159
|
-
return retval = ret_arr ? [res] : res
|
160
|
-
rescue => exc
|
161
|
-
err_msg = Delorean::Engine.grok_runtime_exception(exc).symbolize_keys
|
162
|
-
logger.info "Evaluation error: #{err_msg}"
|
163
|
-
return retval = err_msg
|
164
|
-
ensure
|
165
|
-
error = Hash === retval ? retval[:error] : nil
|
166
|
-
Marty::Log.write_log('api',
|
167
|
-
"#{sname} - #{node}",
|
168
|
-
{script: sname,
|
169
|
-
node: node,
|
170
|
-
attrs: (ret_arr ? [attr] : attr),
|
171
|
-
input: orig_params,
|
172
|
-
output: error ? nil : retval,
|
173
|
-
start_time: start_time,
|
174
|
-
end_time: Time.zone.now,
|
175
|
-
error: error,
|
176
|
-
remote_ip: request.remote_ip,
|
177
|
-
auth_name: auth
|
178
|
-
}) if need_log.present?
|
179
|
-
end
|
83
|
+
{
|
84
|
+
script: sname,
|
85
|
+
tag: tag,
|
86
|
+
node: node,
|
87
|
+
attr: attr,
|
88
|
+
params: params,
|
89
|
+
api_key: api_key,
|
90
|
+
background: background,
|
91
|
+
return_array: ret_arr
|
92
|
+
}
|
180
93
|
end
|
181
94
|
end
|