marty 2.5.7 → 2.5.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e21e7788214cabe5b48e33e15fbefcdbc30ba526f1a8870a3c5c7ab240b48b4d
4
- data.tar.gz: 285129ffcd5648deeaa816a7923efc6b146adc01ba2a75624f0a5944063c7372
3
+ metadata.gz: 17d4c8cca5e227120b347328f76f6b5c2844a3662fe4fa31c186d4ac5b422f9b
4
+ data.tar.gz: 5ae6f1ec90da4b1543ed781e2bd9b9ef88224d9b51bde8257f9e9188dc44b82c
5
5
  SHA512:
6
- metadata.gz: 16931641ca8a4478ee399f24fe50398989d35aae7353efebd550e371ad76d45de9faf465f4e139cf4bbb28ae5502fb734f0be49de1f9e054d2d85369c059b190
7
- data.tar.gz: de0f280f2a9d0077134e8d717d2e5882c0e35cb3909b9049b4127435b9cb34040bdc8de5081946be80e5085325aee769e48fe8906a919f07fcdc217486e2cf3e
6
+ metadata.gz: 5705fbd63836311b4f6b2847d9b2b2fe998a413980a5a795a98494f94e8dc0dda78dc0a3a05d994c821102e8bf8320afe6465393dd663674cb22b5cfa2b63a52
7
+ data.tar.gz: 806137fda06674d6d4fa937689a0da78898f1c4589ee1f52833030aea10537e48a76037ebbe2acc7a1c90eaccee1bb4d2af7ea325a09f93dbbc35028af5f37e9
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- marty (2.5.7)
4
+ marty (2.5.8)
5
5
  aws-sigv4 (~> 1.0, >= 1.0.2)
6
6
  axlsx (= 3.0.0pre)
7
7
  coderay
@@ -1,5 +1,6 @@
1
1
  class Marty::PromiseView < Netzke::Tree::Base
2
2
  extend ::Marty::Permissions
3
+ has_marty_permissions read: :any
3
4
 
4
5
  client_styles do |config|
5
6
  config.require :promise_view
@@ -15,11 +16,17 @@ class Marty::PromiseView < Netzke::Tree::Base
15
16
  c.include :promise_view
16
17
  end
17
18
 
18
- def configure(config)
19
+ ######################################################################
20
+
21
+ def class_can?(op)
22
+ self.class.can_perform_action?(op)
23
+ end
24
+
25
+ def configure(c)
19
26
  super
