gooddata 0.6.3 → 0.6.4

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.markdown +6 -0
  4. data/README.md +1 -0
  5. data/gooddata.gemspec +2 -1
  6. data/lib/gooddata.rb +4 -1
  7. data/lib/gooddata/bricks/base_downloader.rb +33 -19
  8. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +49 -25
  9. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +36 -33
  10. data/lib/gooddata/cli/commands/project_cmd.rb +6 -4
  11. data/lib/gooddata/client.rb +1 -1
  12. data/lib/gooddata/commands/api.rb +1 -1
  13. data/lib/gooddata/commands/auth.rb +1 -1
  14. data/lib/gooddata/connection.rb +13 -10
  15. data/lib/gooddata/core/connection.rb +1 -1
  16. data/lib/gooddata/core/user.rb +11 -3
  17. data/lib/gooddata/exceptions/validation_error.rb +12 -0
  18. data/lib/gooddata/extensions/extensions.rb +6 -0
  19. data/lib/gooddata/goodzilla/goodzilla.rb +2 -2
  20. data/lib/gooddata/helpers/csv_helper.rb +57 -0
  21. data/lib/gooddata/{helpers.rb → helpers/global_helpers.rb} +0 -0
  22. data/lib/gooddata/helpers/helpers.rb +6 -0
  23. data/lib/gooddata/models/domain.rb +134 -24
  24. data/lib/gooddata/models/membership.rb +402 -0
  25. data/lib/gooddata/models/metadata.rb +64 -7
  26. data/lib/gooddata/models/metadata/attribute.rb +27 -12
  27. data/lib/gooddata/models/metadata/column.rb +1 -1
  28. data/lib/gooddata/models/metadata/dashboard.rb +7 -6
  29. data/lib/gooddata/models/metadata/display_form.rb +17 -2
  30. data/lib/gooddata/models/metadata/fact.rb +13 -7
  31. data/lib/gooddata/models/metadata/metric.rb +9 -9
  32. data/lib/gooddata/models/metadata/report.rb +7 -8
  33. data/lib/gooddata/models/metadata/report_definition.rb +10 -11
  34. data/lib/gooddata/models/metadata/schema.rb +1 -1
  35. data/lib/gooddata/models/model.rb +1 -1
  36. data/lib/gooddata/models/process.rb +44 -25
  37. data/lib/gooddata/models/profile.rb +365 -13
  38. data/lib/gooddata/models/project.rb +245 -35
  39. data/lib/gooddata/models/project_blueprint.rb +42 -18
  40. data/lib/gooddata/models/project_creator.rb +4 -1
  41. data/lib/gooddata/models/project_role.rb +7 -7
  42. data/lib/gooddata/models/schedule.rb +17 -1
  43. data/lib/gooddata/models/schema_blueprint.rb +19 -2
  44. data/lib/gooddata/version.rb +1 -1
  45. data/out.txt +0 -0
  46. data/spec/data/users.csv +12 -0
  47. data/spec/helpers/connection_helper.rb +1 -0
  48. data/spec/helpers/csv_helper.rb +12 -0
  49. data/spec/helpers/project_helper.rb +1 -1
  50. data/spec/integration/full_project_spec.rb +136 -3
  51. data/spec/spec_helper.rb +9 -0
  52. data/spec/unit/commands/command_user_spec.rb +1 -1
  53. data/spec/unit/extensions/hash_spec.rb +19 -0
  54. data/spec/unit/godzilla/goodzilla_spec.rb +15 -0
  55. data/spec/unit/helpers/csv_helper_spec.rb +18 -0
  56. data/spec/unit/models/domain_spec.rb +47 -4
  57. data/spec/unit/models/md_object_spec.rb +8 -0
  58. data/spec/unit/models/membership_spec.rb +128 -0
  59. data/spec/unit/models/metadata_spec.rb +38 -0
  60. data/spec/unit/models/profile_spec.rb +212 -0
  61. data/spec/unit/models/project_blueprint_spec.rb +35 -8
  62. data/spec/unit/models/project_role_spec.rb +6 -6
  63. data/spec/unit/models/project_spec.rb +226 -13
  64. data/spec/unit/models/schedule_spec.rb +58 -0
  65. data/tmp/.gitkeepme +0 -0
  66. metadata +36 -11
  67. data/lib/gooddata/models/account_settings.rb +0 -124
  68. data/lib/gooddata/models/user.rb +0 -165
  69. data/spec/unit/models/account_settings_spec.rb +0 -28
  70. data/spec/unit/models/user_spec.rb +0 -16
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+
3
+ module GoodData
4
+ # Project Not Found
5
+ class ValidationError < RuntimeError
6
+ DEFAULT_MSG = 'Validation has failed'
7
+
8
+ def initialize(msg = DEFAULT_MSG)
9
+ super(msg)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: UTF-8
2
+
3
+ base = Pathname(__FILE__).dirname.expand_path
4
+ Dir.glob(base + '*.rb').each do |file|
5
+ require_relative file
6
+ end
@@ -6,7 +6,7 @@ module GoodData
6
6
  # @param a_maql_string Input MAQL string
