marty 3.1.0 → 4.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -7
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +15 -2
- data/Dockerfile.dummy +0 -3
- data/Gemfile +15 -21
- data/Gemfile.lock +289 -0
- data/app/components/marty/data_grid_view.rb +18 -68
- data/app/components/marty/extras/layout.rb +1 -1
- data/app/components/marty/grid.rb +1 -1
- data/app/components/marty/import_view.rb +3 -3
- data/app/components/marty/main_auth_app.rb +1 -11
- data/app/components/marty/report_form.rb +6 -6
- data/app/components/marty/script_form.rb +5 -5
- data/app/components/marty/script_tester.rb +2 -2
- data/app/components/marty/user_view.rb +9 -3
- data/app/models/marty/data_grid.rb +11 -16
- data/app/models/marty/event.rb +2 -2
- data/app/models/marty/promise.rb +4 -4
- data/app/models/marty/role_type.rb +1 -14
- data/app/services/marty/data_grid_view/save_grid.rb +2 -2
- data/app/services/marty/promises/delorean/create.rb +2 -2
- data/app/services/marty/promises/ruby/create.rb +2 -2
- data/config/locales/en.yml +2 -11
- data/docker-compose.dummy.yml +0 -1
- data/lib/marty/content_handler.rb +2 -2
- data/lib/marty/data_change.rb +1 -1
- data/lib/marty/data_conversion.rb +4 -3
- data/lib/marty/data_importer.rb +4 -4
- data/lib/marty/mcfly_model.rb +10 -7
- data/lib/marty/migrations.rb +1 -1
- data/lib/marty/monkey.rb +2 -2
- data/lib/marty/promise_job.rb +5 -5
- data/lib/marty/promise_proxy.rb +2 -2
- data/lib/marty/promise_ruby_job.rb +4 -4
- data/lib/marty/version.rb +1 -1
- data/marty.gemspec +18 -13
- data/other/marty/diagnostic/aws/ec2_instance.rb +2 -17
- data/other/marty/diagnostic/database.rb +2 -2
- data/other/marty/diagnostic/delayed_job_version.rb +1 -0
- data/spec/dummy/app/models/gemini/fannie_bup.rb +20 -13
- data/spec/dummy/config/application.rb +0 -1
- data/spec/dummy/config/initializers/secret_token.rb +1 -1
- data/spec/features/data_grid_spec.rb +46 -109
- data/spec/features/reporting_spec.rb +4 -4
- data/spec/features/rule_spec.rb +1 -1
- data/spec/features/scripting_spec.rb +3 -3
- data/spec/features/user_view_spec.rb +8 -17
- data/spec/lib/data_importer_spec.rb +8 -8
- data/spec/lib/mcfly_model_spec.rb +6 -6
- data/spec/models/data_grid_spec.rb +4 -19
- data/spec/spec_helper.rb +2 -2
- data/spec/support/netzke.rb +3 -4
- metadata +53 -50
- data/.ssh-docker/.keep +0 -0
- data/app/components/marty/data_grid_user_view.rb +0 -39
- data/db/migrate/108_add_data_grid_perms.rb +0 -16
- data/other/marty/diagnostic/aws/error.rb +0 -8
data/lib/marty/migrations.rb
CHANGED
data/lib/marty/monkey.rb
CHANGED
@@ -54,8 +54,8 @@ class Delorean::BaseModule::NodeCall
|
|
54
54
|
begin
|
55
55
|
# make sure params is serialzable before starting a Job
|
56
56
|
JSON.dump(params)
|
57
|
-
rescue StandardError =>
|
58
|
-
raise "non-serializable parameters: #{params} #{
|
57
|
+
rescue StandardError => exc
|
58
|
+
raise "non-serializable parameters: #{params} #{exc}"
|
59
59
|
end
|
60
60
|
|
61
61
|
Marty::Promises::Delorean::Create.call(
|
data/lib/marty/promise_job.rb
CHANGED
@@ -41,9 +41,9 @@ class Marty::PromiseJob < Struct.new(:promise,
|
|
41
41
|
end
|
42
42
|
|
43
43
|
# log "DONE #{Process.pid} #{promise.id} #{Time.now.to_f} #{res}"
|
44
|
-
rescue StandardError =>
|
45
|
-
res = Delorean::Engine.grok_runtime_exception(
|
46
|
-
# log "ERR- #{Process.pid} #{promise.id} #{Time.now.to_f} #{
|
44
|
+
rescue StandardError => exc
|
45
|
+
res = Delorean::Engine.grok_runtime_exception(exc)
|
46
|
+
# log "ERR- #{Process.pid} #{promise.id} #{Time.now.to_f} #{exc}"
|
47
47
|
end
|
48
48
|
promise.set_result(res)
|
49
49
|
process_hook(res)
|
@@ -53,8 +53,8 @@ class Marty::PromiseJob < Struct.new(:promise,
|
|
53
53
|
return unless hook
|
54
54
|
|
55
55
|
hook.run(params: params, result: res)
|
56
|
-
rescue StandardError =>
|
57
|
-
Marty::Util.logger.error "promise hook failed: #{
|
56
|
+
rescue StandardError => exc
|
57
|
+
Marty::Util.logger.error "promise hook failed: #{exc}"
|
58
58
|
end
|
59
59
|
|
60
60
|
def max_attempts
|
data/lib/marty/promise_proxy.rb
CHANGED
@@ -55,8 +55,8 @@ class Marty::PromiseProxy < BasicObject
|
|
55
55
|
begin
|
56
56
|
@result = @promise.wait_for_result(@timeout)
|
57
57
|
@result = @result[@attr] if @attr && !@result['error']
|
58
|
-
rescue ::Exception =>
|
59
|
-
@result = ::Delorean::Engine.grok_runtime_exception(
|
58
|
+
rescue ::Exception => exc
|
59
|
+
@result = ::Delorean::Engine.grok_runtime_exception(exc)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -25,8 +25,8 @@ class Marty::PromiseRubyJob < Struct.new(:promise,
|
|
25
25
|
|
26
26
|
mod = module_name.constantize
|
27
27
|
res = { 'result' => mod.send(method_name, *method_args) }
|
28
|
-
rescue StandardError =>
|
29
|
-
res = ::Marty::Promise.exception_to_result(promise: promise, exception:
|
28
|
+
rescue StandardError => exc
|
29
|
+
res = ::Marty::Promise.exception_to_result(promise: promise, exception: exc)
|
30
30
|
end
|
31
31
|
|
32
32
|
promise.set_result(res)
|
@@ -37,8 +37,8 @@ class Marty::PromiseRubyJob < Struct.new(:promise,
|
|
37
37
|
return unless hook
|
38
38
|
|
39
39
|
hook.run(params: method_args, result: res)
|
40
|
-
rescue StandardError =>
|
41
|
-
Marty::Util.logger.error "promise hook failed: #{
|
40
|
+
rescue StandardError => exc
|
41
|
+
Marty::Util.logger.error "promise hook failed: #{exc}"
|
42
42
|
end
|
43
43
|
|
44
44
|
def max_attempts
|
data/lib/marty/version.rb
CHANGED
data/marty.gemspec
CHANGED
@@ -26,21 +26,26 @@ Gem::Specification.new do |s|
|
|
26
26
|
'Marty is a framework for viewing and reporting on versioned data.'
|
27
27
|
s.files = `git ls-files`.split($\)
|
28
28
|
s.licenses = ['MIT']
|
29
|
-
|
30
|
-
s.add_dependency '
|
31
|
-
|
32
|
-
|
29
|
+
|
30
|
+
s.add_dependency 'pg', '~> 0.21'
|
31
|
+
|
32
|
+
s.add_dependency 'netzke', '6.5.0.0'
|
33
|
+
|
33
34
|
s.add_dependency 'axlsx', '3.0.0pre'
|
35
|
+
|
36
|
+
s.add_dependency 'delorean_lang', '~> 1.0'
|
37
|
+
s.add_dependency 'mcfly', '~> 0.0.20'
|
38
|
+
|
34
39
|
s.add_dependency 'coderay'
|
35
|
-
s.add_dependency 'daemons'
|
36
|
-
s.add_dependency 'delayed_cron_job'
|
37
|
-
s.add_dependency 'delayed_job_active_record'
|
38
|
-
s.add_dependency 'delorean_lang'
|
39
40
|
s.add_dependency 'json-schema'
|
40
|
-
s.add_dependency '
|
41
|
-
s.add_dependency 'net-ldap'
|
42
|
-
s.add_dependency 'netzke'
|
43
|
-
s.add_dependency 'pg'
|
41
|
+
s.add_dependency 'net-ldap', '~> 0.16.1'
|
44
42
|
s.add_dependency 'rubyzip'
|
45
|
-
s.add_dependency '
|
43
|
+
s.add_dependency 'sqlite3'
|
44
|
+
|
45
|
+
# used for signing aws ec2 requests
|
46
|
+
s.add_dependency 'aws-sigv4', '~> 1.0', '>= 1.0.2'
|
47
|
+
|
48
|
+
s.add_dependency 'daemons', '~> 1.3.1'
|
49
|
+
s.add_dependency 'delayed_cron_job'
|
50
|
+
s.add_dependency 'delayed_job_active_record'
|
46
51
|
end
|
@@ -35,30 +35,15 @@ class Marty::Diagnostic::Aws::Ec2Instance < Marty::Aws::Request
|
|
35
35
|
|
36
36
|
def ec2_request action, params = {}
|
37
37
|
resp = request({ action: action }, params)
|
38
|
-
|
39
|
-
|
40
|
-
# check AWS response for errors
|
41
|
-
error = parsed.dig('Response', 'Errors', 'Error')
|
42
|
-
raise Marty::Diagnostic::Aws::Error.new(action, error) if error
|
43
|
-
|
44
|
-
action_resp = parsed["#{action}Response"]
|
45
|
-
raise Marty::Diagnostic::Aws::Error.new(action, parsed) unless action_resp
|
46
|
-
|
47
|
-
action_resp
|
38
|
+
Hash.from_xml(resp)["#{action}Response"]
|
48
39
|
end
|
49
40
|
|
50
41
|
def get_tag
|
51
|
-
action = 'DescribeTags'
|
52
42
|
params = { 'Filter.1.Name' => 'resource-id',
|
53
43
|
'Filter.1.Value.1' => get_instance_id,
|
54
44
|
'Filter.2.Name' => 'key',
|
55
45
|
'Filter.2.Value.1' => 'Name' }
|
56
|
-
|
57
|
-
action_resp = ec2_request(action, params)
|
58
|
-
tag = action_resp.dig('tagSet', 'item', 'value')
|
59
|
-
raise Marty::Diagnostic::Aws::Error.new(action, action_resp) unless tag
|
60
|
-
|
61
|
-
tag
|
46
|
+
ec2_request('DescribeTags', params)['tagSet']['item']['value']
|
62
47
|
end
|
63
48
|
|
64
49
|
def get_instances
|
@@ -20,9 +20,9 @@ module Marty::Diagnostic::Database
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.db_schema
|
23
|
-
current = ActiveRecord::
|
23
|
+
current = ActiveRecord::Migrator.current_version
|
24
24
|
raise "Migration is needed.\nCurrent Version: #{current}" if
|
25
|
-
ActiveRecord::
|
25
|
+
ActiveRecord::Migrator.needs_migration?
|
26
26
|
|
27
27
|
current.to_s
|
28
28
|
end
|
@@ -29,63 +29,70 @@ module Gemini
|
|
29
29
|
gen_mcfly_lookup :lookup, {
|
30
30
|
entity: true,
|
31
31
|
note_rate: false
|
32
|
-
}
|
32
|
+
}, to_hash: true
|
33
|
+
|
33
34
|
gen_mcfly_lookup :lookup_p, {
|
34
35
|
entity: true,
|
35
36
|
note_rate: false
|
36
|
-
},
|
37
|
+
}, to_hash: false
|
38
|
+
|
37
39
|
gen_mcfly_lookup :clookup, {
|
38
40
|
entity: true,
|
39
41
|
note_rate: false
|
40
|
-
}, cache: true
|
42
|
+
}, cache: true, to_hash: true
|
43
|
+
|
41
44
|
gen_mcfly_lookup :clookup_p, {
|
42
45
|
entity: true,
|
43
46
|
note_rate: false
|
44
|
-
}, cache: true,
|
47
|
+
}, cache: true, to_hash: false
|
48
|
+
|
45
49
|
gen_mcfly_lookup :lookupn, {
|
46
50
|
entity: true,
|
47
51
|
note_rate: false
|
48
|
-
}, mode: nil
|
52
|
+
}, mode: nil, to_hash: true
|
53
|
+
|
49
54
|
gen_mcfly_lookup :lookupn_p, {
|
50
55
|
entity: true,
|
51
56
|
note_rate: false
|
52
|
-
},
|
57
|
+
}, to_hash: false, mode: nil
|
58
|
+
|
53
59
|
gen_mcfly_lookup :clookupn, {
|
54
60
|
entity: true,
|
55
61
|
note_rate: false
|
56
|
-
}, cache: true, mode: nil
|
62
|
+
}, cache: true, mode: nil, to_hash: true
|
63
|
+
|
57
64
|
gen_mcfly_lookup :clookupn_p, {
|
58
65
|
entity: true,
|
59
66
|
note_rate: false
|
60
|
-
}, cache: true,
|
67
|
+
}, cache: true, to_hash: false, mode: nil
|
61
68
|
|
62
|
-
mcfly_lookup :a_func, sig: 3 do
|
69
|
+
mcfly_lookup :a_func, sig: 3, to_hash: true do
|
63
70
|
|pt, e_id, bc_id|
|
64
71
|
where(entity_id: e_id, bud_category_id: bc_id).
|
65
72
|
order(:settlement_mm)
|
66
73
|
end
|
67
74
|
|
68
|
-
mcfly_lookup :b_func, sig: [3, 4] do
|
75
|
+
mcfly_lookup :b_func, sig: [3, 4], to_hash: true do
|
69
76
|
|pt, e_id, bc_id, mm = nil|
|
70
77
|
q = where(entity_id: e_id, bud_category_id: bc_id)
|
71
78
|
q = q.where(settlement_mm: mm) if mm
|
72
79
|
q.order(:settlement_mm).first
|
73
80
|
end
|
74
81
|
|
75
|
-
mcfly_lookup :a_func_p, sig: 3,
|
82
|
+
mcfly_lookup :a_func_p, sig: 3, to_hash: false do
|
76
83
|
|pt, e_id, bc_id|
|
77
84
|
where(entity_id: e_id, bud_category_id: bc_id).
|
78
85
|
order(:settlement_mm)
|
79
86
|
end
|
80
87
|
|
81
|
-
mcfly_lookup :b_func_p, sig: [3, 4],
|
88
|
+
mcfly_lookup :b_func_p, sig: [3, 4], to_hash: false do
|
82
89
|
|pt, e_id, bc_id, mm = nil|
|
83
90
|
q = where(entity_id: e_id, bud_category_id: bc_id)
|
84
91
|
q = q.where(settlement_mm: mm) if mm
|
85
92
|
q.order(:settlement_mm)
|
86
93
|
end
|
87
94
|
|
88
|
-
cached_mcfly_lookup :ca_func, sig: 3 do
|
95
|
+
cached_mcfly_lookup :ca_func, sig: 3, to_hash: true do
|
89
96
|
|pt, e_id, bc_id|
|
90
97
|
where(entity_id: e_id, bud_category_id: bc_id).
|
91
98
|
order(:settlement_mm)
|
@@ -4,4 +4,4 @@
|
|
4
4
|
# If you change this key, all old signed cookies will become invalid!
|
5
5
|
# Make sure the secret is at least 30 characters and all random,
|
6
6
|
# no regular words or you'll be exposed to dictionary attacks.
|
7
|
-
Dummy::Application.config.
|
7
|
+
Dummy::Application.config.secret_token = 'a087c113817a728e1552d63682abbd7f19fd7481ea3e24154889af53ab56d114f8901f63909a5e8310260c7187f6fd203cddc8743f6486fead0a4043cd7976c2'
|
@@ -2,10 +2,6 @@ require 'spec_helper'
|
|
2
2
|
require 'marty_rspec'
|
3
3
|
|
4
4
|
feature 'data grid view', js: true do
|
5
|
-
before(:all) do
|
6
|
-
self.use_transactional_tests = true
|
7
|
-
end
|
8
|
-
|
9
5
|
before(:each) do
|
10
6
|
marty_whodunnit
|
11
7
|
Marty::Script.load_scripts
|
@@ -15,22 +11,12 @@ feature 'data grid view', js: true do
|
|
15
11
|
n = File.basename(path, '.txt').camelize
|
16
12
|
Marty::DataGrid.create_from_import(n, File.read(path), dt)
|
17
13
|
end
|
18
|
-
u = Marty::User.create!(login: 'grid_user',
|
19
|
-
firstname: 'grid',
|
20
|
-
lastname: 'user',
|
21
|
-
active: true)
|
22
|
-
Marty::UserRole.create!(user_id: u.id, role: 'data_grid_editor')
|
23
|
-
@no_perm = { 'view' => [],
|
24
|
-
'edit_data' => [],
|
25
|
-
'edit_all' => [] }
|
26
14
|
end
|
27
15
|
|
28
|
-
def go_to_data_grids
|
29
|
-
log_in_as(admin ? 'marty' : 'grid_user')
|
16
|
+
def go_to_data_grids
|
30
17
|
press('Applications')
|
31
|
-
|
32
|
-
|
33
|
-
expect(page).to have_content dest
|
18
|
+
press('Data Grids')
|
19
|
+
expect(page).to have_content 'Data Grids'
|
34
20
|
end
|
35
21
|
|
36
22
|
# setup the info for the ext grid
|
@@ -38,7 +24,7 @@ feature 'data grid view', js: true do
|
|
38
24
|
widths, rows = get_grid_info
|
39
25
|
@grid = page.all(:xpath,
|
40
26
|
".//div[contains(@class, 'x-grid-item-container')]").
|
41
|
-
reject { |e| e.text.include?('
|
27
|
+
reject { |e| e.text.include?('2016-12-31') }.first
|
42
28
|
@gridx = @grid.native.rect.x
|
43
29
|
@gridy = @grid.native.rect.y
|
44
30
|
height = @grid.native.size.height
|
@@ -292,96 +278,18 @@ feature 'data grid view', js: true do
|
|
292
278
|
expect(grid_meta).to eq(exp_meta)
|
293
279
|
end
|
294
280
|
|
295
|
-
it 'dg
|
296
|
-
log_in_as('marty')
|
297
|
-
go_to_data_grids
|
298
|
-
dgv = netzke_find('data_grid_view')
|
299
|
-
grids = dgv.get_col_vals('name', 5)
|
300
|
-
set_one = lambda do |grid, perms|
|
301
|
-
pos = grids.index(grid) + 1
|
302
|
-
dgv.select_row(pos)
|
303
|
-
press('Edit')
|
304
|
-
wait_for_ajax
|
305
|
-
view_combo = netzke_find('Can View', 'combobox')
|
306
|
-
edit_data_combo = netzke_find('Can Edit Data', 'combobox')
|
307
|
-
edit_all_combo = netzke_find('Can Edit All', 'combobox')
|
308
|
-
view_combo.select_values(perms['view'].join(', '))
|
309
|
-
edit_data_combo.select_values(perms['edit_data'].join(', '))
|
310
|
-
edit_all_combo.select_values(perms['edit_all'].join(', '))
|
311
|
-
press('OK')
|
312
|
-
wait_for_ajax
|
313
|
-
end
|
314
|
-
dg1p = { 'view' => ['Data Grid Editor'],
|
315
|
-
'edit_data' => ['Data Grid Editor'],
|
316
|
-
'edit_all' => ['Admin'] }
|
317
|
-
dg2p = { 'view' => ['Data Grid Editor', 'User Manager'],
|
318
|
-
'edit_data' => ['Data Grid Editor', 'User Manager'],
|
319
|
-
'edit_all' => ['Data Grid Editor', 'Admin'] }
|
320
|
-
set_one.call('DataGrid1', dg1p)
|
321
|
-
set_one.call('DataGrid2', dg2p)
|
322
|
-
dg1 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid1')
|
323
|
-
dg2 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid2')
|
324
|
-
fixexp = lambda do |orig_h|
|
325
|
-
orig_h.each_with_object({}) do |(k, v), h|
|
326
|
-
h[k] = v.map do |vals|
|
327
|
-
vals.split(' ').map(&:downcase).join('_')
|
328
|
-
end.sort
|
329
|
-
end
|
330
|
-
end
|
331
|
-
exp1 = fixexp.call(dg1p)
|
332
|
-
exp2 = fixexp.call(dg2p)
|
333
|
-
fixgot = ->(orig_h) { Hash[orig_h.map { |k, v| [k, v.sort] }] }
|
334
|
-
got1 = fixgot.call(dg1.permissions)
|
335
|
-
got2 = fixgot.call(dg2.permissions)
|
336
|
-
cmp1 = struct_compare(got1, exp1)
|
337
|
-
cmp2 = struct_compare(got2, exp2)
|
338
|
-
expect(cmp1).to be_falsey
|
339
|
-
expect(cmp2).to be_falsey
|
340
|
-
|
341
|
-
set_one.call('DataGrid1', @no_perm)
|
342
|
-
set_one.call('DataGrid2', @no_perm)
|
343
|
-
dg1 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid1')
|
344
|
-
dg2 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid2')
|
345
|
-
expect(dg1.permissions).to eq(@no_perm)
|
346
|
-
expect(dg2.permissions).to eq(@no_perm)
|
347
|
-
end
|
348
|
-
|
349
|
-
it 'show grid' do
|
281
|
+
it 'dg editor' do
|
350
282
|
log_in_as('marty')
|
351
283
|
go_to_data_grids
|
352
284
|
dgv = netzke_find('data_grid_view')
|
353
285
|
grids = dgv.get_col_vals('name', 5)
|
354
|
-
|
355
|
-
|
356
|
-
press('Show Grid')
|
357
|
-
expect(page).to have_content('Antwerp')
|
358
|
-
end
|
359
|
-
|
360
|
-
def set_perm(perm)
|
361
|
-
p = @no_perm + (perm ? { perm => ['data_grid_editor'] } : {})
|
362
|
-
Marty::DataGrid.mcfly_pt('infinity').each do |dg|
|
363
|
-
dg.permissions = p
|
364
|
-
dg.save!
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
it 'dg context menus' do
|
369
|
-
log_in_as('grid_user')
|
370
|
-
go_to_data_grids(admin: false)
|
371
|
-
dgv = netzke_find('data_grid_user_view')
|
372
|
-
context_test_all = ENV['DG_FEATURE_FULL'] == 'true'
|
373
|
-
[[nil, nil],
|
374
|
-
['edit_all', context_test_all],
|
286
|
+
context_test_all = ENV['DG_FEATURE_QUICK'] != 'true'
|
287
|
+
[['edit_all', context_test_all],
|
375
288
|
['edit_data', false],
|
376
289
|
['view', false]].each do |perm, all_cells|
|
377
|
-
set_perm(perm)
|
378
|
-
press('Refresh')
|
379
|
-
grids = dgv.get_col_vals('name', 5)
|
380
|
-
if perm.nil?
|
381
|
-
expect(grids).to be_nil
|
382
|
-
next
|
383
|
-
end
|
384
290
|
grids.each do |grid|
|
291
|
+
Marty::Config['grid_edit_edit_perm'] = perm
|
292
|
+
Marty::Config['grid_edit_save_perm'] = perm
|
385
293
|
pos = grids.index(grid) + 1
|
386
294
|
dgv.select_row(pos)
|
387
295
|
press('Edit Grid')
|
@@ -392,14 +300,8 @@ feature 'data grid view', js: true do
|
|
392
300
|
wait_for_ajax
|
393
301
|
end
|
394
302
|
end
|
395
|
-
|
396
|
-
|
397
|
-
it 'dg editor' do
|
398
|
-
set_perm('edit_all')
|
399
|
-
log_in_as('grid_user')
|
400
|
-
go_to_data_grids(admin: false)
|
401
|
-
dgv = netzke_find('data_grid_user_view')
|
402
|
-
grids = dgv.get_col_vals('name', 5)
|
303
|
+
Marty::Config['grid_edit_edit_perm'] = 'edit_all'
|
304
|
+
Marty::Config['grid_edit_save_perm'] = 'edit_all'
|
403
305
|
|
404
306
|
# now test some editing, saving, and cancel logic
|
405
307
|
get_latest = lambda do
|
@@ -558,5 +460,40 @@ feature 'data grid view', js: true do
|
|
558
460
|
press('Save')
|
559
461
|
sleep 1
|
560
462
|
validate_grid('1')
|
463
|
+
|
464
|
+
Marty::Config['grid_edit_save_perm'] = 'view'
|
465
|
+
pos = grids.index('DataGrid5') + 1
|
466
|
+
dgv.select_row(pos)
|
467
|
+
count = 1
|
468
|
+
begin
|
469
|
+
press('Edit Grid')
|
470
|
+
wait_for_ajax
|
471
|
+
grid_setup
|
472
|
+
cell_edit(2, 3, '123.456')
|
473
|
+
rescue StandardError => e
|
474
|
+
if count > 0
|
475
|
+
sleep 1
|
476
|
+
retry
|
477
|
+
end
|
478
|
+
count -= 1
|
479
|
+
end
|
480
|
+
press('Save')
|
481
|
+
errexp = 'error: save_grid: entered with view permissions'
|
482
|
+
expect(page).to have_content(errexp)
|
483
|
+
press('OK')
|
484
|
+
wait_for_ajax
|
485
|
+
context_click(2, 4, 4, click: true)
|
486
|
+
Marty::Config['grid_edit_save_perm'] = 'edit_data'
|
487
|
+
press('Save')
|
488
|
+
errexp = 'error: save_grid: grid modification not allowed'
|
489
|
+
expect(page).to have_content(errexp)
|
490
|
+
exp_log = JSON.parse(File.read('spec/fixtures/misc/grid_log_errs.json'))
|
491
|
+
got = Marty::Log.all.select(:message, :details).attributes.map do |l|
|
492
|
+
newl = l.except('id')
|
493
|
+
newl['details'].delete('rec_id')
|
494
|
+
newl
|
495
|
+
end
|
496
|
+
cmp = struct_compare(got, exp_log)
|
497
|
+
expect(cmp).to be_falsey
|
561
498
|
end
|
562
499
|
end
|