idnio 2.3.2b

Sign up to get free protection for your applications and to get access to all the features.
@@ -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