grafana 0.8.2

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.
@@ -0,0 +1,139 @@
1
+
2
+ module Grafana
3
+
4
+ # Abstract base class for Login.
5
+ #
6
+ module Login
7
+
8
+ # Login into Grafana
9
+ #
10
+ # @param [Hash] params
11
+ # @option params [String] username username for the login
12
+ # @option params [String] password password for the login
13
+ # @option params [Integer] max_retries (2) maximum retries
14
+ # @option params [Integer] sleep_between_retries (5) sleep seconds between retries
15
+ #
16
+ # @example
17
+ # login( username: 'admin', password: 'admin' )
18
+ # login( username: 'admin', password: 'admin', max_retries: 10, sleep_between_retries: 8 )
19
+ #
20
+ # @return [Hash]
21
+ #
22
+ def login( params )
23
+
24
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
25
+ raise ArgumentError.new('missing params') if( params.size.zero? )
26
+
27
+ username = validate( params, required: true, var: 'username', type: String )
28
+ password = validate( params, required: true, var: 'password', type: String )
29
+ max_retries = validate( params, required: false, var: 'max_retries', type: Integer ) || 2
30
+ sleep_between_retries = validate( params, required: false, var: 'sleep_between_retries', type: Integer ) || 5
31
+
32
+ begin
33
+ @api_instance = RestClient::Resource.new(
34
+ @url,
35
+ timeout: @timeout.to_i,
36
+ open_timeout: @open_timeout.to_i,
37
+ headers: @http_headers,
38
+ verify_ssl: false
39
+ )
40
+ rescue => e
41
+ logger.error( e ) if @debug
42
+ logger.debug( e.backtrace.join("\n") ) if @debug
43
+ false
44
+ end
45
+
46
+ request_data = { 'User' => username, 'Password' => password }
47
+
48
+ if( @api_instance )
49
+ retried ||= 0
50
+ response_cookies = ''
51
+ @headers = {}
52
+
53
+ begin
54
+ logger.debug('Attempting to establish user session') if @debug
55
+
56
+ response = @api_instance['/login'].post(
57
+ request_data.to_json,
58
+ content_type: 'application/json; charset=UTF-8'
59
+ )
60
+
61
+ response_cookies = response.cookies
62
+ response_code = response.code.to_i
63
+
64
+ if( response_code == 200 )
65
+ @headers = {
66
+ content_type: 'application/json',
67
+ accept: 'application/json',
68
+ cookies: response_cookies
69
+ }
70
+ end
71
+
72
+ rescue SocketError
73
+ if( retried < max_retries )
74
+ retried += 1
75
+ logger.debug( format( 'cannot login, socket error (retry %d / %d)', retried, max_retries ) ) if @debug
76
+ sleep( sleep_between_retries )
77
+ retry
78
+ else
79
+ raise format( 'Maximum retries (%d) against \'%s/login\' reached. Giving up ...', max_retries, @url )
80
+ end
81
+
82
+ rescue RestClient::Unauthorized
83
+ logger.debug( request_data.to_json ) if @debug
84
+ raise format( 'Not authorized to connect \'%s\' - wrong username or password?', @url )
85
+
86
+ rescue RestClient::BadGateway
87
+ if( retried < max_retries )
88
+ retried += 1
89
+ logger.debug( format( 'cannot login, connection refused (retry %d / %d)', retried, max_retries ) ) if @debug
90
+ sleep( sleep_between_retries )
91
+ retry
92
+ else
93
+ raise format( 'Maximum retries (%d) against \'%s/login\' reached. Giving up ...', max_retries, @url )
94
+ end
95
+
96
+ rescue Errno::ECONNREFUSED
97
+ if( retried < max_retries )
98
+ retried += 1
99
+ logger.debug( format( 'cannot login, connection refused (retry %d / %d)', retried, max_retries ) ) if @debug
100
+ sleep( sleep_between_retries )
101
+ retry
102
+ else
103
+ raise format( 'Maximum retries (%d) against \'%s/login\' reached. Giving up ...', max_retries, @url )
104
+ end
105
+
106
+ rescue Errno::EHOSTUNREACH
107
+ if( retried < max_retries )
108
+ retried += 1
109
+ logger.debug( format( 'cannot login, host unreachable (retry %d / %d)', retried, max_retries ) ) if @debug
110
+ sleep( sleep_between_retries )
111
+ retry
112
+ else
113
+ raise format( 'Maximum retries (%d) against \'%s/login\' reached. Giving up ...', max_retries, @url )
114
+ end
115
+ end
116
+
117
+ logger.debug('User session initiated') if @debug
118
+
119
+ return true
120
+ end
121
+
122
+ false
123
+ end
124
+
125
+ # Renew session based on remember cookie
126
+ #
127
+ # @example
128
+ # ping_session
129
+ #
130
+ # @return [Hash]
131
+ #
132
+ def ping_session
133
+ endpoint = '/api/login/ping'
134
+ logger.debug( "Pinging current session (GET #{endpoint})" ) if @debug
135
+ get( endpoint )
136
+ end
137
+ end
138
+
139
+ end
@@ -0,0 +1,169 @@
1
+
2
+ module Grafana
3
+
4
+ module Network
5
+
6
+ def get( endpoint )
7
+
8
+ request( 'GET', endpoint )
9
+ end
10
+
11
+ def post( endpoint, data )
12
+
13
+ request( 'POST', endpoint, data )
14
+ end
15
+
16
+ def put( endpoint, data )
17
+
18
+ request( 'PUT', endpoint, data )
19
+ end
20
+
21
+ def patch( endpoint, data )
22
+
23
+ request( 'PATCH', endpoint, data )
24
+ end
25
+
26
+ def delete( endpoint )
27
+
28
+ request( 'DELETE', endpoint )
29
+ end
30
+
31
+ def request( method_type = 'GET', endpoint = '/', data = {} )
32
+
33
+ raise 'try first login()' if @api_instance.nil?
34
+
35
+ response = nil
36
+ response_code = 404
37
+ response_body = ''
38
+
39
+ begin
40
+
41
+ case method_type.upcase
42
+ when 'GET'
43
+ response = @api_instance[endpoint].get( @headers )
44
+ when 'POST'
45
+ response = @api_instance[endpoint].post( data, @headers )
46
+ when 'PATCH'
47
+ response = @api_instance[endpoint].patch( data, @headers )
48
+ when 'PUT'
49
+ # response = @api_instance[endpoint].put( data, @headers )
50
+ @api_instance[endpoint].put( data, @headers ) do |response, request, result|
51
+
52
+ case response.code
53
+ when 200
54
+ response_body = response.body
55
+ response_code = response.code.to_i
56
+ response_body = JSON.parse(response_body) if response_body.is_a?(String)
57
+
58
+ return {
59
+ 'status' => response_code,
60
+ 'message' => response_body.dig('message').nil? ? 'Successful' : response_body.dig('message')
61
+ }
62
+ when 400
63
+ response_body = response.body
64
+ response_code = response.code.to_i
65
+ raise RestClient::BadRequest
66
+ else
67
+ logger.error( response.code )
68
+ logger.error( response.body )
69
+ response.return! # (request, result)
70
+ end
71
+ end
72
+
73
+ when 'DELETE'
74
+ response = @api_instance[endpoint].delete( @headers )
75
+ else
76
+ @logger.error( "Error: #{__method__} is not a valid request method." )
77
+ return false
78
+ end
79
+
80
+ response_code = response.code.to_i
81
+ response_body = response.body
82
+ response_headers = response.headers
83
+
84
+ if( @debug )
85
+ logger.debug("response_code : #{response_code}" )
86
+ logger.debug("response_body : #{response_body}" )
87
+ logger.debug("response_headers : #{response_headers}" )
88
+ end
89
+
90
+ if( ( response_code >= 200 && response_code <= 299 ) || ( response_code >= 400 && response_code <= 499 ) )
91
+
92
+ result = JSON.parse( response_body )
93
+
94
+ if( result.is_a?(Array) )
95
+ r_result= {
96
+ 'status' => response_code,
97
+ 'message' => result
98
+ }
99
+ return r_result
100
+ end
101
+
102
+ result_status = result.dig('status') if( result.is_a?( Hash ) )
103
+
104
+ result['message'] = result_status unless( result_status.nil? )
105
+ result['status'] = response_code
106
+
107
+ return result
108
+ else
109
+
110
+ @logger.error( "#{__method__} #{method_type.upcase} on #{endpoint} failed: HTTP #{response.code} - #{response_body}" )
111
+ @logger.error( @headers )
112
+ @logger.error( JSON.pretty_generate( response_headers ) )
113
+
114
+ return JSON.parse( response_body )
115
+ end
116
+
117
+ rescue RestClient::BadRequest
118
+
119
+ response_body = JSON.parse(response_body) if response_body.is_a?(String)
120
+
121
+ return {
122
+ 'status' => 400,
123
+ 'message' => response_body.dig('message').nil? ? 'Bad Request' : response_body.dig('message')
124
+ }
125
+
126
+ rescue RestClient::Unauthorized
127
+
128
+ return {
129
+ 'status' => 401,
130
+ 'message' => format('Not authorized to connect \'%s/%s\' - wrong username or password?', @url, endpoint)
131
+ }
132
+
133
+ rescue RestClient::NotFound
134
+
135
+ return {
136
+ 'status' => 404,
137
+ 'message' => 'Not Found'
138
+ }
139
+
140
+ rescue RestClient::Conflict
141
+
142
+ return {
143
+ 'status' => 409,
144
+ 'message' => 'Conflict with the current state of the target resource'
145
+ }
146
+
147
+ rescue RestClient::PreconditionFailed
148
+
149
+ return {
150
+ 'status' => 412,
151
+ 'message' => 'Precondition failed. The Object probably already exists.'
152
+ }
153
+
154
+ rescue RestClient::ExceptionWithResponse => e
155
+
156
+ logger.error( "Error: #{__method__} #{method_type.upcase} on #{endpoint} error: '#{e}'" )
157
+ logger.error( data )
158
+ logger.error( @headers )
159
+ logger.error( JSON.pretty_generate( response_headers ) )
160
+
161
+ return false
162
+
163
+ end
164
+
165
+ end
166
+
167
+ end
168
+
169
+ end
@@ -0,0 +1,101 @@
1
+
2
+ module Grafana
3
+
4
+ # http://docs.grafana.org/http_api/org/#organisation-api
5
+ #
6
+ module Organization
7
+
8
+ # Get current Organisation
9
+ # GET /api/org
10
+ #
11
+ # -> {"id"=>1, "name"=>"Docker", "address"=>{"address1"=>"", "address2"=>"", "city"=>"", "zipCode"=>"", "state"=>"", "country"=>""}, "status"=>200}
12
+ #
13
+ def current_organization
14
+ endpoint = '/api/org'
15
+ @logger.debug("Get current Organisation (GET #{endpoint})") if @debug
16
+ get(endpoint)
17
+ end
18
+
19
+ # Update current Organisation
20
+ # PUT /api/org
21
+ #
22
+ #
23
+ #
24
+ def update_current_organization( params = {} )
25
+
26
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
27
+ name = params.dig(:name)
28
+ raise ArgumentError.new('missing name') if( name.nil? )
29
+
30
+ endpoint = '/api/org'
31
+ @logger.debug("Updating current organization (PUT #{endpoint})") if @debug
32
+ put(endpoint, params.to_json)
33
+ end
34
+
35
+ # Get all users within the actual organisation
36
+ # GET /api/org/users
37
+ #
38
+ #
39
+ #
40
+ def current_organization_users
41
+ endpoint = '/api/org/users'
42
+ @logger.debug("Getting organization users (GET #{endpoint})") if @debug
43
+ get(endpoint)
44
+ end
45
+
46
+ # Add a new user to the actual organisation
47
+ # POST /api/org/users
48
+ #
49
+ #
50
+ #
51
+ def add_user_to_current_organization( params = {} )
52
+
53
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
54
+ login_or_email = params.dig(:loginOrEmail)
55
+ role = params.dig(:role)
56
+ raise ArgumentError.new('missing loginOrEmail') if( login_or_email.nil? )
57
+ raise ArgumentError.new('missing role') if( role.nil? )
58
+ # Defaults to Viewer, other valid options are Admin and Editor and Read Only Editor
59
+ # valid_perms = ['Viewer','Editor','Read Only Editor','Admin']
60
+ raise ArgumentError.new( format( 'wrong role. only \'Admin\', \'Viewer\' or \'Editor\' allowed (\'%s\' giving)',role)) if( %w[Admin Viewer Editor].include?(role) == false )
61
+
62
+ org = current_organization_users
63
+ usr = user_by_name( login_or_email )
64
+
65
+ if( org )
66
+
67
+ org = org.dig('message')
68
+
69
+ if( org.select { |x| x.dig('email') == login_or_email }.count >= 1 )
70
+ return {
71
+ 'status' => 404,
72
+ 'message' => format('User \'%s\' are already in the organisation', login_or_email)
73
+ }
74
+ end
75
+ end
76
+
77
+ if( usr.nil? || usr.dig('status').to_i != 200 )
78
+ return {
79
+ 'status' => 404,
80
+ 'message' => format('User \'%s\' not found', login_or_email)
81
+ }
82
+ end
83
+
84
+ endpoint = '/api/org/users'
85
+ @logger.debug("Adding user to current organization (POST #{endpoint})") if @debug
86
+ post(endpoint, params.to_json)
87
+ end
88
+
89
+ # Updates the given user
90
+ # PATCH /api/org/users/:userId
91
+
92
+
93
+ # Delete user in actual organisation
94
+ # DELETE /api/org/users/:userId
95
+
96
+
97
+ #
98
+
99
+ end
100
+
101
+ end
@@ -0,0 +1,406 @@
1
+
2
+ module Grafana
3
+
4
+ # http://docs.grafana.org/http_api/org/#organisations
5
+ #
6
+ module Organizations
7
+
8
+ # Search all Organisations
9
+ # GET /api/orgs
10
+ def organizations
11
+ endpoint = '/api/orgs'
12
+ @logger.debug("Getting all organizations (GET #{endpoint})") if @debug
13
+ get( endpoint )
14
+ end
15
+
16
+
17
+ # Get a single data sources by Id or Name
18
+ #
19
+ # @example
20
+ # organisation( 1 )
21
+ # organisation( 'foo' )
22
+ #
23
+ # @return [Hash]
24
+ #
25
+ def organization( organisation_id )
26
+
27
+ raise ArgumentError.new(format('wrong type. user \'organisation_id\' must be an String (for an Datasource name) or an Integer (for an Datasource Id), given \'%s\'', organisation_id.class.to_s)) if( organisation_id.is_a?(String) && organisation_id.is_a?(Integer) )
28
+ raise ArgumentError.new('missing \'organisation_id\'') if( organisation_id.size.zero? )
29
+
30
+ endpoint = format( '/api/orgs/%d', organisation_id ) if(organisation_id.is_a?(Integer))
31
+ endpoint = format( '/api/orgs/name/%s', URI.escape( organisation_id ) ) if(organisation_id.is_a?(String))
32
+
33
+ @logger.debug("Attempting to get existing data source Id #{organisation_id} (GET #{endpoint})") if @debug
34
+
35
+ get(endpoint)
36
+ end
37
+
38
+ # # Get Organisation by Id
39
+ # # GET /api/orgs/:orgId
40
+ # def organization_by_id( id )
41
+ #
42
+ # raise ArgumentError.new('id must be an Integer') unless( id.is_a?(Integer) )
43
+ #
44
+ # endpoint = format( '/api/orgs/%d', id )
45
+ # @logger.debug("Get Organisation by Id (GET #{endpoint}})") if @debug
46
+ # get( endpoint )
47
+ # end
48
+ #
49
+ # # Get Organisation by Name
50
+ # # GET /api/orgs/name/:orgName
51
+ # def organization_by_name( name )
52
+ #
53
+ # raise ArgumentError.new('name must be an String') unless( name.is_a?(String) )
54
+ #
55
+ # endpoint = format( '/api/orgs/name/%s', URI.escape( name ) )
56
+ # @logger.debug("Get Organisation by Name (GET #{endpoint})") if @debug
57
+ # get( endpoint )
58
+ # end
59
+
60
+ # Update Organisation
61
+ #
62
+ # fields Adress 1, Adress 2, City are not implemented yet.
63
+ #
64
+ # @param [Hash] params
65
+ # @option params [String] organization name of the Organisation
66
+ # @option params [String] name new name
67
+ # @option params [String] adress_1
68
+ # @option params [String] adress_2
69
+ # @option params [String] city
70
+ #
71
+ # @example
72
+ # update_organization( organization: 'Main. Org', name: 'Foo+Bar' )
73
+ #
74
+ # @return [Hash]
75
+ #
76
+ def update_organization( params )
77
+
78
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
79
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
80
+
81
+ organization = validate( params, required: true, var: 'organization', type: String )
82
+ name = validate( params, required: true, var: 'name', type: String )
83
+
84
+ org = organization( organization )
85
+
86
+ if( org.nil? || org.dig('status').to_i != 200 )
87
+ return {
88
+ 'status' => 404,
89
+ 'message' => format('Organization \'%s\' not found', organization)
90
+ }
91
+ end
92
+ org_id = org.dig('id')
93
+
94
+ payload = { name: name }
95
+
96
+ endpoint = format( '/api/orgs/%s', org_id )
97
+ @logger.debug("Update Organisation id #{org_id} (PUT #{endpoint})") if @debug
98
+
99
+ put( endpoint, payload.to_json )
100
+ end
101
+
102
+ # Get Users in Organisation
103
+ #
104
+ # @param [Mixed] user_id Username (String) or Userid (Integer) for delete User
105
+ #
106
+ # @example
107
+ # organization_users( 1 )
108
+ # organization_users( 'Foo Bar' )
109
+ #
110
+ # @return [Hash]
111
+ #
112
+ def organization_users( org_id )
113
+
114
+ raise ArgumentError.new(format('wrong type. user \'org_id\' must be an String (for an Organisation name) or an Integer (for an Organisation Id), given \'%s\'', org_id.class.to_s)) if( org_id.is_a?(String) && org_id.is_a?(Integer) )
115
+ raise ArgumentError.new('missing \'org_id\'') if( org_id.size.zero? )
116
+
117
+ if(org_id.is_a?(String))
118
+ org = organization(org_id)
119
+ if( org.nil? || org.dig('status').to_i != 200 )
120
+ return {
121
+ 'status' => 404,
122
+ 'message' => format('Organization \'%s\' not found', organization)
123
+ }
124
+ end
125
+ org_id = org.dig('id')
126
+ end
127
+
128
+ endpoint = format( '/api/orgs/%s/users', org_id )
129
+
130
+ @logger.debug("Getting users in Organisation id #{org_id} (GET #{endpoint})") if @debug
131
+ get(endpoint)
132
+ end
133
+
134
+ # Add User in Organisation
135
+ #
136
+ # @param
137
+ # @option params [String] organization Organisation name
138
+ # @option params [String] login_or_email Login or email
139
+ # @option params [String] role Name of the Role - only 'Viewer', 'Editor', 'Read Only Editor' or 'Admin' allowed
140
+ #
141
+ # @examle
142
+ # params = {
143
+ # organization: 'Foo',
144
+ # login_or_email: 'foo@foo-bar.tld',
145
+ # role: 'Viewer'
146
+ # }
147
+ # add_user_to_organization( params )
148
+ #
149
+ # @return [Hash]
150
+ #
151
+ def add_user_to_organization( params )
152
+
153
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
154
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
155
+
156
+ organization = validate( params, required: true, var: 'organization', type: String )
157
+ login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
158
+ role = validate( params, required: true, var: 'role', type: String )
159
+ valid_roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin']
160
+
161
+ # https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
162
+ # Do this once, or each time the array changes
163
+ downcased = Set.new valid_roles.map(&:downcase)
164
+ unless( downcased.include?( role.downcase ) )
165
+
166
+ message = format( 'wrong role. Role must be one of %s, given \'%s\'', valid_roles.join(', '), role )
167
+
168
+ return {
169
+ 'status' => 404,
170
+ 'login_or_email' => login_or_email,
171
+ 'role' => role,
172
+ 'message' => message
173
+ }
174
+ end
175
+
176
+ org = organization( organization )
177
+ usr = user_by_name( login_or_email )
178
+
179
+ if( org.nil? || org.dig('status').to_i != 200 )
180
+ return {
181
+ 'status' => 404,
182
+ 'message' => format('Organization \'%s\' not found', organization)
183
+ }
184
+ end
185
+
186
+ if( usr.nil? || usr.dig('status').to_i != 200 )
187
+ return {
188
+ 'status' => 404,
189
+ 'message' => format('User \'%s\' not found', login_or_email)
190
+ }
191
+ end
192
+
193
+ org_id = org.dig('id')
194
+
195
+ payload = {
196
+ loginOrEmail: login_or_email,
197
+ role: role
198
+ }
199
+
200
+ endpoint = format( '/api/orgs/%d/users', org_id )
201
+ @logger.debug("Adding user '#{login_or_email}' to organisation '#{organization}' (POST #{endpoint})") if @debug
202
+
203
+ post( endpoint, payload.to_json )
204
+ end
205
+
206
+ # Update Users in Organisation
207
+ #
208
+ # @param
209
+ # @option params [String] organization Organisation name
210
+ # @option params [String] login_or_email Login or email
211
+ # @option params [String] role Name of the Role - only 'Viewer', 'Editor', 'Read Only Editor' or 'Admin' allowed
212
+ #
213
+ # @examle
214
+ # params = {
215
+ # organization: 'Foo',
216
+ # login_or_email: 'foo@foo-bar.tld',
217
+ # role: 'Viewer'
218
+ # }
219
+ # update_organization_user( params )
220
+ #
221
+ # @return [Hash]
222
+ #
223
+ def update_organization_user( params )
224
+
225
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
226
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
227
+
228
+ organization = validate( params, required: true, var: 'organization', type: String )
229
+ login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
230
+ role = validate( params, required: true, var: 'role', type: String )
231
+ valid_roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin']
232
+
233
+ # https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
234
+ # Do this once, or each time the array changes
235
+ downcased = Set.new valid_roles.map(&:downcase)
236
+ unless( downcased.include?( role.downcase ) )
237
+
238
+ message = format( 'wrong role. Role must be one of %s, given \'%s\'', valid_roles.join(', '), role )
239
+
240
+ return {
241
+ 'status' => 404,
242
+ 'login_or_email' => login_or_email,
243
+ 'role' => role,
244
+ 'message' => message
245
+ }
246
+ end
247
+
248
+ org = organization( organization )
249
+ usr = user_by_name( login_or_email )
250
+
251
+ if( org.nil? || org.dig('status').to_i != 200 )
252
+ return {
253
+ 'status' => 404,
254
+ 'message' => format('Organization \'%s\' not found', organization)
255
+ }
256
+ end
257
+
258
+ if( usr.nil? || usr.dig('status').to_i != 200 )
259
+ return {
260
+ 'status' => 404,
261
+ 'message' => format('User \'%s\' not found', login_or_email)
262
+ }
263
+ end
264
+
265
+ org_id = org.dig('id')
266
+ usr_id = usr.dig('id')
267
+
268
+ payload = {
269
+ role: role
270
+ }
271
+
272
+ endpoint = format( '/api/orgs/%d/users/%d', org_id, usr_id )
273
+
274
+ @logger.debug("Updating user '#{login_or_email}' in organization '#{organization}' (PATCH #{endpoint})") if @debug
275
+ patch( endpoint, payload.to_json )
276
+ end
277
+
278
+ # Delete User in Organisation
279
+ #
280
+ # @param
281
+ # @option params [String] organization Organisation name
282
+ # @option params [String] login_or_email Login or email
283
+ # @option params [String] role Name of the Role - only 'Viewer', 'Editor', 'Read Only Editor' or 'Admin' allowed
284
+ #
285
+ # @examle
286
+ # params = {
287
+ # organization: 'Foo',
288
+ # login_or_email: 'foo@foo-bar.tld'
289
+ # }
290
+ # delete_user_from_organization( params )
291
+ #
292
+ # @return [Hash]
293
+ #
294
+ # DELETE /api/orgs/:orgId/users/:userId
295
+ def delete_user_from_organization( params )
296
+
297
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
298
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
299
+
300
+ organization = validate( params, required: true, var: 'organization', type: String )
301
+ login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
302
+
303
+ org = organization( organization )
304
+ usr = user_by_name( login_or_email )
305
+
306
+ if( org.nil? || org.dig('status').to_i != 200 )
307
+ return {
308
+ 'status' => 404,
309
+ 'message' => format('Organization \'%s\' not found', organization)
310
+ }
311
+ end
312
+
313
+ if( usr.nil? || usr.dig('status').to_i != 200 )
314
+ return {
315
+ 'status' => 404,
316
+ 'message' => format('User \'%s\' not found', login_or_email)
317
+ }
318
+ end
319
+
320
+ org_id = org.dig('id')
321
+ usr_id = usr.dig('id')
322
+
323
+ endpoint = format( '/api/orgs/%d/users/%d', org_id, usr_id )
324
+
325
+ @logger.debug("Deleting user '#{login_or_email}' in organization '#{organization}' (DELETE #{endpoint})") if @debug
326
+ delete(endpoint)
327
+ end
328
+
329
+ # Create Organisation
330
+ #
331
+ # @param
332
+ # @option params [String] organization Organisation name
333
+ #
334
+ # @examle
335
+ # params = {
336
+ # name: 'Foo'
337
+ # }
338
+ # create_organisation( params )
339
+ #
340
+ # @return [Hash]
341
+ #
342
+ def create_organisation( params )
343
+
344
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
345
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
346
+
347
+ name = validate( params, required: true, var: 'name', type: String )
348
+
349
+ org = organization( name )
350
+
351
+ if( org.nil? || org.dig('status').to_i == 200 )
352
+ return {
353
+ 'status' => 409,
354
+ 'message' => format('Organisation \'%s\' already exists', name )
355
+ }
356
+ end
357
+
358
+ endpoint = '/api/orgs'
359
+ payload = {
360
+ name: name
361
+ }
362
+ @logger.debug("Create Organisation (POST #{endpoint})") if @debug
363
+
364
+ post( endpoint, payload.to_json )
365
+ end
366
+
367
+ # Delete Organisation
368
+ #
369
+ # @param [Mixed] organisation_id Organisation Name (String) or Organisation Id (Integer) for delete Organisation
370
+ #
371
+ # @example
372
+ # delete_organisation( 1 )
373
+ # delete_organisation( 'Foo' )
374
+ #
375
+ # @return [Hash]
376
+ #
377
+ def delete_organisation( organisation_id )
378
+
379
+ raise ArgumentError.new(format('wrong type. user \'organisation_id\' must be an String (for an Datasource name) or an Integer (for an Datasource Id), given \'%s\'', organisation_id.class.to_s)) if( organisation_id.is_a?(String) && organisation_id.is_a?(Integer) )
380
+ raise ArgumentError.new('missing \'organisation_id\'') if( organisation_id.size.zero? )
381
+
382
+ if(organisation_id.is_a?(String))
383
+ data = organizations.dig('message')
384
+ organisation_map = {}
385
+ data.each do |ds|
386
+ organisation_map[ds['id']] = ds
387
+ end
388
+ organisation_map.select { |_k,v| v['name'] == organisation_id }
389
+ organisation_id = organisation_map.keys.first if( data )
390
+ end
391
+
392
+ if( organisation_id.nil? )
393
+ return {
394
+ 'status' => 404,
395
+ 'message' => format( 'No Organisation \'%s\' found', organisation_id)
396
+ }
397
+ end
398
+
399
+ endpoint = format( '/api/orgs/%d', organisation_id )
400
+ @logger.debug("Deleting organization #{organisation_id} (DELETE #{endpoint})") if @debug
401
+
402
+ delete(endpoint)
403
+ end
404
+
405
+ end
406
+ end