@@ -134,28 +134,56 @@ class CIS2Client:
134134class CIS2CLI :
135135 """Command-line interface for the CIS2 Connection Manager."""
136136
137+ # ANSI color codes
138+ BLUE = "\033 [94m"
139+ WHITE = "\033 [97m"
140+ GREEN = "\033 [92m"
141+ RED = "\033 [91m"
142+ RESET = "\033 [0m"
143+
137144 def __init__ (self ):
138145 self .client = CIS2Client ()
139146 self .last_config_hash : Optional [str ] = None
140147 self .last_config_id : Optional [str ] = None
141148
149+ def show_banner (self ):
150+ """Display the CLI tool banner."""
151+ print (
152+ f"""
153+ { self .BLUE } ╔═══════════════════════════════════════════════════════════════╗
154+ ║ ║
155+ ║{ self .WHITE } ███ ██ ██ ██ ███████ ██████ ██ ███████ ██████{ self .BLUE } ║
156+ ║{ self .WHITE } ████ ██ ██ ██ ██ ██ ██ ██ ██{ self .BLUE } ║
157+ ║{ self .WHITE } ██ ██ ██ ███████ ███████ ██ ██ ███████ █████{ self .BLUE } ║
158+ ║{ self .WHITE } ██ ██ ██ ██ ██ ██ ██ ██ ██ ██{ self .BLUE } ║
159+ ║{ self .WHITE } ██ ████ ██ ██ ███████ ██████ ██ ███████ ███████{ self .BLUE } ║
160+ ║ ║
161+ ║{ self .WHITE } Connection Manager CLI Tool { self .BLUE } ║
162+ ║ ║
163+ ╚═══════════════════════════════════════════════════════════════╝{ self .RESET }
164+ """
165+ )
166+ print ("=" * 40 )
167+
142168 def setup_credentials (self ):
143169 """Prompt user for secret and team ID, then authenticate."""
144170 # Get secret
145171 secret = getpass .getpass ("Enter your API secret: " )
146172 if not secret :
147- print (" Error: Secret is required" )
173+ print (f" { self . RED } Error: Secret is required{ self . RESET } " )
148174 sys .exit (1 )
149175
150176 # Authenticate
151177 try :
152- print (" Authenticating with CIS2..." )
178+ print (f" { self . BLUE } Authenticating with CIS2...{ self . RESET } " )
153179 auth_result = self .client .authenticate (secret )
154- print ("✓ Authentication successful " )
180+ print (f" { self . GREEN } ✓ Authenticated { self . RESET } " )
155181
156182 # Handle team ID selection
157183 if "team_ids" not in auth_result or not auth_result ["team_ids" ]:
158- print ("✗ Error: No team IDs available for this account" )
184+ print (
185+ f"{ self .RED } ✗ Error: No team IDs available for this account{ self .RESET } "
186+ )
159187 print (
160188 "Please contact your administrator to ensure your account has team access."
161189 )
@@ -175,7 +203,9 @@ class CIS2CLI:
175203 if 1 <= choice_num <= len (team_ids ):
176204 selected_team_id = team_ids [choice_num - 1 ]
177205 self .client .team_id = selected_team_id
178- print (f"✓ Team ID set to: { selected_team_id } " )
206+ print (
207+ f"{ self .GREEN } ✓ Team ID set to: { selected_team_id } { self .RESET } "
208+ )
179209 break
180210 else :
181211 print (
@@ -188,7 +218,7 @@ class CIS2CLI:
188218 sys .exit (1 )
189219
190220 except Exception as e :
191- print (f"✗ Authentication failed: { e } " )
221+ print (f"{ self . RED } ✗ Authentication failed: { e } { self . RESET } " )
192222 sys .exit (1 )
193223
194224 print ()
@@ -207,14 +237,18 @@ class CIS2CLI:
207237 """Display details of a specific configuration."""
208238 try :
209239 # First, get the list of available configurations
210- print (f"Fetching configs for team { self .client .team_id } ..." )
240+ print (
241+ f"{ self .BLUE } Fetching configs for team { self .client .team_id } ...{ self .RESET } "
242+ )
211243 configs_response = self .client .get_configs (self .client .team_id )
212244
213245 # Extract config IDs from the response
214246 config_ids = configs_response .get ("configs" , [])
215247
216248 if not config_ids :
217- print ("✗ Error: No configurations available for this team" )
249+ print (
250+ f"{ self .RED } ✗ Error: No configurations available for this team{ self .RESET } "
251+ )
218252 return
219253
220254 # Show numbered menu for selection
@@ -244,21 +278,23 @@ class CIS2CLI:
244278 return
245279
246280 # Fetch and display the selected configuration
247- print (f"Fetching config '{ selected_config_id } '..." )
281+ print (f"{ self . BLUE } Fetching config '{ selected_config_id } '...{ self . RESET } " )
248282 config = self .client .get_config (self .client .team_id , selected_config_id )
249283
250284 # Store config hash and ID for future updates
251285 if isinstance (config , dict ) and "hash" in config :
252286 self .last_config_hash = config ["hash" ]
253287 self .last_config_id = selected_config_id
254- print (f"✓ Cached hash for updates: { self .last_config_hash [:8 ]} ..." )
288+ print (
289+ f"{ self .GREEN } ✓ Cached hash for updates: { self .last_config_hash [:8 ]} ...{ self .RESET } "
290+ )
255291
256292 print (f"\n Configuration Details for '{ selected_config_id } ':" )
257293 print ("=" * 40 )
258294 print (json .dumps (config , indent = 2 ))
259295
260296 except Exception as e :
261- print (f"✗ Error displaying config: { e } " )
297+ print (f"{ self . RED } ✗ Error displaying config: { e } { self . RESET } " )
262298
263299 def create_config (self ):
264300 """Create a new configuration."""
@@ -268,14 +304,16 @@ class CIS2CLI:
268304
269305 client_name = input ("Enter client name: " ).strip ()
270306 if not client_name :
271- print (" Error: Client name is required" )
307+ print (f" { self . RED } Error: Client name is required{ self . RESET } " )
272308 return
273309
274310 redirect_uris_input = input (
275311 "Enter redirect URIs (comma-separated): "
276312 ).strip ()
277313 if not redirect_uris_input :
278- print ("Error: At least one redirect URI is required" )
314+ print (
315+ f"{ self .RED } Error: At least one redirect URI is required{ self .RESET } "
316+ )
279317 return
280318
281319 redirect_uris = [uri .strip () for uri in redirect_uris_input .split ("," )]
@@ -304,7 +342,9 @@ class CIS2CLI:
304342 "Enter JWKS URI (required for private_key_jwt): "
305343 ).strip ()
306344 if not jwks_uri :
307- print ("Error: JWKS URI is required when using private_key_jwt" )
345+ print (
346+ f"{ self .RED } Error: JWKS URI is required when using private_key_jwt{ self .RESET } "
347+ )
308348 return
309349
310350 jwks_uri_signing_algorithm = (
@@ -329,32 +369,34 @@ class CIS2CLI:
329369 payload ["jwks_uri_signing_algorithm" ] = jwks_uri_signing_algorithm
330370
331371 print ()
332- print (f"Creating config for team { self .client .team_id } ..." )
333- print ("Payload:" )
372+ print (
373+ f"{ self .BLUE } Creating config for team { self .client .team_id } ...{ self .RESET } "
374+ )
375+ print (f"{ self .BLUE } Payload:{ self .RESET } " )
334376 print (json .dumps (payload , indent = 2 ))
335377 print ()
336378
337379 result = self .client .create_config (self .client .team_id , payload )
338380
339- print (" ✓ Config created" )
381+ print (f" { self . GREEN } ✓ Config created{ self . RESET } " )
340382 print (json .dumps (result , indent = 2 ))
341383
342384 except Exception as e :
343- print (f"✗ Error creating config: { e } " )
385+ print (f"{ self . RED } ✗ Error creating config: { e } { self . RESET } " )
344386
345387 def update_config (self ):
346388 """Update an existing configuration."""
347389 # Check if we have a cached hash from displaying a config
348390 if not self .last_config_hash or not self .last_config_id :
349- print (" Error: No config hash available for update." )
391+ print (f" { self . RED } Error: No config hash available for update.{ self . RESET } " )
350392 print ("Please display a configuration first to cache its hash." )
351393 return
352394
353395 try :
354396 print ("Update existing configuration" )
355397 print ("-" * 30 )
356- print (f"Config: { self .last_config_id } " )
357- print (f"Hash: { self .last_config_hash [:8 ]} ..." )
398+ print (f"{ self . BLUE } Config: { self .last_config_id } { self . RESET } " )
399+ print (f"{ self . BLUE } Hash: { self .last_config_hash [:8 ]} ...{ self . RESET } " )
358400 print ()
359401
360402 print ("Enter the new client_config as JSON:" )
@@ -370,7 +412,7 @@ class CIS2CLI:
370412 json_lines .append (line )
371413
372414 if not json_lines :
373- print (" Error: JSON payload is required" )
415+ print (f" { self . RED } Error: JSON payload is required{ self . RESET } " )
374416 return
375417
376418 json_text = "\n " .join (json_lines )
@@ -379,13 +421,13 @@ class CIS2CLI:
379421 try :
380422 client_config = json .loads (json_text )
381423 except json .JSONDecodeError as e :
382- print (f"Error: Invalid JSON format - { e } " )
424+ print (f"{ self . RED } Error: Invalid JSON format - { e } { self . RESET } " )
383425 return
384426
385427 print (
386- f"Updating config '{ self .last_config_id } ' for team { self .client .team_id } ..."
428+ f"{ self . BLUE } Updating config '{ self .last_config_id } ' for team { self .client .team_id } ...{ self . RESET } "
387429 )
388- print (" Payload:" )
430+ print (f" { self . BLUE } Payload:{ self . RESET } " )
389431 print (json .dumps (client_config , indent = 2 ))
390432 print ()
391433
@@ -396,33 +438,36 @@ class CIS2CLI:
396438 self .last_config_hash ,
397439 )
398440
399- print (" ✓ Config updated" )
441+ print (f" { self . GREEN } ✓ Config updated{ self . RESET } " )
400442 print (json .dumps (result , indent = 2 ))
401443
402444 # Update the cached hash if provided in response
403445 if isinstance (result , dict ) and "hash" in result :
404446 self .last_config_hash = result ["hash" ]
405- print (f"✓ Cached new hash: { self .last_config_hash [:8 ]} ..." )
447+ print (
448+ f"{ self .GREEN } ✓ Cached new hash: { self .last_config_hash [:8 ]} ...{ self .RESET } "
449+ )
406450
407451 except Exception as e :
408- print (f"✗ Error updating config: { e } " )
452+ print (f"{ self . RED } ✗ Error updating config: { e } { self . RESET } " )
409453
410454 def re_authenticate (self ):
411455 """Re-authenticate with a new secret."""
412456 secret = getpass .getpass ("Enter your API secret: " )
413457 if not secret :
414- print (" Error: Secret is required" )
458+ print (f" { self . RED } Error: Secret is required{ self . RESET } " )
415459 return
416460
417461 try :
418- print (" Re-authenticating with CIS2..." )
462+ print (f" { self . BLUE } Re-authenticating with CIS2...{ self . RESET } " )
419463 self .client .authenticate (secret )
420- print (" ✓ Re-authenticated" )
464+ print (f" { self . GREEN } ✓ Re-authenticated{ self . RESET } " )
421465 except Exception as e :
422- print (f"✗ Re-authentication failed: { e } " )
466+ print (f"{ self . RED } ✗ Re-authentication failed: { e } { self . RESET } " )
423467
424468 def run (self ):
425469 """Run the CLI application."""
470+ self .show_banner ()
426471 # Initial setup
427472 self .setup_credentials ()
428473
0 commit comments