gooddata 1.3.0-java → 1.3.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +2 -0
  3. data/.document +0 -0
  4. data/.yardopts +0 -0
  5. data/CHANGELOG.md +48 -0
  6. data/CLI.md +0 -0
  7. data/CONTRIBUTING.md +19 -12
  8. data/Dockerfile +37 -0
  9. data/Guardfile +0 -0
  10. data/README.md +1 -1
  11. data/Rakefile +17 -1
  12. data/TODO.md +0 -0
  13. data/bin/run_brick.rb +31 -0
  14. data/dependency_decisions.yml +0 -0
  15. data/gooddata.gemspec +1 -0
  16. data/lib/gooddata/bricks/hello_world_brick.rb +21 -0
  17. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +12 -0
  18. data/lib/gooddata/bricks/middleware/logger_middleware.rb +12 -0
  19. data/lib/gooddata/bricks/pipeline.rb +12 -0
  20. data/lib/gooddata/exceptions/filter_maqlization.rb +0 -6
  21. data/lib/gooddata/extensions/class.rb +4 -0
  22. data/lib/gooddata/extensions/enumerable.rb +0 -3
  23. data/lib/gooddata/extensions/extensions.rb +0 -3
  24. data/lib/gooddata/extensions/false.rb +8 -16
  25. data/lib/gooddata/extensions/hash.rb +10 -41
  26. data/lib/gooddata/extensions/integer.rb +9 -3
  27. data/lib/gooddata/extensions/nil.rb +5 -13
  28. data/lib/gooddata/extensions/object.rb +0 -11
  29. data/lib/gooddata/extensions/string.rb +11 -5
  30. data/lib/gooddata/extensions/true.rb +8 -16
  31. data/lib/gooddata/helpers/global_helpers.rb +12 -0
  32. data/lib/gooddata/helpers/global_helpers_params.rb +5 -3
  33. data/lib/gooddata/lcm/actions/apply_custom_maql.rb +6 -0
  34. data/lib/gooddata/lcm/actions/base_action.rb +8 -2
  35. data/lib/gooddata/lcm/actions/collect_multiple_projects_column.rb +46 -0
  36. data/lib/gooddata/lcm/actions/collect_users_brick_users.rb +9 -2
  37. data/lib/gooddata/lcm/actions/execute_schedules.rb +0 -2
  38. data/lib/gooddata/lcm/actions/hello_world.rb +1 -1
  39. data/lib/gooddata/lcm/actions/synchronize_cas.rb +6 -0
  40. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +6 -0
  41. data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +70 -107
  42. data/lib/gooddata/lcm/actions/synchronize_users.rb +1 -13
  43. data/lib/gooddata/lcm/brick_logger.rb +26 -0
  44. data/lib/gooddata/lcm/lcm2.rb +46 -7
  45. data/lib/gooddata/lcm/types/base_type.rb +4 -0
  46. data/lib/gooddata/lcm/types/class/class.rb +2 -0
  47. data/lib/gooddata/lcm/types/complex/complex.rb +2 -0
  48. data/lib/gooddata/lcm/types/special/array.rb +2 -0
  49. data/lib/gooddata/mixins/is_folder.rb +0 -0
  50. data/lib/gooddata/mixins/to_json.rb +0 -0
  51. data/lib/gooddata/mixins/uri_getter.rb +0 -0
  52. data/lib/gooddata/models/blueprint/project_blueprint.rb +5 -5
  53. data/lib/gooddata/models/blueprint/to_manifest.rb +0 -2
  54. data/lib/gooddata/models/domain.rb +1 -0
  55. data/lib/gooddata/models/from_wire.rb +0 -2
  56. data/lib/gooddata/models/profile.rb +1 -1
  57. data/lib/gooddata/models/project.rb +5 -0
  58. data/lib/gooddata/models/user_filters/user_filter_builder.rb +49 -32
  59. data/lib/gooddata/models/user_group.rb +3 -0
  60. data/lib/gooddata/rest/README.md +0 -0
  61. data/lib/gooddata/rest/client.rb +4 -4
  62. data/lib/gooddata/rest/object.rb +2 -0
  63. data/lib/gooddata/version.rb +1 -1
  64. data/lib/templates/bricks/brick.rb.erb +0 -0
  65. data/lib/templates/bricks/main.rb.erb +0 -0
  66. data/lib/templates/project/Goodfile.erb +0 -0
  67. data/lib/templates/project/data/commits.csv +0 -0
  68. data/lib/templates/project/data/devs.csv +0 -0
  69. data/lib/templates/project/data/repos.csv +0 -0
  70. data/lib/templates/project/model/model.rb.erb +0 -0
  71. metadata +23 -5
  72. data/lib/gooddata/extensions/big_decimal.rb +0 -17
  73. data/lib/gooddata/extensions/numeric.rb +0 -15
  74. data/lib/gooddata/extensions/symbol.rb +0 -15
