Exemplo n.º 1
0
class LoginFNS(QDialog, Ui_LoginFNSDialog):
    def __init__(self, db, parent=None):
        QDialog.__init__(self, parent=parent)
        self.setupUi(self)
        self.db = db

        self.web_session = requests.Session()
        self.web_profile = QWebEngineProfile()
        self.web_interceptor = RequestInterceptor()
        self.web_interceptor.response_intercepted.connect(self.response_esia)
        self.web_profile.setRequestInterceptor(self.web_interceptor)
        self.ESIAWebView.setPage(QWebEnginePage(self.web_profile, self))

        self.LoginMethodTabs.currentChanged.connect(self.on_tab_changed)
        self.FNSLoginBtn.clicked.connect(self.login_fns)

    def on_tab_changed(self, index):
        if index == 1:  # ESIA login selected
            self.login_esia()

    def login_fns(self):
        client_secret = readSQL(
            self.db,
            "SELECT value FROM settings WHERE name='RuTaxClientSecret'")
        inn = self.InnEdit.text()
        password = self.PasswordEdit.text()

        s = requests.Session()
        s.headers['ClientVersion'] = '2.9.0'
        s.headers['Device-Id'] = str(uuid.uuid1())
        s.headers['Device-OS'] = 'Android'
        s.headers['Content-Type'] = 'application/json; charset=UTF-8'
        s.headers['Accept-Encoding'] = 'gzip'
        s.headers['User-Agent'] = 'okhttp/4.2.2'
        payload = '{' + f'"client_secret":"{client_secret}","inn":"{inn}","password":"******"' + '}'
        response = s.post(
            'https://irkkt-mobile.nalog.ru:8888/v2/mobile/users/lkfl/auth',
            data=payload)
        if response.status_code != 200:
            logging.error(
                g_tr('SlipsTaxAPI', "FNS login failed: ") +
                f"{response}/{response.text}")
            return
        logging.info(
            g_tr('SlipsTaxAPI', "FNS login successful: ") + f"{response.text}")
        json_content = json.loads(response.text)
        new_session_id = json_content['sessionId']
        new_refresh_token = json_content['refresh_token']
        _ = executeSQL(
            self.db,
            "UPDATE settings SET value=:new_session WHERE name='RuTaxSessionId'",
            [(":new_session", new_session_id)])
        _ = executeSQL(
            self.db,
            "UPDATE settings SET value=:new_refresh_token WHERE name='RuTaxRefreshToken'",
            [(":new_refresh_token", new_refresh_token)])
        self.db.commit()
        self.accept()

    def login_esia(self):
        self.web_session.headers['ClientVersion'] = '2.9.0'
        self.web_session.headers['Device-Id'] = str(uuid.uuid1())
        self.web_session.headers['Device-OS'] = 'Android'
        self.web_session.headers[
            'Content-Type'] = 'application/json; charset=UTF-8'
        self.web_session.headers['Accept-Encoding'] = 'gzip'
        self.web_session.headers['User-Agent'] = 'okhttp/4.2.2'
        response = self.web_session.get(
            'https://irkkt-mobile.nalog.ru:8888/v2/mobile/users/esia/auth/url')
        if response.status_code != 200:
            logging.error(
                g_tr('SlipsTaxAPI', "Get ESIA URL failed: ") +
                f"{response}/{response.text}")
            return
        json_content = json.loads(response.text)
        auth_url = json_content['url']
        self.ESIAWebView.load(QUrl(auth_url))

    @Slot()
    def response_esia(self, auth_code, state):
        client_secret = readSQL(
            self.db,
            "SELECT value FROM settings WHERE name='RuTaxClientSecret'")
        payload = '{' + f'"authorization_code": "{auth_code}", "client_secret": "{client_secret}", "state": "{state}"' \
                  + '}'
        response = self.web_session.post(
            'https://irkkt-mobile.nalog.ru:8888/v2/mobile/users/esia/auth',
            data=payload)
        if response.status_code != 200:
            logging.error(
                g_tr('SlipsTaxAPI', "ESIA login failed: ") +
                f"{response}/{response.text}")
            return
        logging.info(
            g_tr('SlipsTaxAPI', "ESIA login successful: ") +
            f"{response.text}")
        json_content = json.loads(response.text)
        new_session_id = json_content['sessionId']
        new_refresh_token = json_content['refresh_token']
        _ = executeSQL(
            self.db,
            "UPDATE settings SET value=:new_session WHERE name='RuTaxSessionId'",
            [(":new_session", new_session_id)])
        _ = executeSQL(
            self.db,
            "UPDATE settings SET value=:new_refresh_token WHERE name='RuTaxRefreshToken'",
            [(":new_refresh_token", new_refresh_token)])
        self.db.commit()
        self.accept()
