marty 4.0.0.rc2 → 5.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.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +7 -0
  3. data/.rubocop.yml +1 -0
  4. data/.rubocop_todo.yml +3 -16
  5. data/.ssh-docker/.keep +0 -0
  6. data/Dockerfile.dummy +3 -0
  7. data/Gemfile +19 -15
  8. data/app/components/marty/base_rule_view.rb +104 -10
  9. data/app/components/marty/base_rule_view/client/base_rule_view.js +24 -0
  10. data/app/components/marty/data_grid_user_view.rb +39 -0
  11. data/app/components/marty/data_grid_view.rb +68 -18
  12. data/app/components/marty/extras/layout.rb +1 -1
  13. data/app/components/marty/grid.rb +1 -1
  14. data/app/components/marty/grid/client/grid.js +29 -13
  15. data/app/components/marty/import_view.rb +3 -3
  16. data/app/components/marty/main_auth_app.rb +11 -1
  17. data/app/components/marty/report_form.rb +6 -6
  18. data/app/components/marty/script_form.rb +5 -5
  19. data/app/components/marty/script_tester.rb +2 -2
  20. data/app/components/marty/user_view.rb +3 -9
  21. data/app/models/marty/base_rule.rb +92 -32
  22. data/app/models/marty/data_grid.rb +92 -22
  23. data/app/models/marty/event.rb +2 -2
  24. data/app/models/marty/promise.rb +4 -4
  25. data/app/models/marty/role_type.rb +14 -1
  26. data/app/services/marty/data_grid_view/save_grid.rb +2 -2
  27. data/app/services/marty/promises/delorean/create.rb +2 -2
  28. data/app/services/marty/promises/ruby/create.rb +2 -2
  29. data/config/locales/en.yml +11 -2
  30. data/db/migrate/108_add_data_grid_perms.rb +16 -0
  31. data/db/migrate/508_add_not_to_data_grids_tables.rb +18 -0
  32. data/db/migrate/509_update_dg_plpgsql_v1_fns.rb +13 -0
  33. data/db/sql/query_grid_dir_v1.sql +16 -2
  34. data/docker-compose.dummy.yml +1 -0
  35. data/lib/marty/content_handler.rb +2 -2
  36. data/lib/marty/data_change.rb +1 -1
  37. data/lib/marty/data_conversion.rb +3 -4
  38. data/lib/marty/data_importer.rb +4 -4
  39. data/lib/marty/mcfly_model.rb +7 -10
  40. data/lib/marty/migrations.rb +1 -1
  41. data/lib/marty/monkey.rb +2 -2
  42. data/lib/marty/promise_job.rb +5 -5
  43. data/lib/marty/promise_proxy.rb +2 -2
  44. data/lib/marty/promise_ruby_job.rb +4 -4
  45. data/lib/marty/version.rb +1 -1
  46. data/make-app.mk +1 -1
  47. data/marty.gemspec +13 -18
  48. data/other/marty/diagnostic/aws/ec2_instance.rb +17 -2
  49. data/other/marty/diagnostic/aws/error.rb +8 -0
  50. data/other/marty/diagnostic/database.rb +2 -2
  51. data/other/marty/diagnostic/delayed_job_version.rb +0 -1
  52. data/spec/dummy/app/components/gemini/my_rule_view.rb +32 -6
  53. data/spec/dummy/app/models/gemini/fannie_bup.rb +13 -20
  54. data/spec/dummy/app/models/gemini/my_rule.rb +4 -0
  55. data/spec/dummy/app/models/gemini/xyz_rule.rb +3 -1
  56. data/spec/dummy/config/application.rb +1 -0
  57. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  58. data/spec/dummy/db/migrate/20190702115241_add_simple_guards_options_to_rules.rb +37 -0
  59. data/spec/features/data_grid_spec.rb +109 -47
  60. data/spec/features/reporting_spec.rb +4 -4
  61. data/spec/features/rule_spec.rb +62 -31
  62. data/spec/features/scripting_spec.rb +3 -3
  63. data/spec/features/user_view_spec.rb +17 -8
  64. data/spec/fixtures/csv/rule/MyRule.csv +4 -1
  65. data/spec/lib/data_importer_spec.rb +8 -8
  66. data/spec/lib/mcfly_model_spec.rb +6 -6
  67. data/spec/models/data_grid_spec.rb +139 -7
  68. data/spec/models/rule_spec.rb +116 -9
  69. data/spec/spec_helper.rb +2 -2
  70. data/spec/support/netzke.rb +4 -3
  71. metadata +55 -54
  72. data/Gemfile.lock +0 -289