@@ -1,5 +1,11 @@
1
- class Integer
2
- def to_b
3
- self == 1
1
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
2
+ # This source code is licensed under the BSD-style license found in the
3
+ # LICENSE file in the root directory of this source tree.
4
+
5
+ module IntegerExtensions
6
+ refine Integer do
7
+ def to_b
8
+ self == 1
9
+ end
4
10
  end
5
11
  end
@@ -1,19 +1,11 @@
1
- # encoding: UTF-8
2
- #
3
1
  # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
2
  # This source code is licensed under the BSD-style license found in the
5
3
  # LICENSE file in the root directory of this source tree.
6
4
 
7
- class NilClass
8
- # +nil+ is not duplicable:
9
- #
10
- # nil.duplicable? # => false
11
- # nil.dup # => TypeError: can't dup NilClass
12
- def duplicable?
13
- false
14
- end
15
-
16
- def to_b
17
- false
5
+ module NilExtensions
6
+ refine NilClass do
7
+ def to_b
8
+ false
9
+ end
18
10
  end
19
11
  end
@@ -1,9 +1,6 @@
1
- # encoding: UTF-8
2
- #
3
1
  # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
2
  # This source code is licensed under the BSD-style license found in the
5
3
  # LICENSE file in the root directory of this source tree.
6
-
7
4
  class Object
8
5
  class << self
9
6
  def set_const(name, val)
@@ -12,14 +9,6 @@ class Object
12
9
  end
13
10
  end
14
11
 
15
- def blank?
16
- respond_to?(:empty?) ? empty? : !self
17
- end
18
-
19
- def duplicable?
20
- true
21
- end
22
-
23
12
  def set_const(name, val)
24
13
  send(:remove_const, name) if const_defined?(name)
25
14
  send(:const_set, name, val)
@@ -1,7 +1,13 @@
1
- class String
2
- def to_b
3
- return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
4
- return false if self == false || blank? || self =~ (/(false|f|no|n|0)$/i)
5
- raise ArgumentError, "invalid value for Boolean: \"#{self}\""
1
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
2
+ # This source code is licensed under the BSD-style license found in the
3
+ # LICENSE file in the root directory of this source tree.
4
+
5
+ module StringExtensions
6
+ refine String do
7
+ def to_b
8
+ return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
9
+ return false if self == false || blank? || self =~ (/(false|f|no|n|0)$/i)
10
+ raise ArgumentError, "invalid value for Boolean: \"#{self}\""
11
+ end
6
12
  end
7
13
  end
@@ -1,23 +1,15 @@
1
- # encoding: UTF-8
2
- #
3
1
  # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
2
  # This source code is licensed under the BSD-style license found in the
5
3
  # LICENSE file in the root directory of this source tree.
6
4
 
7
- class TrueClass
8
- # +true+ is not duplicable:
9
- #
10
- # true.duplicable? # => false
11
- # true.dup # => TypeError: can't dup TrueClass
12
- def duplicable?
13
- false
14
- end
15
-
16
- def to_b
17
- true
18
- end
5
+ module TrueExtensions
6
+ refine TrueClass do
7
+ def to_b
8
+ true
9
+ end
19
10
 
20
- def to_i
21
- 1
11
+ def to_i
12
+ 1
13
+ end
22
14
  end