20
- config.title = I18n.t('jobs.promise_view')
21
- config.model = 'Marty::VwPromise'
22
- config.attributes = [
27
+ c.title = I18n.t('jobs.promise_view')
28
+ c.model = 'Marty::VwPromise'
29
+ c.attributes = [
23
30
  { name: :title, xtype: :treecolumn },
24
31
  :user__login,
25
32
  :job_id,
@@ -29,14 +36,17 @@ class Marty::PromiseView < Netzke::Tree::Base
29
36
  :cformat,
30
37
  :error,
31
38
  ]
32
- config.root_visible = false
33
- config.paging = :none
34
- config.bbar = bbar
35
- config.read_only = true
36
- config.permissions = { update: false,
37
- create: false,
38
- delete: false,
39
- }
39
+ c.root_visible = false
40
+ c.paging = :none
41
+ c.bbar = bbar
42
+ c.read_only = true
43
+ c.permissions = {
44
+ create: class_can?(:create),
45
+ read: class_can?(:read),
46
+ update: class_can?(:update),
47
+ delete: class_can?(:delete)
48
+ }
49
+
40
50
  # garbage collect old promises (hacky to do this here)
41
51
  Marty::Promise.cleanup(false)
42
52
  end
@@ -1,56 +1,54 @@
1
1
  class Marty::RpcController < ActionController::Base
2
+ INTERNAL_SERVER_ERROR = { error: 'internal server error' }
3
+ PERMISSION_DENIED_ERROR = { error: 'Permission denied' }
4
+
2
5
  def evaluate
3
- # set default result and params in case of unexpected errors
4
- # to ensure logging capabilities
5
- result = nil
6
- api_params = {}
7
- start_time = nil
8
- auth = nil
9
-
10
- # massage request params
11
- massaged_params = massage_params(params)
12
-
13
- # resolve api config in order to determine api class and settings
14
- api_config = Marty::ApiConfig.lookup(*massaged_params.values_at(
15
- :script,
16
- :node,
17
- :attr)
18
- ) || {}
19
-
20
- # default to base class if no config is present
21
- api = api_config.present? ? api_config[:api_class].constantize :
22
- Marty::Api::Base
23
-
24
- return result = massaged_params if massaged_params.include?(:error)
25
-
26
- api_params = api.process_params(massaged_params)
27
- auth = api.is_authorized?(api_params)
28
- return result = { error: 'Permission denied' } unless auth
29
-
30
- start_time = Time.zone.now
31
- api.before_evaluate(api_params)
32
- result = api.evaluate(api_params, request, api_config)
33
- api.after_evaluate(api_params, result)
34
- rescue StandardError => e
35
- # log unexpected failures in rpc controller and respond with
36
- # generic server error
37
- Marty::Logger.log('rpc_controller', 'failure', e.message)
38
- result = { error: 'internal server error' }
39
- ensure
40
- # if logging is enabled, always log the result even on error
41
- if api_config && api_config[:logged] && api
42
- api.log(result,
43
- api_params + { start_time: start_time, auth: auth },
44
- request)
45
- end
6
+ massaged_params = massage_params(params)
7
+
8
+ # resolve api config in order to determine api class and settings
9
+ api_config = get_api_config(massaged_params) || {}
10
+
11
+ # default to base class if no config is present
12
+ api = api_config[:api_class].try(:constantize) || Marty::Api::Base
13
+
14
+ api.respond_to(self) do
15
+ begin
16
+ next massaged_params if massaged_params.include?(:error)
17
+
18
+ api_params = api.process_params(massaged_params)
19
+ auth = api.is_authorized?(api_params)
20
+
21
+ next PERMISSION_DENIED_ERROR unless auth
46
22
 
47
- api.respond_to(self) do
48
- result || { 'error' => 'internal server error' }
23
+ # allow api classes to return hashes with error key for custom responses
24
+ next auth if auth.is_a?(Hash) && auth[:error]
25
+
26
+ start_time = Time.zone.now
27
+ api.before_evaluate(api_params)
28
+
29
+ result = api.evaluate(api_params, request, api_config)
30
+ api.after_evaluate(api_params, result)
31
+
32
+ if api_config[:logged]
33
+ log_params = api_params + { start_time: start_time, auth: auth }
34
+ api.log(result, log_params, request)
35
+ end
36
+
37
+ result
38
+ rescue StandardError => e
39
+ Marty::Logger.log('rpc_controller', 'failure', e.message)
40
+ INTERNAL_SERVER_ERROR
49
41
  end
42
+ end
50
43
  end
51
44
 
52
45
  private
53
46
 
47
+ def get_api_config params
48
+ config_attrs = params.values_at(:script, :node, :attr)
49
+ Marty::ApiConfig.lookup(*config_attrs)
50
+ end
51
+
54
52
  def process_active_params params
55
53
  # must permit params before conversion to_h
56
54
  # convert hash to json and parse to get expected hash (not indifferent)
@@ -53,6 +53,23 @@ class Marty::User < Marty::Base
53
53
  authenticate_with?(login, password) || nil
54
54
  end
55
55
 
56
+ def self.ldap_login(login, password)
57
+ # IMPORTANT NOTE: if server allows anonymous LDAP access, empty
58
+ # passwords will succeed! i.e. if a valid user with empty
59
+ # password is sent in, ldap.bind will return OK.
60
+ cf = Rails.configuration.marty.ldap
61
+ ldap = Net::LDAP.new(host: cf.host,
62
+ port: cf.port,
63
+ base: cf.base_dn,
64
+ encryption: cf.encryption,
65
+ auth: {
66
+ method: :simple,
67
+ username: cf.domain + '\\' + login,
68
+ password: password,
69
+ })
70
+ ldap.bind
71
+ end
72
+
56
73
  def self.authenticate_with?(login, password)
57
74
  cf = Rails.configuration.marty
58
75
 
@@ -61,20 +78,7 @@ class Marty::User < Marty::Base
61
78
  if auth_source == 'local'
62
79
  ok = password == cf.local_password
63
80
  elsif auth_source == 'ldap'
64
- # IMPORTANT NOTE: if server allows anonymous LDAP access, empty
65
- # passwords will succeed! i.e. if a valid user with empty
66
- # password is sent in, ldap.bind will return OK.
67
- cf = Rails.configuration.marty.ldap
68
- ldap = Net::LDAP.new(host: cf.host,
69
- port: cf.port,
70
- base: cf.base_dn,
71
- encryption: cf.encryption,
72
- auth: {
73
- method: :simple,
74
- username: cf.domain + '\\' + login,
75
- password: password,
76
- })
77
- ok = ldap.bind
81
+ ok = ldap_login(login, password)
78
82
  else
79
83
  raise "bad auth_source: #{auth_source.inspect}"
80
84
  end
@@ -1,3 +1,3 @@
1
1
  module Marty
2
- VERSION = '2.5.7'
2
+ VERSION = '2.5.8'
3
3
  end
@@ -168,25 +168,28 @@ class Marty::Api::Base
168
168
  return unless hash
169
169
 
170
170
  pf = ActionDispatch::Http::ParameterFilter.new(filter_params)
171
- pf.filter(hash)
171
+ pf.filter(hash.stringify_keys)
172
172
  end
173
173
 
174
174
  def self.log_hash result, params, request
175
- res = result.is_a?(Hash) ? result.stringify_keys : result
176
175
  ret_arr = params[:return_array]
176
+
177
+ # filter sensitive information from input/output
178
+ is_hash = result.is_a?(Hash)
179
+ res = is_hash ? filter_hash(result, engine_params_filter) : result
177
180
  input = filter_hash(params[:params], engine_params_filter)
181
+ error = res['error'] if is_hash && res.include?('error')
182
+
178
183
  { script: params[:script],
179
- node: params[:node],
180
- attrs: ret_arr ? [params[:attr]] : params[:attr],
181
- input: input,
182
- output: (res.is_a?(Hash) &&
183
- res.include?('error')) ? nil : res,
184
- start_time: params[:start_time],
185
- end_time: Time.zone.now,
186
- error: (res.is_a?(Hash) &&
187
- res.include?('error')) ? res['error'] : nil,
188
- remote_ip: request.remote_ip,
189
- auth_name: params[:auth]
184
+ node: params[:node],
185
+ attrs: ret_arr ? [params[:attr]] : params[:attr],
186
+ input: input,
187
+ output: error ? nil : res,
188
+ start_time: params[:start_time],
189
+ end_time: Time.zone.now,
190
+ error: error,
191
+ remote_ip: request.remote_ip,
192
+ auth_name: params[:auth]
190
193
  }
191
194
  end
192
195
 
@@ -1,4 +1,6 @@
1
1
  module Marty::Diagnostic; class DelayedJobWorkers < Base
2
+ DIAG_NAME = 'Delayed Workers / Node'
3
+ DIAG_CONFIG_TARGET = 'DIAG_DELAYED_TARGET'
2
4
  diagnostic_fn do
3
5
  my_ip = Node.my_ip
4
6
  workers = Database.current_connections.map do |c|
@@ -6,7 +8,16 @@ module Marty::Diagnostic; class DelayedJobWorkers < Base
6
8
  name = c['application_name']
7
9
  name if name.include?('delayed') && (ip == my_ip || ip == '127.0.0.1')
8
10
  end.compact.uniq.count
9
- { 'Delayed Workers / Node' => workers.zero? ? error(workers) : workers }
11
+
12
+ target_count = Marty::Config[DIAG_CONFIG_TARGET]
13
+
14
+ next { DIAG_NAME => workers.zero? ? error(workers) : workers } unless
15
+ target_count
16
+
17
+ next { DIAG_NAME => error("invalid type for #{DIAG_CONFIG_TARGET}") } unless
18
+ target_count.is_a?(Integer)
19
+
20
+ { DIAG_NAME => workers == target_count ? workers : error(workers) }
10
21
  end
11
22
  end
12
23
  end
@@ -2,12 +2,13 @@ require 'spec_helper'
2
2
  require 'job_helper'
3
3
 
4
4
  describe Marty::Diagnostic::DelayedJobWorkers do
5
- def sample_data ip = nil, error = false
5
+ def sample_data opts={}
6
+ ip, error, status = opts.values_at(:ip, :error, :status)
6
7
  {
7
8
  ip || Marty::Helper.my_ip => {
8
9
  'Delayed Workers / Node' => {
9
10
  'description' => error ? '3' : '4',
10
- 'status' => true,
11
+ 'status' => status,
11
12
  'consistent' => nil
12
13
  },
13
14
  }
@@ -16,10 +17,10 @@ describe Marty::Diagnostic::DelayedJobWorkers do
16
17
 
17
18
  def sample_aggregate error = false
18
19
  [
19
- sample_data(ip = '0.0.0.0'),
20
- sample_data(ip = '0.0.0.1'),
21
- sample_data(ip = '0.0.0.2', error = error),
22
- sample_data(ip = '0.0.0.3'),
20
+ sample_data(ip: '0.0.0.0'),
21
+ sample_data(ip: '0.0.0.1'),
22
+ sample_data(ip: '0.0.0.2', error: error),
23
+ sample_data(ip: '0.0.0.3'),
23
24
  ].reduce(:merge)
24
25
  end
25
26
 
@@ -37,8 +38,10 @@ describe Marty::Diagnostic::DelayedJobWorkers do
37
38
  expect(described_class.consistent?(inconsistent)).to eq(false)
38
39
  end
39
40
 
40
- it 'recognizes zero workers as an error' do
41
- data = described_class.generate.values[0]
42
- expect(data['Delayed Workers / Node']['status']).to eq(false)
41
+ it 'allows a config to set the target workers' do
42
+ Marty::Config['DIAG_DELAYED_TARGET'] = 2
43
+ start_delayed_job
44
+ expect(described_class.generate).to eq(sample_data(status: false))
45
+ stop_delayed_job
43
46
  end
44
47
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marty
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.7
4
+ version: 2.5.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arman Bostani
@@ -429,7 +429,6 @@ files:
429
429
  - other/marty/diagnostic/connections.rb
430
430
  - other/marty/diagnostic/database.rb
431
431
  - other/marty/diagnostic/delayed_job_version.rb
432
- - other/marty/diagnostic/delayed_job_worker_total_count.rb
433
432
  - other/marty/diagnostic/delayed_job_workers.rb
434
433
  - other/marty/diagnostic/environment_variables.rb
435
434
  - other/marty/diagnostic/fatal.rb
@@ -1,10 +0,0 @@
1
- module Marty::Diagnostic; class DelayedJobWorkerTotalCount < Base
2
- diagnostic_fn(aggregatable: false) do
3
- count = Database.current_connections.map do |c|
4
- [c['application_name'], c['client_addr'] || '127.0.0.1'] if
5
- c['application_name'].include?('delayed')
6
- end.compact.uniq.count
7
- { 'Delayed Workers' => count.zero? ? error(count) : count }
8
- end
9
- end
10
- end