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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +36 -0
- data/doc/Array.html +200 -0
- data/doc/Boolean.html +122 -0
- data/doc/FalseClass.html +132 -0
- data/doc/Grafana.html +172 -0
- data/doc/Hash.html +212 -0
- data/doc/Logging.html +326 -0
- data/doc/Object.html +286 -0
- data/doc/Time.html +200 -0
- data/doc/TrueClass.html +132 -0
- data/doc/_index.html +380 -0
- data/doc/class_list.html +51 -0
- data/doc/file.README.html +117 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +117 -0
- data/doc/method_list.html +771 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/grafana.rb +7 -0
- data/lib/grafana/admin.rb +310 -0
- data/lib/grafana/alerts.rb +38 -0
- data/lib/grafana/annotations.rb +40 -0
- data/lib/grafana/client.rb +126 -0
- data/lib/grafana/dashboard.rb +149 -0
- data/lib/grafana/dashboard_versions.rb +30 -0
- data/lib/grafana/datasource.rb +271 -0
- data/lib/grafana/login.rb +139 -0
- data/lib/grafana/network.rb +169 -0
- data/lib/grafana/organization.rb +101 -0
- data/lib/grafana/organizations.rb +406 -0
- data/lib/grafana/snapshot.rb +47 -0
- data/lib/grafana/tags.rb +41 -0
- data/lib/grafana/tools.rb +66 -0
- data/lib/grafana/user.rb +116 -0
- data/lib/grafana/users.rb +122 -0
- data/lib/grafana/validator.rb +28 -0
- data/lib/grafana/version.rb +17 -0
- data/lib/logging.rb +35 -0
- data/lib/monkey_patches.rb +92 -0
- metadata +294 -0
@@ -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
|