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
@@ -14,14 +14,14 @@ module GoodData
14
14
 
15
15
  # Returns which objects uses this MD resource
16
16
  def usedby(key = nil, opts = { :client => client, :project => project })
17
- dependency("#{project.md['usedby2']}/#{obj_id}", key, opts)
17
+ dependency("#{project.md['usedby2']}/#{obj_id}", key, { :client => client, :project => project }.merge(opts))
18
18
  end
19
19
 
20
20
  alias_method :used_by, :usedby
21
21
 
22
22
  # Returns which objects this MD resource uses
23
23
  def using(key = nil, opts = { :client => client, :project => project })
24
- dependency("#{project.md['using2']}/#{obj_id}", key, opts)
24
+ dependency("#{project.md['using2']}/#{obj_id}", key, { :client => client, :project => project }.merge(opts))
25
25
  end
26
26
 
27
27
  def usedby?(obj, opts = { :client => client, :project => project })
@@ -29,6 +29,7 @@ module GoodData
29
29
  base.send :include, GoodData::Mixin::NotMetric
30
30
  base.send :include, GoodData::Mixin::NotLabel
31
31
  base.send :include, GoodData::Mixin::MdRelations
32
+ base.send :include, GoodData::Mixin::Author
32
33
 
33
34
  base.extend GoodData::Mixin::MdObjId
34
35
  base.extend GoodData::Mixin::MdObjectQuery
@@ -1,7 +1,6 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  require_relative '../extensions/big_decimal'
4
-
5
4
  require_relative '../rest/object'
6
5
 
7
6
  module GoodData
@@ -0,0 +1,90 @@
1
+ # encoding: UTF-8
2
+ require_relative '../rest/resource'
3
+
4
+ module GoodData
5
+ class DataWarehouse < GoodData::Rest::Resource
6
+ class << self
7
+ CREATE_URL = '/gdc/datawarehouse/instances'
8
+
9
+ # Create a data warehouse from given attributes
10
+ # Expected keys:
11
+ # - :title (mandatory)
12
+ # - :auth_token (mandatory)
13
+ # - :summary
14
+ def create(opts)
15
+ GoodData.logger.info "Creating warehouse #{opts[:title]}"
16
+
17
+ c = client(opts)
18
+ fail ArgumentError, 'No :client specified' if c.nil?
19
+
20
+ auth_token = opts[:auth_token]
21
+ fail ArgumentError, 'You have to provide your token for creating projects as :auth_token parameter' if auth_token.nil? || auth_token.empty?
22
+
23
+ title = opts[:title]
24
+ fail ArgumentError, 'You have to provide a title for creating warehouse as :title parameter' if title.nil? || title.empty?
25
+
26
+ json = {
27
+ 'instance' => {
28
+ 'title' => title,
29
+ 'description' => opts[:description] || opts[:summary] || 'No summary',
30
+ 'authorizationToken' => auth_token
31
+ }
32
+ }
33
+ # do the first post
34
+ res = c.post(CREATE_URL, json)
35
+
36
+ # wait until the instance is created
37
+ final_res = c.poll_on_response(res['asyncTask']['links']['poll'], :sleep_interval => 3) do |r|
38
+ r['asyncTask']['links']['instance'].nil?
39
+ end
40
+
41
+ # get the json of the created instance
42
+ final_json = c.get(final_res['asyncTask']['links']['instance'])
43
+
44
+ # create the public facing object
45
+ c.create(DataWarehouse, final_json)
46
+ end
47
+ end
48
+ attr_accessor :json
49
+
50
+ alias_method :to_json, :json
51
+ alias_method :raw_data, :json
52
+
53
+ def initialize(json)
54
+ super
55
+ @json = json
56
+ end
57
+
58
+ def title
59
+ json['instance']['title']
60
+ end
61
+
62
+ def summary
63
+ json['instance']['description']
64
+ end
65
+
66
+ def status
67
+ json['instance']['status']
68
+ end
69
+
70
+ def uri
71
+ json['instance']['links']['self']
72
+ end
73
+
74
+ def id
75
+ uri.split('/')[-1]
76
+ end
77
+
78
+ def delete
79
+ if state == 'DELETED'
80
+ fail "Warehouse '#{title}' with id #{uri} is already deleted"
81
+ end
82
+ client.delete(uri)
83
+ end
84
+
85
+ # alias methods to prevent confusion and support the same keys
86
+ # project has.
87
+ alias_method :state, :status
88
+ alias_method :description, :summary
89
+ end
90
+ end
@@ -3,7 +3,7 @@
3
3
  require 'cgi'
