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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/app/components/marty/api_auth_view.rb +27 -4
  4. data/app/components/marty/api_config_view.rb +27 -4
  5. data/app/components/marty/extras/layout.rb +4 -7
  6. data/app/components/marty/form.rb +8 -0
  7. data/app/components/marty/grid.rb +45 -19
  8. data/app/components/marty/main_auth_app.rb +12 -11
  9. data/app/controllers/marty/rpc_controller.rb +63 -150
  10. data/app/models/marty/api_auth.rb +86 -14
  11. data/app/models/marty/api_config.rb +11 -6
  12. data/app/models/marty/delorean_rule.rb +3 -2
  13. data/config/routes.rb +1 -1
  14. data/db/migrate/501_add_api_class_to_marty_api_config.rb +6 -0
  15. data/db/migrate/502_add_parameters_to_marty_api_auth.rb +5 -0
  16. data/lib/marty/util.rb +0 -15
  17. data/lib/marty/version.rb +1 -1
  18. data/other/marty/api/base.rb +207 -0
  19. data/other/marty/diagnostic/aws/ec2_instance.rb +12 -87
  20. data/other/marty/diagnostic/environment_variables.rb +1 -1
  21. data/spec/controllers/job_controller_spec.rb +1 -1
  22. data/spec/dummy/app/components/gemini/xyz_rule_view.rb +1 -0
  23. data/spec/dummy/config/application.rb +1 -0
  24. data/spec/features/enum_spec.rb +35 -100
  25. data/spec/features/log_view_spec.rb +5 -5
  26. data/spec/features/rule_spec.rb +30 -30
  27. data/spec/features/user_view_spec.rb +0 -2
  28. data/spec/lib/logger_spec.rb +1 -1
  29. data/spec/models/api_auth_spec.rb +33 -12
  30. data/spec/models/event_spec.rb +1 -1
  31. data/spec/models/promise_spec.rb +1 -1
  32. data/spec/models/user_spec.rb +6 -6
  33. data/spec/spec_helper.rb +69 -9
  34. data/spec/support/{shared_connection_db_helpers.rb → clean_db_helpers.rb} +2 -2
  35. data/spec/support/delayed_job_helpers.rb +1 -1
  36. data/spec/support/{users.rb → integration_helpers.rb} +9 -11
  37. data/spec/support/{setup.rb → spec_setup.rb} +6 -19
  38. data/spec/support/user_helpers.rb +12 -0
  39. metadata +10 -21
  40. data/spec/dummy/app/assets/client/application.css +0 -13
  41. data/spec/dummy/app/assets/client/application.js +0 -15
  42. data/spec/support/chromedriver.rb +0 -41
  43. data/spec/support/components/netzke_combobox.rb +0 -57
  44. data/spec/support/components/netzke_grid.rb +0 -356
  45. data/spec/support/custom_matchers.rb +0 -18
  46. data/spec/support/custom_selectors.rb +0 -49
  47. data/spec/support/download_helper.rb +0 -52
  48. data/spec/support/helper.rb +0 -20
  49. data/spec/support/netzke.rb +0 -306
  50. data/spec/support/performance_helper.rb +0 -26
  51. data/spec/support/post_run_logger.rb +0 -32
  52. data/spec/support/shared_connection.rb +0 -31
  53. data/spec/support/structure_compare.rb +0 -62
  54. data/spec/support/suite.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a297a85d0d4cdfde6d667e399b64684900dba8e9b9faaffa355737c8c5c5678b
4
- data.tar.gz: 46c85fe0f1c7de9d3fba4d55b216d3e7daa24cc6a9f76cf1d75befb15cdf5284
3
+ metadata.gz: 8d6215dc0386a1fa52611c23d576350432d8dc8867f72dec1a7865717182e9e5
4
+ data.tar.gz: 66fe4f011556128fe04d5b897f653db57eb6032c4ef3f440ab363c105f0052ef
5
5
  SHA512:
