diff --git a/.gitignore b/.gitignore index 63d926d..aa4cf4f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .idea/ rokae/testbench.py **/__pycache__/ -NOTRACK/ \ No newline at end of file +NOTRACK/ +gui/assets/database/ \ No newline at end of file diff --git a/gui/assets/conf/config.json b/gui/assets/conf/config.json index c7821c7..243886b 100644 --- a/gui/assets/conf/config.json +++ b/gui/assets/conf/config.json @@ -1,5 +1,10 @@ { - "account": { - "Fan": "Ka2trNyfHPci26UGt3bVyvFjNuUoW9/0QcBVOR79KIw=" - } + "username": "admin", + "login_password": "MkzWVYJoL5o2wDJOsExlS+qCElrJj+P6Rxiy89XwP7I=", + "unlock_password": "MkzWVYJoL5o2wDJOsExlS+qCElrJj+P6Rxiy89XwP7I=", + "code_dict": [4, 11, 4, 31, 22, 12, 19, 23, 7, 16, 7, 23, 1, 8, 7, 18, 27, 32, 28, 25, 7, 32, 9, 15, 2, 32, 0, 12, 26, 15, 14, 17], + "minimum_password_length": 8, + "maximum_db_number": 10, + "api_ali": "", + "api_wechat": "" } \ No newline at end of file diff --git a/gui/assets/database/toolbox.20250909161747.db b/gui/assets/database/toolbox.20250909161747.db deleted file mode 100644 index d67fb4e..0000000 Binary files a/gui/assets/database/toolbox.20250909161747.db and /dev/null differ diff --git a/gui/assets/database/toolbox.20250909161752.db b/gui/assets/database/toolbox.20250909161752.db deleted file mode 100644 index d67fb4e..0000000 Binary files a/gui/assets/database/toolbox.20250909161752.db and /dev/null differ diff --git a/gui/assets/database/toolbox.20250909161758.db b/gui/assets/database/toolbox.20250909161758.db deleted file mode 100644 index d67fb4e..0000000 Binary files a/gui/assets/database/toolbox.20250909161758.db and /dev/null differ diff --git a/gui/assets/database/toolbox.20250909161810.db b/gui/assets/database/toolbox.20250909161810.db deleted file mode 100644 index d67fb4e..0000000 Binary files a/gui/assets/database/toolbox.20250909161810.db and /dev/null differ diff --git a/gui/assets/database/toolbox.20250909161844.db b/gui/assets/database/toolbox.20250909161844.db deleted file mode 100644 index d67fb4e..0000000 Binary files a/gui/assets/database/toolbox.20250909161844.db and /dev/null differ diff --git a/gui/assets/database/toolbox.db b/gui/assets/database/toolbox.db deleted file mode 100644 index d67fb4e..0000000 Binary files a/gui/assets/database/toolbox.db and /dev/null differ diff --git a/gui/assets/database/toolbox.db-shm b/gui/assets/database/toolbox.db-shm deleted file mode 100644 index fa4370f..0000000 Binary files a/gui/assets/database/toolbox.db-shm and /dev/null differ diff --git a/gui/assets/database/toolbox.db-wal b/gui/assets/database/toolbox.db-wal deleted file mode 100644 index e69de29..0000000 diff --git a/gui/assets/ui/app.ui b/gui/assets/ui/app.ui index 23bfe8c..27fc8b5 100644 --- a/gui/assets/ui/app.ui +++ b/gui/assets/ui/app.ui @@ -1,19 +1,19 @@ - MainWindow - + App + 0 0 - 1100 - 550 + 769 + 356 - 1100 - 550 + 0 + 0 @@ -25,67 +25,203 @@ Toolbox - - - - - 0 - 0 - 1100 - 33 - - - - - 文件 - - - - - - - 帮助 - - - - - - 日志 - - - - - + + + + + + + + + 个人 + + + + + 实用 + + + + + 效率 + + + + + 开发 + + + + + 设计 + + + + + 工作 + + + + + + + + 0 + + + + + + 110 + 70 + 54 + 16 + + + + 1 + + + + + + + + 100 + 130 + 54 + 16 + + + + 2 + + + + + + + + 130 + 70 + 54 + 16 + + + + 3 + + + + + + + + - + + + toolBar + + + false + + + TopToolBarArea + + + false + + + + + + + + + - Exit + 主页 + + + Ctrl+Alt+H + + + Ctrl+Alt+H + + + QAction::MenuRole::NoRole - + + + 设置 + + + Ctrl+Alt+S + + + Ctrl+Alt+S + + + QAction::MenuRole::NoRole + + + + + 日志 + + + Ctrl+Alt+L + + + Ctrl+Alt+L + + + QAction::MenuRole::NoRole + + + 关于 - - - - Exit + + Ctrl+Alt+A + + + Ctrl+Alt+A + + + QAction::MenuRole::NoRole - - - 关于 - - - + 退出 + + Ctrl+Alt+Q + + + Ctrl+Alt+Q + + + QAction::MenuRole::NoRole + - + - 设置 + 锁定 + + + Ctrl+Alt+C + + + Ctrl+Alt+C + + + QAction::MenuRole::NoRole diff --git a/gui/assets/ui/login.ui b/gui/assets/ui/login.ui index 46bb7bc..b564388 100644 --- a/gui/assets/ui/login.ui +++ b/gui/assets/ui/login.ui @@ -183,6 +183,9 @@ 登录 + + true + @@ -197,6 +200,9 @@ 取消 + + true + diff --git a/gui/codes/common/clibs.py b/gui/codes/common/clibs.py index 67fdbfa..856979e 100644 --- a/gui/codes/common/clibs.py +++ b/gui/codes/common/clibs.py @@ -1,6 +1,7 @@ from pathlib import Path +from threading import Lock + base_path = Path(__file__).resolve().parent.parent.parent -code_dict = [4, 11, 4, 31, 22, 12, 19, 23, 7, 16, 7, 23, 1, 8, 7, 18, 27, 32, 28, 25, 7, 32, 9, 15, 2, 32, 0, 12, 26, 15, 14, 17] -salt = "" -max_db_number = 10 +lock = Lock() +account = None diff --git a/gui/codes/common/db_operation.py b/gui/codes/common/db_operation.py index 3136878..7c8f71d 100644 --- a/gui/codes/common/db_operation.py +++ b/gui/codes/common/db_operation.py @@ -1,5 +1,4 @@ import sqlite3 -from threading import Lock import time from codes.common import clibs @@ -30,10 +29,10 @@ def db_init(db_file): def db_lock(func): def wrapper(*args, **kwargs): try: - Lock().acquire(True) + clibs.lock.acquire(True) ret = func(*args, **kwargs) finally: - Lock().release() + clibs.lock.release() return ret return wrapper @@ -47,8 +46,7 @@ def db_backup(): db_file_backup.write_bytes(db_file.read_bytes()) db_dir = clibs.base_path / "assets/database" db_list = [db for db in db_dir.glob("*.db")] - print(f"db_list: {sorted(db_list)}") - for db in sorted(db_list)[:-clibs.max_db_number]: + for db in sorted(db_list)[:-clibs.account["maximum_db_number"]]: db.unlink() def db_conn(): @@ -61,4 +59,9 @@ def db_conn(): cursor.execute("PRAGMA temp_store=memory") cursor.execute("PRAGMA mmap_size=30000000000") cursor.execute("PRAGMA cache_size=200000") - return conn, cursor \ No newline at end of file + return conn, cursor + +@db_lock +def db_close(conn, cursor): + cursor.close() + conn.close() \ No newline at end of file diff --git a/gui/codes/common/secure_encrypt.py b/gui/codes/common/secure_encrypt.py index 2c40c64..16b7567 100644 --- a/gui/codes/common/secure_encrypt.py +++ b/gui/codes/common/secure_encrypt.py @@ -3,6 +3,7 @@ import hashlib from Crypto.Cipher import AES from Crypto import Random from Crypto.Util.Padding import pad, unpad +from codes.common import clibs class PassCipher: @@ -25,13 +26,12 @@ class PassCipher: plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size) return plaintext.decode("utf-8") - -# if __name__ == "__main__": -# salt = "my_secret_salt_string" -# cipher = PassCipher(salt) -# original_text = "这是一段需要加密的敏感信息" -# encrypted_text = cipher.encrypt(original_text) -# print(f"加密后的文本: {encrypted_text}") -# decrypted_text = cipher.decrypt(encrypted_text) -# print(f"解密后的文本: {decrypted_text}") -# print(f"加解密是否成功: {original_text == decrypted_text}") \ No newline at end of file + @staticmethod + def gen_salt(text: str): + key = "" + passwd = {idx: char for idx, char in enumerate(text * 4)} + for idx in range(32): + char_i = 0 if ord(passwd[idx]) - clibs.account["code_dict"][idx] < 0 else ord(passwd[idx]) - clibs.account["code_dict"][idx] + key += chr(char_i) + salt = base64.urlsafe_b64encode(key.encode()).decode() + return salt diff --git a/gui/codes/common/ui2py.py b/gui/codes/common/ui2py.py index 59779be..c396862 100644 --- a/gui/codes/common/ui2py.py +++ b/gui/codes/common/ui2py.py @@ -19,8 +19,10 @@ def single_uic(ui_path: str, py_path: str): except subprocess.CalledProcessError as e: print(f"转换失败: {ui_file}\n{e.stderr}", file=sys.stderr) - -if __name__ == "__main__": +def main(): ui_path = clibs.base_path / "assets" / "ui" py_path = clibs.base_path / "codes" / "ui" single_uic(str(ui_path), str(py_path)) + +if __name__ == "__main__": + main() diff --git a/gui/codes/ui/app.py b/gui/codes/ui/app.py index 3a2bc1b..17f3e5d 100644 --- a/gui/codes/ui/app.py +++ b/gui/codes/ui/app.py @@ -16,70 +16,171 @@ from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) -from PySide6.QtWidgets import (QApplication, QMainWindow, QMenu, QMenuBar, - QSizePolicy, QStatusBar, QWidget) +from PySide6.QtWidgets import (QApplication, QHBoxLayout, QLabel, QListWidget, + QListWidgetItem, QMainWindow, QSizePolicy, QStackedWidget, + QStatusBar, QToolBar, QVBoxLayout, QWidget) -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - if not MainWindow.objectName(): - MainWindow.setObjectName(u"MainWindow") - MainWindow.resize(1100, 550) - MainWindow.setMinimumSize(QSize(1100, 550)) +class Ui_App(object): + def setupUi(self, App): + if not App.objectName(): + App.setObjectName(u"App") + App.resize(769, 356) + App.setMinimumSize(QSize(0, 0)) font = QFont() font.setFamilies([u"Consolas"]) font.setPointSize(12) - MainWindow.setFont(font) - self.actionExit = QAction(MainWindow) - self.actionExit.setObjectName(u"actionExit") - self.action = QAction(MainWindow) - self.action.setObjectName(u"action") - self.actionExit_2 = QAction(MainWindow) - self.actionExit_2.setObjectName(u"actionExit_2") - self.action_2 = QAction(MainWindow) - self.action_2.setObjectName(u"action_2") - self.action_3 = QAction(MainWindow) - self.action_3.setObjectName(u"action_3") - self.action_4 = QAction(MainWindow) - self.action_4.setObjectName(u"action_4") - self.centralwidget = QWidget(MainWindow) + App.setFont(font) + self.ac_homepage = QAction(App) + self.ac_homepage.setObjectName(u"ac_homepage") + self.ac_homepage.setMenuRole(QAction.MenuRole.NoRole) + self.ac_settings = QAction(App) + self.ac_settings.setObjectName(u"ac_settings") + self.ac_settings.setMenuRole(QAction.MenuRole.NoRole) + self.ac_logs = QAction(App) + self.ac_logs.setObjectName(u"ac_logs") + self.ac_logs.setMenuRole(QAction.MenuRole.NoRole) + self.ac_about = QAction(App) + self.ac_about.setObjectName(u"ac_about") + self.ac_about.setMenuRole(QAction.MenuRole.NoRole) + self.ac_quit = QAction(App) + self.ac_quit.setObjectName(u"ac_quit") + self.ac_quit.setMenuRole(QAction.MenuRole.NoRole) + self.ac_caging = QAction(App) + self.ac_caging.setObjectName(u"ac_caging") + self.ac_caging.setMenuRole(QAction.MenuRole.NoRole) + self.centralwidget = QWidget(App) self.centralwidget.setObjectName(u"centralwidget") - MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QMenuBar(MainWindow) - self.menubar.setObjectName(u"menubar") - self.menubar.setGeometry(QRect(0, 0, 1100, 33)) - self.menu = QMenu(self.menubar) - self.menu.setObjectName(u"menu") - self.menu_2 = QMenu(self.menubar) - self.menu_2.setObjectName(u"menu_2") - self.menu_3 = QMenu(self.menubar) - self.menu_3.setObjectName(u"menu_3") - MainWindow.setMenuBar(self.menubar) - self.statusbar = QStatusBar(MainWindow) + self.verticalLayout = QVBoxLayout(self.centralwidget) + self.verticalLayout.setObjectName(u"verticalLayout") + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.lw_navigation = QListWidget(self.centralwidget) + QListWidgetItem(self.lw_navigation) + QListWidgetItem(self.lw_navigation) + QListWidgetItem(self.lw_navigation) + QListWidgetItem(self.lw_navigation) + QListWidgetItem(self.lw_navigation) + QListWidgetItem(self.lw_navigation) + self.lw_navigation.setObjectName(u"lw_navigation") + + self.horizontalLayout.addWidget(self.lw_navigation) + + self.sw_pages = QStackedWidget(self.centralwidget) + self.sw_pages.setObjectName(u"sw_pages") + self.page = QWidget() + self.page.setObjectName(u"page") + self.label_3 = QLabel(self.page) + self.label_3.setObjectName(u"label_3") + self.label_3.setGeometry(QRect(110, 70, 54, 16)) + self.sw_pages.addWidget(self.page) + self.page_2 = QWidget() + self.page_2.setObjectName(u"page_2") + self.label_2 = QLabel(self.page_2) + self.label_2.setObjectName(u"label_2") + self.label_2.setGeometry(QRect(100, 130, 54, 16)) + self.sw_pages.addWidget(self.page_2) + self.page_3 = QWidget() + self.page_3.setObjectName(u"page_3") + self.label = QLabel(self.page_3) + self.label.setObjectName(u"label") + self.label.setGeometry(QRect(130, 70, 54, 16)) + self.sw_pages.addWidget(self.page_3) + + self.horizontalLayout.addWidget(self.sw_pages) + + self.horizontalLayout.setStretch(0, 1) + self.horizontalLayout.setStretch(1, 5) + + self.verticalLayout.addLayout(self.horizontalLayout) + + App.setCentralWidget(self.centralwidget) + self.statusbar = QStatusBar(App) self.statusbar.setObjectName(u"statusbar") - MainWindow.setStatusBar(self.statusbar) + App.setStatusBar(self.statusbar) + self.toolBar = QToolBar(App) + self.toolBar.setObjectName(u"toolBar") + self.toolBar.setMovable(False) + App.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.toolBar) - self.menubar.addAction(self.menu.menuAction()) - self.menubar.addAction(self.menu_3.menuAction()) - self.menubar.addAction(self.menu_2.menuAction()) - self.menu.addAction(self.action_4) - self.menu.addAction(self.action_3) - self.menu_2.addAction(self.action_2) + self.toolBar.addAction(self.ac_homepage) + self.toolBar.addAction(self.ac_settings) + self.toolBar.addAction(self.ac_logs) + self.toolBar.addAction(self.ac_about) + self.toolBar.addAction(self.ac_caging) + self.toolBar.addAction(self.ac_quit) - self.retranslateUi(MainWindow) + self.retranslateUi(App) - QMetaObject.connectSlotsByName(MainWindow) + self.sw_pages.setCurrentIndex(0) + + + QMetaObject.connectSlotsByName(App) # setupUi - def retranslateUi(self, MainWindow): - MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Toolbox", None)) - self.actionExit.setText(QCoreApplication.translate("MainWindow", u"Exit", None)) - self.action.setText(QCoreApplication.translate("MainWindow", u"\u5173\u4e8e", None)) - self.actionExit_2.setText(QCoreApplication.translate("MainWindow", u"Exit", None)) - self.action_2.setText(QCoreApplication.translate("MainWindow", u"\u5173\u4e8e", None)) - self.action_3.setText(QCoreApplication.translate("MainWindow", u"\u9000\u51fa", None)) - self.action_4.setText(QCoreApplication.translate("MainWindow", u"\u8bbe\u7f6e", None)) - self.menu.setTitle(QCoreApplication.translate("MainWindow", u"\u6587\u4ef6", None)) - self.menu_2.setTitle(QCoreApplication.translate("MainWindow", u"\u5e2e\u52a9", None)) - self.menu_3.setTitle(QCoreApplication.translate("MainWindow", u"\u65e5\u5fd7", None)) + def retranslateUi(self, App): + App.setWindowTitle(QCoreApplication.translate("App", u"Toolbox", None)) + self.ac_homepage.setText(QCoreApplication.translate("App", u"\u4e3b\u9875", None)) +#if QT_CONFIG(tooltip) + self.ac_homepage.setToolTip(QCoreApplication.translate("App", u"Ctrl+Alt+H", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.ac_homepage.setShortcut(QCoreApplication.translate("App", u"Ctrl+Alt+H", None)) +#endif // QT_CONFIG(shortcut) + self.ac_settings.setText(QCoreApplication.translate("App", u"\u8bbe\u7f6e", None)) +#if QT_CONFIG(tooltip) + self.ac_settings.setToolTip(QCoreApplication.translate("App", u"Ctrl+Alt+S", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.ac_settings.setShortcut(QCoreApplication.translate("App", u"Ctrl+Alt+S", None)) +#endif // QT_CONFIG(shortcut) + self.ac_logs.setText(QCoreApplication.translate("App", u"\u65e5\u5fd7", None)) +#if QT_CONFIG(tooltip) + self.ac_logs.setToolTip(QCoreApplication.translate("App", u"Ctrl+Alt+L", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.ac_logs.setShortcut(QCoreApplication.translate("App", u"Ctrl+Alt+L", None)) +#endif // QT_CONFIG(shortcut) + self.ac_about.setText(QCoreApplication.translate("App", u"\u5173\u4e8e", None)) +#if QT_CONFIG(tooltip) + self.ac_about.setToolTip(QCoreApplication.translate("App", u"Ctrl+Alt+A", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.ac_about.setShortcut(QCoreApplication.translate("App", u"Ctrl+Alt+A", None)) +#endif // QT_CONFIG(shortcut) + self.ac_quit.setText(QCoreApplication.translate("App", u"\u9000\u51fa", None)) +#if QT_CONFIG(tooltip) + self.ac_quit.setToolTip(QCoreApplication.translate("App", u"Ctrl+Alt+Q", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.ac_quit.setShortcut(QCoreApplication.translate("App", u"Ctrl+Alt+Q", None)) +#endif // QT_CONFIG(shortcut) + self.ac_caging.setText(QCoreApplication.translate("App", u"\u9501\u5b9a", None)) +#if QT_CONFIG(tooltip) + self.ac_caging.setToolTip(QCoreApplication.translate("App", u"Ctrl+Alt+C", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.ac_caging.setShortcut(QCoreApplication.translate("App", u"Ctrl+Alt+C", None)) +#endif // QT_CONFIG(shortcut) + + __sortingEnabled = self.lw_navigation.isSortingEnabled() + self.lw_navigation.setSortingEnabled(False) + ___qlistwidgetitem = self.lw_navigation.item(0) + ___qlistwidgetitem.setText(QCoreApplication.translate("App", u"\u4e2a\u4eba", None)); + ___qlistwidgetitem1 = self.lw_navigation.item(1) + ___qlistwidgetitem1.setText(QCoreApplication.translate("App", u"\u5b9e\u7528", None)); + ___qlistwidgetitem2 = self.lw_navigation.item(2) + ___qlistwidgetitem2.setText(QCoreApplication.translate("App", u"\u6548\u7387", None)); + ___qlistwidgetitem3 = self.lw_navigation.item(3) + ___qlistwidgetitem3.setText(QCoreApplication.translate("App", u"\u5f00\u53d1", None)); + ___qlistwidgetitem4 = self.lw_navigation.item(4) + ___qlistwidgetitem4.setText(QCoreApplication.translate("App", u"\u8bbe\u8ba1", None)); + ___qlistwidgetitem5 = self.lw_navigation.item(5) + ___qlistwidgetitem5.setText(QCoreApplication.translate("App", u"\u5de5\u4f5c", None)); + self.lw_navigation.setSortingEnabled(__sortingEnabled) + + self.label_3.setText(QCoreApplication.translate("App", u"1", None)) + self.label_2.setText(QCoreApplication.translate("App", u"2", None)) + self.label.setText(QCoreApplication.translate("App", u"3", None)) + self.toolBar.setWindowTitle(QCoreApplication.translate("App", u"toolBar", None)) # retranslateUi diff --git a/gui/codes/ui/login.py b/gui/codes/ui/login.py index 54ecfdd..a4f6b3e 100644 --- a/gui/codes/ui/login.py +++ b/gui/codes/ui/login.py @@ -109,12 +109,14 @@ class Ui_login(object): font2.setPointSize(12) font2.setBold(True) self.pb_login.setFont(font2) + self.pb_login.setAutoDefault(True) self.horizontalLayout.addWidget(self.pb_login) self.pb_cancel = QPushButton(login) self.pb_cancel.setObjectName(u"pb_cancel") self.pb_cancel.setFont(font2) + self.pb_cancel.setAutoDefault(True) self.horizontalLayout.addWidget(self.pb_cancel) diff --git a/gui/main.py b/gui/main.py index 1905931..3527e02 100644 --- a/gui/main.py +++ b/gui/main.py @@ -1,13 +1,12 @@ import json +import random import sys -import base64 -import time from typing import Callable, Any -from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QMainWindow -from PySide6.QtGui import QIcon, QPixmap, QShortcut -from PySide6.QtCore import Qt +from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QMainWindow, QHBoxLayout, QVBoxLayout, QLineEdit, QLabel +from PySide6.QtGui import QIcon, QPixmap, QShortcut, QResizeEvent, QFont, QKeySequence +from PySide6.QtCore import Qt,QSize from codes.ui.login import Ui_login -from codes.ui.app import Ui_MainWindow +from codes.ui.app import Ui_App from codes.common.worker import Worker from codes.common import clibs from codes.common.secure_encrypt import PassCipher @@ -36,45 +35,40 @@ class LoginWindow(QWidget, Ui_login): self.le_username.setText("") self.le_password.setText("") - def gen_salt(): - clibs.salt = "" - key = "" - passwd = {idx: char for idx, char in enumerate(self.le_password.text() * 4)} - for idx in range(32): - char_i = 0 if ord(passwd[idx]) - clibs.code_dict[idx] < 0 else ord(passwd[idx]) - clibs.code_dict[idx] - key += chr(char_i) - clibs.salt = base64.urlsafe_b64encode(key.encode()).decode() - def validate_login(): - # with open(f"{clibs.base_path}/assets/conf/config.json", mode="rt", encoding="utf-8") as f_conf: - # accounts = json.load(f_conf)["account"] - # username = self.le_username.text() - # if username not in accounts or len(self.le_password.text()) < 8: - # login_failed() - # return False - # - # gen_salt() - # cipher = PassCipher(clibs.salt) - # try: - # password = cipher.decrypt(accounts[username]) - # except ValueError: - # login_failed() - # return False - # - # if password != self.le_password.text(): - # login_failed() - # return False + nonlocal username, password + with open(f"{clibs.base_path}/assets/conf/config.json", mode="rt", encoding="utf-8") as f_conf: + clibs.account = json.load(f_conf) + if username != clibs.account["username"] or len(password) < clibs.account["minimum_password_length"]: + login_failed() + return False + + salt = PassCipher.gen_salt(password) + cipher = PassCipher(salt) + # password_encrypt = cipher.encrypt(password) + # print(f"password_encrypt = {password_encrypt}") + # exit() + try: + decrypt_password = cipher.decrypt(clibs.account["login_password"]) + except ValueError: + login_failed() + return False + + if password != decrypt_password: + login_failed() + return False self.mainWindow = MainWindow() self.mainWindow.show() - self.close() self.deleteLater() return True - + + username = self.le_username.text() + password = self.le_password.text() validate_login() -class MainWindow(QMainWindow, Ui_MainWindow): +class MainWindow(QMainWindow, Ui_App): def __init__(self): super().__init__() self.conn = None @@ -82,12 +76,16 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.thread = None self.setupUi(self) self.pre_dos() + self.lock_overlay = None def pre_dos(self): self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico")) db_operation.db_backup() self.conn, self.cursor = db_operation.db_conn() - + # bindings + self.ac_quit.triggered.connect(self.close) + self.ac_caging.triggered.connect(self.lock_window) + self.ac_logs.triggered.connect(lambda : print("test ac log")) def launch(self, func, on_anything: Callable[..., Any] = print, *args, **kwargs): self.thread = Worker(func, *args, **kwargs) @@ -97,6 +95,127 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.thread.finished.connect(lambda: on_anything({"finished": True})) self.thread.start() + def lock_window(self): + def unlock(): + def check_failed(): + QMessageBox.warning(self, "错误", "\n密码错误,请重新输入!") + le_password.clear() + le_password.setFocus() + + password = le_password.text() + if len(password) < clibs.account["minimum_password_length"]: + check_failed() + return False + + salt = PassCipher.gen_salt(password) + cipher = PassCipher(salt) + try: + decrypt_password = cipher.decrypt(clibs.account["unlock_password"]) + except ValueError: + check_failed() + return False + + if password != decrypt_password: + check_failed() + return False + + self.lock_overlay.deleteLater() + self.lock_overlay = None + self.set_shortcuts(True) + return True + + def gen_lock_screen(): + # generate lock screen + v_layout = QVBoxLayout(self.lock_overlay) # v layout + v_layout.setObjectName(u"v_layout") + h_layout = QHBoxLayout() # h layout + h_layout.setObjectName(u"h_layout") + h_layout.setContentsMargins(-1, -1, 10, 50) + lb_e_1 = QLabel(self.lock_overlay) + lb_e_1.setObjectName(u"lb_e_1") + h_layout.addWidget(lb_e_1) + + lb_password = QLabel(self.lock_overlay) + lb_password.setObjectName(u"lb_password") + lb_password.setMinimumSize(QSize(100, 0)) + lb_password.setMaximumSize(QSize(100, 16777215)) + font = QFont() + font.setFamilies([u"Consolas"]) + font.setPointSize(14) + font.setBold(True) + font.setItalic(True) + lb_password.setFont(font) + lb_password.setAlignment(Qt.AlignmentFlag.AlignCenter) + lb_password.setText("Password") + h_layout.addWidget(lb_password) + + le_password = QLineEdit(self.lock_overlay) + le_password.setObjectName(u"le_password") + le_password.setMinimumSize(QSize(200, 0)) + le_password.setFont(font) + le_password.setEchoMode(QLineEdit.EchoMode.Password) + h_layout.addWidget(le_password) + + lb_e_2 = QLabel(self.lock_overlay) + lb_e_2.setObjectName(u"lb_e_2") + h_layout.addWidget(lb_e_2) + + h_layout.setStretch(0, 5) + h_layout.setStretch(1, 2) + h_layout.setStretch(2, 3) + h_layout.setStretch(3, 5) + v_layout.addLayout(h_layout) + return le_password + + self.set_shortcuts(False) + if not self.lock_overlay: + self.lock_overlay = QWidget(self) + + self.lock_overlay.setObjectName("w_overlay") + cx = random.random() + cy = random.random() + stop1 = random.random() + stop2 = random.random() + angle = random.randint(0, 360) + self.lock_overlay.setStyleSheet(f"""background: qconicalgradient(cx:{cx}, cy:{cy}, angle:{angle}, stop:0 #f6f8fa, stop:{stop1} #eef1f5, stop:{stop2} #dce1e8);""") + # self.lock_overlay.setStyleSheet("""background: qconicalgradient(cx:0.5, cy:0.5, angle:45, stop:0 #f6f8fa, stop:0.5 #eef1f5, stop:1 #dce1e8);""") + + le_password = gen_lock_screen() + le_password.returnPressed.connect(unlock) + self.lock_overlay.setGeometry(self.rect()) + self.lock_overlay.show() + le_password.setFocus() + + def set_shortcuts(self, stat: bool = True): + if stat: + self.ac_homepage.setShortcut(QKeySequence("Ctrl+Alt+H")) + self.ac_settings.setShortcut(QKeySequence("Ctrl+Alt+S")) + self.ac_logs.setShortcut(QKeySequence("Ctrl+Alt+L")) + self.ac_about.setShortcut(QKeySequence("Ctrl+Alt+A")) + self.ac_caging.setShortcut(QKeySequence("Ctrl+Alt+C")) + self.ac_quit.setShortcut(QKeySequence("Ctrl+Alt+Q")) + else: + self.ac_homepage.setShortcut(QKeySequence()) + self.ac_settings.setShortcut(QKeySequence()) + self.ac_logs.setShortcut(QKeySequence()) + self.ac_about.setShortcut(QKeySequence()) + self.ac_caging.setShortcut(QKeySequence()) + self.ac_quit.setShortcut(QKeySequence()) + + def resizeEvent(self, event: QResizeEvent): + super().resizeEvent(event) + if self.lock_overlay: + self.lock_overlay.setGeometry(self.rect()) + + def closeEvent(self, event): + reply = QMessageBox.question(self, "退出", "\n程序可能在运行,确定要退出吗?") + if reply == QMessageBox.StandardButton.Yes: + db_operation.db_close(self.conn, self.cursor) + event.accept() + else: + event.ignore() + + if __name__ == '__main__': app = QApplication(sys.argv) login = LoginWindow()