4
4
 
5
5
  require_relative 'profile'
6
-
6
+ require_relative '../extensions/enumerable'
7
7
  require_relative '../rest/object'
8
8
 
9
9
  module GoodData
@@ -18,6 +18,7 @@ module GoodData
18
18
  # @param domain_name [String] Domain name
19
19
  # @return [String] Domain object instance
20
20
  def [](domain_name, options = { :client => GoodData.connection })
21
+ return domain_name if domain_name.is_a?(Domain)
21
22
  c = client(options)
22
23
  fail "Using pseudo-id 'all' is not supported by GoodData::Domain" if domain_name.to_s == 'all'
23
24
  c.create(GoodData::Domain, domain_name)
@@ -29,19 +30,21 @@ module GoodData
29
30
  # @param login [String] Login of user to be invited
30
31
  # @param password [String] Default preset password
31
32
  # @return [Object] Raw response
32
- def add_user(opts)
33
+ def add_user(user_data, name = nil, opts = { :client => GoodData.connection })
33
34
  generated_pass = rand(10E10).to_s
35
+ domain_name = name || user_data[:domain]
36
+ user_data = user_data.to_hash
34
37
  data = {
35
- :login => opts[:login],
36
- :firstName => opts[:first_name] || 'FirstName',
37
- :lastName => opts[:last_name] || 'LastName',
38
- :password => opts[:password] || generated_pass,
39
- :verifyPassword => opts[:password] || generated_pass,
40
- :email => opts[:login]
38
+ :login => user_data[:login] || user_data[:email],
39
+ :firstName => user_data[:first_name] || 'FirstName',
40
+ :lastName => user_data[:last_name] || 'LastName',
41
+ :password => user_data[:password] || generated_pass,
42
+ :verifyPassword => user_data[:password] || generated_pass,
43
+ :email => user_data[:email] || user_data[:login]
41
44
  }
42
45
 
43
46
  # Optional authentication modes
44
- tmp = opts[:authentication_modes]
47
+ tmp = user_data[:authentication_modes]
45
48
  if tmp
46
49
  if tmp.is_a? Array
47
50
  data[:authenticationModes] = tmp
@@ -51,36 +54,40 @@ module GoodData
51
54
  end
52
55
 
53
56
  # Optional company
54
- tmp = opts[:company_name]
55
- tmp = opts[:company] if tmp.nil? || tmp.empty?
57
+ tmp = user_data[:company_name]
58
+ tmp = user_data[:company] if tmp.nil? || tmp.empty?
56
59
  data[:companyName] = tmp if tmp && !tmp.empty?
57
60
 
58
61
  # Optional country
59
- tmp = opts[:country]
62
+ tmp = user_data[:country]
60
63
  data[:country] = tmp if tmp && !tmp.empty?
61
64
 
62
65
  # Optional phone number
63
- tmp = opts[:phone]
64
- tmp = opts[:phone_number] if tmp.nil? || tmp.empty?
66
+ tmp = user_data[:phone]
67
+ tmp = user_data[:phone_number] if tmp.nil? || tmp.empty?
65
68
  data[:phoneNumber] = tmp if tmp && !tmp.empty?
66
69
 
67
70
  # Optional position
68
- tmp = opts[:position]
71
+ tmp = user_data[:position]
69
72
  data[:position] = tmp if tmp && !tmp.empty?
70
73
 
71
74
  # Optional sso provider
72
- tmp = opts[:sso_provider]
75
+ tmp = user_data[:sso_provider]
73
76
  data['ssoProvider'] = tmp if tmp && !tmp.empty?
74
77
 
75
78
  # Optional timezone
76
- tmp = opts[:timezone]
79
+ tmp = user_data[:timezone]
77
80
  data[:timezone] = tmp if tmp && !tmp.empty?
78
81
 
79
82
  c = client(opts)
80
83
 
81
84
  # TODO: It will be nice if the API will return us user just newly created