class JWebView(QWebEngineView):
    """ #### Imports: from JAK.WebEngine import JWebView """
    def __init__(self,
                 title="",
                 icon="",
                 web_contents="",
                 debug=False,
                 transparent=False,
                 online=False,
                 url_rules="",
                 cookies_path="",
                 user_agent="",
                 custom_css="",
                 custom_js=""):
        """
        * :param title:str
        * :param icon:str
        * :param web_contents:str
        * :param debug:bool
        * :param transparent:bool
        * :param online:bool
        * :param disable_gpu:bool
        * :param url_rules:dict
        * :param cookies_path:str
        * :param user_agent:str
        * :param custom_css:str
        * :param custom_js:str
        * :param toolbar:dict
        """
        super(JWebView, self).__init__()
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.debug = debug
        self.online = online
        self.home = web_contents
        self.profile = QWebEngineProfile().defaultProfile()
        self.webpage = JWebPage(icon, debug, online, cookies_path, url_rules)
        self.setPage(self.webpage)
        self.page().loadFinished.connect(self._page_load_finish)
        if custom_css:
            # Check for custom CSS
            self.custom_css = custom_css
            print("Custom CSS detected")

        if custom_js:
            # Check for custom JavaScript
            self.custom_js = custom_js
            print("Custom JavaScript detected")

        if url_rules:
            # Check for URL rules
            try:
                self.block_rules = url_rules["block"]
            except KeyError:
                self.block_rules = ""
            finally:
                self.interceptor = Interceptor(debug, self.block_rules)
        else:
            self.interceptor = Interceptor(debug)

        if user_agent:
            # Set user agent
            self.user_agent = user_agent
            self.profile.setHttpUserAgent(user_agent)

        if self.debug:
            # TODO implement webinspector
            self.settings().setAttribute(QWebEngineSettings.XSSAuditingEnabled,
                                         True)
        else:
            self.setContextMenuPolicy(Qt.PreventContextMenu)

        if transparent:
            # Activates background transparency
            self.setAttribute(Qt.WA_TranslucentBackground)
            self.page().setBackgroundColor(Qt.transparent)
            self.setStyleSheet("background:transparent;")
            print(
                "Transparency detected, make sure you set [ body {background:transparent;} ]"
            )

        settings = self.settings()
        # * Set Engine options
        # * TODO: allow to set settings per application by passing a list
        settings.setAttribute(QWebEngineSettings.JavascriptCanPaste, True)
        settings.setAttribute(QWebEngineSettings.PlaybackRequiresUserGesture,
                              False)
        settings.setAttribute(QWebEngineSettings.FullScreenSupportEnabled,
                              True)
        settings.setAttribute(
            QWebEngineSettings.AllowWindowActivationFromJavaScript, True)
        settings.setAttribute(
            QWebEngineSettings.LocalContentCanAccessRemoteUrls, True)
        settings.setAttribute(QWebEngineSettings.JavascriptCanAccessClipboard,
                              True)
        settings.setAttribute(QWebEngineSettings.SpatialNavigationEnabled,
                              True)
        settings.setAttribute(QWebEngineSettings.TouchIconsEnabled, True)
        settings.setAttribute(QWebEngineSettings.FocusOnNavigationEnabled,
                              True)
        if online:
            settings.setAttribute(QWebEngineSettings.DnsPrefetchEnabled, True)
            print("Engine online (IPC) Disabled")
            self.page().profile().downloadRequested.connect(
                self._download_requested)

            # Set persistent cookies
            self.profile.setPersistentCookiesPolicy(
                QWebEngineProfile.ForcePersistentCookies)

            # set cookies on user folder
            if cookies_path:
                # allow specific path per application.
                _cookies_path = f"{os.getenv('HOME')}/.jak/{cookies_path}"
            else:
                # use separate cookies database per application
                title = title.lower().replace(" ", "-")
                _cookies_path = f"{os.getenv('HOME')}/.jak/{title}"

            self.profile.setPersistentStoragePath(_cookies_path)
            print(f"Cookies PATH:{_cookies_path}")
        else:
            print("Engine interprocess communication (IPC) up and running:")
            #self.profile.setHttpCacheType(self.profile.MemoryHttpCache)

        self.profile.setRequestInterceptor(self.interceptor)
        print(self.profile.httpUserAgent())
        validate_url(self, web_contents)

    def _page_load_finish(self) -> None:
        result = time.localtime(time.time())
        print(f"Document Ready in: {result.tm_sec} seconds")
        try:
            if self.custom_css:
                print("Custom CSS loaded")
                JavaScript.css(self, self.custom_css)
        except AttributeError:
            pass

        try:
            if self.custom_js:
                print("Custom JavaScript loaded")
                JavaScript.send(self, self.custom_js)
        except AttributeError:
            pass

    def _download_requested(self, download_item) -> None:
        """
        * If a download is requested call a save file dialog
        * :param download_item: file to be downloaded
        """
        from PySide2.QtWidgets import QFileDialog
        self.download_item = download_item
        dialog = QFileDialog(self)
        path = dialog.getSaveFileName(dialog, "Save File",
                                      download_item.path())

        if path[0]:
            print(path)
            download_item.setPath(path[0])
            print(f"downloading file to:( {download_item.path()} )")
            download_item.accept()
            download_item.finished.connect(self._download_finished)

        else:
            print("Download canceled")

    def _download_finished(self) -> None:
        """
        Goes to previous page and pops an alert informing the user that the download is finish and were to find it
        """
        file_path = self.download_item.path()
        msg = f"File Downloaded to: {file_path}"

        try:
            from Widgets import InfoDialog
        except ImportError:
            from JAK.Widgets import InfoDialog
        InfoDialog(self, "Download Complete", msg)
        if self.online:
            self.back()

    def navigate_home(self) -> None:
        """
        Goes back to original application url
        """
        self.load(self.home)