class Cli: def __init__(self): self.core = Core() def list(self): self._info('available profile groups:') profile_groups_list = self.core.config.list_groups() for group in profile_groups_list: print(group.name) def login(self, profile_group_name, region, oneshot=False): profile_group = self.core.config.get_group(profile_group_name) if not profile_group: self._error('profile group not found') self.list() sys.exit(1) if region is not None and region not in region_list: self._error(f'invalid region: {region}') self._warning('available regions:') self._print_regions() sys.exit(1) login_result = self.core.login(profile_group=profile_group, mfa_callback=self.ask_for_mfa_token) self._check_and_signal_error(login_result) if region: region_result = self.core.set_region(region=region) self._check_and_signal_error(region_result) self._info('login successful') if oneshot: return time.sleep(300) self.login(profile_group_name, region) def logout(self): logout_result = self.core.logout() self._check_and_signal_error(logout_result) def rotate_access_key(self): rotate_result = self.core.rotate_access_key() if not self._check_and_signal_error(rotate_result): return self._info('key was successfully rotated') def set_access_key(self): key_id = getpass(prompt='Key ID: ') access_key = getpass(prompt='Secret Access Key: ') self.core.set_access_key(key_id=key_id, access_key=access_key) self._info('key was successfully rotated') @staticmethod def ask_for_mfa_token(): return input(f'mfa token: ') def _check_and_signal_error(self, result: Result): if result.was_error: self._error(result.error_message) sys.exit(1) return True @staticmethod def _info(s): print(f'{CG}{s}{CC}') @staticmethod def _error(s): print(f'{CR}{s}{CC}') @staticmethod def _warning(s): print(f'{CY}{s}{CC}') @staticmethod def _print_regions(): for region in region_list: print(region)
class Gui(QMainWindow): def __init__(self, app): QMainWindow.__init__(self) self.app = app self.core = Core() self.assets: Assets = Assets() self.last_login: str = 'never' self.login_repeater = Repeater() self.tray_icon = SystemTrayIcon(parent=self, assets=self.assets, profile_list=self.core.config.list_groups()) self.log_dialog = LogDialog(self) self.config_dialog = ConfigDialog(self) self.set_key_dialog = SetKeyDialog(self) self.rotate_key_dialog = RotateKeyDialog(self) self.tray_icon.show() def login(self, profile_group: ProfileGroup): self._to_reset_state() self.tray_icon.disable_actions(True) result = self.core.login(profile_group=profile_group, mfa_callback=self.show_mfa_token_fetch_dialog) if not self._check_and_signal_error(result): self._to_error_state() return logger.info('start repeater') prepare_login = partial(self.login, profile_group=profile_group) self.login_repeater.start(task=prepare_login, delay_seconds=300) self._to_login_state() def logout(self): result = self.core.logout() self._check_and_signal_error(result) self._to_reset_state() self.tray_icon.update_region_text('not logged in') def set_region(self, region: str) -> None: result = self.core.set_region(region) if not self._check_and_signal_error(result): return region = self.core.get_region() if not region: region = 'not logged in' self.tray_icon.update_region_text(region) def rotate_access_key(self): logger.info('initiate key rotation') logger.info('check access key') result = self.core.rotate_access_key() if not self._check_and_signal_error(result): return self._signal('Success', 'key was rotated') def edit_config(self, config: Config): result = self.core.edit_config(config) if self._check_and_signal_error(result): self.tray_icon.populate_context_menu(self.core.get_profile_group_list()) self._to_reset_state() def set_access_key(self, key_id, access_key): self.core.set_access_key(key_id=key_id, access_key=access_key) self._signal('Success', 'access key was set') @staticmethod def show_mfa_token_fetch_dialog(): return MfaDialog().get_mfa_token() def show_config_dialog(self): self.config_dialog.show_dialog(self.core.config) def show_set_key_dialog(self): text = '' if credentials.has_access_key().was_success: text = 'this will overwrite the existing key' self.set_key_dialog.show_dialog(text) def show_access_key_rotation_dialog(self): self.rotate_key_dialog.show_dialog() def show_logs(self): logs_as_text = files.load_logs() self.log_dialog.show_dialog(logs_as_text) def _to_login_state(self): self.tray_icon.setIcon(self.assets.get_icon(color_code=self.core.get_active_profile_color())) self.tray_icon.disable_actions(False) self.tray_icon.update_last_login(self.get_timestamp()) def _to_reset_state(self): self.login_repeater.stop() self.tray_icon.setIcon(self.assets.get_icon()) self.tray_icon.disable_actions(False) self.tray_icon.update_last_login('never') def _to_error_state(self): self._to_reset_state() self.tray_icon.setIcon(self.assets.get_icon(style='error', color_code='#ff0000')) def _check_and_signal_error(self, result: Result): if result.was_error: self._signal_error(result.error_message) return False return True def _signal_error(self, message='unknown error'): self._signal(topic='Logsmith Error', message=message) self._to_error_state() def _signal(self, topic, message): self.tray_icon.show_message(topic, message) @staticmethod def get_timestamp(): return datetime.now().strftime('%H:%M') def stop_and_exit(self): self.login_repeater.stop() self.exit() @staticmethod def exit(): QCoreApplication.exit()