82
- url = "/gdc/account/domains/#{opts[:domain]}/users"
83
- response = c.post(url, :accountSetting => data)
85
+ begin
86
+ url = "/gdc/account/domains/#{domain_name}/users"
87
+ response = c.post(url, :accountSetting => data)
88
+ rescue RestClient::BadRequest
89
+ raise GoodData::UserInDifferentDomainError, "User #{data[:login]} is already in different domain"
90
+ end
84
91
 
85
92
  url = response['uri']
86
93
  raw = c.get url
@@ -88,19 +95,82 @@ module GoodData
88
95
  # TODO: Remove this hack when POST /gdc/account/domains/{domain-name}/users returns full profile
89
96
  raw['accountSetting']['links'] = {} unless raw['accountSetting']['links']
90
97
  raw['accountSetting']['links']['self'] = response['uri'] unless raw['accountSetting']['links']['self']
91
-
92
98
  c.create(GoodData::Profile, raw)
93
99
  end
94
100
 
101
+ def update_user(user_data, options = { client: GoodData.connection })
102
+ client = client(options)
103
+ user_data = user_data.to_hash
104
+ # generated_pass = rand(10E10).to_s
105
+ data = {
106
+ :firstName => user_data[:first_name] || 'FirstName',
107
+ :lastName => user_data[:last_name] || 'LastName',
108
+ :email => user_data[:email]
109
+ }
110
+
111
+ # Optional authentication modes
112
+ tmp = user_data[:authentication_modes]
113
+ if tmp
114
+ if tmp.is_a? Array
115
+ data[:authenticationModes] = tmp
116
+ elsif tmp.is_a? String
117
+ data[:authenticationModes] = [tmp]
118
+ end
119
+ end
120
+
121
+ # Optional company
122
+ tmp = user_data[:company_name]
123
+ tmp = user_data[:company] if tmp.nil? || tmp.empty?
124
+ data[:companyName] = tmp if tmp && !tmp.empty?
125
+
126
+ # Optional pass
127
+ tmp = user_data[:password]
128
+ tmp = user_data[:password] if tmp.nil? || tmp.empty?
129
+ data[:password] = tmp if tmp && !tmp.empty?
130
+ data[:verifyPassword] = tmp if tmp && !tmp.empty?
131
+
132
+ # Optional country
133
+ tmp = user_data[:country]
134
+ data[:country] = tmp if tmp && !tmp.empty?
135
+
136
+ # Optional phone number
137
+ tmp = user_data[:phone]
138
+ tmp = user_data[:phone_number] if tmp.nil? || tmp.empty?
139
+ data[:phoneNumber] = tmp if tmp && !tmp.empty?
140
+
141
+ # Optional position
142
+ tmp = user_data[:position]
143
+ data[:position] = tmp if tmp && !tmp.empty?
144
+
145
+ # Optional sso provider
146
+ tmp = user_data[:sso_provider]
147
+ data['ssoProvider'] = tmp if tmp && !tmp.empty?
148
+
149
+ # Optional timezone
150
+ tmp = user_data[:timezone]
151
+ data[:timezone] = tmp if tmp && !tmp.empty?
152
+
153
+ # TODO: It will be nice if the API will return us user just newly created
154
+ url = user_data.delete(:uri)
155
+ data.delete(:password) if client.user.uri == url
156
+ response = client.put(url, :accountSetting => data)
157
+
158
+ # TODO: Remove this hack when POST /gdc/account/domains/{domain-name}/users returns full profile
159
+ response['accountSetting']['links'] = {} unless response['accountSetting']['links']
160
+ response['accountSetting']['links']['self'] = url unless response['accountSetting']['links']['self']
161
+ client.create(GoodData::Profile, response)
162
+ end
163
+
95
164
  # Finds user in domain by login
96
165
  #
97
166
  # @param domain [String] Domain name
98
167
  # @param login [String] User login
99
168
  # @return [GoodData::Profile] User profile
100
- def find_user_by_login(domain, login, opts = {})
169
+ def find_user_by_login(domain, login, opts = { :client => GoodData.connection, :project => GoodData.project })
101
170
  c = client(opts)
102
171
  escaped_login = CGI.escape(login)