23
15
  end
@@ -9,9 +9,21 @@ require 'pathname'
9
9
  require 'hashie'
10
10
  require 'openssl'
11
11
 
12
+ require 'active_support/core_ext/object/duplicable'
13
+
12
14
  require_relative '../extensions/object'
13
15
  require_relative 'global_helpers_params'
14
16
 
17
+ require 'gooddata/extensions/true'
18
+ require 'gooddata/extensions/false'
19
+ require 'gooddata/extensions/integer'
20
+ require 'gooddata/extensions/nil'
21
+
22
+ using TrueExtensions
23
+ using FalseExtensions
24
+ using IntegerExtensions
25
+ using NilExtensions
26
+
15
27
  module GoodData
16
28
  module Helpers
17
29
  extend Hashie::Extensions::StringifyKeys::ClassMethods
@@ -1,14 +1,16 @@
1
- # encoding: UTF-8
2
- #
3
1
  # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
2
  # This source code is licensed under the BSD-style license found in the
5
3
  # LICENSE file in the root directory of this source tree.
4
+ require 'active_support/core_ext/hash/slice'
5
+
6
+ require 'gooddata/extensions/hash'
7
+
8
+ using HashExtensions
6
9
 
7
10
  module GoodData
8
11
  module Helpers
9
12
  ENCODED_PARAMS_KEY = 'gd_encoded_params'
10
13
  ENCODED_HIDDEN_PARAMS_KEY = 'gd_encoded_hidden_params'
11
-
12
14
  class << self
13
15
  # Encodes parameters for passing them to GD execution platform.
14
16
  # Core types are kept and complex types (arrays, structures, etc) are
@@ -6,6 +6,12 @@
6
6
 
7
7
  require_relative 'base_action'
8
8
 
9
+ using TrueExtensions
10
+ using FalseExtensions
11
+ using IntegerExtensions
12
+ using StringExtensions
13
+ using NilExtensions
14
+
9
15
  module GoodData
10
16
  module LCM2
11
17
  # Applies custom MAQL DDL to all client projects so customized
@@ -1,8 +1,14 @@
1
- # encoding: UTF-8
2
- #
3
1
  # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
2
  # This source code is licensed under the BSD-style license found in the
5
3
  # LICENSE file in the root directory of this source tree.
4
+ require 'gooddata/extensions/class'
5
+ require 'gooddata/extensions/true'
6
+ require 'gooddata/extensions/false'
7
+ require 'gooddata/extensions/integer'
8
+ require 'gooddata/extensions/string'
9
+ require 'gooddata/extensions/nil'
10
+
11
+ require 'active_support/core_ext/hash/compact'
6
12
 
7
13
  require_relative '../dsl/dsl'
8
14
  require_relative '../helpers/helpers'
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+ require_relative 'base_action'
7
+
8
+ module GoodData
9
+ module LCM2
10
+ class CollectMultipleProjectsColumn < BaseAction
11
+ DESCRIPTION = 'Collect multiple_projects_column to be used in user actions'
12
+
13
+ PARAMS = define_params(self) do
14
+ description 'Client Used for Connecting to GD'
15
+ param :gdc_gd_client, instance_of(Type::GdClientType), required: true
16
+
17
+ description 'Identifier of column that identifies the relation to the projects in an user action input'
18
+ param :multiple_projects_column, instance_of(Type::StringType), required: false
19
+
20
+ description 'Synchronization Mode for user action (e.g. sync_one_project_based_on_pid)'
21
+ param :sync_mode, instance_of(Type::StringType), required: false
22
+
23
+ description 'Logger'
24
+ param :gdc_logger, instance_of(Type::GdLogger), required: true
25
+ end
26
+
27
+ CLIENT_ID_MODES = %w(
28
+ sync_domain_client_workspaces
29
+ sync_one_project_based_on_custom_id
30
+ sync_multiple_projects_based_on_custom_id
31
+ )
32
+
33
+ class << self
34
+ def call(params)
35
+ column = params.multiple_projects_column
36
+ column = CLIENT_ID_MODES.include?(params.sync_mode) ? 'client_id' : 'project_id' unless column
37
+
38
+ {
39
+ results: [{ multiple_projects_column: column }],
40
+ params: { multiple_projects_column: column }
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -16,6 +16,9 @@ module GoodData
16
16
  'deletion of filters for a user that is to be removed.'
17
17
  param :users_brick_config, instance_of(Type::UsersBrickConfig), required: true
18
18
 
19
+ description 'Column That Contains Target Project IDs'
20
+ param :multiple_projects_column, instance_of(Type::StringType), required: true
21
+
19
22
  description 'Input Source'
20
23
  param :input_source, instance_of(Type::HashType), required: false
21
24
  end
@@ -36,11 +39,15 @@ module GoodData
36
39
  headers: true,
37
40
  return_headers: false,
38
41
  encoding: 'utf-8') do |row|