@@ -1,3 +1,3 @@
1
1
  module Marty
2
- VERSION = '4.0.0.rc2'
2
+ VERSION = '5.1.0'
3
3
  end
@@ -19,7 +19,7 @@ app-bash:
19
19
  docker-compose --file=docker-compose.dummy.yml run --rm app bash
20
20
 
21
21
  app-console:
22
- docker-compose --file=docker-compose.dummy.yml run --rm app /bin/bash -c "cd spec/dummy && bin/rails c"
22
+ docker-compose --file=docker-compose.dummy.yml run --rm app /bin/bash -c "cd spec/dummy && rails c"
23
23
 
24
24
  app-initialise-docker:
25
25
  touch .bash_history.docker
@@ -26,26 +26,21 @@ 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 'pg', '~> 0.21'
31
-
32
- s.add_dependency 'netzke', '6.5.0.0'
33
-
29
+ # used for signing aws ec2 requests
30
+ s.add_dependency 'aws-sigv4'
31
+ # Only pinning this because there's no other way around it for Axlsx.
32
+ # DO NOT unpin this.
34
33
  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
-
39
34
  s.add_dependency 'coderay'
40
- s.add_dependency 'json-schema'
41
- s.add_dependency 'net-ldap', '~> 0.16.1'
42
- s.add_dependency 'rubyzip'
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'
35
+ s.add_dependency 'daemons'
49
36
  s.add_dependency 'delayed_cron_job'
50
37
  s.add_dependency 'delayed_job_active_record'
38
+ s.add_dependency 'delorean_lang'
39
+ s.add_dependency 'json-schema'
40
+ s.add_dependency 'mcfly'
41
+ s.add_dependency 'net-ldap'
42
+ s.add_dependency 'netzke'
43
+ s.add_dependency 'pg'
44
+ s.add_dependency 'rubyzip'
45
+ s.add_dependency 'zip-zip'
51
46
  end
@@ -35,15 +35,30 @@ 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
- Hash.from_xml(resp)["#{action}Response"]
38
+ parsed = Hash.from_xml(resp)
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
39
48
  end
40
49
 
41
50
  def get_tag
51
+ action = 'DescribeTags'
42
52
  params = { 'Filter.1.Name' => 'resource-id',
43
53
  'Filter.1.Value.1' => get_instance_id,
44
54
  'Filter.2.Name' => 'key',
45
55
  'Filter.2.Value.1' => 'Name' }
46
- ec2_request('DescribeTags', params)['tagSet']['item']['value']
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
47
62
  end
48
63
 
49
64
  def get_instances
@@ -0,0 +1,8 @@
1
+ class Marty::Diagnostic::Aws::Error < StandardError
2
+ attr_accessor :object
3
+
4
+ def initialize(action, object = nil)
5
+ super("#{action}: #{object.try(:[], 'Message') || 'Unexpected Response'}")
6
+ self.object = object
7
+ end
8
+ end
@@ -20,9 +20,9 @@ module Marty::Diagnostic::Database
20
20
  end
21
21
 
22
22
  def self.db_schema
23
- current = ActiveRecord::Migrator.current_version
23
+ current = ActiveRecord::Migration.current_version
24
24
  raise "Migration is needed.\nCurrent Version: #{current}" if
25
- ActiveRecord::Migrator.needs_migration?
25
+ ActiveRecord::Base.connection.migration_context.needs_migration?
26
26
 
27
27
  current.to_s
28
28
  end
@@ -31,7 +31,6 @@ module Marty::Diagnostic; class DelayedJobVersion < Base
31
31
  hash[r[0]] ||= []
32
32
  hash[r[0]] << r[1]
33
33
  end.map do |node, result|
34
-
35
34
  versions = result.uniq
36
35
  status = versions.count == 1 && versions[0] == ENV['DELAYED_VER']
37
36
 
