簡體   English   中英

pyqt注銷需要幫助

[英]Need assistance with pyqt logout

我的PyQt5應用程序有問題,不知道如何解決。

在我的Qt托盤應用程序中,有一個與注銷功能連接的用戶注銷操作按鈕。 tray.py注銷的功能應該通過在views.py服務器應用程序上響應我的注銷功能來激活。 views.py中,我具有退出功能,該功能可以返回httpResponse(“用戶已注銷”)。

我的問題是:“當用戶按下該注銷按鈕時如何知道我的桌面pyqt應用程序?因為我收到response.status_code = 200,這僅意味着我僅收到一個頁面,而不是該用戶狀態(如果用戶是登錄或注銷) )”。 似乎一切正常,但不知道如何繼續執行tray.py / logout()中的代碼

桌面應用程序-tray.py

import json
import sys, os, requests, uuid

from Crypto import Random
from Crypto.PublicKey import RSA
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QSystemTrayIcon

from login import LoginForm
from settings import HTTP_PROTOCOL
from settings import SERVER_URL
from timestamp.form import TimestampForm



class SystemTrayIcon(QSystemTrayIcon):

    def __init__(self):
        QSystemTrayIcon.__init__(self)

        self.setIcon(QIcon('icons/icon-placeholder_128x128_red.png'))

        self.http_client = requests.Session()
        self.base_url = '{}://{}'.format(HTTP_PROTOCOL, SERVER_URL)
        self.set_desktop_timezone()


        # Keeping reference to LoginForm object so that window wouldn't close




        self.uuid = self.create_uuid('TTASM')
        self.create_private_key()

        try:
            requests.get(self.base_url)
            self.server_accessible = True
            self.present_login_form()
        except:
            self.server_accessible = False
            pass

        self.set_server_public_key()

        self.create_ui()

    def createURL(self, path):
        return '{}{}'.format(self.base_url, path)

    # Find Desktop's timezone   
    def set_desktop_timezone(self):
        response = requests.get('http://freegeoip.net/json')
        response_json = json.JSONDecoder().decode(response.text)
        self.timezone = response_json['time_zone']

    def verify_initial_data(self):
        url = self.createURL('/initial_synchronization/?timezone={}'.format(self.timezone))
        try:
            response = self.http_client.get(url)
            if response.status_code == 200:
                self.last_timestamp = response.text
            else:
                raise Exception('Server errror: {}'.format(response.status_code))
        except:
            print('Something is wrong with server comms')

    def set_server_public_key(self):
        #get server public key 

        url = self.createURL('/public_key/')
        print('Trying to get the public key from:', url) 

        try:
            response = self.http_client.get(url)
        except:
            print ('No response, server may be down')

        try:
            if response.status_code == 200:
                self.server_rsa_pub  = RSA.importKey(response.text)
                print ('Server private key aquired')
            else:
                print ('Server failed to provide public key')
        except:
            print("\nServer is not responding")
#             self.loginForm.close()

    def create_private_key(self):
        #Create new client RSA private key, public key and public key hash and store them to disk
        random_generator = Random.new().read
        self.client_rsa = RSA.generate(2048, random_generator)
        print ('Client private key created')