6
- metadata.gz: ac982f3abebddb0f92269d41eed6c100c297feac1a9726693abaeba7b93b3d0c281525f2df3ed7d94d43e67a12a95eb2782f65d8010ab94e4e4157b43bb5bbf6
7
- data.tar.gz: f4816a56f8b3b61f72acb67faeffdd17f55010db418ab520f60f11c2058c123928c54e813c78e28c9b22a94b45620ea84568b091de90b41352735334da6658a7
6
+ metadata.gz: 8bde7326c5b29b7561371316e43207ded0b9d5b4246b5eb6948aa711eef74fc7e5fbed0fdf5758b61e7eb1549f0109ada0bcfed3910f86dc4e0cf4eeff128153
7
+ data.tar.gz: 4b2a99929bb2f8fcf4bd75a3b719c3c689dc3cd5e6e04726ea6e6fd07e900bcce821aaec76071d9befd33f604e9a3d4c3884bb0d0051a64669a5dd5c80ccfdd7
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- marty (2.3.15)
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.1)
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 = I18n.t('api_auth', default: "API Authorization")
11
- c.model = "Marty::ApiAuth"
12
- c.attributes = [:app_name, :api_key, :script_name]
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 :app_name do |c|
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 = :pageination
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, direction: :ASC},
27
- { property: :attr, direction: :ASC},
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, col=nil)
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
@@ -1,3 +1,11 @@
1
1
  class Marty::Form < Netzke::Form::Base
2
2
  extend ::Marty::Permissions
3
+
4
+ client_class do |c|
5
+ c.find_component = l(<<-JS)
6
+ function(name) {
7
+ return Ext.ComponentQuery.query(`[name=${name}]`)[0];
8
+ }
9
+ JS
10
+ end
3
11
  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.getSelectionModel().on(
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.netzkeGetComponentFromParent(child);
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.netzkeGetComponentFromParent(link);
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.netzkeGetComponentFromParent(child);
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-wrench glyph",
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 = 'API Config Management'
219
- a.handler = :netzke_load_component_by_action
220
- a.icon_cls = "fa fa-cogs glyph"
221
- a.disabled = !self.class.has_admin_perm?
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 = 'API Log View'
226
- a.handler = :netzke_load_component_by_action
227
- a.icon_cls = "fa fa-cogs glyph"
228
- a.disabled = !self.class.has_admin_perm?
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
- res = do_eval(params["script"],
4
- params["tag"],
5
- params["node"],
6
- params["attrs"] || "[]",
7
- params["params"] || "{}",
8
- params["api_key"] || nil,
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
- private
22
- # FIXME: move to (probably) agrim's schema code in lib
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
- def massage_message(msg)
35
- m = %r|'#/([^']+)' of type ([^ ]+) matched the disallowed schema|.match(msg)
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
- def _get_errors(errs)
41
- if errs.is_a?(Array)
42
- errs.map { |err| _get_errors(err) }
43
- elsif errs.is_a?(Hash)
44
- if !errs.include?(:failed_attribute)
45
- errs.map { |k, v| _get_errors(v) }
46
- else
47
- fa, fragment, message, errors = errs.values_at(:failed_attribute,
48
- :fragment,
49
- :message, :errors)
50
- ((['AllOf','AnyOf','Not'].include?(fa) && fragment =='#/') ?
51
- [] : [massage_message(message)]) + _get_errors(errors || {})
52
- end
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
- def get_errors(errs)
57
- _get_errors(errs).flatten
58
- end
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 = attr[0]
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
- params = ActiveSupport::JSON.decode(params)
79
- orig_params = params.clone
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
- begin
118
- engine = Marty::ScriptSet.new(tag).get_engine(sname)
119
- rescue => e
120
- err_msg = "Can't get engine: #{sname || 'nil'} with tag: " +
121
- "#{tag || 'nil'}; message: #{e.message}"
122
- logger.info err_msg
123
- return {error: err_msg}
124
- end
125
-
126
- retval = nil
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