103
- url = "/gdc/account/domains/#{domain}/users?login=#{escaped_login}"
172
+ domain = c.domain(domain)
173
+ url = "/gdc/account/domains/#{domain.name}/users?login=#{escaped_login}"
104
174
  tmp = c.get url
105
175
  items = tmp['accountSettings']['items'] if tmp['accountSettings']
106
176
  items && items.length > 0 ? c.factory.create(GoodData::Profile, items.first) : nil
@@ -123,6 +193,7 @@ module GoodData
123
193
  tmp['accountSettings']['items'].each do |account|
124
194
  result << client(opts).create(GoodData::Profile, account)
125
195
  end
196
+ break if opts[:limit] && result.length >= opts[:limit]
126
197
  uri = tmp['accountSettings']['paging']['next']
127
198
  end
128
199
 
@@ -133,57 +204,53 @@ module GoodData
133
204
  # @param [Array<GoodData::Membership>] list List of users
134
205
  # @param [String] default_domain_name Default domain name used when no specified in user
135
206
  # @return [Array<GoodData::User>] List of users created
136
- def users_create(list, default_domain = nil, opts = { :client => GoodData.connection, :project => GoodData.project })
207
+ def create_users(list, default_domain = nil, opts = { :client => GoodData.connection, :project => GoodData.project })
208
+ client = client(opts)
137
209
  default_domain_name = default_domain.respond_to?(:name) ? default_domain.name : default_domain
210
+ domain_obj = client.domain(default_domain_name)
138
211
  domains = {}
139
212
  list.map do |user|
140
- # TODO: Add user here
141
- domain_name = user.json['user']['content']['domain'] || default_domain_name
142
-
143
- # Lookup for domain in cache'
144
- domain = domains[domain_name]
145
-
146
- # Get domain info from REST, add to cache
147
- if domain.nil?
148
- d = GoodData::Domain[domain_name, opts]
149
- domain = {
150
- :domain => d,
151
- :users => d.users(opts)
152
- }
153
-
154
- domain[:users_map] = Hash[domain[:users].map { |u| [u.email, u] }]
155
- domains[domain_name] = domain
156
- end
157
-
158
- # Check if user exists in domain
159
- domain_user = domain[:users_map][user.email]
160
-
161
- # Create domain user if needed
162
- unless domain_user
163
- password = user.json['user']['content']['password']
164
-
165
- # Fill necessary user data
166
- user_data = {
167
- :login => user.login,
168
- :firstName => user.first_name,
169
- :lastName => user.last_name,
170
- :password => password,
171
- :verifyPassword => password,
172
- :email => user.login
173
- }
174
-
175
- tmp = user.json['user']['content']['sso_provider']
176
- user_data[:sso_provider] = tmp if tmp && !tmp.empty?
177
-
178
- tmp = user.json['user']['content']['authentication_modes']
179
- user_data[:authentication_modes] = tmp && !tmp.empty?
180
-
181
- # Add created user to cache
182
- domain_user = domain[:domain].add_user(opts.merge(user_data))
183
- domain[:users] << domain_user
184
- domain[:users_map][user.email] = domain_user
213
+ begin
214
+ user_data = user.to_hash
215
+ # TODO: Add user here
216
+ domain_name = user_data[:domain] || default_domain_name
217
+
218
+ # Lookup for domain in cache'
219
+ domain = domains[domain_name]
220
+
221
+ # Get domain info from REST, add to cache
222
+ if domain.nil?
223
+ domain = {
224
+ :domain => domain_obj,
225
+ :users => domain_obj.users
226
+ }
227
+
228
+ domain[:users_map] = Hash[domain[:users].map { |u| [u.login, u] }]
229
+ domains[domain_name] = domain
230
+ end
231
+
232
+ # Check if user exists in domain
233
+ domain_user = domain[:users_map][user_data[:login]]
234
+
235
+ # Create domain user if needed
236
+ if !domain_user
237
+ # Add created user to cache
238
+ domain_user = domain[:domain].add_user(user_data, opts)
239
+ domain[:users] << domain_user
240
+ domain[:users_map][domain_user.login] = domain_user
241
+ { type: :user_added_to_domain, user: domain_user }
242
+ else
243
+ # fields = [:firstName, :email]
244
+ diff = GoodData::Helpers.diff([domain_user.to_hash], [user_data], key: :login)
245
+ next if diff[:changed].empty?
246
+
247
+ domain_user = domain[:domain].update_user(domain_user.to_hash.merge(user_data.compact), opts)
248
+ domain[:users_map][domain_user.login] = domain_user
249
+ { type: :user_changed_in_domain, user: domain_user }
250
+ end
251
+ rescue RuntimeError => e
252
+ { type: :error, reason: e }
185
253
  end
186
- domain_user
187
254
  end
188
255
  end
189
256
  end
@@ -204,9 +271,34 @@ module GoodData
204
271
  # domain = GoodData::Domain['gooddata-tomas-korcak']
205
272
  # domain.add_user 'joe.doe@example', 'sup3rS3cr3tP4ssW0rtH'
206
273
  #
207
- def add_user(opts)
208
- opts[:domain] = name
209
- GoodData::Domain.add_user(opts)
274
+ def add_user(data, opts = {})
275
+ # data[:domain] = name
276
+ GoodData::Domain.add_user(data, name, { client: client }.merge(opts))
277
+ end
278
+
279
+ alias_method :create_user, :add_user
280
+
281
+ def create_users(list, options = {})
282
+ GoodData::Domain.create_users(list, name, { client: client }.merge(options))
283
+ end
284
+
285
+ # Gets user by its login or uri in various shapes
286
+ # It does not find by other information because that is not unique. If you want to search by name or email please
287
+ # use fuzzy_get_user.
288
+ #
289
+ # @param [String] name Name to look for
290
+ # @param [Array<GoodData::User>]user_list Optional cached list of users used for look-ups
291
+ # @return [GoodDta::Membership] User
292
+ def get_user(name, user_list = users)
293
+ return member(name) if name.instance_of?(GoodData::Membership)
294
+ return member(name) if name.instance_of?(GoodData::Profile)
295
+ name = name.is_a?(Hash) ? name[:login] || name[:uri] : name
296
+ return nil unless name
297
+ name.downcase!
298
+ user_list.find do |user|
299
+ user.uri && user.uri.downcase == name ||
300
+ user.login && user.login.downcase == name
301
+ end
210
302
  end
211
303
 
212
304
  # Finds user in domain by login
@@ -214,7 +306,43 @@ module GoodData
214
306
  # @param login [String] User login
215
307
  # @return [GoodData::Profile] User account settings
216
308
  def find_user_by_login(login)
217
- GoodData::Domain.find_user_by_login(name, login)
309
+ GoodData::Domain.find_user_by_login(self, login, client: client)
310
+ end
311
+
312
+ # Gets membership for profile specified
313
+ #
314
+ # @param [GoodData::Profile] profile - Profile to be checked
315
+ # @param [Array<GoodData::Profile>] list Optional list of members to check against
316
+ # @return [GoodData::Profile] Profile if found
317
+ def member(profile, list = members)
318
+ if profile.is_a? String
319
+ return list.find do |m|
320
+ m.uri == profile || m.login == profile
321
+ end
322
+ end
323
+ list.find { |m| m.login == profile.login }
324
+ end
325
+
326
+ # Checks if the profile is member of project
327
+ #
328
+ # @param [GoodData::Profile] profile - Profile to be checked
329
+ # @param [Array<GoodData::Membership>] list Optional list of members to check against
330
+ # @return [Boolean] true if is member else false
331
+ def member?(profile, list = members)
332
+ !member(profile, list).nil?
333
+ end
334
+
335
+ def members?(profiles, list = members)
336
+ profiles.map { |p| member?(p, list) }
337
+ end
338
+
339
+ # Update user in domain
340
+ #
341
+ # @param opts [Hash] Data of the user to be updated
342
+ # @return [Object] Raw response
343
+ #
344
+ def update_user(data, options = {})
345
+ GoodData::Domain.update_user(data, { client: client }.merge(options))
218
346
  end
219
347
 
220
348
  # List users in domain
@@ -234,9 +362,7 @@ module GoodData
234
362
  GoodData::Domain.users(name, opts.merge(client: client))
235
363
  end
236
364
 
237
- def users_create(list)
238
- GoodData::Domain.users_create(list, name)
239
- end
365
+ alias_method :members, :users
240
366
 
241
367
  private
242
368