39
- users_brick_users << { login: row[login_column] }
42
+ users_brick_users << {
43
+ login: row[login_column],
44
+ pid: row[params.multiple_projects_column]
45
+ }
40
46
  end
41
47
 
42
48
  {
43
- results: users_brick_users,
49
+ # TODO; TMA-989 return the real results when print of results is fixed for large sets
50
+ results: [{ status: 'ok' }],
44
51
  params: {
45
52
  users_brick_users: users_brick_users
46
53
  }
@@ -1,5 +1,3 @@
1
- # encoding: UTF-8
2
- #
3
1
  # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
2
  # This source code is licensed under the BSD-style license found in the
5
3
  # LICENSE file in the root directory of this source tree.
@@ -13,7 +13,7 @@ module GoodData
13
13
 
14
14
  PARAMS = define_params(self) do
15
15
  description 'Message to be printed'
16
- param :message, instance_of(Type::StringType), required: true
16
+ param :message, instance_of(Type::StringType), required: false
17
17
 
18
18
  description 'Number of Iterations'
19
19
  param :iterations, instance_of(Type::IntegerType), required: false, default: 1
@@ -6,6 +6,12 @@
6
6
 
7
7
  require_relative 'base_action'
8
8
 
9
+ using TrueExtensions
10
+ using FalseExtensions
11
+ using IntegerExtensions
12
+ using StringExtensions
13
+ using NilExtensions
14
+
9
15
  module GoodData
10
16
  module LCM2
11
17
  class SynchronizeComputedAttributes < BaseAction
@@ -6,6 +6,12 @@
6
6
 
7
7
  require_relative 'base_action'
8
8
 
9
+ using TrueExtensions
10
+ using FalseExtensions
11
+ using IntegerExtensions
12
+ using StringExtensions
13
+ using NilExtensions
14
+
9
15
  module GoodData
10
16
  module LCM2
11
17
  class SynchronizeLdm < BaseAction
@@ -6,6 +6,12 @@
6
6
 
7
7
  require_relative 'base_action'
8
8
 
9
+ using TrueExtensions
10
+ using FalseExtensions
11
+ using IntegerExtensions
12
+ using StringExtensions
13
+ using NilExtensions
14
+
9
15
  module GoodData
10
16
  module LCM2
11
17
  class SynchronizeUserFilters < BaseAction
@@ -64,7 +70,7 @@ module GoodData
64
70
  param :gdc_project_id, instance_of(Type::StringType), required: false
65
71
 
66
72
  description 'User brick users'
67
- param :users_brick_users, instance_of(Type::ObjectType), required: false
73
+ param :users_brick_users, instance_of(Type::ObjectType), required: false, default: []
68
74
 
69
75
  description 'Makes the brick run without altering user filters'
70
76
  param :dry_run, instance_of(Type::StringType), required: false, default: false
@@ -91,36 +97,19 @@ module GoodData
91
97
  fail "Either project or project_id has to be specified in params" unless project
92
98
  data_product = params.data_product
93
99
 
94
- data_source = GoodData::Helpers::DataSource.new(params.input_source)
95
-
96
100
  config = params.filters_config
97
101
  fail 'User filters brick requires configuration how the filter should be setup. For this use the param "filters_config"' if config.blank?
98
102
  symbolized_config = GoodData::Helpers.deep_dup(config)
99
103
  symbolized_config = GoodData::Helpers.symbolize_keys(symbolized_config)
100
104
  symbolized_config[:labels] = symbolized_config[:labels].map { |l| GoodData::Helpers.symbolize_keys(l) }
101
- headers_in_options = params.csv_headers == 'false' || true
105
+ multiple_projects_column = params.multiple_projects_column
102
106
 
103
107
  mode = params.sync_mode
104
108
  unless MODES.include?(mode)
105
109
  fail "The parameter \"sync_mode\" has to have one of the values #{MODES.map(&:to_s).join(', ')} or has to be empty."
106
110
  end
107
- filters = []
108
-
109
- csv_with_headers = if GoodData::UserFilterBuilder.row_based?(symbolized_config)
110
- false
111
- else
112
- headers_in_options
113
- end
114
111
 
115
- multiple_projects_column = params.multiple_projects_column
116
- unless multiple_projects_column
117
- client_modes = %w(sync_domain_client_workspaces sync_one_project_based_on_custom_id sync_multiple_projects_based_on_custom_id)
118
- multiple_projects_column = if client_modes.include?(mode)
119
- 'client_id'
120
- else
121
- 'project_id'
122
- end
123
- end
112
+ user_filters = load_data(params, symbolized_config)
124
113
 
125
114
  run_params = {
126
115
  restrict_if_missing_all_values: params.restrict_if_missing_all_values == 'true',
@@ -133,85 +122,27 @@ module GoodData
133
122
 
134
123
  puts "Synchronizing in mode \"#{mode}\""
135
124
  case mode
136
- when 'sync_project'
137
- without_check(PARAMS, params) do
138
- CSV.foreach(File.open(data_source.realize(params), 'r:UTF-8'), headers: csv_with_headers, return_headers: false, encoding: 'utf-8') do |row|
139
- filters << row
140
- end
141
- end
142
- filters_to_load = GoodData::UserFilterBuilder.get_filters(filters, symbolized_config)
143
- puts "Synchronizing #{filters_to_load.count} filters"
144
- project.add_data_permissions(filters_to_load, run_params)
145
- when 'sync_one_project_based_on_pid'
146
- without_check(PARAMS, params) do
147
- CSV.foreach(File.open(data_source.realize(params), 'r:UTF-8'), headers: csv_with_headers, return_headers: false, encoding: 'utf-8') do |row|
148
- filters << row if row[multiple_projects_column] == project.pid
149
- end
150
- end
151
- filters_to_load = GoodData::UserFilterBuilder.get_filters(filters, symbolized_config)
152
- puts "Synchronizing #{filters_to_load.count} filters"
153
- project.add_data_permissions(filters_to_load, run_params)
154
- when 'sync_multiple_projects_based_on_pid'
155
- without_check(PARAMS, params) do
156
- CSV.foreach(File.open(data_source.realize(params), 'r:UTF-8'), headers: csv_with_headers, return_headers: false, encoding: 'utf-8') do |row|
157
- filters << row.to_hash
158
- end
159
- end
160
- if filters.empty?
161
- fail 'The filter set can not be empty when using sync_multiple_projects_* mode as the filters contain \
162
- the project ids in which the permissions should be changed'
163
- end
164
- filters.group_by { |u| u[multiple_projects_column] }.flat_map do |project_id, new_filters|
165
- fail "Project id cannot be empty" if project_id.blank?
166
- project = client.projects(project_id)
167
- filters_to_load = GoodData::UserFilterBuilder.get_filters(new_filters, symbolized_config)
168
- puts "Synchronizing #{filters_to_load.count} filters in project #{project.pid}"
169
- project.add_data_permissions(filters_to_load, run_params)
125
+ when 'sync_project', 'sync_one_project_based_on_pid', 'sync_one_project_based_on_custom_id'
126
+ if mode == 'sync_one_project_based_on_pid'
127
+ filter = project.pid
128
+ elsif mode == 'sync_one_project_based_on_custom_id'
129
+ filter = UserBricksHelper.resolve_client_id(domain, project, params.data_product)
170
130
  end
171
- when 'sync_one_project_based_on_custom_id'
172
- filter_value = UserBricksHelper.resolve_client_id(domain, project, data_product)
173
-
174
- filepath = without_check(PARAMS, params) do
175
- File.open(data_source.realize(params), 'r:UTF-8')
176
- end
177
- CSV.foreach(filepath, headers: csv_with_headers, return_headers: false, encoding: 'utf-8') do |row|
178
- client_id = row[multiple_projects_column].to_s
179
- filters << row if client_id == filter_value
180
- end
181
-
182
- if filters.empty?
183
- params.gdc_logger.warn "Project \"#{project.pid}\" does not match with any client ids in input source (both GOODOT_CUSTOM_PROJECT_ID and SEGMENT/CLIENT). \
184
- Unable to get the value to filter users."
185
- end
186
-
187
- filters_to_load = GoodData::UserFilterBuilder.get_filters(filters, symbolized_config)
188
- puts "Synchronizing #{filters_to_load.count} filters"
189
- project.add_data_permissions(filters_to_load, run_params)
190
- when 'sync_multiple_projects_based_on_custom_id'
191
- without_check(PARAMS, params) do
192
- CSV.foreach(File.open(data_source.realize(params), 'r:UTF-8'), headers: csv_with_headers, return_headers: false, encoding: 'utf-8') do |row|
193
- filters << row.to_hash
131
+ user_filters = user_filters.select { |f| f[:pid] == filter } if filter
132
+ sync_user_filters(project, user_filters, run_params, symbolized_config)
133
+ when 'sync_multiple_projects_based_on_pid', 'sync_multiple_projects_based_on_custom_id'
134
+ users_by_project = run_params[:users_brick_input].group_by { |u| u[:pid] }
135
+ user_filters.group_by { |u| u[:pid] }.flat_map.pmap do |id, new_filters|
136
+ users = users_by_project[id]
137
+ fail "The #{multiple_projects_column} cannot be empty" if id.blank?
138
+ if mode == 'sync_multiple_projects_based_on_custom_id'
139
+ current_project = domain.clients(id, data_product).project
140
+ elsif mode == 'sync_multiple_projects_based_on_pid'
141
+ current_project = client.projects(id)
194
142
  end
195
- end
196
- if filters.empty?
197
- fail 'The filter set can not be empty when using sync_multiple_projects_* mode as the filters contain \
198
- the project ids in which the permissions should be changed'
199
- end
200
- filters.group_by { |u| u[multiple_projects_column] }.flat_map do |client_id, new_filters|
201
- fail "Client id cannot be empty" if client_id.blank?
202
- project = domain.clients(client_id, data_product).project
203
- fail "Client #{client_id} does not have project." unless project
204
- filters_to_load = GoodData::UserFilterBuilder.get_filters(new_filters, symbolized_config)
205
- puts "Synchronizing #{filters_to_load.count} filters in project #{project.pid} of client #{client_id}"
206
- project.add_data_permissions(filters_to_load, run_params)
143
+ sync_user_filters(current_project, new_filters, run_params.merge(users_brick_input: users), symbolized_config)
207
144
  end
208
145
  when 'sync_domain_client_workspaces'
209
- without_check(PARAMS, params) do
210
- CSV.foreach(File.open(data_source.realize(params), 'r:UTF-8'), headers: csv_with_headers, return_headers: false, encoding: 'utf-8') do |row|
211
- filters << row.to_hash
212
- end
213
- end
214
-
215
146
  domain_clients = domain.clients(:all, data_product)
216
147
  if params.segments
217
148
  segment_uris = params.segments.map(&:uri)
@@ -220,20 +151,20 @@ module GoodData
220
151
 
221
152
  working_client_ids = []
222
153
 
154
+ users_by_project = run_params[:users_brick_input].group_by { |u| u[:pid] }
223
155
  results = []
224
- filters.group_by { |u| u[multiple_projects_column] }.flat_map do |client_id, new_filters|
156
+ user_filters.group_by { |u| u[multiple_projects_column] }.flat_map.pmap do |client_id, new_filters|
157
+ users = users_by_project[client_id]
225
158
  fail "Client id cannot be empty" if client_id.blank?
226
159
  c = domain.clients(client_id, data_product)
227
160
  if params.segments && !segment_uris.include?(c.segment_uri)
228
161
  puts "Client #{client_id} is outside segments_filter #{params.segments}"
229
162
  next
230
163
  end
231
- project = c.project
232
- fail "Client #{client_id} does not have project." unless project
164
+ current_project = c.project
165
+ fail "Client #{client_id} does not have project." unless current_project
233
166
  working_client_ids << client_id
234
- filters_to_load = GoodData::UserFilterBuilder.get_filters(new_filters, symbolized_config)
235
- puts "Synchronizing #{filters_to_load.count} filters in project #{project.pid} of client #{client_id}"
236
- partial_results = project.add_data_permissions(filters_to_load, run_params)
167
+ partial_results = sync_user_filters(current_project, new_filters, run_params.merge(users_brick_input: users), symbolized_config)
237
168
  results.concat(partial_results[:results])
238
169
  end
239
170
 
@@ -241,22 +172,23 @@ module GoodData
241
172
  domain_clients.each do |c|
242
173
  next if working_client_ids.include?(c.client_id)
243
174
  begin
244
- project = c.project
175
+ current_project = c.project
245
176
  rescue => e
246
177
  puts "Error when accessing project of client #{c.client_id}. Error: #{e}"
247
178
  next
248
179
  end
249
- unless project
180
+ unless current_project
250
181
  puts "Client #{c.client_id} has no project."
251
182
  next
252
183
  end
253
- if project.deleted?
254
- puts "Project #{project.pid} of client #{c.client_id} is deleted."
184
+ if current_project.deleted?
185
+ puts "Project #{current_project.pid} of client #{c.client_id} is deleted."
255
186
  next
256
187
  end
257
188
 
258
- puts "Delete all filters in project #{project.pid} of client #{c.client_id}"
259
- delete_results = project.add_data_permissions([], run_params)
189
+ puts "Delete all filters in project #{current_project.pid} of client #{c.client_id}"
190
+ users = users_by_project[c.client_id]
191
+ delete_results = current_project.add_data_permissions([], run_params.merge(users_brick_input: users))
260
192
  results.concat(delete_results[:results])
261
193
  end
262
194
  end
@@ -266,6 +198,37 @@ module GoodData
266
198
  }
267
199
  end
268
200
  end
201
+
202
+ def sync_user_filters(project, filters, params, filters_config)
203
+ # Do not change this line -> can cause paralelisation errors in jRuby viz TMA-963
204
+ project.add_data_permissions(GoodData::UserFilterBuilder.get_filters(filters, filters_config), params)
205
+ end
206
+
207
+ def load_data(params, symbolized_config)
208
+ filters = []
209
+ headers_in_options = params.csv_headers == 'false' || true
210
+ csv_with_headers = if GoodData::UserFilterBuilder.row_based?(symbolized_config)
211
+ false
212
+ else
213
+ headers_in_options
214
+ end
215
+
216
+ multiple_projects_column = params.multiple_projects_column
217
+ data_source = GoodData::Helpers::DataSource.new(params.input_source)
218
+
219
+ without_check(PARAMS, params) do
220
+ CSV.foreach(File.open(data_source.realize(params), 'r:UTF-8'), headers: csv_with_headers, return_headers: false, encoding: 'utf-8') do |row|
221
+ filters << row.to_hash.merge(pid: row[multiple_projects_column])
222
+ end
223
+ end
224
+
225
+ if filters.empty? && %w(sync_multiple_projects_based_on_pid sync_multiple_projects_based_on_custom_id).include?(params.sync_mode)
226
+ fail 'The filter set can not be empty when using sync_multiple_projects_* mode as the filters contain \
227
+ the project ids in which the permissions should be changed'
228
+ end
229
+
230
+ filters
231
+ end
269
232
  end
270
233
  end
271
234
  end