#         with open('./clientdata/client_RSA', 'wb') as f:
#             f.write(cl_rsa.exportKey())
#         with open('./clientdata/client_RSA.pub', 'wb') as f:
#             f.write(cl_rsa.publickey().exportKey())
#         with open('./clientdata/client_RSA.hash', 'w') as f:
#             f.write(SHA256.new(cl_rsa.publickey().exportKey()).hexdigest())

    print ('Client keys created')

    def create_ui(self):
        """Create user interface of Tray icon"""

        mainMenu = QMenu()
        subMenu = QMenu(mainMenu)
        subMenu.setTitle("Util")
        subButton_1 = subMenu.addAction("Show token")
        subButton_1.triggered.connect(self.show_token)
        subButton_2 = subMenu.addAction("Test sockets")
        subButton_2.triggered.connect(self.test_sockets)

        # Set the order of layout and add everything to main menu
        self.logInButton = mainMenu.addAction("Log in")
        self.logInButton.triggered.connect(self.present_login_form)

        self.simButton = mainMenu.addAction("Let's pretend server is accessible")
        self.simButton.triggered.connect(self.enable_login_etc)


        mainMenu.addSeparator()
        self.msgButton = mainMenu.addAction("Send message") # find a way how to hide this button to preserve action on it before user's log in action
        self.msgButton.triggered.connect(self.present_timestamp_form)

        if not self.server_accessible:
            self.logInButton.setEnabled(False)
            self.msgButton.setEnabled(False)


        mainMenu.addSeparator()
        mainMenu.addMenu(subMenu)
        mainMenu.addSeparator()
        self.logoutButton = mainMenu.addAction("Log out")
        self.logoutButton.triggered.connect(self.logout)
        self.logoutButton.setEnabled(False)
        mainMenu.addSeparator()
        exitButton = mainMenu.addAction("Exit")
        exitButton.triggered.connect(self.quit)


        self.setContextMenu(mainMenu)


    def enable_login_etc(self):
        self.logInButton.setEnabled(True)
        self.msgButton.setEnabled(True)

    def toggle_login_logout_button(self):
        self.logInButton.setEnabled(False)
        self.logoutButton.setEnabled(True)

    def create_uuid(self, UUID_string):
        return uuid.uuid3(uuid.NAMESPACE_DNS, UUID_string)

    def change_icon_on_login(self):
        self.setIcon(QIcon('icons/icon-placeholder_128x128_green.png'))

    def present_login_form(self):
        self.login_form = LoginForm(self)
        self.login_form.show()

    def present_timestamp_form(self):
        url = self.createURL('/last_activity_duration/')
        response = self.http_client.get(url)
        self.timestamp_form = TimestampForm(self, response.text)
        self.timestamp_form.show()

    def show_token(self):
        """Placeholder function"""

        try:
            self.showMessage('Token',
                             self.token,
                             QSystemTrayIcon.Information,
                             3000)
        except:
            self.showMessage('Token',
                             'No token received',
                             QSystemTrayIcon.Information,
                             3000)
    def test_sockets(self):
        """Placeholder function"""

        self.showMessage('Testing',
                         'Pending implementation',
                         QSystemTrayIcon.Information,
                         3000)

    #How to logout currently logged in user through get request
    def logout(self):
        url = self.createURL('/user_logout/')
        response = self.http_client.get(url)
        if response.status_code == 200:
            print("Response from view >>>>>>>", response.text)

          **WHAT TO DO HERE?**  


    def quit(self):
        """Exit program in a clean way."""
        if os.path.isfile('pid'):
            os.remove('pid') 
            print ("Deleting pid file")
        print ("Exiting")
        sys.exit(0)

服務器應用-urls.py

url(r'^user_logout/$', views.user_logout, name='user_logout'),

服務器應用程序-views.py

@verified_email_required  
def user_logout(request):
    print(request.user)
    logout(request)
    return HttpResponse('User is logged out')

我的login.py。 這就是我進行用戶登錄的方式。

from PyQt5 import QtCore
from PyQt5.QtWidgets import QDesktopWidget
from PyQt5.QtWidgets import QFormLayout, QHBoxLayout, QMessageBox
from PyQt5.QtWidgets import QLabel, QLineEdit, QPushButton
from PyQt5.QtWidgets import QWidget



#from utility import encrypt_data

class LoginForm(QWidget):

def __init__(self, parent_tray):
    super(LoginForm, self).__init__()

    # keeping reference to parent
    self.parent_tray = parent_tray

    # define fixed size
    self.fixedWidth = 250
    self.fixedHeight = 100

    # no min, max, close button
    self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint |
                        QtCore.Qt.CustomizeWindowHint |
                        QtCore.Qt.WindowTitleHint)

    self.create_ui()
    self.move_to_primary_center()
    self.setWindowTitle("Log in")


