gooddata 0.6.11 → 0.6.12

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/.travis.yml +5 -0
  4. data/CHANGELOG.md +34 -1
  5. data/CLI.md +1 -1
  6. data/authors.sh +4 -0
  7. data/lib/gooddata.rb +1 -1
  8. data/lib/gooddata/cli/commands/api_cmd.rb +0 -2
  9. data/lib/gooddata/cli/commands/auth_cmd.rb +0 -3
  10. data/lib/gooddata/cli/commands/console_cmd.rb +1 -2
  11. data/lib/gooddata/cli/commands/domain_cmd.rb +0 -2
  12. data/lib/gooddata/cli/commands/process_cmd.rb +0 -2
  13. data/lib/gooddata/cli/commands/project_cmd.rb +0 -2
  14. data/lib/gooddata/cli/commands/projects_cmd.rb +0 -2
  15. data/lib/gooddata/cli/commands/run_ruby_cmd.rb +2 -3
  16. data/lib/gooddata/cli/commands/scaffold_cmd.rb +0 -3
  17. data/lib/gooddata/cli/commands/user_cmd.rb +0 -2
  18. data/lib/gooddata/cli/shared.rb +1 -2
  19. data/lib/gooddata/commands/datawarehouse.rb +24 -0
  20. data/lib/gooddata/commands/process.rb +0 -1
  21. data/lib/gooddata/commands/project.rb +1 -1
  22. data/lib/gooddata/commands/scaffold.rb +0 -1
  23. data/lib/gooddata/core/connection.rb +376 -0
  24. data/lib/gooddata/core/logging.rb +13 -0
  25. data/lib/gooddata/core/rest.rb +40 -16
  26. data/lib/gooddata/exceptions/user_in_different_domain.rb +11 -0
  27. data/lib/gooddata/extensions/enumerable.rb +8 -0
  28. data/lib/gooddata/goodzilla/goodzilla.rb +24 -0
  29. data/lib/gooddata/helpers/global_helpers.rb +126 -12
  30. data/lib/gooddata/mixins/author.rb +11 -5
  31. data/lib/gooddata/mixins/is_dimension.rb +13 -0
  32. data/lib/gooddata/mixins/md_object_indexer.rb +17 -1
  33. data/lib/gooddata/mixins/md_object_query.rb +10 -2
  34. data/lib/gooddata/mixins/md_relations.rb +2 -2
  35. data/lib/gooddata/mixins/rest_resource.rb +1 -0
  36. data/lib/gooddata/models/data_result.rb +0 -1
  37. data/lib/gooddata/models/datawarehouse.rb +90 -0
  38. data/lib/gooddata/models/domain.rb +202 -76
  39. data/lib/gooddata/models/execution.rb +11 -0
  40. data/lib/gooddata/models/from_wire.rb +4 -4
  41. data/lib/gooddata/models/invitation.rb +0 -5
  42. data/lib/gooddata/models/membership.rb +121 -91
  43. data/lib/gooddata/models/metadata.rb +1 -2
  44. data/lib/gooddata/models/metadata/attribute.rb +7 -0
  45. data/lib/gooddata/models/metadata/dashboard.rb +1 -1
  46. data/lib/gooddata/models/metadata/dimension.rb +52 -0
  47. data/lib/gooddata/models/metadata/fact.rb +1 -1
  48. data/lib/gooddata/models/metadata/label.rb +21 -7
  49. data/lib/gooddata/models/metadata/metric.rb +1 -23
  50. data/lib/gooddata/models/metadata/report.rb +2 -2
  51. data/lib/gooddata/models/metadata/report_definition.rb +22 -2
  52. data/lib/gooddata/models/metadata/variable.rb +81 -0
  53. data/lib/gooddata/models/model.rb +2 -1
  54. data/lib/gooddata/models/process.rb +3 -4
  55. data/lib/gooddata/models/profile.rb +50 -82
  56. data/lib/gooddata/models/project.rb +170 -213
  57. data/lib/gooddata/models/project_blueprint.rb +14 -5
  58. data/lib/gooddata/models/project_creator.rb +2 -2
  59. data/lib/gooddata/models/schedule.rb +10 -8
  60. data/lib/gooddata/models/to_wire.rb +2 -2
  61. data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +67 -0
  62. data/lib/gooddata/models/user_filters/user_filter.rb +96 -0
  63. data/lib/gooddata/models/user_filters/user_filter_builder.rb +409 -0
  64. data/lib/gooddata/{rest/connections/connections.rb → models/user_filters/user_filters.rb} +1 -0
  65. data/lib/gooddata/models/user_filters/variable_user_filter.rb +14 -0
  66. data/lib/gooddata/rest/client.rb +32 -21
  67. data/lib/gooddata/rest/connection.rb +283 -11
  68. data/lib/gooddata/rest/connections/rest_client_connection.rb +47 -109
  69. data/lib/gooddata/version.rb +1 -1
  70. data/spec/data/column_based_permissions.csv +7 -0
  71. data/spec/data/column_based_permissions2.csv +6 -0
  72. data/spec/data/hello_world_process/hello_world.rb +3 -1
  73. data/spec/data/line_based_permissions.csv +3 -0
  74. data/spec/data/m_n_model/blueprint.json +76 -0
  75. data/spec/data/{model_view.json → wire_models/model_view.json} +0 -0
  76. data/spec/data/wire_models/nu_model.json +3046 -0
  77. data/spec/helpers/process_helper.rb +2 -2
  78. data/spec/helpers/project_helper.rb +29 -0
  79. data/spec/helpers/schedule_helper.rb +1 -1
  80. data/spec/integration/command_datawarehouse_spec.rb +32 -0
  81. data/spec/integration/create_project_spec.rb +0 -1
  82. data/spec/integration/full_process_schedule_spec.rb +13 -5
  83. data/spec/integration/full_project_spec.rb +2 -1
  84. data/spec/integration/over_to_user_filters_spec.rb +92 -0
  85. data/spec/integration/project_spec.rb +233 -0
  86. data/spec/integration/rest_spec.rb +209 -0
  87. data/spec/integration/user_filters_spec.rb +193 -0
  88. data/spec/integration/variables_spec.rb +196 -0
  89. data/spec/unit/commands/command_auth_spec.rb +0 -7
  90. data/spec/unit/commands/command_process_spec.rb +10 -13
  91. data/spec/unit/core/connection_spec.rb +0 -19
  92. data/spec/unit/helpers/global_helpers_spec.rb +57 -0
  93. data/spec/unit/models/domain_spec.rb +80 -40
  94. data/spec/unit/models/from_wire_spec.rb +8 -1
  95. data/spec/unit/models/params_spec.rb +6 -6
  96. data/spec/unit/models/profile_spec.rb +23 -22
  97. data/spec/unit/models/project_blueprint_spec.rb +1 -6
  98. data/spec/unit/models/project_spec.rb +331 -286
  99. data/spec/unit/models/schedule_spec.rb +39 -14
  100. data/spec/unit/models/user_filters_spec.rb +89 -0
  101. data/spec/unit/models/variable_spec.rb +259 -0
  102. metadata +31 -7
  103. data/lib/gooddata/rest/connections/dummy_connection.rb +0 -52
  104. data/spec/unit/core/rest_spec.rb +0 -106