@@ -32,15 +32,41 @@ class Gemini::MyRuleView < Marty::DeloreanRuleView
32
32
  setter: jsonb_simple_setter(:computed_guards),
33
33
  height: 50)]
34
34
  end
35
+
35
36
  def default_form_items
36
37
  [
37
38
  hbox(
38
- vbox(*form_items_attrs +
39
- form_items_guards +
40
- form_items_grids,
41
- border: false,
42
- width: "40%",
43
- ),
39
+ vbox(
40
+ hbox(
41
+ vbox(
42
+ *form_items_attrs,
43
+ width: '100%',
44
+ border: false
45
+ ),
46
+ width: '100%',
47
+ border: false
48
+ ),
49
+ hbox(
50
+ vbox(
51
+ *default_form_items_guards,
52
+ width: '100%',
53
+ border: false
54
+ ),
55
+ width: '100%',
56
+ border: false
57
+ ),
58
+ hbox(
59
+ vbox(
60
+ *form_items_grids,
61
+ width: '100%',
62
+ border: false
63
+ ),
64
+ width: '100%',
65
+ border: false
66
+ ),
67
+ width: '40%',
68
+ border: false
69
+ ),
44
70
  vbox(width: '2%', border: false),
45
71
  vbox(
46
72
  width: '55%', border: false),
@@ -29,70 +29,63 @@ module Gemini
29
29
  gen_mcfly_lookup :lookup, {
30
30
  entity: true,
31
31
  note_rate: false
32
- }, to_hash: true
33
-
32
+ }
34
33
  gen_mcfly_lookup :lookup_p, {
35
34
  entity: true,
36
35
  note_rate: false
37
- }, to_hash: false
38
-
36
+ }, private: true
39
37
  gen_mcfly_lookup :clookup, {
40
38
  entity: true,
41
39
  note_rate: false
42
- }, cache: true, to_hash: true
43
-
40
+ }, cache: true
44
41
  gen_mcfly_lookup :clookup_p, {
45
42
  entity: true,
46
43
  note_rate: false
47
- }, cache: true, to_hash: false
48
-
44
+ }, cache: true, private: true
49
45
  gen_mcfly_lookup :lookupn, {
50
46
  entity: true,
51
47
  note_rate: false
52
- }, mode: nil, to_hash: true
53
-
48
+ }, mode: nil
54
49
  gen_mcfly_lookup :lookupn_p, {
55
50
  entity: true,
56
51
  note_rate: false
57
- }, to_hash: false, mode: nil
58
-
52
+ }, private: true, mode: nil
59
53
  gen_mcfly_lookup :clookupn, {
60
54
  entity: true,
61
55
  note_rate: false
62
- }, cache: true, mode: nil, to_hash: true
63
-
56
+ }, cache: true, mode: nil
64
57
  gen_mcfly_lookup :clookupn_p, {
65
58
  entity: true,
66
59
  note_rate: false
67
- }, cache: true, to_hash: false, mode: nil
60
+ }, cache: true, private: true, mode: nil
68
61
 
69
- mcfly_lookup :a_func, sig: 3, to_hash: true do
62
+ mcfly_lookup :a_func, sig: 3 do
70
63
  |pt, e_id, bc_id|
71
64
  where(entity_id: e_id, bud_category_id: bc_id).
72
65
  order(:settlement_mm)
73
66
  end
74
67
 
75
- mcfly_lookup :b_func, sig: [3, 4], to_hash: true do
68
+ mcfly_lookup :b_func, sig: [3, 4] do
76
69
  |pt, e_id, bc_id, mm = nil|
77
70
  q = where(entity_id: e_id, bud_category_id: bc_id)
78
71
  q = q.where(settlement_mm: mm) if mm
79
72
  q.order(:settlement_mm).first
80
73
  end
81
74
 
82
- mcfly_lookup :a_func_p, sig: 3, to_hash: false do
75
+ mcfly_lookup :a_func_p, sig: 3, private: true do
83
76
  |pt, e_id, bc_id|
84
77
  where(entity_id: e_id, bud_category_id: bc_id).
85
78
  order(:settlement_mm)
86
79
  end
87
80
 
