gooddata 0.6.11 → 0.6.12

Sign up to get free protection for your applications and to get access to all the features.
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