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)