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,345 @@
1
+ require 'fileutils'
2
+ #
3
+ # Markdown Writing Utility
4
+ #
5
+ module Markdown
6
+
7
+ @@buffer = ""
8
+ @@file = nil
9
+
10
+
11
+
12
+ # private_class_method :new
13
+
14
+ #def self.open( file )
15
+ # open( file )
16
+ #end
17
+
18
+ def self.open( file )
19
+ @@file = file
20
+ if File.exist?( @@file )
21
+ FileUtils.rm_f( @@file )
22
+ end
23
+
24
+ FileUtils.mkdir_p File.dirname( file )
25
+ end
26
+
27
+ def self.toc
28
+ text = "\n[TOC]\n"
29
+ @@buffer << text
30
+ return text
31
+ end
32
+
33
+ def self.strong( text )
34
+ text = "**#{text}**"
35
+ @@buffer << text
36
+ return text
37
+ end
38
+
39
+ def self.h1( text )
40
+ text = "\n# #{text}\n"
41
+ @@buffer << text
42
+ return text
43
+ end
44
+
45
+ def self.h2( text )
46
+ text = "\n## #{text}\n"
47
+ @@buffer << text
48
+ return text
49
+ end
50
+
51
+ def self.h3( text )
52
+ text = "\n### #{text}\n"
53
+ @@buffer << text
54
+ return text
55
+ end
56
+
57
+ def self.h4( text )
58
+ text = "\n#### #{text}\n"
59
+ @@buffer << text
60
+ return text
61
+ end
62
+
63
+ def self.h5( text )
64
+ text = "\n##### #{text}\n"
65
+ @@buffer << text
66
+ return text
67
+ end
68
+
69
+ def self.link( link, label )
70
+ text = "[#{label}](#{link})"
71
+ @@buffer << text
72
+ return text
73
+ end
74
+
75
+ def self.image( file, alt_text )
76
+ text = "\n![#{alt_text}](#{file})\n"
77
+ @@buffer << text
78
+ return text
79
+ end
80
+
81
+ def self.code( text )
82
+ text = "\n~~~\n#{text}\n~~~\n"
83
+ @@buffer << text
84
+ return text
85
+ end
86
+
87
+ def self.json( text )
88
+ text = "\n~~~json\n#{text}\n~~~\n"
89
+ @@buffer << text
90
+ return text
91
+ end
92
+
93
+ def self.xml( text )
94
+ text = "\n~~~xml\n#{text}\n~~~\n"
95
+ @@buffer << text
96
+ return text
97
+ end
98
+
99
+ def self.text( text )
100
+ text = "#{text}"
101
+ @@buffer << text
102
+ return text
103
+ end
104
+
105
+ def self.line( text )
106
+ text = "\n***\n"
107
+ @@buffer << text
108
+ return text
109
+ end
110
+
111
+ def self.ul( list )
112
+ text = ""
113
+ list.each do |item|
114
+ text << "- #{item}\n"
115
+ end
116
+ @@buffer << text
117
+ return text
118
+ end
119
+
120
+ def self.ul2( list )
121
+ text = ""
122
+ list.each do |item|
123
+ text << "\t- #{item}\n"
124
+ end
125
+ @@buffer << text
126
+ return text
127
+ end
128
+
129
+ def self.ol( list )
130
+ text = ""
131
+ list.each_with_index do |item, index|
132
+ output << "#{index + 1}. #{item}\n"
133
+ end
134
+ @@buffer << text
135
+ return text
136
+ end
137
+
138
+ # Generate a Markdown table.
139
+ # labels and data are one and two-dimensional arrays, respectively.
140
+ # All input must have a to_s method.
141
+ # Pass align: 'l' for left alignment or 'r' for right alignment. Anything
142
+ # else will result in cells being centered. Pass an array of align values
143
+ # to specify alignment per column.
144
+ # If is_rows is true, then each sub-array of data represents a row.
145
+ # Conversely, if is_rows is false, each sub-array of data represents a column.
146
+ # Empty cells can be given with nil or an empty string.
147
+ def self.make_table(labels, data, align: '', is_rows: false)
148
+ validate(labels, data, align, is_rows)
149
+
150
+ # Deep copy the arguments so we don't mutate the originals.
151
+ labels = Marshal.load(Marshal.dump(labels))
152
+ data = Marshal.load(Marshal.dump(data))
153
+
154
+ # Remove any breaking Markdown characters.
155
+ labels.map! {|label| sanitize(label)}
156
+ data.map! {|datum| datum.map {|cell| sanitize(cell)}}
157
+
158
+ # Convert align to something that other methods won't need to validate.
159
+ align.class == String && align = [align] * labels.length
160
+ align.map! {|a| a =~ /[lr]/i ? a.downcase : 'c'}
161
+
162
+ # Generate the column labels and alignment line.
163
+ header_line = labels.join('|')
164
+ alignment_line = parse_alignment(align, labels.length)
165
+
166
+ # Pad the data arrays so that it can be transposed if necessary.
167
+ max_len = data.map(&:length).max
168
+ data.map! {|datum| fill(datum, max_len)}
169
+
170
+ # Generate the table rows.
171
+ rows = (is_rows ? data : data.transpose).map {|row| row.join('|')}
172
+
173
+ text = [header_line, alignment_line, rows.join("\n")].join("\n")
174
+ @@buffer << text
175
+ return text
176
+ end
177
+
178
+ # Convert a Markdown table into human-readable form.
179
+ # def self.plain_text( md_table )
180
+ # md_table !~ // && raise('Invalid input')
181
+ #
182
+ # # Split the table into lines to get the labels, rows, and alignments.
183
+ # lines = md_table.split("\n")
184
+ # alignments = lines[1].split('|')
185
+ # # labels or rows might have some empty values but alignments
186
+ # # is guaranteed to be of the right width.
187
+ # table_width = alignments.length
188
+ # # '|||'.split('|') == [], so we need to manually add trailing empty cells.
189
+ # # Leading empty cells are taken care of automatically.
190
+ # labels = fill(lines[0].split('|'), table_width)
191
+ # rows = lines[2..-1].map {|line| fill(line.split('|'), table_width)}
192
+ #
193
+ # # Get the width for each column.
194
+ # cols = rows.transpose
195
+ # widths = cols.each_index.map {|i| column_width(cols[i].push(labels[i]))}
196
+ #
197
+ # # Align the labels and cells.
198
+ # labels = labels.each_index.map { |i|
199
+ # aligned_cell(unsanitize(labels[i]), widths[i], alignments[i])
200
+ # }
201
+ # rows.map! { |row|
202
+ # row.each_index.map { |i|
203
+ # aligned_cell(unsanitize(row[i]), widths[i], alignments[i])
204
+ # }
205
+ # }
206
+ #
207
+ # border = "\n|" + widths.map {|w| '=' * w}.join('|') + "|\n"
208
+ # return (
209
+ # border + [
210
+ # '|' + labels.join('|') + '|',
211
+ # rows.map {|row| '|' + row.join('|') + '|'}.join(border.tr('=', '-'))
212
+ # ].join(border) + border
213
+ # ).strip
214
+ #
215
+ # end
216
+
217
+ # Sanity checks for make_table.
218
+ private_class_method def self.validate(labels, data, align, is_rows)
219
+ if labels.class != Array
220
+ raise('labels must be an array')
221
+ end
222
+ if data.class != Array || data.any? {|datum| datum.class != Array}
223
+ raise('data must be a two-dimensional array')
224
+ end
225
+ if labels.empty?
226
+ raise('No column labels given')
227
+ end
228
+ if data.all? {|datum| datum.empty?}
229
+ raise('No cells given')
230
+ end
231
+ if labels.any? {|label| !label.respond_to?(:to_s)}
232
+ raise('One or more column labels cannot be made into a string')
233
+ end
234
+ if data.any? {|datum| datum.any? {|cell| !cell.respond_to?(:to_s)}}
235
+ raise('One or more cells cannot be made into a string')
236
+ end
237
+ if ![String, Array].include?(align.class)
238
+ raise('align must be a string or array')
239
+ end
240
+ if align.class == Array && align.any? {|val| val.class != String}
241
+ raise('One or more align values is not a string')
242
+ end
243
+ if !is_rows && data.length > labels.length
244
+ raise('Too many data columns given')
245
+ end
246
+ if is_rows && data.any? {|row| row.length > labels.length}
247
+ raise('One or more rows has too many cells')
248
+ end
249
+ end
250
+
251
+ # Convert some input to a string and replace any '|' characters with
252
+ # a non-breaking equivalent,
253
+ private_class_method def self.sanitize(input)
254
+ bar = '&#124;' # Non-breaking HTML vertical bar.
255
+ return input.to_s.gsub('|', bar)
256
+ end
257
+
258
+ # Replace non-breaking HTML characters with their plaintext counterparts.
259
+ private_class_method def self.unsanitize(input)
260
+ return input.gsub(/(&nbsp;)|(&#124;)/, '&nbsp;' => ' ', '&#124;' => '|')
261
+ end
262
+
263
+ # Generate the alignment line from a string or array.
264
+ # align must be a string or array of strings.
265
+ # n: number of labels in the table to be created.
266
+ private_class_method def self.parse_alignment(align, n)
267
+ align_map = {'l' => ':-', 'c' => ':-:', 'r' => '-:'}
268
+ alignments = align.map {|a| align_map[a]}
269
+ # If not enough values were given, center the remaining columns.
270
+ alignments.length < n && alignments += [':-:'] * (n - alignments.length)
271
+ return alignments.join('|')
272
+ end
273
+
274
+ # Align some text in a cell.
275
+ private_class_method def self.aligned_cell(text, width, align)
276
+ if align =~ /:-+:/ # Center alignment.
277
+ start = (width / 2) - (text.length / 2)
278
+ elsif align =~ /-+:/ # Right alignment.
279
+ start = width - text.length - 1
280
+ else # Left alignment.
281
+ start = 1
282
+ end
283
+ return ' ' * start + text + ' ' * (width - start - text.length)
284
+ end
285
+
286
+ # Get the width for a column.
287
+ private_class_method def self.column_width(col)
288
+ # Pad each cell on either side and maintain a minimum 3 width of characters.
289
+ return [(!col.empty? ? col.map(&:length).max : 0) + 2, 3].max
290
+ end
291
+
292
+ # Add any missing empty values to a row.
293
+ private_class_method def self.fill(row, n)
294
+ row.length > n && raise('Sanity checks failed for fill')
295
+ return row.length < n ? row + ([''] * (n - row.length)) : row
296
+ end
297
+
298
+ #
299
+ # Used to get the string buffer (if needed).
300
+ #
301
+ def self.get_buffer
302
+ return @@buffer
303
+ end
304
+
305
+ #
306
+ # Used to set the string buffer (if needed).
307
+ #
308
+ def self.set_buffer( new_buffer )
309
+ @@buffer = new_buffer
310
+ return @@buffer
311
+ end
312
+
313
+ #
314
+ # Replaces a string in the buffer.
315
+ #
316
+ def self.replace( lookups, replacement )
317
+
318
+ #
319
+ # Check to see if the lookups are an array;
320
+ # If yes, do all the replacements.
321
+ # If no, then only do the single replacement.
322
+ #
323
+ if lookups.kind_of?(Array)
324
+ lookups.each do |lookup|
325
+ @@buffer.gsub!( lookup, replacement )
326
+ end
327
+ else
328
+ @@buffer.gsub!( lookups, replacement )
329
+ end
330
+
331
+ #
332
+ # Return the string buffer
333
+ #
334
+ return @@buffer
335
+ end
336
+
337
+ #
338
+ # Write the string out to file; and clear the string buffer.
339
+ #
340
+ def self.write
341
+ File.open( @@file, 'a+') { |file| file.write( @@buffer ) }
342
+ @@buffer = ""
343
+ end
344
+
345
+ end
@@ -0,0 +1,153 @@
1
+ require 'idnio/timer'
2
+ require "json"
3
+ #
4
+ # Program Utility
5
+ #
6
+ module Program
7
+
8
+ def self.setConfig(config)
9
+
10
+ end
11
+
12
+ def self.line
13
+ $log.info "--------------------------------------------------------------"
14
+ end
15
+
16
+ #
17
+ # Utility method for printing messages.
18
+ #
19
+ def self.output( message )
20
+ Program.line
21
+ $log.info " #{message}"
22
+ Program.line
23
+ end
24
+
25
+ #
26
+ # Utility to start the program
27
+ #
28
+ def self.start( name, author, version, date )
29
+ Timer.start
30
+
31
+ $log.unknown "--------------------------------------------------------------"
32
+ $log.unknown " #{name}"
33
+ $log.unknown "--------------------------------------------------------------"
34
+ $log.unknown " Version: #{version}"
35
+ $log.unknown " Date: #{date}"
36
+ $log.unknown " Author: #{author}"
37
+ $log.unknown "--------------------------------------------------------------"
38
+
39
+ if $config.has_key?( 'tenant' )
40
+
41
+ $log.debug "Personal Access Token configuration detected. Using settings from 'tenant'."
42
+
43
+ $url = $config['tenant']['url']
44
+ $tenant = $config['tenant']['url'].clone.gsub!(/.api|https:\/\//,"")
45
+
46
+ $log.debug "Calling IdentityNow to get a JWT OAuth token..."
47
+
48
+ response = IDNAPI.post_unauth( "#{$url}/oauth/token?grant_type=client_credentials&client_id=#{$config['tenant']['client-id']}&client_secret=#{$config['tenant']['client-secret']}" )
49
+
50
+ case response
51
+ when Net::HTTPSuccess
52
+
53
+ session = JSON.parse( response.body )
54
+
55
+ if !session.nil? && session.has_key?( 'access_token' )
56
+ $token = session['access_token']
57
+ $log.debug "Session token: #{$token}"
58
+ else
59
+ $log.fatal "Error: Unable to parse session token from response. (#{response.code})"
60
+ abort
61
+ end
62
+
63
+ else
64
+ $log.fatal "Error: Unable to retreive session token. Please check 'tenant' configuration and try again. (#{response.code})"
65
+ abort
66
+ end
67
+
68
+ elsif $config.has_key?( 'session' )
69
+
70
+ $log.debug "Session configuration detected. Using settings from 'session'."
71
+
72
+ $tenant = $config['session']['baseUrl'].clone.gsub!(/.api|https:\/\//,"")
73
+ $url = $config['session']['baseUrl']
74
+ $token = $config['session']['accessToken']
75
+
76
+ $log.debug "Session token: #{$token}"
77
+
78
+ else
79
+
80
+ $log.fatal "Error: Configuration does not have details to retreive session. Please configure 'session' or 'tenant' settings."
81
+ abort
82
+
83
+ end
84
+
85
+ unless $tenant.nil?
86
+ $log.unknown " Tenant: #{$tenant}"
87
+ $log.unknown "--------------------------------------------------------------"
88
+ end
89
+
90
+ end
91
+
92
+ #
93
+ # Utility to end the program
94
+ #
95
+ def self.end( )
96
+ Timer.stop
97
+ output( "Process completed in #{Timer.elapsed}" )
98
+ end
99
+
100
+ #
101
+ # Utility method to write output files to a directory.
102
+ #
103
+ def self.write_file( directory, name, text )
104
+ name.gsub!(/[^0-9A-Za-z. -]/,"-")
105
+ FileUtils.mkdir_p directory
106
+ File.open( File.join( directory, name ), 'w+') { |file| file.write( text ) }
107
+ end
108
+
109
+ def self.get_filenames( directory )
110
+ output = Array.new
111
+ Dir.glob("#{directory}/*.json") do |file|
112
+ #tmp = file.slice! "#{directory}/"
113
+ output.push(file)
114
+ end
115
+ return output
116
+ end
117
+
118
+ def self.read_directory( directory )
119
+ output = Array.new
120
+ Dir.glob("#{directory}/*.json") do |file|
121
+ output.push(Program.read_file(file))
122
+ end
123
+ return output
124
+ end
125
+
126
+ #
127
+ # Utility method to read output files to a directory.
128
+ #
129
+ def self.read_file( directory, name )
130
+ return Program.read_file("#{directory}/#{name}")
131
+ end
132
+
133
+ def self.read_file( name )
134
+ output = ""
135
+ #name.gsub!(/[^0-9A-Za-z. -]/,"-")
136
+ f = File.open( name, 'r')
137
+ f.each_line do |line|
138
+ output += line
139
+ end
140
+ f.close
141
+ return output
142
+ end
143
+
144
+ def self.write_csv(directory, name, content)
145
+ if !File.file?("#{directory}/#{name}")
146
+ Program.write_file(directory, name, "")
147
+ end
148
+ CSV.open("#{directory}/#{name}", "ab") do |csv|
149
+ csv << content
150
+ end
151
+ end
152
+
153
+ end