idnio 2.3.2b

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,57 @@
1
+ #
2
+ # Time Utility
3
+ #
4
+ module Timer
5
+ @@timeStart = nil
6
+ @@timeEnd = nil
7
+
8
+ #
9
+ # Starts the timer
10
+ #
11
+ def self.start
12
+ @@timeStart = Process.clock_gettime( Process::CLOCK_MONOTONIC )
13
+ end
14
+
15
+ #
16
+ # Stops the timer
17
+ #
18
+ def self.stop
19
+ @@timeEnd = Process.clock_gettime( Process::CLOCK_MONOTONIC )
20
+ end
21
+
22
+ #
23
+ # Gets elapsed time
24
+ #
25
+ def self.elapsed
26
+ unless @@timeEnd.nil? || @@timeStart.nil?
27
+
28
+ elapsed = @@timeEnd.to_i - @@timeStart.to_i # distance between t1 and t2 in seconds
29
+
30
+ resolution = if elapsed > 29030400 # seconds in a year
31
+ [(elapsed/29030400), 'years']
32
+ elsif elapsed > 2419200
33
+ [(elapsed/2419200), 'months']
34
+ elsif elapsed > 604800
35
+ [(elapsed/604800), 'weeks']
36
+ elsif elapsed > 86400
37
+ [(elapsed/86400), 'days']
38
+ elsif elapsed > 3600 # seconds in an hour
39
+ [(elapsed/3600), 'hours']
40
+ elsif elapsed > 60
41
+ [(elapsed/60), 'minutes']
42
+ else
43
+ [elapsed, 'seconds']
44
+ end
45
+
46
+ if resolution[0] == 1
47
+ return resolution.join(' ')[0...-1]
48
+ else
49
+ return resolution.join(' ')
50
+ end
51
+
52
+ else
53
+ return nil
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,4 @@
1
+ module Idnio
2
+ VERSION = "2.3.2b"
3
+ UPDATE_DATE = "2019-11-11"
4
+ end
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+ require "json"
3
+ require "idnio/idnapi"
4
+ require "idnio/program"
5
+ require "idnio/markdown"
6
+
7
+ module AccessProfiles
8
+
9
+ #
10
+ # Converts Entitlement IDs to Entitlement Names
11
+ #
12
+ def self.getEntitlements( entitlement_ids )
13
+
14
+ entitlementNames = ""
15
+
16
+ entitlement_ids.each do |entitlement_id|
17
+
18
+ response = IDNAPI.get( "#{$url}/v2/search/entitlements?query='id=#{entitlement_id}''", $token )
19
+
20
+ case response
21
+ when Net::HTTPSuccess
22
+
23
+ entitlements = JSON.parse( response.body )
24
+
25
+ entitlements.each do |entitlement|
26
+ if (entitlementNames != "")
27
+ entitlementNames << ";"
28
+ end
29
+ entitlementNames << entitlement['name']
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ return entitlementNames
36
+ end
37
+
38
+ #
39
+ # Exports Access Profile configurations.
40
+ #
41
+ def self.export( directory )
42
+
43
+ response = IDNAPI.get( "#{$url}/cc/api/accessProfile/list", $token )
44
+
45
+ case response
46
+ when Net::HTTPSuccess
47
+
48
+ accessProfiles = JSON.parse( response.body )
49
+
50
+ $log.info "\tDetected #{accessProfiles['count']} access profiles."
51
+
52
+ accessProfiles['items'].each do |accessProfile|
53
+
54
+ $log.info "\tAccess Profile: #{accessProfile["name"]}"
55
+
56
+ accessProfile['entitlementNames'] = AccessProfiles.getEntitlements( accessProfile['entitlements'] )
57
+
58
+ Program.write_file( "#{directory}/access-profiles/", "Access Profile - #{accessProfile["name"]}.json", JSON.pretty_generate( accessProfile ) )
59
+
60
+ end # transforms["items"].each do |transform|
61
+
62
+ else
63
+ $log.error "\tError: Unable to fetch access profiles."
64
+ end # case response
65
+
66
+ end # def self.export( directory )
67
+
68
+ #
69
+ # Imports Access Profile configurations.
70
+ #
71
+ def self.import( directory )
72
+ $log.warn "\tImport for object type access-profiles is not supported at this time."
73
+ end
74
+
75
+ #
76
+ # Documents Access Profile configurations.
77
+ #
78
+ def self.doc
79
+
80
+ response = IDNAPI.get( "#{$url}/cc/api/accessProfile/list", $token )
81
+
82
+ case response
83
+ when Net::HTTPSuccess
84
+
85
+ accessProfiles = JSON.parse( response.body )
86
+
87
+ $log.info "\tDetected #{accessProfiles['count']} access profiles."
88
+
89
+ Markdown.h2( "Access Profiles" )
90
+ Markdown.text( "| Name | Description | Entitlements | Requestable |\n")
91
+ Markdown.text( "|------|-------------|--------------|-------------|\n")
92
+
93
+ accessProfiles['items'].each do |accessProfile|
94
+
95
+ $log.info "\tAccess Profile: #{accessProfile["name"]}"
96
+ Markdown.text( "|#{accessProfile["name"]}|#{accessProfile["description"]}|#{accessProfile["sourceName"]}: #{AccessProfiles.getEntitlements(accessProfile["entitlements"])}|#{accessProfile["requestable"]}|\n")
97
+
98
+ end # transforms["items"].each do |transform|
99
+
100
+ else
101
+ $log.error "\tError: Unable to fetch access profiles."
102
+ end # case response
103
+
104
+ Markdown.write
105
+ end # def self.doc
106
+
107
+ end
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ require "json"
3
+ require "uri"
4
+ require "idnio/idnapi"
5
+ require "idnio/program"
6
+ require "idnio/markdown"
7
+
8
+ module AccessRequestConfig
9
+
10
+ #
11
+ # Exports Access Request Config
12
+ #
13
+ def self.export( directory )
14
+
15
+ response = IDNAPI.get( "#{$url}/beta/access-request-config/", $token )
16
+ case response
17
+ when Net::HTTPSuccess
18
+ $log.info "\tRetreived configuration."
19
+ config = JSON.parse( response.body )
20
+ Program.write_file( "#{directory}/access-request-config/", "access-request-config.json", JSON.pretty_generate( config ) )
21
+ else
22
+ $log.error "\tUnable to retreive configuration."
23
+ end
24
+
25
+ end
26
+
27
+ #
28
+ # Imports Access Request Config
29
+ #
30
+ def self.import( directory )
31
+
32
+ # Read from the file system to determine how many configs we have. We should really only have one.
33
+ configs = Program.read_directory( "#{directory}/access-request-config/" )
34
+ $log.info "\tRetreived configuration."
35
+
36
+ # Iterate through each transform.
37
+ configs.each do |config|
38
+
39
+ $log.debug "\tResolving fallback approver..."
40
+
41
+ unless config['approvalReminderAndEscalationConfig']['fallbackApproverRef'].nil? || config['approvalReminderAndEscalationConfig']['fallbackApproverRef']['name'].nil?
42
+ config['approvalReminderAndEscalationConfig']['fallbackApproverRef'] = ReferenceResolver.get_identity_ref( config['approvalReminderAndEscalationConfig']['fallbackApproverRef']['name'] )
43
+ end
44
+
45
+ $log.debug "\tImporting access request config..."
46
+
47
+ response = IDNAPI.put_json( "#{$url}/beta/access-request-config/", $token, JSON.parse( config ) )
48
+
49
+ case response
50
+ when Net::HTTPSuccess
51
+ $log.info "\tUpdated access request config."
52
+ else
53
+ $log.error "\tUnable to import access request config."
54
+ end
55
+ end
56
+ end
57
+
58
+ #
59
+ # Documents Access Request Config
60
+ #
61
+ def self.doc
62
+
63
+ Markdown.h2( "Access Request Config" )
64
+
65
+ response = IDNAPI.get( "#{$url}/beta/access-request-config/", $token )
66
+ case response
67
+ when Net::HTTPSuccess
68
+ $log.info "\tRetreived configuration."
69
+
70
+ config = JSON.parse( response.body )
71
+
72
+ Markdown.h3( "Request Settings" )
73
+ Markdown.text "- Allow requests on behalf of anyone, by anyone: #{config['requestOnBehalfOfConfig']['allowRequestOnBehalfOfAnyoneByAnyone']}\n"
74
+ Markdown.text "- Allow requests on behalf of employees, by manager: #{config['requestOnBehalfOfConfig']['allowRequestOnBehalfOfEmployeeByManager']}\n"
75
+
76
+ Markdown.h3( "Approval and Reminders" )
77
+ Markdown.text "- Days until escalation: #{config['approvalReminderAndEscalationConfig']['daysUntilEscalation']}\n"
78
+ Markdown.text "- Days between reminders: #{config['approvalReminderAndEscalationConfig']['daysBetweenReminders']}\n"
79
+ Markdown.text "- Maximum reminders: #{config['approvalReminderAndEscalationConfig']['maxReminders']}\n"
80
+ unless config['approvalReminderAndEscalationConfig']['fallbackApproverRef'].nil?
81
+ Markdown.text "- Fallback approver: #{config['approvalReminderAndEscalationConfig']['fallbackApproverRef']['name']}\n"
82
+ end
83
+
84
+ else
85
+ $log.error "\tUnable to retreive configuration."
86
+ end
87
+
88
+ Markdown.write
89
+ end
90
+ end
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env ruby
2
+ require "json"
3
+ require "idnio/idnapi"
4
+ require "idnio/program"
5
+ require "idnio/markdown"
6
+
7
+ module AccountProfiles
8
+
9
+ #
10
+ # Exports Account Profile configurations.
11
+ #
12
+ def self.export( directory )
13
+
14
+ response = IDNAPI.get( "#{$url}/cc/api/source/list", $token )
15
+
16
+ case response
17
+ when Net::HTTPSuccess
18
+
19
+ sources = JSON.parse( response.body )
20
+
21
+ $log.info "\tDetected #{sources.count} account profiles, across #{sources.count} sources."
22
+
23
+ sources.each do |source|
24
+
25
+ response = IDNAPI.get( "#{$url}/cc/api/accountProfile/list/#{source["id"]}", $token )
26
+
27
+ case response
28
+ when Net::HTTPSuccess
29
+
30
+ accountProfiles = JSON.parse( response.body )
31
+
32
+ accountProfiles.each do |accountProfile|
33
+
34
+ $log.info "\tAccount Profile: #{source["name"]} - #{accountProfile["name"]} - #{accountProfile["usage"]}"
35
+ Program.write_file( "#{directory}/account-profiles/", "Account Profile - #{source["name"]} - #{accountProfile["name"]} - #{accountProfile["usage"]}.json", JSON.pretty_generate( accountProfile ) )
36
+
37
+ end # accountProfiles.each do |accountProfile|
38
+
39
+ else
40
+ $log.error "\tError: Unable to fetch account profile for source #{source["name"]}."
41
+ end # case response
42
+
43
+ end # sources.each do |source|
44
+
45
+ else
46
+ $log.error "\tError: Unable to fetch sources, for account profiles."
47
+ end # case response
48
+
49
+ end # def self.export( directory )
50
+
51
+ #
52
+ # Imports Account Profile configurations.
53
+ #
54
+ def self.import( directory )
55
+
56
+ #
57
+ # Read from the file system to determine how many account profiles we have.
58
+ #
59
+ objects = []
60
+ Dir.glob("#{directory}/account-profiles/*.json").each do |file|
61
+ object = {
62
+ "file" => file,
63
+ "source" => File.basename( file, ".json" ).split(/\W?-\W?/)[1],
64
+ "name" => File.basename( file, ".json" ).split(/\W?-\W?/)[2],
65
+ "usage" => File.basename( file, ".json" ).split(/\W?-\W?/)[3]
66
+ }
67
+ objects.push( object )
68
+ end
69
+
70
+ $log.info "\tDetected #{objects.count} account profiles."
71
+
72
+ #
73
+ # Iterate through each account profile.
74
+ #
75
+ objects.each do |object|
76
+
77
+ $log.info "\tAccount Profile: #{object['source']} - #{object['name']} - #{object['usage']}"
78
+
79
+ #
80
+ # Get the account profile JSON.
81
+ #
82
+ template_account_profile = JSON.parse( File.read( object['file'] ) )
83
+
84
+ #
85
+ # Lookup the existing source.
86
+ #
87
+ existing_source_id = Sources.get_cc_id( object['source'] )
88
+
89
+ unless existing_source_id.nil? || template_account_profile.nil?
90
+
91
+ $log.debug "\t\tUpdating account profile..."
92
+
93
+ IDNAPI.post_json( "#{$url}/cc/api/accountProfile/update/#{existing_source_id}?usage=#{object['usage']}", $token, template_account_profile )
94
+
95
+ $log.info "\t\tUpdate complete."
96
+
97
+ else
98
+ $log.warn "\t\tSkipping account profile creation. Source [#{object['source']}] does not exist.\n"
99
+ end
100
+
101
+ end
102
+
103
+ end
104
+
105
+ #
106
+ # Documents Account Profile configurations.
107
+ #
108
+ def self.doc
109
+
110
+ response = IDNAPI.get( "#{$url}/cc/api/source/list", $token )
111
+
112
+ case response
113
+ when Net::HTTPSuccess
114
+
115
+ sources = JSON.parse( response.body )
116
+
117
+ $log.info "\tDetected #{sources.count} account profiles, across #{sources.count} sources."
118
+
119
+ Markdown.h2( "Account Profiles" )
120
+
121
+ sources.each do |source|
122
+
123
+ response = IDNAPI.get( "#{$url}/cc/api/accountProfile/list/#{source["id"]}", $token )
124
+
125
+ case response
126
+ when Net::HTTPSuccess
127
+
128
+ accountProfiles = JSON.parse( response.body )
129
+
130
+ accountProfiles.each do |accountProfile|
131
+
132
+ $log.info "\tAccount Profile: #{source["name"]} - #{accountProfile["name"]} - #{accountProfile["usage"]}"
133
+ Markdown.h3 "#{source["name"]} #{accountProfile["usage"]} #{accountProfile["name"]}"
134
+ Markdown.text " - Name: #{accountProfile["name"]}\n"
135
+ Markdown.text " - Description: #{accountProfile["description"]}\n"
136
+ Markdown.text " - Usage: #{accountProfile["usage"]}\n"
137
+ Markdown.text " - Enabled: #{accountProfile["validPolicy"]}\n"
138
+
139
+ unless accountProfile["usage"].nil? || accountProfile["usage"].empty?
140
+
141
+ Markdown.text "| Name | Type | Required | Multi-valued | Transform |\n"
142
+ Markdown.text "|------|------|----------|--------------|-----------|\n"
143
+
144
+ accountProfile["fields"].each do |field|
145
+
146
+ Markdown.text "|#{field['name']}|#{field['type']}|#{field['isRequired']}|#{field['multi']}|#{field['transform']}|\n"
147
+
148
+ end # accountProfile["fields"].each do |field|
149
+
150
+ end # unless accountProfile["usage"].nil? ...
151
+
152
+ end # accountProfiles.each do |accountProfile|
153
+
154
+ else
155
+ $log.error "\tError: Unable to fetch account profile for source #{source["name"]}."
156
+ end # case response
157
+
158
+ end # sources.each do |source|
159
+
160
+ else
161
+ $log.error "\tError: Unable to fetch sources, for account profiles."
162
+ end # case response
163
+
164
+ Markdown.write
165
+ end
166
+
167
+ end
@@ -0,0 +1,341 @@
1
+ #!/usr/bin/env ruby
2
+ require 'json'
3
+ require "idnio/idnapi"
4
+ require "idnio/program"
5
+ require "idnio/markdown"
6
+
7
+ module AccountSchemas
8
+
9
+ @@account_schema_cache = {}
10
+
11
+ def self.get_existing_schema_attribute( id, attribute_name )
12
+
13
+ unless id.nil? || attribute_name.nil?
14
+
15
+ existing_account_schema = AccountSchemas.get_by_id( id )
16
+
17
+ unless existing_account_schema.nil?
18
+
19
+ existing_account_schema['attributes'].each do |existing_attribute|
20
+
21
+ if existing_attribute['name'] == attribute_name
22
+ return existing_attribute
23
+ end # existing_attribute['name'] == attribute_name
24
+
25
+ end # existing_account_schema['attributes'].each do |existing_attribute|
26
+
27
+ end # unless existing_account_schema.nil?
28
+
29
+ end # unless id.nil? || attribute_name.nil?
30
+
31
+ return nil
32
+ end
33
+
34
+ def self.get_by_id( id )
35
+
36
+ unless @@account_schema_cache.key?( id )
37
+
38
+ response = IDNAPI.get( "#{$url}/cc/api/source/getAccountSchema/#{id}", $token )
39
+
40
+ case response
41
+ when Net::HTTPSuccess
42
+ @@account_schema_cache[id] = JSON.parse( response.body )
43
+ else
44
+ @@account_schema_cache[id] = nil
45
+ end
46
+
47
+ end
48
+
49
+ return @@account_schema_cache[id]
50
+ end
51
+
52
+ #
53
+ # Creates a Schema Attribute
54
+ #
55
+ def self.create( id, attribute )
56
+
57
+ $log.debug "\t\t\tCreating attribute."
58
+
59
+ form_data = {
60
+ 'name' => attribute['name'],
61
+ 'description' => attribute['description'],
62
+ 'type' => attribute['type'],
63
+ 'objectType' => 'account',
64
+ 'entitlement' => attribute['entitlement'],
65
+ 'identityAttribute' => attribute['identityAttribute'],
66
+ 'managed' => attribute['managed'],
67
+ 'multi' => attribute['multi'],
68
+ 'displayAttribute' => attribute['displayAttribute']
69
+ }
70
+
71
+ response = IDNAPI.post_form( "#{$url}/cc/api/source/createSchemaAttribute/#{id}", $token, form_data )
72
+
73
+ case response
74
+ when Net::HTTPSuccess
75
+ $log.debug "\t\tAttribute [#{attribute['name']}] successfully created."
76
+ else
77
+ $log.debug "\t\tError: Attribute [#{attribute['name']}] could not be successfully created."
78
+ end
79
+ end
80
+
81
+ #
82
+ # Updates a Schema Attribute
83
+ #
84
+ def self.update( id, attribute )
85
+
86
+ $log.debug "\t\t\tUpdating attribute."
87
+
88
+ existing_attribute = AccountSchemas.get_existing_schema_attribute( id, attribute['name'] )
89
+
90
+ #
91
+ # The API only supports updating certain properties of an attribute. The descriptions, name, type cannot be updated.
92
+ #
93
+
94
+ # Check 'entitlement's
95
+ unless ( attribute['entitlement'] == existing_attribute['entitlement'] )
96
+
97
+ form_data = {
98
+ 'objectType': 'account',
99
+ 'names': existing_attribute['name'],
100
+ 'fieldName': 'entitlement',
101
+ 'fieldValue': attribute['entitlement']
102
+ }
103
+
104
+ response = IDNAPI.post_form( "#{$url}/cc/api/source/updateSchemaAttributes/#{id}", $token, form_data )
105
+
106
+ case response
107
+ when Net::HTTPSuccess
108
+ $log.debug "\t\t\tAttribute [#{attribute['name']}] updated 'entitlement' property."
109
+ else
110
+ $log.debug "\t\tError: Attribute [#{attribute['name']}] could not update 'entitlement' property."
111
+ end
112
+
113
+ end # unless ( attribute['entitlement'] == existing_attribute['entitlement'] )
114
+
115
+ # Check 'managed'
116
+ unless ( attribute['managed'] == existing_attribute['managed'] )
117
+
118
+ form_data = {
119
+ 'objectType': 'account',
120
+ 'names': existing_attribute['name'],
121
+ 'fieldName': 'managed',
122
+ 'fieldValue': attribute['managed']
123
+ }
124
+
125
+ response = IDNAPI.post_form( "#{$url}/cc/api/source/updateSchemaAttributes/#{id}", $token, form_data )
126
+ s
127
+ case response
128
+ when Net::HTTPSuccess
129
+ $log.debug "\t\t\tAttribute [#{attribute['name']}] updated 'managed' property."
130
+ else
131
+ $log.debug "\t\tError: Attribute [#{attribute['name']}] could not update 'managed' property."
132
+ end
133
+
134
+ end # unless ( attribute['managed'] == existing_attribute['managed'] )
135
+
136
+ # Check 'multi'
137
+ unless ( attribute['multi'] == existing_attribute['multi'] )
138
+
139
+ form_data = {
140
+ 'objectType': 'account',
141
+ 'names': existing_attribute['name'],
142
+ 'fieldName': 'multi',
143
+ 'fieldValue': attribute['multi']
144
+ }
145
+
146
+ response = IDNAPI.post_form( "#{$url}/cc/api/source/updateSchemaAttributes/#{id}", $token, form_data )
147
+
148
+ case response
149
+ when Net::HTTPSuccess
150
+ $log.debug "\t\t\tAttribute [#{attribute['name']}] updated 'multi' property."
151
+ else
152
+ $log.debug "\t\tError: Attribute [#{attribute['name']}] could not update 'multi' property."
153
+ end
154
+
155
+ end # unless ( attribute['multi'] == existing_attribute['multi'] )
156
+
157
+ # Check 'displayAttribute'
158
+ unless ( attribute['displayAttribute'] == existing_attribute['displayAttribute'] )
159
+
160
+ form_data = {
161
+ 'objectType': 'account',
162
+ 'names': existing_attribute['name'],
163
+ 'fieldName': 'displayAttribute',
164
+ 'fieldValue': attribute['displayAttribute']
165
+ }
166
+
167
+ response = IDNAPI.post_form( "#{$url}/cc/api/source/updateSchemaAttributes/#{id}", $token, form_data )
168
+
169
+ case response
170
+ when Net::HTTPSuccess
171
+ $log.debug "\t\t\tAttribute [#{attribute['name']}] updated 'displayAttribute' property."
172
+ else
173
+ $log.debug "\t\tError: Attribute [#{attribute['name']}] could not update 'displayAttribute' property."
174
+ end
175
+
176
+ end # unless ( attribute['displayAttribute'] == existing_attribute['displayAttribute'] )
177
+
178
+ # Check 'identityAttribute'
179
+ unless ( attribute['identityAttribute'] == existing_attribute['identityAttribute'] )
180
+
181
+ form_data = {
182
+ 'objectType': 'account',
183
+ 'names': existing_attribute['name'],
184
+ 'fieldName': 'identityAttribute',
185
+ 'fieldValue': attribute['identityAttribute']
186
+ }
187
+
188
+ response = IDNAPI.post_form( "#{$url}/cc/api/source/updateSchemaAttributes/#{id}", $token, form_data )
189
+
190
+ case response
191
+ when Net::HTTPSuccess
192
+ $log.debug "\t\t\tAttribute [#{attribute['name']}] updated 'identityAttribute' property."
193
+ else
194
+ $log.debug "\t\tError: Attribute [#{attribute['name']}] could not update 'identityAttribute' property."
195
+ end
196
+
197
+ end # unless ( attribute['identityAttribute'] == existing_attribute['identityAttribute'] )
198
+
199
+ end
200
+
201
+ #
202
+ # Exports Account Schema configurations.
203
+ #
204
+ def self.export( directory )
205
+
206
+ response = IDNAPI.get("#{$url}/cc/api/source/list", $token)
207
+
208
+ case response
209
+ when Net::HTTPSuccess
210
+
211
+ sources = JSON.parse( response.body )
212
+
213
+ unless sources.nil?
214
+
215
+ $log.info "\tDetected #{sources.count} account schemas, across #{sources.count} sources."
216
+
217
+ sources.each do |source|
218
+
219
+ $log.info "\tAccount Schema: #{source['name']}"
220
+
221
+ response = IDNAPI.get( "#{$url}/cc/api/source/getAccountSchema/#{source['id']}", $token )
222
+
223
+ case response
224
+ when Net::HTTPSuccess
225
+
226
+ account_schema = JSON.parse( response.body )
227
+
228
+ Program.write_file("#{directory}/account-schemas/", "Account Schema - #{source['name']} - #{account_schema['objectType']}.json", JSON.pretty_generate( account_schema ) )
229
+
230
+ else
231
+ $log.error "\tError: Unable to fetch account schema for source '#{source['name']}'."
232
+ end # case response
233
+
234
+ end # sources.each do |source|
235
+
236
+ end # unless sources.nil?
237
+
238
+ else
239
+ $log.error "\tError: Unable to fetch sources."
240
+ end # case response
241
+
242
+ end
243
+
244
+ #
245
+ # Imports Account Schema configurations.
246
+ #
247
+ def self.import( directory )
248
+
249
+ # Read from the file system to determine how many account profiles we have.
250
+ objects = []
251
+ Dir.glob("#{directory}/account-schemas/*.json").each do |file|
252
+ object = {
253
+ "data" => file,
254
+ "source" => File.basename( file, ".json" ).split(" - ")[1],
255
+ "objectType" => File.basename( file, ".json" ).split(" - ")[2]
256
+ }
257
+ objects.push( object )
258
+ end
259
+
260
+ $log.info "\tDetected #{objects.count} account schemas."
261
+
262
+ objects.each do |object|
263
+
264
+ $log.info "\tAccount Schema: #{object['source']} - #{object['objectType']}"
265
+
266
+ existing_source_id = Sources.get_cc_id( object['source'] )
267
+
268
+ unless existing_source_id.nil?
269
+
270
+ data = Program.read_file( object['data'] )
271
+
272
+ unless data.nil?
273
+
274
+ account_schema = JSON.parse( data )
275
+
276
+ account_schema['attributes'].each do |attribute|
277
+
278
+ $log.debug "\t\tAnalyzing attribute [#{attribute['name']}]."
279
+
280
+ existing_attribute = AccountSchemas.get_existing_schema_attribute( existing_source_id, attribute['name'] ) # Get the existing attribute
281
+
282
+ unless attribute == existing_attribute
283
+
284
+ unless existing_attribute.nil?
285
+ AccountSchemas.update( existing_source_id, attribute ) # If the existing attribute is not-null, we'll update.
286
+ else
287
+ AccountSchemas.create( existing_source_id, attribute ) # If the existing attribute is null, we'll create.
288
+ end # unless existing_attribute.nil?
289
+
290
+ else
291
+ $log.debug "\t\t\tNo action to perform."
292
+ end # attribute == existing_attribute
293
+
294
+ end # account_schema['attributes'].each do |attribute|
295
+
296
+ end # unless data.nil?
297
+
298
+ end # unless existing_source_id.nil?
299
+
300
+ end # objects.each do |object|
301
+
302
+ end
303
+
304
+ #
305
+ # Documents Account Schema configurations.
306
+ #
307
+ def self.doc
308
+ Markdown.h2( "Account Schemas" )
309
+
310
+ response = IDNAPI.get( "#{$url}/cc/api/source/list", $token )
311
+ unless response.nil?
312
+ sources = JSON.parse( response.body )
313
+
314
+ $log.info "\tDetected #{sources.count} account schemas, across #{sources.count} sources."
315
+
316
+ sources.each do |source|
317
+
318
+ accountSchema = IDNAPI.get( "#{$url}/cc/api/source/getAccountSchema/#{source["id"]}", $token )
319
+ unless accountSchema.nil?
320
+ accountSchema = JSON.parse( accountSchema.body )
321
+ $log.info "\tAccount Schema: #{source["name"]} - #{accountSchema["objectType"]}"
322
+
323
+ unless ( accountSchema["attributes"].nil? || accountSchema["attributes"].empty? )
324
+ Markdown.h3( "#{source["name"]}" )
325
+ Markdown.text( " - Object Type: #{accountSchema["objectType"]}\n" )
326
+ Markdown.text( " - Account ID: #{accountSchema["identityAttribute"]}\n" )
327
+ Markdown.text( " - Account Name: #{accountSchema["displayAttribute"]}\n" )
328
+ Markdown.text( " - Group Attribute: #{accountSchema["groupAttribute"]}\n\n" )
329
+ Markdown.text( "| Name | Description | Type | Multi-valued | Entitlement |\n" )
330
+ Markdown.text( "|------|-------------|------|--------------|-------------|\n" )
331
+ accountSchema["attributes"].each do |attribute|
332
+ Markdown.text( "|#{attribute["name"]}|#{attribute["description"]}|#{attribute["type"]}|#{attribute["entitlement"]}|#{attribute["multi"]}|\n" )
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ Markdown.write
340
+ end
341
+ end