@@ -0,0 +1,209 @@
1
+ # encoding: UTF-8
2
+ require 'tempfile'
3
+
4
+ require 'gooddata/core/rest'
5
+
6
+ describe GoodData do
7
+ before(:each) do
8
+ @client = ConnectionHelper.create_default_connection
9
+ # @project = ProjectHelper.get_default_project(:client => @client)
10
+ @project = @client.create_project(title: 'Project for schedule testing', auth_token: ConnectionHelper::GD_PROJECT_TOKEN)
11
+ end
12
+
13
+ after(:each) do
14
+ @project && @project.delete
15
+ @client.disconnect
16
+ end
17
+
18
+ describe '#get_project_webdav_path' do
19
+ it 'Returns path' do
20
+ @client.get_project_webdav_path('test-file.csv', :project => @project)
21
+ end
22
+ end
23
+
24
+ def test_webdav_upload(params)
25
+ GoodData.with_project(@project, :client => @client) do
26
+
27
+ # use current timestamp as a directory name on webdav
28
+ dir = params[:no_dir] ? nil : Time.now.to_i.to_s
29
+ dir = "#{dir}/#{dir}" if params[:nested_dir]
30
+ dir = "#{dir}/" if params[:slash_in_dir]
31
+
32
+ # local file path
33
+ path = 'spec/data/test-ci-data.csv'
34
+
35
+ if params[:special_chars]
36
+ source_file = Tempfile.new('abc-16:55:29+ha#he.csv')
37
+ FileUtils.cp(path, source_file)
38
+ path = source_file.path
39
+ end
40
+
41
+ path = File.expand_path(path) if params[:absolute_path]
42
+
43
+ # upload it there
44
+ upload_method = GoodData.method(params[:upload_method])
45
+ upload_method.call(path, directory: dir)
46
+
47
+ # download it from there
48
+ temp_file = Tempfile.new('foo.csv')
49
+ expect(temp_file.size).to be == 0
50
+
51
+ download_method = GoodData.method(params[:download_method])
52
+
53
+ file_basename = File.basename(path)
54
+ file_basename = "NOTTHERE_#{file_basename}" if params[:unknown_file]
55
+
56
+ download_block = proc do
57
+ if params[:path_in_file]
58
+ # pass the dir directly in the first param
59
+ # e.g. GoodData.download_from_project_webdav('1234/test-ci-data.csv', '/tmp/myfile.csv')
60
+ download_method.call(File.join(dir, file_basename).to_s, temp_file)
61
+ else
62
+ # pass the dir in the :directory option
63
+ # e.g. GoodData.download_from_project_webdav('test-ci-data.csv', '/tmp/myfile.csv', :directory => '1234')
64
+ download_method.call(file_basename, temp_file, directory: dir)
65
+ end
66
+ end
67
+
68
+ # if it's unknown it should raise an error, otherwise it should download the right stuff
69
+ if params[:unknown_file]
70
+ expect{ download_block.call }.to raise_error(ArgumentError)
71
+ else
72
+ download_block.call
73
+
74
+ expect(temp_file.size).to be > 0
75
+
76
+ # expect the contents of the original file and the downloaded file are the same
77
+ expect(IO.read(temp_file)).to be == IO.read(path)
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#download_from_project_webdav' do
83
+ it "Works with directory directly in the 'file' param for project" do
84
+ test_webdav_upload(
85
+ upload_method: 'upload_to_project_webdav',
86
+ download_method: 'download_from_project_webdav',
87
+ path_in_file: true
88
+ )
89
+ end
90
+ it "Works with directory directly in the 'file' param for user" do
91
+ test_webdav_upload(
92
+ upload_method: 'upload_to_user_webdav',
93
+ download_method: 'download_from_user_webdav',
94
+ path_in_file: true
95
+ )
96
+ end
97
+ it "Works with directories with slash at the end for project" do
98
+ test_webdav_upload(
99
+ upload_method: 'upload_to_project_webdav',
100
+ download_method: 'download_from_project_webdav',
101
+ slash_in_dir: true
102
+ )
103
+ end
104
+ it "Works with directories with slash at the end for user" do
105
+ test_webdav_upload(
106
+ upload_method: 'upload_to_user_webdav',
107
+ download_method: 'download_from_user_webdav',
108
+ slash_in_dir: true
109
+ )
110
+ end
111
+ it "Fails for non-existing file for project" do
112
+ test_webdav_upload(
113
+ upload_method: 'upload_to_project_webdav',
114
+ download_method: 'download_from_project_webdav',
115
+ unknown_file: true
116
+ )
117
+ end
118
+ it "Fails for non-existing file for user" do
119
+ test_webdav_upload(
120
+ upload_method: 'upload_to_user_webdav',
121
+ download_method: 'download_from_user_webdav',
122
+ unknown_file: true
123
+ )
124
+ end
125
+ it 'Works with nested directories for project' do
126
+ test_webdav_upload(
127
+ upload_method: 'upload_to_project_webdav',
128
+ download_method: 'download_from_project_webdav',
129
+ nested_dir: true
130
+ )
131
+ end
132
+ it 'Works with nested directories for user' do
133
+ test_webdav_upload(
134
+ upload_method: 'upload_to_user_webdav',
135
+ download_method: 'download_from_user_webdav',
136
+ nested_dir: true
137
+ )
138
+ end
139
+ it 'Works with no directory for user' do
140
+ test_webdav_upload(
141
+ upload_method: 'upload_to_user_webdav',
142
+ download_method: 'download_from_user_webdav',
143
+ no_dir: true
144
+ )
145
+ end
146
+ it 'Works with no directory for project' do
147
+ test_webdav_upload(
148
+ upload_method: 'upload_to_project_webdav',
149
+ download_method: 'download_from_project_webdav',
150
+ no_dir: true
151
+ )
152
+ end
153
+ end
154
+ describe '#upload_to_project_webdav' do
155
+ it 'Uploads file with relative path to a dir' do
156
+ test_webdav_upload(
157
+ upload_method: 'upload_to_project_webdav',
158
+ download_method: 'download_from_project_webdav'
159
+ )
160
+ end
161
+
162
+ it 'Uploads file with absolute path to a dir' do
163
+ test_webdav_upload(
164
+ absolute_path: true,
165
+ upload_method: 'upload_to_project_webdav',
166
+ download_method: 'download_from_project_webdav'
167
+ )
168
+ end
169
+
170
+ it 'Uploads file with special chars in filename' do
171
+ test_webdav_upload(
172
+ special_chars: true,
173
+ upload_method: 'upload_to_project_webdav',
174
+ download_method: 'download_from_project_webdav'
175
+ )
176
+ end
177
+ end
178
+
179
+ describe '#upload_to_user_webdav' do
180
+ it 'Uploads file with relative path to a dir' do
181
+ test_webdav_upload(
182
+ upload_method: 'upload_to_user_webdav',
183
+ download_method: 'download_from_user_webdav'
184
+ )
185
+ end
186
+
187
+ it 'Uploads file with absolute path to a dir' do
188
+ test_webdav_upload(
189
+ absolute_path: true,
190
+ upload_method: 'upload_to_user_webdav',
191
+ download_method: 'download_from_user_webdav'
192
+ )
193
+ end
194
+ it 'Uploads file with special chars in filename' do
195
+ test_webdav_upload(
196
+ special_chars: true,
197
+ upload_method: 'upload_to_user_webdav',
198
+ download_method: 'download_from_user_webdav'
199
+ )
200
+ end
201
+ end
202
+
203
+
204
+ describe '#get_user_webdav_path' do
205
+ it 'Gets the path' do
206
+ @client.get_user_webdav_path('test.csv', :project => @project)
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,193 @@
1
+ require 'gooddata'
2
+
3
+ describe "User filters implementation", :constraint => 'slow' do
4
+ before(:all) do
5
+ @spec = JSON.parse(File.read("./spec/data/test_project_model_spec.json"), :symbolize_names => true)
6
+ @client = ConnectionHelper::create_default_connection
7
+ @project = @client.create_project_from_blueprint(@spec, :auth_token => ConnectionHelper::GD_PROJECT_TOKEN)
8
+ @domain = @client.domain(ConnectionHelper::DEFAULT_DOMAIN)
9
+
10
+ GoodData.with_project(@project) do |p|
11
+ @label = GoodData::Attribute.find_first_by_title('Dev', client: @client, project: @project).label_by_name('email')
12
+
13
+ blueprint = GoodData::Model::ProjectBlueprint.new(@spec)
14
+ commits_data = [
15
+ ["lines_changed","committed_on","dev_id","repo_id"],
16
+ [1,"01/01/2014",1,1],
17
+ [3,"01/02/2014",2,2],
18
+ [5,"05/02/2014",3,1]]
19
+ GoodData::Model.upload_data(commits_data, blueprint, 'commits', :client => @client, :project => @project)
20
+ # blueprint.find_dataset('commits').upload(commits_data)
21
+
22
+ devs_data = [
23
+ ["dev_id", "email"],
24
+ [1, "tomas@gooddata.com"],
25
+ [2, "petr@gooddata.com"],
26
+ [3, "jirka@gooddata.com"]]
27
+ GoodData::Model.upload_data(devs_data, blueprint, 'devs', :client => @client, :project => @project)
28
+ # blueprint.find_dataset('devs').upload(devs_data)
29
+ end
30
+ end
31
+
32
+ after(:all) do
33
+ @project.delete if @project
34
+ end
35
+
36
+ after(:each) do
37
+ @project.data_permissions.pmap &:delete
38
+ end
39
+
40
+ it "should create a mandatory user filter" do
41
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, 'tomas@gooddata.com', 'jirka@gooddata.com']]
42
+
43
+ metric = @project.create_metric("SELECT SUM(#\"Lines Changed\")", :title => 'x')
44
+ # [jirka@gooddata.com | petr@gooddata.com | tomas@gooddata.com]
45
+ # [5.0 | 3.0 | 1.0 ]
46
+
47
+ metric.execute.should == 9
48
+ @project.add_data_permissions(filters)
49
+ metric.execute.should == 6
50
+ r = @project.compute_report(left: [metric], top: [@label.attribute])
51
+ r.include_column?(['tomas@gooddata.com', 1]).should == true
52
+
53
+ r.include_column?(['tomas@gooddata.com', 1]).should == true
54
+ r.include_column?(['jirka@gooddata.com', 5]).should == true
55
+ r.include_column?(['petr@gooddata.com', 3]).should == false
56
+ end
57
+
58
+ it "should fail when asked to set a user not in project. No filters should be set up." do
59
+ filters = [
60
+ ['nonexistent_user@gooddata.com', @label.uri, "tomas@gooddata.com"],
61
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]
62
+ ]
63
+ expect do
64
+ @project.add_data_permissions(filters)
65
+ end.to raise_error
66
+ expect(@project.data_permissions.count).to eq 0
67
+ end
68
+
69
+ it "should pass and set users that are in the projects" do
70
+ filters = [
71
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]
72
+ ]
73
+ @project.add_data_permissions(filters)
74
+ expect(@project.data_permissions.count).to eq 1
75
+ end
76
+
77
+ it "should pass and set only users that are in the projects if asked" do
78
+ filters = [
79
+ ['nonexistent_user@gooddata.com', @label.uri, 'tomas@gooddata.com'],
80
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, 'tomas@gooddata.com']
81
+ ]
82
+ @project.add_data_permissions(filters, users_must_exist: false)
83
+ expect(@project.data_permissions.count).to eq 1
84
+ expect(@project.data_permissions.first.pretty_expression).to eq "[Dev] IN ([tomas@gooddata.com])"
85
+ end
86
+
87
+ it "should fail when asked to set a value not in the proejct" do
88
+ filters = [
89
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, '%^&*( nonexistent value', 'tomas@gooddata.com'],
90
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, 'tomas@gooddata.com']]
91
+ expect do
92
+ @project.add_data_permissions(filters)
93
+ end.to raise_error
94
+ expect(@project.data_permissions.count).to eq 0
95
+ end
96
+
97
+ it "should add a filter with nonexistent values when asked" do
98
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, '%^&*( nonexistent value', 'jirka@gooddata.com']]
99
+ @project.add_data_permissions(filters, ignore_missing_values: true)
100
+
101
+ expect(@project.data_permissions.pmap {|m| m.pretty_expression}).to eq ["[Dev] IN ([jirka@gooddata.com])"]
102
+ expect(@project.data_permissions.count).to eq 1
103
+ end
104
+
105
+ it "should be able to add mandatory filter to a user not in the project if domain is provided" do
106
+ domain = @client.domain(ConnectionHelper::DEFAULT_DOMAIN)
107
+ u = domain.users.find { |u| u.login != ConnectionHelper::DEFAULT_USERNAME }
108
+
109
+ filters = [[u.login, @label.uri, "tomas@gooddata.com"]]
110
+ expect do
111
+ @project.add_data_permissions(filters)
112
+ end.to raise_error
113
+ @project.add_data_permissions(filters, :domain => domain)
114
+ filters = @project.data_permissions
115
+ expect(filters.first.related.login).to eq u.login
116
+ expect(filters.count).to eq 1
117
+ expect(filters.first.pretty_expression).to eq "[Dev] IN ([tomas@gooddata.com])"
118
+ end
119
+
120
+ it "should be able to print data permissions in a human readable form" do
121
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]]
122
+ @project.add_data_permissions(filters)
123
+ perms = @project.data_permissions
124
+ pretty = perms.pmap {|f| [f.related.login, f.pretty_expression]}
125
+ expect(perms.first.related).to eq @client.user
126
+ expect(pretty).to eq [["svarovsky+gem_tester@gooddata.com", "[Dev] IN ([tomas@gooddata.com])"]]
127
+ end
128
+
129
+ it "sets up mandatory users based on the state given as an end state by default." do
130
+ # first let's prepare some user filters
131
+ user_with_already_set_up_filter = @project.get_user(ConnectionHelper::DEFAULT_USERNAME)
132
+
133
+ filters = [
134
+ [user_with_already_set_up_filter.login, @label.uri, "tomas@gooddata.com"]
135
+ ]
136
+ @project.add_data_permissions(filters)
137
+ expect(@project.data_permissions.map {|f| [f.related.login, f.pretty_expression] })
138
+ .to eq [[ConnectionHelper::DEFAULT_USERNAME, "[Dev] IN ([tomas@gooddata.com])"]]
139
+
140
+ # Now let's add user filter to a different user. If we do not explicitely state that
141
+ # user_with_already_set_up_filter should keep his filter it will be removed
142
+ another_user = @domain.users.find { |u| u.login != ConnectionHelper::DEFAULT_USERNAME }
143
+ @project.add_user(another_user, 'Admin', domain: @domain)
144
+ new_filters = [
145
+ [another_user.login, @label.uri, "tomas@gooddata.com"]
146
+ ]
147
+ @project.add_data_permissions(new_filters)
148
+ expect(@project.data_permissions.map {|f| [f.related.login, f.pretty_expression] })
149
+ .to eq [[another_user.login, "[Dev] IN ([tomas@gooddata.com])"]]
150
+ end
151
+
152
+ it "should set up false if all values are nonexistent" do
153
+ metric = GoodData::Fact.find_first_by_title('Lines Changed', client: @client, project: @project).create_metric
154
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "NONEXISTENT1", "NONEXISTENT2", "NONEXISTENT3"]]
155
+ @project.add_data_permissions(filters, ignore_missing_values: true)
156
+ expect(metric.execute).to eq 9
157
+ @project.add_data_permissions(filters, ignore_missing_values: true, restrict_if_missing_all_values: true)
158
+ expect(metric.execute).to eq nil
159
+ end
160
+
161
+ it "you can switch the updates. Whatever is not mentioned will not be touched" do
162
+ # first let's prepare some user filters
163
+ user_with_already_set_up_filter = @project.get_user(ConnectionHelper::DEFAULT_USERNAME)
164
+
165
+ filters = [
166
+ [user_with_already_set_up_filter.login, @label.uri, "tomas@gooddata.com"]
167
+ ]
168
+ @project.add_data_permissions(filters)
169
+ expect(@project.data_permissions.map {|f| [f.related.login, f.pretty_expression] })
170
+ .to eq [[ConnectionHelper::DEFAULT_USERNAME, "[Dev] IN ([tomas@gooddata.com])"]]
171
+
172
+ # Now let's add user filter to a different user. If we do not explicitely state that
173
+ # user_with_already_set_up_filter should keep his filter it will be removed
174
+ another_user = @domain.users.find { |u| u.login != ConnectionHelper::DEFAULT_USERNAME }
175
+ @project.add_user(another_user, 'Admin', domain: @domain)
176
+ new_filters = [
177
+ [another_user.login, @label.uri, "tomas@gooddata.com"]
178
+ ]
179
+ @project.add_data_permissions(new_filters, do_not_touch_filters_that_are_not_mentioned: true)
180
+ expect(@project.data_permissions.map {|f| [f.related.login, f.pretty_expression] })
181
+ .to include([ConnectionHelper::DEFAULT_USERNAME, "[Dev] IN ([tomas@gooddata.com])"], [another_user.login, "[Dev] IN ([tomas@gooddata.com])"])
182
+ end
183
+
184
+ it "should be able to update the filter value" do
185
+ pending('We cannot swap filters yet')
186
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com", "jirka@gooddata.com"]]
187
+ @project.add_data_permissions(filters)
188
+ perm = @project.data_permissions.first
189
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]]
190
+ @project.add_data_permissions(filters)
191
+ expect(perm.reload!.pretty_expression).to eq '[Dev] IN ([tomas@gooddata.com, jirka@gooddata.com])'
192
+ end
193
+ end
@@ -0,0 +1,196 @@
1
+ require 'gooddata'
2
+
3
+ describe "Variables implementation", :constraint => 'slow' do
4
+ before(:all) do
5
+ @spec = JSON.parse(File.read("./spec/data/test_project_model_spec.json"), :symbolize_names => true)
6
+ @client = ConnectionHelper::create_default_connection
7
+ @project = @client.create_project_from_blueprint(@spec, :auth_token => ConnectionHelper::GD_PROJECT_TOKEN)
8
+ @domain = @client.domain(ConnectionHelper::DEFAULT_DOMAIN)
9
+
10
+ @label = GoodData::Attribute.find_first_by_title('Dev', client: @client, project: @project).label_by_name('email')
11
+
12
+ blueprint = GoodData::Model::ProjectBlueprint.new(@spec)
13
+ commits_data = [
14
+ ["lines_changed","committed_on","dev_id","repo_id"],
15
+ [1,"01/01/2014",1,1],
16
+ [3,"01/02/2014",2,2],
17
+ [5,"05/02/2014",3,1]]
18
+ GoodData::Model.upload_data(commits_data, blueprint, 'commits', :client => @client, :project => @project)
19
+ # blueprint.find_dataset('commits').upload(commits_data)
20
+
21
+ devs_data = [
22
+ ["dev_id", "email"],
23
+ [1, "tomas@gooddata.com"],
24
+ [2, "petr@gooddata.com"],
25
+ [3, "jirka@gooddata.com"]]
26
+ GoodData::Model.upload_data(devs_data, blueprint, 'devs', :client => @client, :project => @project)
27
+ # blueprint.find_dataset('devs').upload(devs_data)
28
+
29
+ @variable = @project.create_variable(title: 'uaaa', attribute: @label.attribute).save
30
+
31
+ end
32
+
33
+ after(:all) do
34
+ @project.delete if @project
35
+ end
36
+
37
+ after(:each) do
38
+ @variable.user_values.select {|x| x.level == :user}.pmap &:delete
39
+ end
40
+
41
+ it "should create a variable filter" do
42
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, 'tomas@gooddata.com', 'jirka@gooddata.com']]
43
+
44
+ metric = @project.create_metric("SELECT SUM(#\"Lines Changed\")", :title => 'x')
45
+
46
+ # [jirka@gooddata.com | petr@gooddata.com | tomas@gooddata.com]
47
+ # [5.0 | 3.0 | 1.0 ]
48
+ @project.add_variable_permissions(filters, @variable)
49
+ r = @project.compute_report(left: [metric], top: [@label.attribute], filters: [@variable])
50
+ r.include_column?(['tomas@gooddata.com', 1]).should == true
51
+ r.include_column?(['jirka@gooddata.com', 5]).should == true
52
+ r.include_column?(['petr@gooddata.com', 3]).should == false
53
+
54
+ r = @project.compute_report(left: [metric], top: [@label.attribute])
55
+ r.include_column?(['tomas@gooddata.com', 1]).should == true
56
+ r.include_column?(['jirka@gooddata.com', 5]).should == true
57
+ r.include_column?(['petr@gooddata.com', 3]).should == true
58
+ end
59
+
60
+ it "should fail when asked to set a user not in project. No filters should be set up." do
61
+ filters = [
62
+ ['nonexistent_user@gooddata.com', @label.uri, "tomas@gooddata.com"],
63
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]
64
+ ]
65
+ expect do
66
+ @project.add_variable_permissions(filters, @variable)
67
+ end.to raise_error
68
+ expect(@variable.user_values.count).to eq 0
69
+ end
70
+
71
+ it "should pass and set users that are in the projects" do
72
+ filters = [
73
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]
74
+ ]
75
+ @project.add_variable_permissions(filters, @variable)
76
+ expect(@variable.user_values.count).to eq 1
77
+ end
78
+
79
+ it "should pass and set only users that are in the projects if asked" do
80
+ filters = [
81
+ ['nonexistent_user@gooddata.com', @label.uri, 'tomas@gooddata.com'],
82
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, 'tomas@gooddata.com']
83
+ ]
84
+ @project.add_variable_permissions(filters, @variable, users_must_exist: false)
85
+ expect(@variable.user_values.count).to eq 1
86
+ end
87
+
88
+ it "should fail when asked to set a value not in the proejct" do
89
+ filters = [
90
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, '%^&*( nonexistent value', 'tomas@gooddata.com'],
91
+ [ConnectionHelper::DEFAULT_USERNAME, @label.uri, 'tomas@gooddata.com']]
92
+ expect do
93
+ @project.add_variable_permissions(filters, @variable)
94
+ end.to raise_error
95
+ expect(@variable.user_values.count).to eq 0
96
+ end
97
+
98
+ it "should add a filter with nonexistent values when asked" do
99
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, '%^&*( nonexistent value', 'jirka@gooddata.com']]
100
+ @project.add_variable_permissions(filters, @variable, ignore_missing_values: true)
101
+
102
+ expect(@variable.user_values.pmap {|m| m.pretty_expression}).to eq ["[Dev] IN ([jirka@gooddata.com])"]
103
+ expect(@variable.user_values.count).to eq 1
104
+ end
105
+
106
+ it "should be able to add mandatory filter to a user not in the project if domain is provided" do
107
+ domain = @client.domain(ConnectionHelper::DEFAULT_DOMAIN)
108
+ u = domain.users.find { |u| u.login != ConnectionHelper::DEFAULT_USERNAME }
109
+ filters = [[u.login, @label.uri, "tomas@gooddata.com"]]
110
+ expect do
111
+ @project.add_variable_permissions(filters, @variable)
112
+ end.to raise_error
113
+ @project.add_variable_permissions(filters, @variable, :domain => domain)
114
+ filters = @variable.user_values
115
+ expect(filters.first.related.login).to eq u.login
116
+ expect(filters.count).to eq 1
117
+ end
118
+
119
+ it "should be able to print data permissions in a human readable form" do
120
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]]
121
+ @project.add_variable_permissions(filters, @variable)
122
+ perms = @variable.user_values
123
+ pretty = perms.pmap {|f| [f.related.login, f.pretty_expression]}
124
+ expect(perms.first.related).to eq @client.user
125
+ expect(pretty).to eq [["svarovsky+gem_tester@gooddata.com", "[Dev] IN ([tomas@gooddata.com])"]]
126
+ end
127
+
128
+ it "sets up mandatory users based on the state given as an end state by default." do
129
+ # first let's prepare some user filters
130
+ user_with_already_set_up_filter = @project.get_user(ConnectionHelper::DEFAULT_USERNAME)
131
+
132
+ filters = [
133
+ [user_with_already_set_up_filter.login, @label.uri, "tomas@gooddata.com"]
134
+ ]
135
+ @project.add_variable_permissions(filters, @variable)
136
+ expect(@variable.user_values.map {|f| [f.related.login, f.pretty_expression] })
137
+ .to eq [[ConnectionHelper::DEFAULT_USERNAME, "[Dev] IN ([tomas@gooddata.com])"]]
138
+
139
+ # Now let's add user filter to a different user. If we do not explicitely state that
140
+ # user_with_already_set_up_filter should keep his filter it will be removed
141
+ another_user = @domain.users.find { |u| u.login != ConnectionHelper::DEFAULT_USERNAME }
142
+ @project.add_user(another_user, 'Admin', domain: @domain)
143
+ new_filters = [
144
+ [another_user.login, @label.uri, "tomas@gooddata.com"]
145
+ ]
146
+ @project.add_variable_permissions(new_filters, @variable)
147
+ expect(@variable.user_values.map {|f| [f.related.login, f.pretty_expression] })
148
+ .to eq [[another_user.login, "[Dev] IN ([tomas@gooddata.com])"]]
149
+ end
150
+
151
+ it "should set up false if all values are nonexistent" do
152
+ metric = GoodData::Fact.find_first_by_title('Lines Changed', client: @client, project: @project).create_metric
153
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "NONEXISTENT1", "NONEXISTENT2", "NONEXISTENT3"]]
154
+ @project.add_variable_permissions(filters, @variable, ignore_missing_values: true)
155
+ # expect(metric.execute).to eq 9
156
+ expect(@variable.user_values.map {|f| [f.related.login, f.pretty_expression] })
157
+ .to eq [[ConnectionHelper::DEFAULT_USERNAME, "TRUE"]]
158
+
159
+ @project.add_variable_permissions(filters, @variable, ignore_missing_values: true, restrict_if_missing_all_values: true)
160
+ # expect(metric.execute).to eq nil
161
+ expect(@variable.user_values.count).to eq 0
162
+ end
163
+
164
+ it "you can switch the updates. Whatever is not mentioned will not be touched" do
165
+ # first let's prepare some user filters
166
+ user_with_already_set_up_filter = @project.get_user(ConnectionHelper::DEFAULT_USERNAME)
167
+
168
+ filters = [
169
+ [user_with_already_set_up_filter.login, @label.uri, "tomas@gooddata.com"]
170
+ ]
171
+ @project.add_variable_permissions(filters, @variable)
172
+ expect(@variable.user_values.map {|f| [f.related.login, f.pretty_expression] })
173
+ .to eq [[ConnectionHelper::DEFAULT_USERNAME, "[Dev] IN ([tomas@gooddata.com])"]]
174
+ # Now let's add user filter to a different user. If we do not explicitely state that
175
+ # user_with_already_set_up_filter should keep his filter it will be removed
176
+ another_user = @domain.users.find { |u| u.login != ConnectionHelper::DEFAULT_USERNAME }
177
+ @project.add_user(another_user, 'Admin', domain: @domain)
178
+ new_filters = [
179
+ [another_user.login, @label.uri, "tomas@gooddata.com"]
180
+ ]
181
+ @project.add_variable_permissions(new_filters, @variable, do_not_touch_filters_that_are_not_mentioned: true)
182
+ expect(@variable.user_values.map {|f| [f.related.login, f.pretty_expression] })
183
+ .to include([ConnectionHelper::DEFAULT_USERNAME, "[Dev] IN ([tomas@gooddata.com])"],
184
+ [another_user.login, "[Dev] IN ([tomas@gooddata.com])"])
185
+ end
186
+
187
+ it "should be able to update the filter value in place" do
188
+ pending('We cannot swap filters yet')
189
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com", "jirka@gooddata.com"]]
190
+ @project.add_variable_permissions(filters, @variable)
191
+ perm = @variable.user_values.first
192
+ filters = [[ConnectionHelper::DEFAULT_USERNAME, @label.uri, "tomas@gooddata.com"]]
193
+ @project.add_variable_permissions(filters, @variable)
194
+ expect(perm.reload!.pretty_expression).to eq '[Dev] IN ([tomas@gooddata.com, jirka@gooddata.com])'
195
+ end
196
+ end