def list_systems(ctx, system: str, mandant: int, user: str, customer: str, description: str, url: bool, verbose: bool, enum: bool) -> list: """ \b Print information about SAP systems \b \b Optional arguments: 1. System: Request a SAP system by system id 2. Mandant: Request a SAP system by mandant/client\n \b If no arguments - print information about all SAP systems from database """ result = "" with _sap_db(ctx.obj.config): sap_system_sql = Sap_system( str(system).upper() if system else None, str(mandant) if mandant else None, user if user else None, None, customer if customer else None, description if description else None, None) result = sap.query_system(sap_system_sql) if not result: no_system_found = Sap_system( str(system).upper() if system else "", str(mandant).zfill(3) if mandant else "", user.upper() if user else "", "", str(customer).upper() if customer else "", description.upper() if description else "", "") utilities.print_system_list( no_system_found, title="NOTHING FOUND according to search criteria", color=utilities.color_warning, ) return list() else: sap_system = [ Sap_system(item[0], item[1], item[2], ctx.obj.crypto.decrypto(item[3]), item[4], item[5], item[6]) for item in result ] utilities.print_system_list(*sap_system, title="Available systems", verbose=verbose, url=url, enum=enum) if verbose: click.echo( f"Information about passwords will be deleted from screen in {TIMER_TO_CLEAR_SCREEN}: \n" ) try: utilities.countdown(TIMER_TO_CLEAR_SCREEN) except KeyboardInterrupt: click.echo("Aborted!") click.clear() return sap_system
def test_update_record(db, added_record, crypto): system_updated = Sap_system(system='XXX', mandant='111', user='******', password=crypto.encrypto(str.encode('123')), customer='TEST_test', description='Development', url='') db.update(system_updated) result_lst = db.query_system( Sap_system(system='XXX', mandant='111', user='******')) assert Sap_system(*result_lst[0]) == system_updated
def add(ctx, system: str, mandant: str, user: str, password: str, description: str, customer: str, url: str, verbose: bool): """ Add sap system with it's parameters to db. Just run 'sap add' and follow instructions. """ with _sap_db(ctx.obj.config): encrypted_password = ctx.obj.crypto.encrypto(str.encode(password)) sap_system = Sap_system( str(system).upper(), str(mandant).zfill(3), str(user).upper(), encrypted_password, str(customer).upper(), str(description), str(url), ) result = sap.add(sap_system) if result is not None: click.echo( click.style( "Failed to add system to database ... \n", **utilities.color_sensitive, )) click.echo(result) else: sap_system = Sap_system( str(system).upper() if system else None, str(mandant) if mandant else None, user.upper() if user else None) result = sap.query_system(sap_system) added_system = [ Sap_system(item[0], item[1], item[2], ctx.obj.crypto.decrypto(item[3]), item[4], item[5], item[6]) for item in result ] utilities.print_system_list( *added_system, title="The following system is ADDED to the database: ", verbose=verbose) if verbose: click.echo( f"Information about passwords will be deleted from screen in {TIMER_TO_CLEAR_SCREEN}: \n" ) try: utilities.countdown(TIMER_TO_CLEAR_SCREEN) except KeyboardInterrupt: click.echo("Aborted!") click.clear()
def added_record(db, crypto): """ Add temporary record for testing purpose """ system = Sap_system(system='XXX', mandant='111', user='******', password=crypto.encrypto(str.encode('123')), customer='Test', description='Dev', url='') db.add(system) return system
def stat(ctx, system: str, mandant: str, user: str, customer: str, description: str, language: str): """ \b Displays 'System: status' window \n \b Optional arguments: 1. SYSTEM: Request a SAP system by system id 2. MANDANT: Request a SAP system by mandant/client """ query_result = ctx.invoke(list_systems, system=system, mandant=mandant, user=user, customer=customer, description=description, url=False, verbose=False, enum=True) # -------------------------- if query_result != []: selected_sap_systems = [ Sap_system(item[0], item[1], item[2], item[3], item[4], item[5], item[6]) for item in query_result ] if language is None: language = ctx.obj.config.language selected_system = utilities.choose_system(selected_sap_systems) try: argument = utilities.prepare_parameters_to_launch_system( selected_system, None, language, None, None, None, user, "", ctx.obj.config.command_line_path) except WrongPath as err: click.echo(f"{err}") raise click.Abort argument = argument + " -command=?STAT" + " -type=SystemCommand" utilities.print_system_list( selected_system, title="Opening STATUS of the following system") logger.info(f"{argument}") pop = Popen(argument) pop.wait() if pop.returncode: click.echo(pop.returncode, pop.communicate()[0])
def choose_system(sap_systems: list, verbose=False) -> Sap_system: ans = 0 if len(sap_systems) >= 2: # print_system_list(sap_systems, 'Available systems', verbose=verbose, enum=True) while int(ans) > len(sap_systems) or int(ans) < 1: if 1 <= int(ans) <= len(sap_systems): break click.echo() ans = click.prompt(click.style( f"\nChoose system you want to logon. Available values from 1 to {str(len(sap_systems))}: \n>>>", **color_message), type=int) ans = ans - 1 selected_system: Sap_system = Sap_system( sap_systems[ans].system, sap_systems[ans].mandant, sap_systems[ans].user, sap_systems[ans].password, sap_systems[ans].customer, sap_systems[ans].description, sap_systems[ans].url) return selected_system
def delete(ctx, system: str, mandant: str, user: str, customer: str, description: str, confirm: bool): """ \b Delete requested record about SAP system from database\n \b Optional arguments: 1. SYSTEM: Request a SAP system by system id 2. MANDANT: Request a SAP system by mandant/client """ query_result = ctx.invoke(list_systems, system=system, mandant=mandant, user=user, customer=customer, description=description, url=False, verbose=False, enum=True) # -------------------------- if query_result != []: selected_sap_systems = [ Sap_system(item[0], item[1], item[2], item[3], item[4], item[5], item[6]) for item in query_result ] selected_system = utilities.choose_system(selected_sap_systems) message = "Trying to DELETE the following systtem" utilities.print_system_list(selected_system, title=message) click.confirm(click.style('\nDo you really want to delete the system?', **utilities.color_sensitive), abort=True, default=confirm) system_to_delete = Sap_system( selected_system.system, selected_system.mandant, selected_system.user, selected_system.password, selected_system.customer, selected_system.description, selected_system.url) result = sap.delete(system_to_delete) result = sap.query_system(system_to_delete) if result == []: utilities.print_system_list( system_to_delete, title="The following system is DELETED from database") else: no_system_found = Sap_system( system.upper() if system else None, str(mandant).zfill(3) if mandant else None, user.upper() if user else None, None, customer.upper() if customer else None, description.upper() if description else None, None) utilities.print_system_list( no_system_found, title="FAILED TO UPDATE the following system", color=utilities.color_warning)
def update(ctx, system: str, mandant: str, user: str, customer: str, description: str, verbose: bool): """ \b Update password, customer, system description or url of the requested record from database\n \b Optional arguments: 1. SYSTEM: Request a SAP system by system id 2. MANDANT: Request a SAP system by mandant/client """ query_result = ctx.invoke(list_systems, system=system, mandant=mandant, user=user, customer=customer, description=description, url=False, verbose=False, enum=True) # -------------------------- if query_result != []: selected_sap_systems = [ Sap_system(item[0], item[1], item[2], item[3], item[4], item[5], item[6]) for item in query_result ] selected_system = utilities.choose_system(selected_sap_systems) password_new = click.prompt("\nEnter new password", default=selected_system.password) customer_new = click.prompt("Enter Customer", default=selected_system.customer) description_new = click.prompt("Enter system description", default=selected_system.description) url_new = click.prompt("Enter URL", default=selected_system.url) sap_encrypted_system = Sap_system( str(selected_system.system).upper(), str(selected_system.mandant).zfill(3), str(selected_system.user).upper(), ctx.obj.crypto.encrypto(str.encode(password_new)), str(customer_new), str(description_new), str(url_new), ) result = sap.update(sap_encrypted_system) if result is None: result = sap.query_system(sap_encrypted_system) updated_system = [ Sap_system(item[0], item[1], item[2], ctx.obj.crypto.decrypto(item[3]), item[4], item[5], item[6]) for item in result ] utilities.print_system_list( *updated_system, title="The following system is UPDATED", verbose=verbose) click.echo( f"Information about passwords will be deleted from screen in {TIMER_TO_CLEAR_SCREEN}: \n" ) try: utilities.countdown(TIMER_TO_CLEAR_SCREEN) except KeyboardInterrupt: click.echo("Aborted!") click.clear() else: no_system_found = Sap_system( system.upper() if system else None, str(mandant).zfill(3) if mandant else None, user.upper() if user else None, None, customer.upper() if customer else None, description.upper() if description else None, None) utilities.print_system_list( no_system_found, title="FAILED TO UPDATE the following system", color=utilities.color_warning)
def pw(ctx, system: str, mandant: int, user: str, customer: str, description: str, clear_clipboard: bool, time_to_clear: int): """ \b Copy password for the requested system into clipboard. Script waits 15 seconds and clears clipboard.\n \b Optional argument: 1. SYSTEM: Request a SAP system by system id 2. MANDANT: Request a SAP system by mandant/client """ query_result = ctx.invoke(list_systems, system=system, mandant=mandant, user=user, customer=customer, description=description, url=False, verbose=False, enum=True) # -------------------------- if query_result != []: selected_sap_systems = [ Sap_system(item[0], item[1], item[2], item[3], item[4], item[5], item[6]) for item in query_result ] selected_system = utilities.choose_system(selected_sap_systems) pyperclip.copy(selected_system.password) click.echo( click.style( f"\nPassword is copied into clipboard.\n", **utilities.color_message, )) if clear_clipboard: click.echo( click.style( "If you use Clipboard manager, you should add PY.EXE, CMD.EXE applications to the exclusion list,\n" "in order to keep sensitive information safe.", **utilities.color_sensitive, )) click.echo( click.style( f"\nClipboard will be cleared in {time_to_clear} seconds.\n", **utilities.color_message, )) try: utilities.countdown(time_to_clear) except KeyboardInterrupt: click.echo("\nAborted!") if ctypes.windll.user32.OpenClipboard(None): ctypes.windll.user32.EmptyClipboard() ctypes.windll.user32.CloseClipboard() click.echo( click.style("\nClipboard is cleared. \n", **utilities.color_success))
def debug(ctx, system: str, mandant: str, user: str, customer: str, description: str, language: str, guiparm: str, snc_name: str, snc_qop: str, file: bool, open_file: bool): """ \b System debug You can: 1. Creat debug file - to debug modal dialog box: run 'sap debug -f' 2. Start debuggin of the opened system (the last used windows will be used): run 'sap debug <system> <mandant>' \b Optional arguments: 1. SYSTEM: Request a SAP system by system 2. MANDANT: Request a SAP system by mandant/clien """ if file: debug_folder = ctx.obj.config.config_path if ctx.obj.config.config_path else utilities.path( ) debug_file_path = os.path.join(debug_folder, DEBUG_FILE_NAME) click.echo(f"\n{debug_file_path} file will be created.") click.echo( f"After creation, a folder with {DEBUG_FILE_NAME} file will be opened \n" ) click.echo("Drag the file to the SAP system to start debug mode \n") click.pause("Press Enter to continue") with open(debug_file_path, "w", encoding='utf-8') as writer: writer.write("[FUNCTION]\n") writer.write("Command =/H\n") writer.write("Title=Debugger\n") writer.write("Type=SystemCommand") if open_file: click.launch(url=debug_file_path, locate=True) else: query_result = ctx.invoke(list_systems, system=system, mandant=mandant, user=user, customer=customer, description=description, url=False, verbose=False, enum=True) # -------------------------- if query_result != []: selected_sap_systems = [ Sap_system(item[0], item[1], item[2], item[3], item[4], item[5], item[6]) for item in query_result ] if language is None: language = ctx.obj.config.language # As soon as dubugger stops working - revert all the changes to "prepare_parameters_to_launch_system" # as it influence whether to open new windows, or to debug the latest opened. All arguments # values must be entered selected_system = utilities.choose_system(selected_sap_systems) try: argument = utilities.prepare_parameters_to_launch_system( selected_system, None, language, guiparm, snc_name, snc_qop, None, user, "", ctx.obj.config.command_line_path) except WrongPath as err: click.echo(f"{err}") raise click.Abort argument = argument + " -command=/H" + " -type=SystemCommand" utilities.print_system_list( selected_system, title="Trying to DEBUG the following system") logger.info(f"{argument}") pop = Popen(argument) pop.wait() if pop.returncode: click.echo(pop.returncode, pop.communicate()[0])
def run(ctx, system: str, mandant: int, user: str, customer: str, description: str, external_user: bool, language: str, guiparm: str, snc_name: str, snc_qop: str, transaction: str, system_command: str, report: str, parameter: str, web: bool, reuse: bool): """ \b Launch SAP system \n \b Optional arguments: 1. SYSTEM: Request a SAP system by systedm id 2. MANDANT: Request a SAP system by mandant/client """ password = "" if snc_name is not None and snc_qop is None or snc_name is None and snc_qop is not None: click.echo( click.style( f"\nBoth parameters must be used: -sname/--snc_name and -sqop/--snc_qop", **utilities.color_warning)) raise click.Abort if external_user: if not mandant: mandant = input("Enter mandant: ") user = input("Enter external user id: ") password = getpass.getpass("Enter password for external user: "******"", "", "") ] else: query_result = ctx.invoke(list_systems, system=system, mandant=mandant, user=user, customer=customer, description=description, url=False, verbose=False, enum=True) # -------------------------- if query_result != []: selected_sap_systems = [ Sap_system(item[0], item[1], item[2], item[3], item[4], item[5], item[6]) for item in query_result ] if language is None: language = ctx.obj.config.language selected_system = utilities.choose_system(selected_sap_systems) try: argument = utilities.prepare_parameters_to_launch_system( selected_system, password, language, guiparm, snc_name, snc_qop, user, "", ctx.obj.config.command_line_path) except WrongPath as err: click.echo(f"{err}") raise click.Abort if web: if selected_system.url != " ": # TODO: доделать передачу пароля для авторизации по аналогии с KeePass # https://keepass.info/help/base/autotype.html # https://github.com/allo-/passautotype - РЕАЛИЗАЦИЯ # Сделать настройку для каждого сайта - т.е. отдельная таблица по параметрам сайтов # Not enough good solution but it works click.echo( click.style( f"\nLaunching web: {selected_system.description} of {selected_system.customer} ", **utilities.color_success)) click.launch(url=f"{selected_system.url}") time.sleep(2) pyautogui.write(selected_system.user) pyautogui.keyDown('tab') pyautogui.write(selected_system.password) pyautogui.keyDown('tab') pyautogui.keyDown('tab') pyautogui.keyDown('enter') else: no_system_found = Sap_system( system.upper() if system else None, str(mandant).zfill(3) if mandant else None, user.upper() if user else None, None, customer.upper() if customer else None, description.upper() if description else None, None) utilities.print_system_list( no_system_found, title="NO URL FOUND according to search criteria", color=utilities.color_warning) raise click.Abort else: if transaction: command = transaction command_type = 'transaction' argument = argument + " -type=transaction" if parameter: param_data = sap.query_param(str(transaction).upper()) if param_data: argument = argument + f' -command="{transaction.upper()} {param_data[0][1]}={parameter};"' else: click.echo( click.style( f"\nThere is no parameter info for {transaction.upper()} transaction", **utilities.color_sensitive)) argument = argument + f' -command="{transaction.upper()}"' else: argument = argument + " -command=" + transaction elif system_command: command = system_command command_type = 'system command' argument = argument + " -type=SystemCommand" argument = argument + " -command=" + system_command elif report: command = report command_type = 'report' argument = argument + " -type=report" argument = argument + " -command=" + report else: command = None command_type = None if external_user: message = "Trying to LAUNCH the following system with EXTERNAL USERS" else: message = "Trying to LAUNCH the following system " if reuse: argument = argument + f' -reuse=1' else: argument = argument + f' -reuse=0' utilities.print_system_list(selected_system, title=message, command=command, command_type=command_type) logger.info(f"{argument}") # Запускаем SAP pop = Popen(argument) pop.wait() if pop.returncode: click.echo(pop.returncode, pop.communicate()[0])
def test_delete_record_from_db(db, added_record): """ Test deleting records from database """ system = Sap_system(*added_record) db.delete(system) result_lst = db.query_system(Sap_system(system='XXX')) assert result_lst == []
def test_add_record_to_db(db, added_record): """ Test adding records to database """ result_lst = db.query_system(Sap_system(system='XXX')) assert Sap_system(*result_lst[0]) == added_record
def added_record(temp_db, crypto): """ Add temporary record for testing purpose """ system = Sap_system('XXX', '100', 'USER', crypto.encrypto(str.encode('123')), 'CUSTOMER', 'DEV_SYSTEM', '') temp_db.add(system)