From 061e72a8f617c061b14998999b1e5a9329abe4d8 Mon Sep 17 00:00:00 2001 From: Maximilian Zettler Date: Thu, 10 Mar 2022 16:23:46 +0100 Subject: [PATCH] add password dialog --- timebot/app.py | 2 ++ timebot/gui.py | 36 +++++++++++++++++++++++++++++++----- timebot/timebot.py | 14 ++++++++++---- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/timebot/app.py b/timebot/app.py index b174523..190cfe2 100644 --- a/timebot/app.py +++ b/timebot/app.py @@ -3,6 +3,7 @@ import configparser import datetime import logging import os +import signal import sys from timebot.constants import PUNCH_COMMANDS, DateFormats @@ -107,6 +108,7 @@ def run(): elif args.subparser_name == "gui": from PyQt5.QtWidgets import QApplication from timebot.gui import TimebotMain + signal.signal(signal.SIGINT, lambda *_args: QApplication.quit()) app = QApplication(sys.argv) main_window = TimebotMain(timebot=tb) main_window.show() diff --git a/timebot/gui.py b/timebot/gui.py index e9ae08e..899d72f 100644 --- a/timebot/gui.py +++ b/timebot/gui.py @@ -2,15 +2,16 @@ import datetime from PyQt5 import QtGui from PyQt5.QtCore import QTimer, QObject, pyqtSignal, QThread -from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QMessageBox +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QMessageBox, QInputDialog, QLineEdit -from timebot.timebot import TimeBot +from timebot.timebot import TimeBot, TimebotObtainPasswordError class TimebotApiWorker(QObject): status_msg = pyqtSignal(object) hours_present_msg = pyqtSignal(object) error = pyqtSignal(object) + obtain_password = pyqtSignal() finished = pyqtSignal() def __init__(self, timebot: TimeBot): @@ -23,6 +24,8 @@ class TimebotApiWorker(QObject): hours_present = hours_present - datetime.timedelta(microseconds=hours_present.microseconds) self.hours_present_msg.emit(str(hours_present)) self.status_msg.emit(self.timebot.status()) + except TimebotObtainPasswordError as e: + self.obtain_password.emit() except Exception as e: self.error.emit(e) self.finished.emit() @@ -54,24 +57,46 @@ class TimebotMain(QWidget): self.btn_update_status.clicked.connect(self.update_status) self.btnPress2.clicked.connect(self.btnPress2_Clicked) + self.status_timer_time = 29000 self.status_timer = QTimer() self.status_timer.timeout.connect(self.update_status) - self.status_timer.start(29999) + self.status_timer.start(self.status_timer_time) + + # Timer to refresh the main window ... is needed to react on Ctrl+C + self.main_window_timer = QTimer() + self.main_window_timer.timeout.connect(lambda: None) + self.main_window_timer.start(500) self.error_msg = QMessageBox() self.error_msg.setWindowTitle("Timebot ERROR") + self.error_msg.setIcon(QMessageBox.Critical) self.error_msg.finished.connect(self.error_msg_finished) + self.password_dialog = QInputDialog() + self.update_status_running = False self.update_status() + def get_password(self, callback: callable = None): + self.status_timer.stop() + password, ok = self.password_dialog.getText(self, "Timebot Password", 'Enter your password:', QLineEdit.Password) + if ok: + self.timebot.mobatime_api.password = password + try: + _ = self.timebot.mobatime_api.session + except Exception as e: + self.error_msg_show(str(e)) + self.timebot.mobatime_api.password = None + callback() + self.status_timer.start(self.status_timer_time) + def error_msg_show(self, error_text: str): self.error_msg.setText(error_text) self.status_timer.stop() self.error_msg.exec_() def error_msg_finished(self): - self.status_timer.start(29999) + self.status_timer.start(self.status_timer_time) def update_status_started(self): self.btn_update_status.setEnabled(False) @@ -96,7 +121,8 @@ class TimebotMain(QWidget): self.status_thread.finished.connect(self.update_status_finished) self.status_worker.status_msg.connect(self.text_box_status.setText) self.status_worker.hours_present_msg.connect(self.text_box_hours_present.setText) - self.status_worker.error.connect(lambda exp: self.error_msg_show(str(exp))) + self.status_worker.error.connect(lambda exp, *args: self.error_msg_show(str(exp))) + self.status_worker.obtain_password.connect(lambda *args: self.get_password(self.update_status)) self.status_thread.start() self.update_status_started() diff --git a/timebot/timebot.py b/timebot/timebot.py index a40f14d..757f1ee 100644 --- a/timebot/timebot.py +++ b/timebot/timebot.py @@ -9,10 +9,13 @@ import requests as requests from timebot.constants import PunchCodes, DateFormats, USER_AGENT - package_logger = logging.getLogger(__name__) +class TimebotObtainPasswordError(Exception): + pass + + class TimeParseError(Exception): pass @@ -91,15 +94,18 @@ class MobatimeApi: """ if self.password is None and self.ask_for_password: self.password = self._get_password() + elif self.password and not self.ask_for_password: + pass else: - raise Exception("could not obtain password") + raise TimebotObtainPasswordError("Unauthorized: could not obtain password") login_data = { "username": self.user, "password": self.password, } session.cookies.clear_session_cookies() - request = session.post(self.baseurl + "Account/LogOn", data=login_data) - request.raise_for_status() + session.post(self.baseurl + "Account/LogOn", + data=login_data).raise_for_status() # This always gives 200 ... even with wrong password + session.get(self.baseurl + "Employee/GetEmployeeList").raise_for_status() @staticmethod def _get_password():