237 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import sys
 | 
						|
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTabWidget, QLineEdit, QMessageBox, QSizePolicy
 | 
						|
from PySide6.QtCore import Qt, QSize
 | 
						|
from PySide6.QtGui import QFont, QIcon, QPixmap, QShortcut
 | 
						|
from codes.common import clibs, db_operation
 | 
						|
from codes.common.secure_encrypt import PassCipher
 | 
						|
from codes.ui import main_ui
 | 
						|
from codes.common.exception_handler import handle_exception
 | 
						|
 | 
						|
 | 
						|
class LoginWindow(QWidget):
 | 
						|
    def __init__(self):
 | 
						|
        super().__init__()
 | 
						|
        self.predos()
 | 
						|
        self.init_ui()
 | 
						|
        self.setup_slot()
 | 
						|
 | 
						|
    def predos(self):
 | 
						|
        db_operation.db_init()
 | 
						|
        db_operation.db_conn()
 | 
						|
 | 
						|
    def init_ui(self):
 | 
						|
        self.setMinimumSize(420, 200)
 | 
						|
        self.setMaximumSize(500, 240)
 | 
						|
        self.resize(480, 200)
 | 
						|
        self.setWindowTitle("登录")
 | 
						|
        self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico"))
 | 
						|
        self.setFont(QFont("Consolas", 14))
 | 
						|
 | 
						|
        self.layout_outer = QHBoxLayout()
 | 
						|
        self.lb_logo = QLabel()
 | 
						|
        self.lb_logo.setAlignment(Qt.AlignmentFlag.AlignCenter)
 | 
						|
        self.lb_logo.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred)
 | 
						|
        self.lb_logo.setPixmap(QPixmap(f"{clibs.base_path}/assets/media/logo.png"))
 | 
						|
        self.lb_logo.setFixedSize(QSize(120, 120))
 | 
						|
        self.lb_logo.setScaledContents(True)
 | 
						|
        self.layout_outer.addWidget(self.lb_logo)
 | 
						|
 | 
						|
        self.tabW_login = QTabWidget()
 | 
						|
        self.tab_login = QWidget()
 | 
						|
        self.tabW_login.addTab(self.tab_login, "登录")
 | 
						|
        self.tab_register = QWidget()
 | 
						|
        self.tabW_login.addTab(self.tab_register, "注册")
 | 
						|
        self.layout_outer.addWidget(self.tabW_login)
 | 
						|
 | 
						|
        # 登陆页面
 | 
						|
        self.layout_H_username = QHBoxLayout()
 | 
						|
        self.lb_username = QLabel("账号")
 | 
						|
        self.lb_username.setAlignment(Qt.AlignmentFlag.AlignCenter)
 | 
						|
        self.layout_H_username.addWidget(self.lb_username)
 | 
						|
        self.le_username = QLineEdit()
 | 
						|
        self.le_username.setFocus()
 | 
						|
        self.layout_H_username.addWidget(self.le_username)
 | 
						|
 | 
						|
        self.layout_H_password = QHBoxLayout()
 | 
						|
        self.lb_password = QLabel("密码")
 | 
						|
        self.lb_password.setAlignment(Qt.AlignmentFlag.AlignCenter)
 | 
						|
        self.layout_H_password.addWidget(self.lb_password)
 | 
						|
        self.le_password = QLineEdit()
 | 
						|
        self.le_password.setEchoMode(QLineEdit.EchoMode.Password)
 | 
						|
        self.layout_H_password.addWidget(self.le_password)
 | 
						|
 | 
						|
        self.layout_H_button = QHBoxLayout()
 | 
						|
        self.btn_login = QPushButton("登录")
 | 
						|
        self.btn_login.setAutoDefault(True)
 | 
						|
        self.btn_cancel = QPushButton("取消")
 | 
						|
        self.btn_cancel.setAutoDefault(True)
 | 
						|
        self.layout_H_button.addWidget(self.btn_login)
 | 
						|
        self.layout_H_button.addWidget(self.btn_cancel)
 | 
						|
 | 
						|
        self.layout_V_user_pass = QVBoxLayout()
 | 
						|
        self.layout_V_user_pass.addLayout(self.layout_H_username)
 | 
						|
        self.layout_V_user_pass.addLayout(self.layout_H_password)
 | 
						|
        self.layout_V_user_pass.addLayout(self.layout_H_button)
 | 
						|
        self.tab_login.setLayout(self.layout_V_user_pass)
 | 
						|
 | 
						|
        # 注册页面
 | 
						|
        self.layout_H_username_reg = QHBoxLayout()
 | 
						|
        self.lb_username_reg = QLabel("账号设定")
 | 
						|
        self.lb_username_reg.setAlignment(Qt.AlignmentFlag.AlignCenter)
 | 
						|
        self.layout_H_username_reg.addWidget(self.lb_username_reg)
 | 
						|
        self.le_username_reg = QLineEdit()
 | 
						|
        self.le_username_reg.setFocus()
 | 
						|
        self.layout_H_username_reg.addWidget(self.le_username_reg)
 | 
						|
 | 
						|
        self.layout_H_password_reg = QHBoxLayout()
 | 
						|
        self.lb_password_reg = QLabel("密码设定")
 | 
						|
        self.lb_password_reg.setAlignment(Qt.AlignmentFlag.AlignCenter)
 | 
						|
        self.layout_H_password_reg.addWidget(self.lb_password_reg)
 | 
						|
        self.le_password_reg = QLineEdit()
 | 
						|
        self.le_password_reg.setEchoMode(QLineEdit.EchoMode.Password)
 | 
						|
        self.layout_H_password_reg.addWidget(self.le_password_reg)
 | 
						|
 | 
						|
        self.layout_H_password_reg_confirm = QHBoxLayout()
 | 
						|
        self.lb_password_reg_confirm = QLabel("密码确认")
 | 
						|
        self.lb_password_reg_confirm.setAlignment(Qt.AlignmentFlag.AlignCenter)
 | 
						|
        self.layout_H_password_reg_confirm.addWidget(self.lb_password_reg_confirm)
 | 
						|
        self.le_password_reg_confirm = QLineEdit()
 | 
						|
        self.le_password_reg_confirm.setEchoMode(QLineEdit.EchoMode.Password)
 | 
						|
        self.layout_H_password_reg_confirm.addWidget(self.le_password_reg_confirm)
 | 
						|
 | 
						|
        self.layout_H_button_reg = QHBoxLayout()
 | 
						|
        self.btn_login_reg = QPushButton("确认")
 | 
						|
        self.btn_login_reg.setAutoDefault(True)
 | 
						|
        self.btn_cancel_reg = QPushButton("取消")
 | 
						|
        self.btn_cancel_reg.setAutoDefault(True)
 | 
						|
        self.layout_H_button_reg.addWidget(self.btn_login_reg)
 | 
						|
        self.layout_H_button_reg.addWidget(self.btn_cancel_reg)
 | 
						|
 | 
						|
        self.layout_V_user_pass_reg = QVBoxLayout()
 | 
						|
        self.layout_V_user_pass_reg.addLayout(self.layout_H_username_reg)
 | 
						|
        self.layout_V_user_pass_reg.addLayout(self.layout_H_password_reg)
 | 
						|
        self.layout_V_user_pass_reg.addLayout(self.layout_H_password_reg_confirm)
 | 
						|
        self.layout_V_user_pass_reg.addLayout(self.layout_H_button_reg)
 | 
						|
        self.tab_register.setLayout(self.layout_V_user_pass_reg)
 | 
						|
 | 
						|
        self.setLayout(self.layout_outer)
 | 
						|
        self.le_username.setFocus()
 | 
						|
 | 
						|
    def setup_slot(self):
 | 
						|
        self.tabW_login.currentChanged.connect(self.onChange_tabW)
 | 
						|
        self.btn_login.clicked.connect(self.login_check)
 | 
						|
        self.btn_cancel.clicked.connect(self.close)
 | 
						|
        self.btn_login_reg.clicked.connect(self.register_check)
 | 
						|
        self.btn_cancel_reg.clicked.connect(self.close)
 | 
						|
        self.le_password.returnPressed.connect(self.login_check)
 | 
						|
        self.le_password_reg_confirm.returnPressed.connect(self.register_check)
 | 
						|
        QShortcut("Esc", self).activated.connect(self.close)
 | 
						|
 | 
						|
    def onChange_tabW(self):
 | 
						|
        text = self.tabW_login.tabText(self.tabW_login.currentIndex())
 | 
						|
        if text == "登录":
 | 
						|
            self.le_username.clear()
 | 
						|
            self.le_password.clear()
 | 
						|
            self.le_username.setFocus()
 | 
						|
        elif text == "注册":
 | 
						|
            self.le_username_reg.clear()
 | 
						|
            self.le_password_reg.clear()
 | 
						|
            self.le_password_reg_confirm.clear()
 | 
						|
            self.le_username_reg.setFocus()
 | 
						|
 | 
						|
    @handle_exception()
 | 
						|
    def login_check(self):
 | 
						|
        def login_failed(flag: int = 0):
 | 
						|
            reason = {-1: "用户名或密码为空", 0: "用户名未注册", 1: "解迷成功,密码错误", 2: "解迷失败,密码错误", 3: "数据库中有重复的用户名"}
 | 
						|
            self.le_username.clear()
 | 
						|
            self.le_password.clear()
 | 
						|
            self.le_username.setFocus()
 | 
						|
            QMessageBox.critical(self, "错误", "账号或密码错误,请重新输入!")
 | 
						|
            raise Exception(f"username:{username} login failed, reason: {reason[flag]}")
 | 
						|
 | 
						|
        def validate_login():
 | 
						|
            nonlocal username, password
 | 
						|
            record = db_operation.db_query_users(username)
 | 
						|
            if username == "" or password == "":
 | 
						|
                login_failed(flag=-1)
 | 
						|
 | 
						|
            if len(record) == 0:
 | 
						|
                login_failed(flag=0)
 | 
						|
            elif len(record) == 1:
 | 
						|
                keys = ["id", "timestamp", "username", "password", "salt"]
 | 
						|
                login_info = dict(zip(keys, record[0]))
 | 
						|
                salt = PassCipher.gen_salt("@".join([username, password]))
 | 
						|
                cipher = PassCipher(salt)
 | 
						|
                try:
 | 
						|
                    decrypt_password = cipher.decrypt(login_info["password"])
 | 
						|
                    if password != decrypt_password:
 | 
						|
                        login_failed(flag=1)
 | 
						|
                    else:
 | 
						|
                        self.mainWindow = main_ui.MainWindow()
 | 
						|
                        self.mainWindow.show()
 | 
						|
                        clibs.username = username
 | 
						|
                        clibs.password = password
 | 
						|
                        db_operation.db_write_logs(f"username:{username} 登录成功!")
 | 
						|
                        db_operation.db_close()
 | 
						|
                        self.deleteLater()
 | 
						|
                except ValueError:
 | 
						|
                    login_failed(flag=2)
 | 
						|
            else:
 | 
						|
                login_failed(flag=3)
 | 
						|
 | 
						|
        username = self.le_username.text()
 | 
						|
        password = self.le_password.text()
 | 
						|
        validate_login()
 | 
						|
 | 
						|
    @handle_exception()
 | 
						|
    def register_check(self):
 | 
						|
        def register_failed(flag: int = 0):
 | 
						|
            reason = {-1: "用户名或密码为空", 0: "两次密码不一致", 1: "密码长度不合规", 2: "用户名已存在", 3: "数据库中有重复的用户名"}
 | 
						|
            self.le_username_reg.clear()
 | 
						|
            self.le_password_reg.clear()
 | 
						|
            self.le_password_reg_confirm.clear()
 | 
						|
            self.le_username_reg.setFocus()
 | 
						|
            QMessageBox.critical(self, "错误", "账号错误,密码长度(>8)不合规,或两次输入密码不一致,请确认后重新输入!")
 | 
						|
            raise Exception(f"register failed, reason: {reason[flag]}")
 | 
						|
 | 
						|
        def validate_register():
 | 
						|
            nonlocal username, password, password_confirm
 | 
						|
            record = db_operation.db_query_users(username)
 | 
						|
            if username == "" or password == "" or password_confirm == "":
 | 
						|
                register_failed(flag=-1)
 | 
						|
 | 
						|
            if password != password_confirm:
 | 
						|
                register_failed(flag=0)
 | 
						|
 | 
						|
            if len(password) < clibs.config["minimum_password_length"]:
 | 
						|
                register_failed(flag=1)
 | 
						|
 | 
						|
            if len(record) == 0:
 | 
						|
                salt = PassCipher.gen_salt("@".join([username, password]))
 | 
						|
                cipher = PassCipher(salt)
 | 
						|
                password_encrypted = cipher.encrypt(password)
 | 
						|
                db_operation.db_write_users(username, password_encrypted, salt)
 | 
						|
                QMessageBox.information(self, "成功", "注册成功,切换至登录窗口进行登录!")
 | 
						|
                self.tabW_login.setCurrentIndex(self.tabW_login.indexOf(self.tab_login))
 | 
						|
            elif len(record) == 1:
 | 
						|
                register_failed(flag=2)
 | 
						|
            else:
 | 
						|
                register_failed(flag=3)
 | 
						|
 | 
						|
        username = self.le_username_reg.text()
 | 
						|
        password = self.le_password_reg.text()
 | 
						|
        password_confirm = self.le_password_reg_confirm.text()
 | 
						|
        validate_register()
 | 
						|
 | 
						|
    def closeEvent(self, event):
 | 
						|
        db_operation.db_close()
 | 
						|
        event.accept()
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    app = QApplication(sys.argv)
 | 
						|
    window = LoginWindow()
 | 
						|
    window.show()
 | 
						|
    sys.exit(app.exec())
 | 
						|
 |