def create_ui(self):
    """Create user interface for login popup window"""

    emailLabel = QLabel("Email:")
    passwordLabel = QLabel("Password:")
    self.email = QLineEdit()
    self.password = QLineEdit()
    print (self.email.whatsThis())

    self.email.setPlaceholderText("Enter your email")
    self.password.setPlaceholderText("Enter your password")



    # Show asterisk in input instead of password chars
    self.password.setEchoMode(QLineEdit.Password)

    submitButton = QPushButton("Submit")

    # Usign lambda because Qt doesn't allow for arguments to by passed to slots
    # And we want to keep email and password as a private variables so we
    # don't want to make them direct members of Class and call them with self
    # directly inside self.submit() function
    submitButton.clicked.connect(lambda: self.submit(self.parent_tray,
                                                     self.email.text(),
                                                     self.password.text()))

    # Enter pressed inside password line edit
    self.password.returnPressed.connect(lambda: self.submit(self.parent_tray,
                                                       self.email.text(),
                                                       self.password.text()))

    self.email.returnPressed.connect(self.password.setFocus)

    cancelButton = QPushButton("Cancel")
    cancelButton.clicked.connect(self.cancel)

    #Design a form layout
    formBox = QFormLayout()
    formBox.addRow(emailLabel, self.email)
    formBox.addRow(passwordLabel, self.password)

    # sign up label / link
    signUpLabel = QLabel()
    signUpLabel.setText('<a href="http://localhost:8000/sign-up/">Sign Up</a>')
    signUpLabel.setOpenExternalLinks(True)
    signUpLabel.show()

    # recover password link
    recoverLabel = QLabel()
    recoverLabel.setText('<a href="http://localhost:8000/recover-password/">Forgot your password?</a>')
    recoverLabel.setOpenExternalLinks(True)
    recoverLabel.show()

    # build sign up row
    signUpRow = QHBoxLayout()
    signUpRow.addWidget(signUpLabel)
    signUpRow.addWidget(recoverLabel)

    #add sign up row
    formBox.addRow(signUpRow)


    buttonRow = QHBoxLayout()
    buttonRow.addWidget(submitButton)
    buttonRow.addWidget(cancelButton)

    # add button row
    formBox.addRow(buttonRow)

    # Set layout for the Login Form (self)
    self.setLayout(formBox)

    try:
        last_user = open ('last_user', 'r').read()
        self.email.setText(last_user)
        self.password.setFocus()
    except:
        pass

    # Disable resize
    self.setFixedSize(self.fixedWidth, self.fixedHeight)

def move_to_primary_center(self):
    """Reposition window to center of primary screen"""

    desktop = QDesktopWidget()
    primaryScreenIndex = desktop.primaryScreen()
    rectScreenPrimarty = desktop.screenGeometry(primaryScreenIndex)

    # center in the middle of screen, considering window's own size
    self.move(rectScreenPrimarty.center().x() - self.fixedWidth/2,
              rectScreenPrimarty.center().y() - self.fixedHeight/2)


def submit(self, parentTray, email, password):
    """Send data to server."""

    if not email or not password:

        msgBox = QMessageBox()
        info_text = []
        if not email:
            info_text.append('Email cannot be empty!')
        if not password:
            info_text.append('Password cannot be empty!')

        joined_info_text = '\n \n'.join(info_text)

        msgBox.setInformativeText(joined_info_text)
        msgBox.setIcon(QMessageBox.Information)
        msgBox.setWindowTitle("Oops!")

        msgBox.setStandardButtons(QMessageBox.Ok)
        msgBox.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        msgBox.exec()

    else:
        url = parentTray.createURL('/accounts/login/')
        print('Trying to authenticate on', url)
        try:
            response = self.parent_tray.http_client.post(
                url,
                headers = {
                    'X-CSRFToken':self.parent_tray.http_client.cookies.get('csrftoken'),
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                data={
                    'login' : email,
                    'password' : password,
                    'client_public_key' : self.parent_tray.client_rsa.publickey().exportKey(),
                    'uuid' : parentTray.uuid
                }
            )
            print(parentTray.uuid)
        except Exception as e:
            print ('No response, server may be down')

        if response.status_code != 200:
            msgBox = QMessageBox()
            msgBox.setInformativeText('Invalid email and/or password')
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Oops!")

            msgBox.setStandardButtons(QMessageBox.Ok)
            msgBox.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
            msgBox.exec()
            self.show()
            return False

        else: # if user logged in successfully
            parentTray.change_icon_on_login()
            parentTray.verify_initial_data()
            with open ('last_user' ,'w') as f:
                f.write(email) 
            self.parent_tray.showMessage('Success',
                 'You are logged in as {}'.format(email),
                 parentTray.Information,
                 3000)
            self.close()



def cancel(self):
    """Close password input"""
    self.close()

這是一個意見問題,取決於您希望應用程序體系結構(前端和后端)如何運行。

如果我在做django的事情作為桌面應用程序的后端,那么我會將其編寫為API並使用JWOT身份驗證。 這樣,我的身份驗證狀態將僅使用令牌,我可以設置令牌的到期限制,並且每個請求都將需要此令牌作為身份驗證的形式。

我沒有看到僅表單顯示形式的登錄方法,您究竟如何登錄用戶並跟蹤該狀態? 如果您回答此問題,將更容易回答注銷問題。

抱歉,根據StackOverflow的出色規定,尚無法評論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM