33import click
44from pandas import DataFrame
55from pandas import json_normalize
6+ from py42 .exceptions import Py42BadRequestError
67from py42 .exceptions import Py42NotFoundError
78
89from code42cli .bulk import generate_template_cmd_factory
@@ -215,6 +216,8 @@ def reactivate(state, username):
215216
216217_bulk_user_roles_headers = ["username" , "role_name" ]
217218
219+ _bulk_user_alias_headers = ["username" , "alias" ]
220+
218221
219222@users .command (name = "move" )
220223@username_option ("The username of the user to move." , required = True )
@@ -226,6 +229,37 @@ def change_organization(state, username, org_id):
226229 _change_organization (state .sdk , username , org_id )
227230
228231
232+ @users .command ()
233+ @click .argument ("username" )
234+ @click .argument ("alias" )
235+ @sdk_options ()
236+ def add_alias (state , username , alias ):
237+ """Add a cloud alias for a given user."""
238+ _add_cloud_alias (state .sdk , username , alias )
239+
240+
241+ @users .command ()
242+ @click .argument ("username" )
243+ @click .argument ("alias" )
244+ @sdk_options ()
245+ def remove_alias (state , username , alias ):
246+ """Remove a cloud alias for a given user."""
247+ _remove_cloud_alias (state .sdk , username , alias )
248+
249+
250+ @users .command ()
251+ @click .argument ("username" )
252+ @sdk_options ()
253+ def list_aliases (state , username ):
254+ """List the cloud aliases for a given user."""
255+ user = _get_user (state .sdk , username )
256+ aliases = user ["cloudUsernames" ]
257+ if aliases :
258+ click .echo (aliases )
259+ else :
260+ click .echo (f"No cloud aliases for user '{ username } ' found." )
261+
262+
229263@users .group (cls = OrderedGroup )
230264@sdk_options (hidden = True )
231265def orgs (state ):
@@ -292,6 +326,8 @@ def bulk(state):
292326 commands_dict = {
293327 "update" : _bulk_user_update_headers ,
294328 "move" : _bulk_user_move_headers ,
329+ "add-alias" : _bulk_user_alias_headers ,
330+ "remove-alias" : _bulk_user_alias_headers ,
295331 },
296332 help_message = "Generate the CSV template needed for bulk user commands." ,
297333)
@@ -539,6 +575,86 @@ def handle_row(**row):
539575 formatter .echo_formatted_list (result_rows )
540576
541577
578+ @bulk .command (
579+ name = "add-alias" ,
580+ help = f"Add aliases to a list of users from the provided CSV in format: { ',' .join (_bulk_user_alias_headers )} " ,
581+ )
582+ @read_csv_arg (headers = _bulk_user_alias_headers )
583+ @format_option
584+ @sdk_options ()
585+ def bulk_add_alias (state , csv_rows , format ):
586+ """Bulk add aliases to users"""
587+
588+ # Initialize the SDK before starting any bulk processes
589+ # to prevent multiple instances and having to enter 2fa multiple times.
590+ sdk = state .sdk
591+ success_header = "alias added"
592+
593+ csv_rows [0 ][success_header ] = "False"
594+ formatter = OutputFormatter (format , {key : key for key in csv_rows [0 ].keys ()})
595+ stats = create_worker_stats (len (csv_rows ))
596+
597+ def handle_row (** row ):
598+ try :
599+ _add_cloud_alias (
600+ sdk , ** {key : row [key ] for key in row .keys () if key != success_header }
601+ )
602+ row [success_header ] = "True"
603+ except Exception as err :
604+ row [success_header ] = f"False: { err } "
605+ stats .increment_total_errors ()
606+ return row
607+
608+ result_rows = run_bulk_process (
609+ handle_row ,
610+ csv_rows ,
611+ progress_label = "Adding aliases to users:" ,
612+ stats = stats ,
613+ raise_global_error = False ,
614+ )
615+ formatter .echo_formatted_list (result_rows )
616+
617+
618+ @bulk .command (
619+ name = "remove-alias" ,
620+ help = f"Remove aliases from a list of users from the provided CSV in format: { ',' .join (_bulk_user_alias_headers )} " ,
621+ )
622+ @read_csv_arg (headers = _bulk_user_alias_headers )
623+ @format_option
624+ @sdk_options ()
625+ def bulk_remove_alias (state , csv_rows , format ):
626+ """Bulk remove aliases from users"""
627+
628+ # Initialize the SDK before starting any bulk processes
629+ # to prevent multiple instances and having to enter 2fa multiple times.
630+ sdk = state .sdk
631+ success_header = "alias removed"
632+
633+ csv_rows [0 ][success_header ] = "False"
634+ formatter = OutputFormatter (format , {key : key for key in csv_rows [0 ].keys ()})
635+ stats = create_worker_stats (len (csv_rows ))
636+
637+ def handle_row (** row ):
638+ try :
639+ _remove_cloud_alias (
640+ sdk , ** {key : row [key ] for key in row .keys () if key != success_header }
641+ )
642+ row [success_header ] = "True"
643+ except Exception as err :
644+ row [success_header ] = f"False: { err } "
645+ stats .increment_total_errors ()
646+ return row
647+
648+ result_rows = run_bulk_process (
649+ handle_row ,
650+ csv_rows ,
651+ progress_label = "Removing aliases from users:" ,
652+ stats = stats ,
653+ raise_global_error = False ,
654+ )
655+ formatter .echo_formatted_list (result_rows )
656+
657+
542658def _add_user_role (sdk , username , role_name ):
543659 user_id = _get_legacy_user_id (sdk , username )
544660 _get_role_id (sdk , role_name ) # function provides role name validation
@@ -666,3 +782,21 @@ def _deactivate_user(sdk, username):
666782def _reactivate_user (sdk , username ):
667783 user_id = _get_legacy_user_id (sdk , username )
668784 sdk .users .reactivate (user_id )
785+
786+
787+ def _get_user (sdk , username ):
788+ # use when retrieving the user information from the detectionlists module
789+ try :
790+ return sdk .detectionlists .get_user (username ).data
791+ except Py42BadRequestError :
792+ raise UserDoesNotExistError (username )
793+
794+
795+ def _add_cloud_alias (sdk , username , alias ):
796+ user = _get_user (sdk , username )
797+ sdk .detectionlists .add_user_cloud_alias (user ["userId" ], alias )
798+
799+
800+ def _remove_cloud_alias (sdk , username , alias ):
801+ user = _get_user (sdk , username )
802+ sdk .detectionlists .remove_user_cloud_alias (user ["userId" ], alias )
0 commit comments