7
7
  # @return [Array<String>] List of IDS
8
8
  def self.get_ids(a_maql_string)
9
- a_maql_string.scan(/!\[([^\"]+)\]/).flatten
9
+ a_maql_string.scan(/!\[([^\"\]]+)\]/).flatten.uniq
10
10
  end
11
11
 
12
12
  # Get Facts from MAQL string
@@ -67,7 +67,7 @@ module GoodData
67
67
  metric = interpolated[:facts].reduce(metric) { |a, e| a.sub("#\"#{e[0]}\"", "[#{e[1]}]") }
68
68
  metric = interpolated[:attributes].reduce(metric) { |a, e| a.sub("@\"#{e[0]}\"", "[#{e[1]}]") }
69
69
  metric = interpolated[:metrics].reduce(metric) { |a, e| a.sub("?\"#{e[0]}\"", "[#{e[1]}]") }
70
- metric = interpolated_ids.reduce(metric) { |a, e| a.sub("![#{e[0]}]", "[#{e[1]}]") }
70
+ metric = interpolated_ids.reduce(metric) { |a, e| a.gsub("![#{e[0]}]", "[#{e[1]}]") }
71
71
  metric
72
72
  end
73
73
  end
@@ -0,0 +1,57 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'csv'
4
+
5
+ module GoodData
6
+ module Helpers
7
+ class Csv
8
+ class << self
9
+ # Read data from CSV
10
+ #
11
+ # @param [Hash] opts
12
+ # @option opts [String] :path File to read data from
13
+ # @option opts [Boolean] :header File to read data from
14
+ # @return Array of rows with loaded data
15
+ def read(opts)
16
+ path = opts[:path]
17
+ res = []
18
+
19
+ line = 0
20
+
21
+ CSV.foreach(path) do |row|
22
+ line += 1
23
+ next if opts[:header] && line == 1
24
+
25
+ if block_given?
26
+ data = yield row
27
+ else
28
+ data = row
29
+ end
30
+
31
+ res << data if data
32
+ end
33
+
34
+ res
35
+ end
36
+
37
+ # Write data to CSV
38
+ # @option opts [String] :path File to write data to
39
+ # @option opts [Array] :data Mandatory array of data to write
40
+ # @option opts [String] :header Optional Header row
41
+ def write(opts, &block)
42
+ path = opts[:path]
43
+ header = opts[:header]
44
+ data = opts[:data]
45
+
46
+ CSV.open(path, 'w') do |csv|
47
+ csv << header unless header.nil?
48
+ data.each do |entry|
49
+ res = yield entry
50
+ csv << res if res
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: UTF-8
2
+
3
+ base = Pathname(__FILE__).dirname.expand_path
4
+ Dir.glob(base + '*.rb').each do |file|
5
+ require_relative file
6
+ end
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require_relative 'account_settings'
3
+ require_relative 'profile'
4
4
 
5
5
  module GoodData
6
6
  class Domain
@@ -24,34 +24,76 @@ module GoodData
24
24
  # @param login [String] Login of user to be invited
25
25
  # @param password [String] Default preset password
26
26
  # @return [Object] Raw response
27
- def add_user(domain, login, password)
27
+ def add_user(opts)
28
+ generated_pass = rand(10E10).to_s
28
29
  data = {
29
- :accountSetting => {
30
- :login => login,
31
- :firstName => 'FirstName',
32
- :lastName => 'LastName',
33
- :password => password,
34
- :verifyPassword => password,
35
- :email => login
36
- }
30
+ :login => opts[:login],
31
+ :firstName => opts[:first_name] || 'FirstName',
32
+ :lastName => opts[:last_name] || 'LastName',
33
+ :password => opts[:password] || generated_pass,
34
+ :verifyPassword => opts[:password] || generated_pass,
35
+ :email => opts[:login]
37
36
  }
38
37
 
39
- url = "/gdc/account/domains/#{domain}/users"
40
- GoodData.post(url, data)
38
+ # Optional authentication modes
39
+ tmp = opts[:authentication_modes]
40
+ if tmp
41
+ if tmp.kind_of? Array
42
+ data[:authenticationModes] = tmp
43
+ elsif tmp.kind_of? String
44
+ data[:authenticationModes] = [tmp]
45
+ end
46
+ end
47
+
48
+ # Optional company
49
+ tmp = opts[:company_name]
50
+ tmp = opts[:company] if tmp.nil? || tmp.empty?
51
+ data[:companyName] = tmp if tmp && !tmp.empty?
52
+
53
+ # Optional country
54
+ tmp = opts[:country]
55
+ data[:country] = tmp if tmp && !tmp.empty?
56
+
57
+ # Optional phone number
58
+ tmp = opts[:phone]
59
+ tmp = opts[:phone_number] if tmp.nil? || tmp.empty?
60
+ data[:phoneNumber] = tmp if tmp && !tmp.empty?
61
+
62
+ # Optional position
63
+ tmp = opts[:position]
64
+ data[:position] = tmp if tmp && !tmp.empty?
65
+
66
+ # Optional sso provider
67
+ tmp = opts[:sso_provider]
68
+ data['ssoProvider'] = tmp if tmp && !tmp.empty?
69
+
70
+ # Optional timezone
71
+ tmp = opts[:timezone]
72
+ data[:timezone] = tmp if tmp && !tmp.empty?
73
+
74
+ # TODO: It will be nice if the API will return us user just newly created
75
+ url = "/gdc/account/domains/#{opts[:domain]}/users"
76
+ response = GoodData.post(url, :accountSetting => data)
77
+
78
+ raw = GoodData.get response['uri']
79
+
80
+ # TODO: Remove this hack when POST /gdc/account/domains/{domain-name}/users returns full profile
81
+ raw['accountSetting']['links'] = {} unless raw['accountSetting']['links']
82
+ raw['accountSetting']['links']['self'] = response['uri'] unless raw['accountSetting']['links']['self']
83
+
84
+ GoodData::Profile.new(raw)
41
85
  end
42
86
 
43
87
  # Finds user in domain by login
44
88
  #
45
89
  # @param domain [String] Domain name
46
90
  # @param login [String] User login
47
- # @return [GoodData::AccountSettings] User account settings
91
+ # @return [GoodData::Profile] User profile
48
92
  def find_user_by_login(domain, login)
49
93
  url = "/gdc/account/domains/#{domain}/users?login=#{login}"
50
94
  tmp = GoodData.get url
51
95
  items = tmp['accountSettings']['items'] if tmp['accountSettings']
52
- if items && items.length > 0
53
- return GoodData::AccountSettings.new(items.first)
54
- end
96
+ return GoodData::Profile.new(items.first) if items && items.length > 0
55
97
  nil
56
98
  end
57
99
 
@@ -60,18 +102,81 @@ module GoodData
60
102
  # @param [Hash] opts Options.
61
103
  # @option opts [Number] :offset The subject
62
104
  # @option opts [Number] :limit From address
105
+ # TODO: Review opts[:limit] functionality
63
106
  def users(domain, opts = USERS_OPTIONS)
64
107
  result = []
65
108
 
66
109
  options = USERS_OPTIONS.merge(opts)
67
-
68
- tmp = GoodData.get("/gdc/account/domains/#{domain}/users?offset=#{options[:offset]}&limit=#{options[:limit]}")
69
- tmp['accountSettings']['items'].each do |account|
70
- result << GoodData::AccountSettings.new(account)
110
+ offset = 0 || options[:offset]
111
+ uri = "/gdc/account/domains/#{domain}/users?offset=#{offset}&limit=#{options[:limit]}"
112
+ loop do
113
+ break unless uri
114
+ tmp = GoodData.get(uri)
115
+ tmp['accountSettings']['items'].each do |account|
116
+ result << GoodData::Profile.new(account)
117
+ end
118
+ uri = tmp['accountSettings']['paging']['next']
71
119
  end
72
120
 
73
121
  result
74
122
  end
123
+
124
+ # Create users specified in list
125
+ # @param [Array<GoodData::Membership>] list List of users
126
+ # @param [String] default_domain_name Default domain name used when no specified in user
127
+ # @return [Array<GoodData::User>] List of users created
128
+ def users_create(list, default_domain = nil)
129
+ default_domain_name = default_domain.respond_to?(:name) ? default_domain.name : default_domain
130
+ domains = {}
131
+ list.map do |user|
132
+ # TODO: Add user here
133
+ domain_name = user.json['user']['content']['domain'] || default_domain_name
134
+
135
+ # Lookup for domain in cache'
136
+ domain = domains[domain_name]
137
+
138
+ # Get domain info from REST, add to cache
139
+ if domain.nil?
140
+ domain = {
141
+ :domain => GoodData::Domain[domain_name],
142
+ :users => GoodData::Domain[domain_name].users
143
+ }
144
+
145
+ domain[:users_map] = Hash[domain[:users].map { |u| [u.email, u] }]
146
+ domains[domain_name] = domain
147
+ end
148
+
149
+ # Check if user exists in domain
150
+ domain_user = domain[:users_map][user.email]
151
+
152
+ # Create domain user if needed
153
+ unless domain_user
154
+ password = user.json['user']['content']['password']
155
+
156
+ # Fill necessary user data
157
+ user_data = {
158
+ :login => user.login,
159
+ :firstName => user.first_name,
160
+ :lastName => user.last_name,
161
+ :password => password,
162
+ :verifyPassword => password,
163
+ :email => user.login
164
+ }
165
+
166
+ tmp = user.json['user']['content']['sso_provider']
167
+ user_data[:sso_provider] = tmp if tmp && !tmp.empty?
168
+
169
+ tmp = user.json['user']['content']['authentication_modes']
170
+ user_data[:authentication_modes] = tmp && !tmp.empty?
171
+
172
+ # Add created user to cache
173
+ domain_user = domain[:domain].add_user(user_data)
174
+ domain[:users] << domain_user
175
+ domain[:users_map][user.email] = domain_user
176
+ end
177
+ domain_user
178
+ end
179
+ end
75
180
  end
76
181
 
77
182
  def initialize(domain_name)
@@ -90,14 +195,15 @@ module GoodData
90
195
  # domain = GoodData::Domain['gooddata-tomas-korcak']
91
196
  # domain.add_user 'joe.doe@example', 'sup3rS3cr3tP4ssW0rtH'
92
197
  #
93
- def add_user(login, password)
94
- GoodData::Domain.add_user(name, login, password)
198
+ def add_user(opts)
199
+ opts[:domain] = name
200
+ GoodData::Domain.add_user(opts)
95
201
  end
96
202
 
97
203
  # Finds user in domain by login
98
204
  #
99
205
  # @param login [String] User login
100
- # @return [GoodData::AccountSettings] User account settings
206
+ # @return [GoodData::Profile] User account settings
101
207
  def find_user_by_login(login)
102
208
  GoodData::Domain.find_user_by_login(name, login)
103
209
  end
@@ -107,7 +213,7 @@ module GoodData
107
213
  # @param [Hash] opts Additional user listing options.
108
214
  # @option opts [Number] :offset Offset to start listing from
109
215
  # @option opts [Number] :limit Limit of users to be listed
110
- # @return [Array<GoodData::AccountSettings>] List of user account settings
216
+ # @return [Array<GoodData::Profile>] List of user account settings
111
217
  #
112
218
  # Example
113
219
  #
@@ -119,6 +225,10 @@ module GoodData
119
225
  GoodData::Domain.users(name, opts)
120
226
  end
121
227
 
228
+ def users_create(list)
229
+ GoodData::Domain.users_create(list, name)
230
+ end
231
+
122
232
  private
123
233
 
124
234
  # Private setter of domain name. Used by constructor not available for external users.
@@ -0,0 +1,402 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'multi_json'
4
+
5
+ require_relative 'project'
6
+ require_relative 'project_role'
7
+
8
+ module GoodData
9
+ class Membership
10
+ attr_reader :json
11
+
12
+ ASSIGNABLE_MEMBERS = [
13
+ :email,
14
+ :first_name,
15
+ :last_name,
16
+ :login,
17
+ :phone,
18
+ :status,
19
+ :title
20
+ ]
21
+
22
+ class << self
23
+ # Apply changes to object.
24
+ #
25
+ # @param obj [GoodData::User] Object to be modified
26
+ # @param changes [Hash] Hash with modifications
27
+ # @return [GoodData::User] Modified object
28
+ def apply(obj, changes)
29
+ changes.each do |param, val|
30
+ next unless ASSIGNABLE_MEMBERS.include? param
31
+ obj.send("#{param}=", val)
32
+ end
33
+ obj
34
+ end
35
+
36
+ # Gets hash representing diff of users
37
+ #
38
+ # @param user1 [GoodData::User] Original user
39
+ # @param user2 [GoodData::User] User to compare with
40
+ # @return [Hash] Hash representing diff
41
+ def diff(user1, user2)
42
+ res = {}
43
+ ASSIGNABLE_MEMBERS.each do |k|
44
+ l_value = user1.send("#{k}")
45
+ r_value = user2.send("#{k}")
46
+ res[k] = r_value if l_value != r_value
47
+ end
48
+ res
49
+ end
50
+
51
+ def diff_list(list1, list2)
52
+ tmp = Hash[list1.map { |v| [v.email, v] }]
53
+
54
+ res = {
55
+ :added => [],
56
+ :removed => [],
57
+ :changed => [],
58
+ :same => []
59
+ }
60
+
61
+ list2.each do |user_new|
62
+ user_existing = tmp[user_new.email]
63
+ if user_existing.nil?
64
+ res[:added] << user_new
65
+ next
66
+ end
67
+
68
+ if user_existing != user_new
69
+ diff = self.diff(user_existing, user_new)
70
+ res[:changed] << {
71
+ :user => user_existing,
72
+ :diff => diff
73
+ }
74
+ else
75
+ res[:same] << user_existing
76
+ end
77
+ end
78
+
79
+ tmp = Hash[list2.map { |v| [v.email, v] }]
80
+ list1.each do |user_existing|
81
+ user_new = tmp[user_existing.email]
82
+ if user_new.nil?
83
+ res[:removed] << user_existing
84
+ next
85
+ end
86
+ end
87
+
88
+ res
89
+ end
90
+ end
91
+
92
+ def initialize(json)
93
+ @json = json
94
+ end
95
+
96
+ # Checks objects for equality
97
+ #
98
+ # @param right [GoodData::User] Project to compare with
99
+ # @return [Boolean] True if same else false
100
+ def ==(other)
101
+ res = true
102
+ ASSIGNABLE_MEMBERS.each do |k|
103
+ l_val = send("#{k}")
104
+ r_val = other.send("#{k}")
105
+ res = false if l_val != r_val
106
+ end
107
+ res
108
+ end
109
+
110
+ # Checks objects for non-equality
111
+ #
112
+ # @param right [GoodData::User] Project to compare with
113
+ # @return [Boolean] True if different else false
114
+ def !=(other)
115
+ !(self == other)
116
+ end
117
+
118
+ # Apply changes to object.
119
+ #
120
+ # @param changes [Hash] Hash with modifications
121
+ # @return [GoodData::User] Modified object
122
+ def apply(changes)
123
+ GoodData::User.apply(self, changes)
124
+ end
125
+
126
+ # Gets author (person who created) of this object
127
+ #
128
+ # @return [String] Author
129
+ def author
130
+ url = @json['user']['meta']['author']
131
+ data = GoodData.get url
132
+ GoodData::Membership.new(data)
133
+ end
134
+
135
+ # Gets the contributor
136
+ #
137
+ # @return [String] Contributor
138
+ def contributor
139
+ url = @json['user']['meta']['contributor']
140
+ data = GoodData.get url
141
+ GoodData::Membership.new(data)
142
+ end
143
+
144
+ # Gets date when created
145
+ #
146
+ # @return [DateTime] Created date
147
+ def created
148
+ Time.parse(@json['user']['meta']['created'])
149
+ end
150
+
151
+ # Gets hash representing diff of users
152
+ #
153
+ # @param user [GoodData::User] Another profile to compare with
154
+ # @return [Hash] Hash representing diff
155
+ def diff(user)
156
+ GoodData::User.diff(self, user)
157
+ end
158
+
159
+ # Gets the email
160
+ #
161
+ # @return [String] Email address
162
+ def email
163
+ @json['user']['content']['email'] || ''
164
+ end
165
+
166
+ # Sets the email
167
+ #
168
+ # @param new_email [String] New email to be assigned
169
+ def email=(new_email)
170
+ @json['user']['content']['email'] = new_email
171
+ end
172
+
173
+ # Gets the first name
174
+ #
175
+ # @return [String] First name
176
+ def first_name
177
+ @json['user']['content']['firstname'] || ''
178
+ end
179
+
180
+ # Sets the first name
181
+ #
182
+ # @param new_first_name [String] New first name to be assigned
183
+ def first_name=(new_first_name)
184
+ @json['user']['content']['firstname'] = new_first_name
185
+ end
186
+
187
+ # Gets the invitations
188
+ #
189
+ # @return [Array<GoodData::Invitation>] List of invitations
190
+ def invitations
191
+ res = []
192
+
193
+ tmp = GoodData.get @json['user']['links']['invitations']
194
+ tmp['invitations'].each do |invitation|
195
+ # TODO: Something is missing here
196
+ end
197
+
198
+ res
199
+ end
200
+
201
+ # Gets the last name
202
+ #
203
+ # @return [String] Last name
204
+ def last_name
205
+ @json['user']['content']['lastname'] || ''
206
+ end
207
+
208
+ # Sets the last name
209
+ #
210
+ # @param new_last_name [String] New last name to be assigned
211
+ def last_name=(new_last_name)
212
+ @json['user']['content']['lastname'] = new_last_name
213
+ end
214
+
215
+ # Gets the login
216
+ #
217
+ # @return [String] Login
218
+ def login
219
+ @json['user']['content']['login'] || ''
220
+ end
221
+
222
+ # Sets the last name
223
+ #
224
+ # @param new_login [String] New login to be assigned
225
+ def login=(new_login)
226
+ @json['user']['content']['login'] = new_login
227
+ end
228
+
229
+ # Gets user raw object ID
230
+ #
231
+ # @return [String] Raw Object ID
232
+ def obj_id
233
+ uri.split('/').last
234
+ end
235
+
236
+ # Gets the permissions
237
+ #
238
+ # @return [Hash] Hash with permissions
239
+ def permissions
240
+ res = {}
241
+
242
+ tmp = GoodData.get @json['user']['links']['permissions']
243
+ tmp['associatedPermissions']['permissions'].each do |permission_name, permission_value|
244
+ res[permission_name] = permission_value
245
+ end
246
+
247
+ res
248
+ end
249
+
250
+ # Gets the phone number
251
+ #
252
+ # @return [String] Phone number
253
+ def phone
254
+ @json['user']['content']['phonenumber'] || ''
255
+ end
256
+
257
+ # Sets the phone number
258
+ #
259
+ # @param new_phone_number [String] New phone number to be assigned
260
+ def phone=(new_phone_number)
261
+ @json['user']['content']['phonenumber'] = new_phone_number
262
+ end
263
+
264
+ # Gets profile of this membership
265
+ def profile
266
+ raw = GoodData.get @json['user']['links']['self']
267
+ GoodData::Profile.new(raw)
268
+ end
269
+
270
+ # Gets URL of profile membership
271
+ def profile_url
272
+ @json['user']['links']['self']
273
+ end
274
+
275
+ # Gets project which this membership relates to
276
+ def project
277
+ raw = GoodData.get project_url
278
+ GoodData::Project.new(raw)
279
+ end
280
+
281
+ # Gets project id
282
+ def project_id
283
+ @json['user']['links']['roles'].split('/')[3]
284
+ end
285
+
286
+ # Gets project url
287
+ def project_url
288
+ @json['user']['links']['roles'].split('/')[0..3].join('/')
289
+ end
290
+
291
+ # Gets the projects of user
292
+ #
293
+ # @return [Array<GoodData::Project>] Array of projets
294
+ def projects
295
+ res = []
296
+
297
+ tmp = GoodData.get @json['user']['links']['projects']
298
+ tmp['projects'].each do |project_meta|
299
+ project_uri = project_meta['project']['links']['self']
300
+ project = GoodData.get project_uri
301
+ res << GoodData::Project.new(project)
302
+ end
303
+
304
+ res
305
+ end
306
+
307
+ # Gets first role
308
+ def role
309
+ roles.first
310
+ end
311
+
312
+ # Gets the project roles of user
313
+ #
314
+ # @return [Array<GoodData::ProjectRole>] Array of project roles
315
+ def roles
316
+ res = []
317
+
318
+ tmp = GoodData.get @json['user']['links']['roles']
319
+ tmp['associatedRoles']['roles'].each do |role_uri|
320
+ role = GoodData.get role_uri
321
+ res << GoodData::ProjectRole.new(role)
322
+ end
323
+
324
+ res
325
+ end
326
+
327
+ # Gets the status
328
+ #
329
+ # @return [String] Status
330
+ def status
331
+ @json['user']['content']['status'] || ''
332
+ end
333
+
334
+ # Sets the status
335
+ #
336
+ # @param new_status [String] New phone number to be assigned
337
+ def status=(new_status)
338
+ @json['user']['content']['status'] = new_status
339
+ end
340
+
341
+ # Gets the title
342
+ #
343
+ # @return [String] User title
344
+ def title
345
+ @json['user']['meta']['title'] || ''
346
+ end
347
+
348
+ # Sets the title
349
+ #
350
+ # @param new_title [String] New title to be assigned
351
+ def title=(new_title)
352
+ @json['user']['content']['title'] = new_title
353
+ end
354
+
355
+ # Gets the date when updated
356
+ #
357
+ # @return [DateTime] Date of last update
358
+ def updated
359
+ DateTime.parse(@json['user']['meta']['updated'])
360
+ end
361
+
362
+ # Gets the object URI
363
+ #
364
+ # @return [String] Object URI
365
+ def uri
366
+ @json['user']['links']['self']
367
+ end
368
+
369
+ # Enables membership
370
+ #
371
+ # @return result from post execution
372
+ def enable
373
+ self.status = 'enabled'
374
+ end
375
+
376
+ # Disables membership
377
+ #
378
+ # @return result from post execution
379
+ def disable
380
+ self.status = 'disabled'
381
+ end
382
+
383
+ private
384
+
385
+ # Sets status to 'ENABLED' or 'DISABLED'
386
+ def status=(new_status)
387
+ payload = {
388
+ 'user' => {
389
+ 'content' => {
390
+ 'status' => new_status.to_s.upcase,
391
+ 'userRoles' => @json['user']['content']['userRoles']
392
+ },
393
+ 'links' => {
394
+ 'self' => uri
395
+ }
396
+ }
397
+ }
398
+
399
+ @json = GoodData.post("/gdc/projects/#{project_id}/users", payload)
400
+ end
401
+ end
402
+ end