88
- mcfly_lookup :b_func_p, sig: [3, 4], to_hash: false do
81
+ mcfly_lookup :b_func_p, sig: [3, 4], private: true do
89
82
  |pt, e_id, bc_id, mm = nil|
90
83
  q = where(entity_id: e_id, bud_category_id: bc_id)
91
84
  q = q.where(settlement_mm: mm) if mm
92
85
  q.order(:settlement_mm)
93
86
  end
94
87
 
95
- cached_mcfly_lookup :ca_func, sig: 3, to_hash: true do
88
+ cached_mcfly_lookup :ca_func, sig: 3 do
96
89
  |pt, e_id, bc_id|
97
90
  where(entity_id: e_id, bud_category_id: bc_id).
98
91
  order(:settlement_mm)
@@ -16,17 +16,21 @@ class Gemini::MyRule < Marty::DeloreanRule
16
16
  super + {"g_array" => { multi: true, type: :string,
17
17
  enum: Gemini::GuardOne,},
18
18
  "g_single" => { type: :string,
19
+ allow_not: false,
19
20
  enum: Gemini::GuardTwo,
20
21
  width: 100},
21
22
  "g_string" => { type: :string,
22
23
  values: ["Hi Mom", "abc", "def", "zzz"],
23
24
  width: 100},
24
25
  "g_bool" => { type: :boolean,
26
+ allow_not: true,
25
27
  width: 100,
26
28
  null: false},
27
29
  "g_nullbool" => { type: :boolean,
30
+ allow_not: false,
28
31
  width: 100},
29
32
  "g_range" => { type: :range,
33
+ allow_not: true,
30
34
  width: 100},
31
35
  "g_integer" => { type: :integer,
32
36
  width: 100},
@@ -16,7 +16,9 @@ class Gemini::XyzRule < Marty::DeloreanRule
16
16
  'RULEOPTS_XYZ'
17
17
  end
18
18
  def self.guard_info
19
- super + {"flavors" => { multi: true, type: :string,
19
+ super + {"flavors" => { multi: true,
20
+ type: :string,
21
+ allow_not: false,
20
22
  enum: Gemini::XyzEnum,
21
23
  width: 150},
22
24
  "guard_two" => { type: :string,
@@ -79,6 +79,7 @@ module Dummy
79
79
  :dev,
80
80
  :viewer,
81
81
  :user_manager,
82
+ :data_grid_editor,
82
83
  ]
83
84
  #config.marty.default_posting_type = 'BASE'
84
85
  config.secret_key_base = "SECRET_KEY_BASE"
@@ -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.secret_token = 'a087c113817a728e1552d63682abbd7f19fd7481ea3e24154889af53ab56d114f8901f63909a5e8310260c7187f6fd203cddc8743f6486fead0a4043cd7976c2'
7
+ Dummy::Application.config.secret_key_base = 'a087c113817a728e1552d63682abbd7f19fd7481ea3e24154889af53ab56d114f8901f63909a5e8310260c7187f6fd203cddc8743f6486fead0a4043cd7976c2'
@@ -0,0 +1,37 @@
1
+ class AddSimpleGuardsOptionsToRules < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :gemini_my_rules, :simple_guards_options, :jsonb, null: false, default: {}
4
+ add_column :gemini_xyz_rules, :simple_guards_options, :jsonb, null: false, default: {}
5
+
6
+ reversible do |dir|
7
+ dir.up { create_indexes }
8
+ end
9
+ end
10
+
11
+ def create_indexes
12
+ ['gemini_my_rules', 'g_array', :array,
13
+ 'gemini_my_rules', 'g_single', :scalar,
14
+ 'gemini_my_rules', 'g_string', :scalar,
15
+ 'gemini_my_rules', 'g_bool', :scalar,
16
+ 'gemini_my_rules', 'g_integer', :scalar,
17
+ 'gemini_my_rules', 'g_range', :range,
18
+ 'gemini_xyz_rules', 'flavors', :array,
19
+ 'gemini_xyz_rules', 'guard_two', :scalar,
20
+ 'gemini_xyz_rules', 'g_date', :scalar,
21
+ 'gemini_xyz_rules', 'g_datetime', :scalar,
22
+ 'gemini_xyz_rules', 'g_bool', :scalar,
23
+ 'gemini_xyz_rules', 'g_integer', :scalar,
24
+ 'gemini_xyz_rules', 'g_range1', :range,
25
+ 'gemini_xyz_rules', 'g_range2', :range,
26
+ ].in_groups_of(3).each do |table, field, type|
27
+
28
+ col = "(simple_guards_options -> '#{field}' -> 'not')"
29
+ sql = <<-SQL
30
+ CREATE INDEX idx_#{table}_#{field}_not ON #{table} USING BTREE
31
+ (#{col});
32
+ SQL
33
+
34
+ execute sql
35
+ end
36
+ end
37
+ end
@@ -1,7 +1,10 @@
1
1
  require 'spec_helper'
2
- require 'marty_rspec'
3
2
 
4
3
  feature 'data grid view', js: true do
4
+ before(:all) do
5
+ self.use_transactional_tests = true
6
+ end
7
+
5
8
  before(:each) do
6
9
  marty_whodunnit
7
10
  Marty::Script.load_scripts
@@ -11,12 +14,22 @@ feature 'data grid view', js: true do
11
14
  n = File.basename(path, '.txt').camelize
12
15
  Marty::DataGrid.create_from_import(n, File.read(path), dt)
13
16
  end
17
+ u = Marty::User.create!(login: 'grid_user',
18
+ firstname: 'grid',
19
+ lastname: 'user',
20
+ active: true)
21
+ Marty::UserRole.create!(user_id: u.id, role: 'data_grid_editor')
22
+ @no_perm = { 'view' => [],
23
+ 'edit_data' => [],
24
+ 'edit_all' => [] }
14
25
  end
15
26
 
16
- def go_to_data_grids
27
+ def go_to_data_grids(admin: true)
28
+ log_in_as(admin ? 'marty' : 'grid_user')
17
29
  press('Applications')
18
- press('Data Grids')
19
- expect(page).to have_content 'Data Grids'
30
+ dest = 'Data Grids' + (admin ? ' Admin' : '')
31
+ press(dest)
32
+ expect(page).to have_content dest
20
33
  end
21
34
 
22
35
  # setup the info for the ext grid
@@ -24,7 +37,7 @@ feature 'data grid view', js: true do
24
37
  widths, rows = get_grid_info
25
38
  @grid = page.all(:xpath,
26
39
  ".//div[contains(@class, 'x-grid-item-container')]").
27
- reject { |e| e.text.include?('2016-12-31') }.first
40
+ reject { |e| e.text.include?('DataGrid1') }.first
28
41
  @gridx = @grid.native.rect.x
29
42
  @gridy = @grid.native.rect.y
30
43
  height = @grid.native.size.height
@@ -278,18 +291,96 @@ feature 'data grid view', js: true do
278
291
  expect(grid_meta).to eq(exp_meta)
279
292
  end
280
293
 
281
- it 'dg editor' do
294
+ it 'dg perms' do
295
+ log_in_as('marty')
296
+ go_to_data_grids
297
+ dgv = netzke_find('data_grid_view')
298
+ grids = dgv.get_col_vals('name', 5)
299
+ set_one = lambda do |grid, perms|
300
+ pos = grids.index(grid) + 1
301
+ dgv.select_row(pos)
302
+ press('Edit')
303
+ wait_for_ajax
304
+ view_combo = netzke_find('Can View', 'combobox')
305
+ edit_data_combo = netzke_find('Can Edit Data', 'combobox')
306
+ edit_all_combo = netzke_find('Can Edit All', 'combobox')
307
+ view_combo.select_values(perms['view'].join(', '))
308
+ edit_data_combo.select_values(perms['edit_data'].join(', '))
309
+ edit_all_combo.select_values(perms['edit_all'].join(', '))
310
+ press('OK')
311
+ wait_for_ajax
312
+ end
313
+ dg1p = { 'view' => ['Data Grid Editor'],
314
+ 'edit_data' => ['Data Grid Editor'],
315
+ 'edit_all' => ['Admin'] }
316
+ dg2p = { 'view' => ['Data Grid Editor', 'User Manager'],
317
+ 'edit_data' => ['Data Grid Editor', 'User Manager'],
318
+ 'edit_all' => ['Data Grid Editor', 'Admin'] }
319
+ set_one.call('DataGrid1', dg1p)
320
+ set_one.call('DataGrid2', dg2p)
321
+ dg1 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid1')
322
+ dg2 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid2')
323
+ fixexp = lambda do |orig_h|
324
+ orig_h.each_with_object({}) do |(k, v), h|
325
+ h[k] = v.map do |vals|
326
+ vals.split(' ').map(&:downcase).join('_')
327
+ end.sort
328
+ end
329
+ end
330
+ exp1 = fixexp.call(dg1p)
331
+ exp2 = fixexp.call(dg2p)
332
+ fixgot = ->(orig_h) { Hash[orig_h.map { |k, v| [k, v.sort] }] }
333
+ got1 = fixgot.call(dg1.permissions)
334
+ got2 = fixgot.call(dg2.permissions)
335
+ cmp1 = struct_compare(got1, exp1)
336
+ cmp2 = struct_compare(got2, exp2)
337
+ expect(cmp1).to be_falsey
338
+ expect(cmp2).to be_falsey
339
+
340
+ set_one.call('DataGrid1', @no_perm)
341
+ set_one.call('DataGrid2', @no_perm)
342
+ dg1 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid1')
343
+ dg2 = Marty::DataGrid.mcfly_pt('infinity').find_by(name: 'DataGrid2')
344
+ expect(dg1.permissions).to eq(@no_perm)
345
+ expect(dg2.permissions).to eq(@no_perm)
346
+ end
347
+
348
+ it 'show grid' do
282
349
  log_in_as('marty')
283
350
  go_to_data_grids
284
351
  dgv = netzke_find('data_grid_view')
285
352
  grids = dgv.get_col_vals('name', 5)
286
- context_test_all = ENV['DG_FEATURE_QUICK'] != 'true'
287
- [['edit_all', context_test_all],
353
+ pos = grids.index('DataGrid1') + 1
354
+ dgv.select_row(pos)
355
+ press('Show Grid')
356
+ expect(page).to have_content('Antwerp')
357
+ end
358
+
359
+ def set_perm(perm)
360
+ p = @no_perm + (perm ? { perm => ['data_grid_editor'] } : {})
361
+ Marty::DataGrid.mcfly_pt('infinity').each do |dg|
362
+ dg.permissions = p
363
+ dg.save!
364
+ end
365
+ end
366
+
367
+ it 'dg context menus' do
368
+ log_in_as('grid_user')
369
+ go_to_data_grids(admin: false)
370
+ dgv = netzke_find('data_grid_user_view')
371
+ context_test_all = ENV['DG_FEATURE_FULL'] == 'true'
372
+ [[nil, nil],
373
+ ['edit_all', context_test_all],
288
374
  ['edit_data', false],
289
375
  ['view', false]].each do |perm, all_cells|
376
+ set_perm(perm)
377
+ press('Refresh')
378
+ grids = dgv.get_col_vals('name', 5)
379
+ if perm.nil?
380
+ expect(grids).to be_nil
381
+ next
382
+ end
290
383
  grids.each do |grid|
291
- Marty::Config['grid_edit_edit_perm'] = perm
292
- Marty::Config['grid_edit_save_perm'] = perm
293
384
  pos = grids.index(grid) + 1
294
385
  dgv.select_row(pos)
295
386
  press('Edit Grid')
@@ -300,8 +391,14 @@ feature 'data grid view', js: true do
300
391
  wait_for_ajax
301
392
  end
302
393
  end
303
- Marty::Config['grid_edit_edit_perm'] = 'edit_all'
304
- Marty::Config['grid_edit_save_perm'] = 'edit_all'
394
+ end
395
+
396
+ it 'dg editor' do
397
+ set_perm('edit_all')
398
+ log_in_as('grid_user')
399
+ go_to_data_grids(admin: false)
400
+ dgv = netzke_find('data_grid_user_view')
401
+ grids = dgv.get_col_vals('name', 5)
305
402
 
306
403
  # now test some editing, saving, and cancel logic
307
404
  get_latest = lambda do
@@ -460,40 +557,5 @@ feature 'data grid view', js: true do
460
557
  press('Save')
461
558
  sleep 1
462
559
  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
498
560
  end
499
561
  end