marty 3.0.0 → 3.0.1
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/.gitignore +5 -0
- data/.ssh-docker/.keep +0 -0
- data/Dockerfile.dummy +3 -0
- data/Gemfile.lock +1 -1
- data/app/components/marty/data_grid_user_view.rb +39 -0
- data/app/components/marty/data_grid_view.rb +64 -14
- data/app/components/marty/main_auth_app.rb +11 -1
- data/app/components/marty/user_view.rb +3 -9
- data/app/models/marty/data_grid.rb +12 -6
- data/app/models/marty/role_type.rb +14 -1
- data/app/services/marty/data_grid_view/save_grid.rb +2 -2
- data/config/locales/en.yml +11 -2
- data/db/migrate/108_add_data_grid_perms.rb +16 -0
- data/docker-compose.dummy.yml +1 -0
- data/lib/marty/data_conversion.rb +1 -1
- data/lib/marty/migrations.rb +1 -1
- data/lib/marty/version.rb +1 -1
- data/other/marty/diagnostic/aws/ec2_instance.rb +17 -2
- data/other/marty/diagnostic/aws/error.rb +8 -0
- data/spec/dummy/config/application.rb +1 -0
- data/spec/features/data_grid_spec.rb +110 -46
- data/spec/features/rule_spec.rb +1 -1
- data/spec/features/user_view_spec.rb +16 -7
- data/spec/models/data_grid_spec.rb +19 -4
- data/spec/support/netzke.rb +2 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdb72d97f91a1f370754d64b41ca268addf4f001b061cc3e531f5993d7f5dae7
|
4
|
+
data.tar.gz: 1cefbf2a2e8d6e1176be63e876f7207fbc1fe8c07dd8b78b182ac4621e9f638b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c82561e607fcb7ffd5e154e85279c7afd1c992867d495cee261310282fa55912247b09db6bff1d88d773a3e49fac0fe5f361fc2048c4f8cd4ea5f70a3d70db2c
|
7
|
+
data.tar.gz: 540081cb0f2474a32ebb47a5fc42741cedc717d2dc71ebc7bb772af7a8c24c475db5c6812b403b29b2997b95c1123ba576997b95af5cc84f5b1afa9163bc7168
|
data/.gitignore
CHANGED
data/.ssh-docker/.keep
ADDED
File without changes
|
data/Dockerfile.dummy
CHANGED
@@ -24,6 +24,9 @@ RUN curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrom
|
|
24
24
|
&& sed -i 's|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g' /opt/google/chrome/google-chrome \
|
25
25
|
&& rm google-chrome.deb
|
26
26
|
|
27
|
+
# Install additional tools
|
28
|
+
RUN apt-get install -qq -y --no-install-recommends netcat-openbsd vim
|
29
|
+
|
27
30
|
RUN gem install bundler
|
28
31
|
|
29
32
|
ENV BUNDLE_PATH /bundle_box/bundle
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Marty
|
2
|
+
class DataGridUserView < DataGridView
|
3
|
+
has_marty_permissions read: [:data_grid_editor, :admin, :dev]
|
4
|
+
|
5
|
+
def configure(c)
|
6
|
+
super
|
7
|
+
|
8
|
+
c.attributes =
|
9
|
+
[
|
10
|
+
:name,
|
11
|
+
:created_dt,
|
12
|
+
]
|
13
|
+
c.editing = :inline
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_bbar
|
17
|
+
[:edit_grid]
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_records(params)
|
21
|
+
cur_perms = Mcfly.whodunnit.roles.map(&:to_sym)
|
22
|
+
model.where("permissions->'view' ?| ARRAY[:roles] OR "\
|
23
|
+
"permissions->'edit_data' ?| ARRAY[:roles] OR "\
|
24
|
+
"permissions->'edit_all' ?| ARRAY[:roles]",
|
25
|
+
roles: cur_perms).scoping do
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.get_edit_permission(permissions)
|
31
|
+
cur_perms = current_user_roles.map(&:to_s)
|
32
|
+
['edit_all', 'edit_data', 'view'].detect do |p|
|
33
|
+
permissions[p] - cur_perms != permissions[p]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
DataGridUserView = Marty::DataGridUserView
|
@@ -98,6 +98,9 @@ module Marty; class DataGridView < McflyGridPanel
|
|
98
98
|
:lenient,
|
99
99
|
:data_type,
|
100
100
|
:constraint,
|
101
|
+
:perm_view,
|
102
|
+
:perm_edit_data,
|
103
|
+
:perm_edit_all,
|
101
104
|
:created_dt,
|
102
105
|
]
|
103
106
|
|
@@ -107,6 +110,19 @@ module Marty; class DataGridView < McflyGridPanel
|
|
107
110
|
c.multi_select = false
|
108
111
|
end
|
109
112
|
|
113
|
+
def set_perms(dg, data)
|
114
|
+
permstrs = %w[perm_view perm_edit_data perm_edit_all]
|
115
|
+
view, edit_data, edit_all = data.values_at(*permstrs).map do |plist|
|
116
|
+
Marty::RoleType.from_nice_names(plist)
|
117
|
+
end
|
118
|
+
dg.permissions = {
|
119
|
+
view: view.present? ? view : [],
|
120
|
+
edit_data: edit_data.present? ? edit_data : [],
|
121
|
+
edit_all: edit_all.present? ? edit_all : [],
|
122
|
+
}
|
123
|
+
dg.save!
|
124
|
+
end
|
125
|
+
|
110
126
|
endpoint :add_window__add_form__submit do |params|
|
111
127
|
data = ActiveSupport::JSON.decode(params[:data])
|
112
128
|
|
@@ -114,7 +130,8 @@ module Marty; class DataGridView < McflyGridPanel
|
|
114
130
|
!config[:permissions][:create]
|
115
131
|
|
116
132
|
begin
|
117
|
-
DataGrid.create_from_import(data['name'], data['export'])
|
133
|
+
dg = DataGrid.create_from_import(data['name'], data['export'])
|
134
|
+
set_perms(dg, data)
|
118
135
|
client.success = true
|
119
136
|
client.netzke_on_submit_success
|
120
137
|
rescue StandardError => exc
|
@@ -129,6 +146,7 @@ module Marty; class DataGridView < McflyGridPanel
|
|
129
146
|
|
130
147
|
begin
|
131
148
|
dg.update_from_import(data['name'], data['export'])
|
149
|
+
set_perms(dg, data)
|
132
150
|
client.success = true
|
133
151
|
client.netzke_on_submit_success
|
134
152
|
rescue StandardError => exc
|
@@ -168,14 +186,8 @@ module Marty; class DataGridView < McflyGridPanel
|
|
168
186
|
client.netzke_client_show_grid maxcount, res, 'Data Grid'
|
169
187
|
end
|
170
188
|
|
171
|
-
|
172
|
-
|
173
|
-
def self.get_edit_edit_permission
|
174
|
-
Marty::Config['grid_edit_edit_perm'] || 'edit_all'
|
175
|
-
end
|
176
|
-
|
177
|
-
def self.get_edit_save_permission
|
178
|
-
Marty::Config['grid_edit_save_perm'] || 'edit_all'
|
189
|
+
def self.get_edit_permission(_permissions)
|
190
|
+
'edit_all'
|
179
191
|
end
|
180
192
|
|
181
193
|
endpoint :edit_grid do |params|
|
@@ -193,9 +205,21 @@ module Marty; class DataGridView < McflyGridPanel
|
|
193
205
|
vdim = md.map { |m| m['dir'] == 'v' && m['attr'] }.select { |v| v }
|
194
206
|
hdim_en = hdim.map { |d| I18n.t('attributes.' + d, default: d) }
|
195
207
|
vdim_en = vdim.map { |d| I18n.t('attributes.' + d, default: d) }
|
196
|
-
|
197
|
-
|
198
|
-
client.
|
208
|
+
perm = self.class.get_edit_permission(dg.permissions)
|
209
|
+
# should never happen
|
210
|
+
return client.netzke_notify('No permission to edit/view grid.') unless perm
|
211
|
+
|
212
|
+
doing = case perm
|
213
|
+
when 'view'
|
214
|
+
'Viewing'
|
215
|
+
when 'edit_all'
|
216
|
+
'Editing (all)'
|
217
|
+
when 'edit_data'
|
218
|
+
'Editing (data only)'
|
219
|
+
end
|
220
|
+
name = "#{doing} Data Grid '#{dg.name}'"
|
221
|
+
|
222
|
+
client.edit_grid(record_id, hdim_en, vdim_en, res, name, perm)
|
199
223
|
end
|
200
224
|
|
201
225
|
endpoint :save_grid do |params|
|
@@ -213,10 +237,36 @@ module Marty; class DataGridView < McflyGridPanel
|
|
213
237
|
def default_form_items
|
214
238
|
[
|
215
239
|
:name,
|
240
|
+
:perm_view, :perm_edit_data, :perm_edit_all,
|
216
241
|
textarea_field(:export, height: 300, hide_label: true),
|
217
242
|
]
|
218
243
|
end
|
219
244
|
|
245
|
+
['view', 'edit_data', 'edit_all'].each do |p|
|
246
|
+
s = ('perm_' + p).to_s
|
247
|
+
attribute s do |c|
|
248
|
+
c.width = 100
|
249
|
+
c.flex = 1
|
250
|
+
c.label = I18n.t("data_grid_view_perms.#{s}")
|
251
|
+
c.type = :string
|
252
|
+
c.getter = lambda do |r|
|
253
|
+
Marty::RoleType.to_nice_names(r.permissions[p].sort)
|
254
|
+
end
|
255
|
+
store = Marty::RoleType.to_nice_names(::Marty::RoleType.get_all.sort.map)
|
256
|
+
|
257
|
+
# edit does not work without this dummy setter
|
258
|
+
c.setter = ->(r, v) {}
|
259
|
+
|
260
|
+
c.editor_config = {
|
261
|
+
multi_select: true,
|
262
|
+
empty_text: I18n.t('user_grid.select_roles'),
|
263
|
+
store: store,
|
264
|
+
type: :string,
|
265
|
+
xtype: :combo,
|
266
|
+
}
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
220
270
|
component :edit_window do |c|
|
221
271
|
super(c)
|
222
272
|
c.width = 700
|
@@ -228,11 +278,11 @@ module Marty; class DataGridView < McflyGridPanel
|
|
228
278
|
end
|
229
279
|
|
230
280
|
attribute :name do |c|
|
231
|
-
c.width =
|
281
|
+
c.width = 400
|
232
282
|
end
|
233
283
|
|
234
284
|
attribute :constraint do |c|
|
235
|
-
c.width =
|
285
|
+
c.width = 150
|
236
286
|
end
|
237
287
|
|
238
288
|
attribute :hcols do |c|
|
@@ -4,6 +4,7 @@ require 'marty/api_log_view'
|
|
4
4
|
require 'marty/config_view'
|
5
5
|
require 'marty/data_grid_view'
|
6
6
|
require 'marty/schedule_jobs_dashboard'
|
7
|
+
require 'marty/data_grid_user_view'
|
7
8
|
require 'marty/event_view'
|
8
9
|
require 'marty/import_type_view'
|
9
10
|
require 'marty/new_posting_window'
|
@@ -96,6 +97,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
96
97
|
icon_cls: 'fa fa-window-restore glyph',
|
97
98
|
menu: [
|
98
99
|
:data_grid_view,
|
100
|
+
:data_grid_user_view,
|
99
101
|
:reporting,
|
100
102
|
:scripting,
|
101
103
|
:promise_view,
|
@@ -237,7 +239,14 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
237
239
|
end
|
238
240
|
|
239
241
|
action :data_grid_view do |a|
|
240
|
-
a.text = I18n.t('data_grid_view'
|
242
|
+
a.text = I18n.t('data_grid_view')
|
243
|
+
a.handler = :netzke_load_component_by_action
|
244
|
+
a.icon_cls = 'fa fa-table glyph'
|
245
|
+
a.disabled = !self.class.has_any_perm?
|
246
|
+
end
|
247
|
+
|
248
|
+
action :data_grid_user_view do |a|
|
249
|
+
a.text = I18n.t('data_grid_user_view')
|
241
250
|
a.handler = :netzke_load_component_by_action
|
242
251
|
a.icon_cls = 'fa fa-table glyph'
|
243
252
|
a.disabled = !self.class.has_any_perm?
|
@@ -388,6 +397,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
388
397
|
component :config_view
|
389
398
|
|
390
399
|
component :data_grid_view
|
400
|
+
component :data_grid_user_view
|
391
401
|
|
392
402
|
component :event_view
|
393
403
|
|
@@ -33,9 +33,7 @@ module Marty; class UserView < Marty::Grid
|
|
33
33
|
def self.set_roles(roles, user)
|
34
34
|
roles = [] unless roles.present?
|
35
35
|
|
36
|
-
roles = Marty::RoleType.
|
37
|
-
roles.include?(I18n.t("roles.#{role}", default: role))
|
38
|
-
end
|
36
|
+
roles = ::Marty::RoleType.from_nice_names(roles)
|
39
37
|
|
40
38
|
roles_in_user = user.user_roles.map(&:role)
|
41
39
|
roles_to_delete = roles_in_user - roles
|
@@ -152,14 +150,10 @@ module Marty; class UserView < Marty::Grid
|
|
152
150
|
c.type = :string
|
153
151
|
|
154
152
|
c.getter = lambda do |r|
|
155
|
-
r.user_roles.map
|
156
|
-
I18n.t("roles.#{ur.role}", default: ur.role)
|
157
|
-
end
|
153
|
+
Marty::RoleType.to_nice_names(r.user_roles.map(&:role))
|
158
154
|
end
|
159
155
|
|
160
|
-
store = ::Marty::RoleType.
|
161
|
-
I18n.t("roles.#{role}", default: role)
|
162
|
-
end
|
156
|
+
store = ::Marty::RoleType.to_nice_names(::Marty::RoleType::VALUES.sort)
|
163
157
|
|
164
158
|
c.editor_config = {
|
165
159
|
multi_select: true,
|
@@ -360,13 +360,19 @@ class Marty::DataGrid < Marty::Base
|
|
360
360
|
def export_array
|
361
361
|
# add data type metadata row if not default
|
362
362
|
lenstr = 'lenient' if lenient
|
363
|
-
typestr = data_type unless [nil, DEFAULT_DATA_TYPE].member?(data_type) &&
|
364
|
-
!constraint.present?
|
365
363
|
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
364
|
+
typestr = data_type unless [nil, DEFAULT_DATA_TYPE].member?(data_type)
|
365
|
+
len_type = [lenstr, typestr].compact.join(' ')
|
366
|
+
|
367
|
+
meta_rows = if (lenient || typestr) && constraint
|
368
|
+
[[len_type, constraint]]
|
369
|
+
elsif lenient || typestr
|
370
|
+
[[len_type]]
|
371
|
+
elsif constraint
|
372
|
+
[['', constraint]]
|
373
|
+
else
|
374
|
+
[]
|
375
|
+
end
|
370
376
|
|
371
377
|
meta_rows += metadata.map do |inf|
|
372
378
|
[inf['attr'], inf['type'], inf['dir'], inf['rs_keep'] || '']
|
@@ -5,6 +5,19 @@ class Marty::RoleType < Marty::Base
|
|
5
5
|
'admin',
|
6
6
|
'user_manager',
|
7
7
|
'dev',
|
8
|
-
'viewer'
|
8
|
+
'viewer',
|
9
|
+
'data_grid_editor'
|
9
10
|
]
|
11
|
+
|
12
|
+
def self.from_nice_names(roles)
|
13
|
+
Marty::RoleType.get_all.select do |role|
|
14
|
+
roles.include?(I18n.t("roles.#{role}", default: role))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.to_nice_names(roles)
|
19
|
+
roles.map do |role|
|
20
|
+
I18n.t("roles.#{role}", default: role)
|
21
|
+
end
|
22
|
+
end
|
10
23
|
end
|
@@ -15,8 +15,9 @@ module Marty
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.call(params)
|
18
|
-
user_perm = Marty::DataGridView.get_edit_save_permission
|
19
18
|
rec_id = params['record_id']
|
19
|
+
dg = Marty::DataGrid.mcfly_pt('infinity').find_by(group_id: rec_id)
|
20
|
+
user_perm = Marty::DataGridView.get_edit_permission(dg.permissions)
|
20
21
|
data = params['data']
|
21
22
|
raise GridError.new('entered with view permissions', data, rec_id) if
|
22
23
|
user_perm == 'view'
|
@@ -24,7 +25,6 @@ module Marty
|
|
24
25
|
data_as_array = data.map do |row|
|
25
26
|
row.keys.map { |key| row[key] }
|
26
27
|
end
|
27
|
-
dg = Marty::DataGrid.mcfly_pt('infinity').find_by(group_id: rec_id)
|
28
28
|
vcnt = dg.metadata.select { |md| md['dir'] == 'v' }.count
|
29
29
|
hcnt = dg.metadata.select { |md| md['dir'] == 'h' }.count
|
30
30
|
cur_data_dim = [dg.data.length, dg.data[0].length]
|
data/config/locales/en.yml
CHANGED
@@ -18,8 +18,10 @@ en:
|
|
18
18
|
create_posting: Create
|
19
19
|
api_auth: API Authorization
|
20
20
|
event_view: Event View
|
21
|
-
data_grid_view: Data Grids
|
22
|
-
data_grid: Data Grids
|
21
|
+
data_grid_view: Data Grids Admin
|
22
|
+
data_grid: Data Grids Admin
|
23
|
+
data_grid_user: Data Grids
|
24
|
+
data_grid_user_view: Data Grids
|
23
25
|
|
24
26
|
data_import_view:
|
25
27
|
import: Import
|
@@ -30,6 +32,7 @@ en:
|
|
30
32
|
admin: Admin
|
31
33
|
dev: Developer
|
32
34
|
user_manager: User Manager
|
35
|
+
data_grid_editor: Data Grid Editor
|
33
36
|
|
34
37
|
posting_types:
|
35
38
|
BASE: BASE
|
@@ -176,3 +179,9 @@ en:
|
|
176
179
|
grid:
|
177
180
|
base:
|
178
181
|
view_record: "%{model} (Read-only)"
|
182
|
+
|
183
|
+
data_grid_view_perms:
|
184
|
+
perm_view: Can View
|
185
|
+
perm_edit_data: Can Edit Data
|
186
|
+
perm_edit_all: Can Edit All
|
187
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class AddDataGridPerms < ActiveRecord::Migration[4.2]
|
2
|
+
def self.up
|
3
|
+
default = {
|
4
|
+
view: [],
|
5
|
+
edit_data: [],
|
6
|
+
edit_all: []
|
7
|
+
}
|
8
|
+
table = :marty_data_grids
|
9
|
+
add_column table, :permissions, :jsonb, null: false, default: default
|
10
|
+
add_index table, "(permissions->'view')", using: "GIN",
|
11
|
+
name: :marty_data_grids_perm_idx
|
12
|
+
end
|
13
|
+
def self.down
|
14
|
+
remove_column :marty_data_grids, :permissions
|
15
|
+
end
|
16
|
+
end
|
data/docker-compose.dummy.yml
CHANGED
data/lib/marty/migrations.rb
CHANGED
data/lib/marty/version.rb
CHANGED
@@ -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)
|
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
|
-
|
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
|
@@ -2,6 +2,10 @@ 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
|
+
|
5
9
|
before(:each) do
|
6
10
|
marty_whodunnit
|
7
11
|
Marty::Script.load_scripts
|
@@ -11,12 +15,22 @@ feature 'data grid view', js: true do
|
|
11
15
|
n = File.basename(path, '.txt').camelize
|
12
16
|
Marty::DataGrid.create_from_import(n, File.read(path), dt)
|
13
17
|
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' => [] }
|
14
26
|
end
|
15
27
|
|
16
|
-
def go_to_data_grids
|
28
|
+
def go_to_data_grids(admin: true)
|
29
|
+
log_in_as(admin ? 'marty' : 'grid_user')
|
17
30
|
press('Applications')
|
18
|
-
|
19
|
-
|
31
|
+
dest = 'Data Grids' + (admin ? ' Admin' : '')
|
32
|
+
press(dest)
|
33
|
+
expect(page).to have_content dest
|
20
34
|
end
|
21
35
|
|
22
36
|
# setup the info for the ext grid
|
@@ -24,7 +38,7 @@ feature 'data grid view', js: true do
|
|
24
38
|
widths, rows = get_grid_info
|
25
39
|
@grid = page.all(:xpath,
|
26
40
|
".//div[contains(@class, 'x-grid-item-container')]").
|
27
|
-
reject { |e| e.text.include?('
|
41
|
+
reject { |e| e.text.include?('DataGrid1') }.first
|
28
42
|
@gridx = @grid.native.rect.x
|
29
43
|
@gridy = @grid.native.rect.y
|
30
44
|
height = @grid.native.size.height
|
@@ -278,18 +292,97 @@ feature 'data grid view', js: true do
|
|
278
292
|
expect(grid_meta).to eq(exp_meta)
|
279
293
|
end
|
280
294
|
|
281
|
-
it 'dg
|
295
|
+
it 'dg perms' do
|
282
296
|
log_in_as('marty')
|
283
297
|
go_to_data_grids
|
284
298
|
dgv = netzke_find('data_grid_view')
|
285
299
|
grids = dgv.get_col_vals('name', 5)
|
286
|
-
|
287
|
-
|
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
|
350
|
+
log_in_as('marty')
|
351
|
+
go_to_data_grids
|
352
|
+
dgv = netzke_find('data_grid_view')
|
353
|
+
grids = dgv.get_col_vals('name', 5)
|
354
|
+
pos = grids.index('DataGrid1') + 1
|
355
|
+
dgv.select_row(pos)
|
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],
|
288
375
|
['edit_data', false],
|
289
376
|
['view', false]].each do |perm, all_cells|
|
377
|
+
|
378
|
+
set_perm(perm)
|
379
|
+
press('Refresh')
|
380
|
+
grids = dgv.get_col_vals('name', 5)
|
381
|
+
if perm.nil?
|
382
|
+
expect(grids).to be_nil
|
383
|
+
next
|
384
|
+
end
|
290
385
|
grids.each do |grid|
|
291
|
-
Marty::Config['grid_edit_edit_perm'] = perm
|
292
|
-
Marty::Config['grid_edit_save_perm'] = perm
|
293
386
|
pos = grids.index(grid) + 1
|
294
387
|
dgv.select_row(pos)
|
295
388
|
press('Edit Grid')
|
@@ -300,8 +393,14 @@ feature 'data grid view', js: true do
|
|
300
393
|
wait_for_ajax
|
301
394
|
end
|
302
395
|
end
|
303
|
-
|
304
|
-
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'dg editor' do
|
399
|
+
set_perm('edit_all')
|
400
|
+
log_in_as('grid_user')
|
401
|
+
go_to_data_grids(admin: false)
|
402
|
+
dgv = netzke_find('data_grid_user_view')
|
403
|
+
grids = dgv.get_col_vals('name', 5)
|
305
404
|
|
306
405
|
# now test some editing, saving, and cancel logic
|
307
406
|
get_latest = lambda do
|
@@ -460,40 +559,5 @@ feature 'data grid view', js: true do
|
|
460
559
|
press('Save')
|
461
560
|
sleep 1
|
462
561
|
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
562
|
end
|
499
563
|
end
|
data/spec/features/rule_spec.rb
CHANGED
@@ -419,7 +419,7 @@ EOL
|
|
419
419
|
%Q({"grid1":"DataGrid1"}),
|
420
420
|
%Q({"grid1":"DataGrid1"})])
|
421
421
|
press('Applications')
|
422
|
-
press('Data Grids')
|
422
|
+
press('Data Grids Admin')
|
423
423
|
dgv = netzke_find('data_grid_view')
|
424
424
|
cvs = dgv.get_col_vals(:name, 4, 0)
|
425
425
|
ind1 = cvs.index('DataGrid1') + 1
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
feature 'under
|
3
|
+
feature 'under System menu, User Management worflows', js: true do
|
4
4
|
def go_to_user_view
|
5
5
|
press('System')
|
6
6
|
press('User Management')
|
@@ -77,6 +77,7 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
77
77
|
|
78
78
|
and_by 'check row got edited' do
|
79
79
|
wait_for_ajax
|
80
|
+
r2 = user_view.get_row_vals(2)
|
80
81
|
expect(user_view.get_row_vals(2)).to netzke_include(
|
81
82
|
login: 'new_login',
|
82
83
|
firstname: 'new_fname',
|
@@ -114,6 +115,9 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
114
115
|
by 'check buttons' do
|
115
116
|
find(:btn, 'New User', match: :first)
|
116
117
|
user_view.select_row(1)
|
118
|
+
expect { find(:btn, 'New User') }.not_to raise_error
|
119
|
+
expect { find(:btn, 'Edit') }.not_to raise_error
|
120
|
+
expect { find(:btn, 'Delete') }.not_to raise_error
|
117
121
|
expect(btn_disabled?('New User')).to be_falsy
|
118
122
|
expect(btn_disabled?('Edit')).to be_falsy
|
119
123
|
expect(btn_disabled?('Delete')).to be_falsy
|
@@ -127,6 +131,9 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
127
131
|
by 'check buttons' do
|
128
132
|
find(:btn, 'New User', match: :first)
|
129
133
|
user_view.select_row(1)
|
134
|
+
expect { find(:btn, 'New User') }.not_to raise_error
|
135
|
+
expect { find(:btn, 'Edit') }.not_to raise_error
|
136
|
+
expect { find(:btn, 'Delete') }.not_to raise_error
|
130
137
|
expect(btn_disabled?('New User')).to be_falsy
|
131
138
|
expect(btn_disabled?('Edit')).to be_falsy
|
132
139
|
expect(btn_disabled?('Delete')).to be_falsy
|
@@ -140,9 +147,10 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
140
147
|
user_view = netzke_find('user_view')
|
141
148
|
by 'check buttons' do
|
142
149
|
user_view.select_row(1)
|
143
|
-
|
144
|
-
expect(
|
145
|
-
expect(
|
150
|
+
err = /Unable to find visible btn/
|
151
|
+
expect { find(:btn, 'New User') }.to raise_error(err)
|
152
|
+
expect { find(:btn, 'Edit') }.to raise_error(err)
|
153
|
+
expect { find(:btn, 'Delete') }.to raise_error(err)
|
146
154
|
end
|
147
155
|
end
|
148
156
|
|
@@ -153,9 +161,10 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
153
161
|
user_view = netzke_find('user_view')
|
154
162
|
by 'check buttons' do
|
155
163
|
user_view.select_row(1)
|
156
|
-
|
157
|
-
expect(
|
158
|
-
expect(
|
164
|
+
err = /Unable to find visible btn/
|
165
|
+
expect { find(:btn, 'New User') }.to raise_error(err)
|
166
|
+
expect { find(:btn, 'Edit') }.to raise_error(err)
|
167
|
+
expect { find(:btn, 'Delete') }.to raise_error(err)
|
159
168
|
end
|
160
169
|
end
|
161
170
|
end
|
@@ -814,7 +814,8 @@ EOS
|
|
814
814
|
# rubocop:disable Style/NestedTernaryOperator
|
815
815
|
type_str = type == 'float' ? (explicit_float ? 'float' : nil) : type
|
816
816
|
# rubocop:enable Style/NestedTernaryOperator
|
817
|
-
|
817
|
+
con_part = constraint.present? ? "\t" + constraint : ''
|
818
|
+
top = [lenient_str, type_str].compact.join(' ') + con_part + "\n"
|
818
819
|
(top =~ /\A\s*\z/ ? '' : top) +
|
819
820
|
<<~EOS
|
820
821
|
b\tboolean\tv
|
@@ -836,8 +837,8 @@ EOS
|
|
836
837
|
tests = JSON.parse(File.read('spec/fixtures/json/data_grid.json'))
|
837
838
|
aggregate_failures do
|
838
839
|
tests.each do |test|
|
839
|
-
keys = %w[id type constraint values error]
|
840
|
-
id, type, constraint, values, error = test.values_at(*keys)
|
840
|
+
keys = %w[id type constraint values error line1]
|
841
|
+
id, type, constraint, values, error, line1 = test.values_at(*keys)
|
841
842
|
err_re = Regexp.new(error) if error
|
842
843
|
# for float, do both ex- and implicit declaration
|
843
844
|
exfls = type == 'float' ? [true, false] : [true]
|
@@ -848,7 +849,21 @@ EOS
|
|
848
849
|
got = nil
|
849
850
|
tnam = "Test #{id} lenient=#{lenient} exfl=#{exfl}"
|
850
851
|
begin
|
851
|
-
dg_from_import(tnam, grid)
|
852
|
+
dg = dg_from_import(tnam, grid)
|
853
|
+
|
854
|
+
# make sure export of line1 works correctly
|
855
|
+
# when dg is lenient and/or has constraint and/or
|
856
|
+
# not float
|
857
|
+
next unless lenient || constraint.present? ||
|
858
|
+
type != 'float'
|
859
|
+
|
860
|
+
# also skip grids where we included float explicitly
|
861
|
+
# because export will convert back to implicit
|
862
|
+
next if type == 'float' && exfl
|
863
|
+
|
864
|
+
dga = dg.export_array
|
865
|
+
line1 = dga.first.first.join("\t") + "\n"
|
866
|
+
expect(line1).to eq(grid.lines.first)
|
852
867
|
rescue StandardError => e
|
853
868
|
got = e.message
|
854
869
|
end
|
data/spec/support/netzke.rb
CHANGED
@@ -53,7 +53,8 @@ module Marty; module RSpec; module Netzke
|
|
53
53
|
wait_for_element do
|
54
54
|
begin
|
55
55
|
cmp = first("a[data-qtip='#{button_name}']")
|
56
|
-
cmp ||=
|
56
|
+
cmp ||= all(:xpath, './/a', text: button_name.to_s).
|
57
|
+
detect { |c| c.text == button_name.to_s }
|
57
58
|
cmp ||= find(:btn, button_name, match: :first)
|
58
59
|
cmp.click
|
59
60
|
true
|
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: 3.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arman Bostani
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2019-
|
17
|
+
date: 2019-07-05 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: pg
|
@@ -230,6 +230,7 @@ files:
|
|
230
230
|
- ".rspec"
|
231
231
|
- ".rubocop.yml"
|
232
232
|
- ".rubocop_todo.yml"
|
233
|
+
- ".ssh-docker/.keep"
|
233
234
|
- ".travis.yml"
|
234
235
|
- Dockerfile.dummy
|
235
236
|
- Gemfile
|
@@ -256,6 +257,7 @@ files:
|
|
256
257
|
- app/components/marty/auth_app/client/auth_app.js
|
257
258
|
- app/components/marty/base_rule_view.rb
|
258
259
|
- app/components/marty/config_view.rb
|
260
|
+
- app/components/marty/data_grid_user_view.rb
|
259
261
|
- app/components/marty/data_grid_view.rb
|
260
262
|
- app/components/marty/data_grid_view/client/data_grid_edit.js
|
261
263
|
- app/components/marty/delorean_rule_view.rb
|
@@ -394,6 +396,7 @@ files:
|
|
394
396
|
- db/migrate/105_create_marty_grid_index_booleans.rb
|
395
397
|
- db/migrate/106_make_grid_indexes_nullable.rb
|
396
398
|
- db/migrate/107_add_data_grid_constraint.rb
|
399
|
+
- db/migrate/108_add_data_grid_perms.rb
|
397
400
|
- db/migrate/200_create_marty_event_operation_enum.rb
|
398
401
|
- db/migrate/201_create_marty_events.rb
|
399
402
|
- db/migrate/202_add_completion_status_to_event.rb
|
@@ -462,6 +465,7 @@ files:
|
|
462
465
|
- marty.gemspec
|
463
466
|
- other/marty/api/base.rb
|
464
467
|
- other/marty/diagnostic/aws/ec2_instance.rb
|
468
|
+
- other/marty/diagnostic/aws/error.rb
|
465
469
|
- other/marty/diagnostic/base.rb
|
466
470
|
- other/marty/diagnostic/collection.rb
|
467
471
|
- other/marty/diagnostic/connections.rb
|