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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/idnio.rb +295 -0
- data/lib/idnio/crypto.rb +34 -0
- data/lib/idnio/idnapi.rb +158 -0
- data/lib/idnio/markdown.rb +345 -0
- data/lib/idnio/program.rb +153 -0
- data/lib/idnio/timer.rb +57 -0
- data/lib/idnio/version.rb +4 -0
- data/lib/objects/access-profiles.rb +107 -0
- data/lib/objects/access-request-config.rb +90 -0
- data/lib/objects/account-profiles.rb +167 -0
- data/lib/objects/account-schemas.rb +341 -0
- data/lib/objects/applications.rb +145 -0
- data/lib/objects/attribute-sync-config.rb +122 -0
- data/lib/objects/branding.rb +49 -0
- data/lib/objects/campaign-filters.rb +61 -0
- data/lib/objects/connectors.rb +291 -0
- data/lib/objects/email-templates.rb +226 -0
- data/lib/objects/identity-attributes.rb +136 -0
- data/lib/objects/identity-profiles.rb +206 -0
- data/lib/objects/integrations.rb +149 -0
- data/lib/objects/lifecycle-states.rb +86 -0
- data/lib/objects/password-policies.rb +107 -0
- data/lib/objects/password-sync-groups.rb +100 -0
- data/lib/objects/public-identities-config.rb +78 -0
- data/lib/objects/reference-resolver.rb +137 -0
- data/lib/objects/roles.rb +117 -0
- data/lib/objects/rules.rb +198 -0
- data/lib/objects/sources.rb +217 -0
- data/lib/objects/system-settings.rb +185 -0
- data/lib/objects/transforms.rb +157 -0
- metadata +124 -0
- metadata.gz.sig +0 -0
data/lib/idnio/timer.rb
ADDED
@@ -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,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
|