def on_load(self): msg = CleanText('//div[@class="confirmation"]//span[span]')(self.doc) self.logger.warning('Password expired.') if not self.browser.rotating_password: raise BrowserPasswordExpired(msg) if not self.looks_legit(self.browser.password): # we may not be able to restore the password, so reject it self.logger.warning('Unable to restore it, it is not legit.') raise BrowserPasswordExpired(msg) new_passwords = [] for i in range(self.NOT_REUSABLE_PASSWORDS_COUNT): new_pass = ''.join( [str((int(l) + i + 1) % 10) for l in self.browser.password]) if not self.looks_legit(new_pass): self.logger.warning('One of rotating password is not legit') raise BrowserPasswordExpired(msg) new_passwords.append(new_pass) current_password = self.browser.password for new_pass in new_passwords: self.logger.warning('Renewing with temp password') if not self.browser.change_pass(current_password, new_pass): self.logger.warning('New temp password is rejected, giving up') raise BrowserPasswordExpired(msg) current_password = new_pass if not self.browser.change_pass(current_password, self.browser.password): self.logger.error('Could not restore old password!') self.logger.warning('Old password restored.')
def on_load(self): if not self.looks_legit(self.browser.password): # we may not be able to restore the password, so reject it raise BrowserPasswordExpired() new_pass = ''.join( [str((int(l) + 1) % 10) for l in self.browser.password]) self.logger.warning( 'Password expired. Renewing it. Temporary password is %s', new_pass) if not self.change_pass(self.browser.password, new_pass): self.logger.warning('New temp password is rejected, giving up') raise BrowserPasswordExpired() if not self.change_pass(new_pass, self.browser.password): self.logger.error('Could not restore old password!')
def iter_accounts(self): if self.type == '1': self.ti_card_go() elif self.type == '2': self.accounts.go() if self.error.is_here(): raise BrowserPasswordExpired() if self.type == '1': for account in self.page.iter_accounts(rib=None): self.page.expand(account=account) account.coming = self.page.get_balance() yield account if self.type == '2': for rib in self.page.get_rib_list(): self.accounts.stay_or_go() self.page.expand(rib=rib) accounts = list(self.page.iter_accounts(rib=rib)) ids = {} prev_rib = None for account in accounts: if account.id in ids: self.logger.warning('duplicate account %r', account.id) account.id += '_%s' % ''.join(account.label.split()) if prev_rib != account._rib: self.coming.go() self.page.expand(rib=account._rib) account.coming = self.page.get_balance(account) prev_rib = account._rib ids[account.id] = account yield account
def on_load(self): # Handle <p class="h1">Modifier mon code personnel </p> # Handle <h1><span class="h1">Modifier votre code personnel</span></h1> msg = CleanText( '//*[@class="h1" and contains(text(), "code personnel")]')( self.doc) if msg: raise BrowserPasswordExpired(msg)
def do_login(self): self.login.go().login(self.username, self.password) if self.accounts.is_here(): expired_error = self.page.get_password_expired() if expired_error: raise BrowserPasswordExpired(expired_error) # Force redirection to entry page if the redirect page does not contain an url if self.redirect.is_here(): self.entrypage.go() if self.entrypage.is_here() or self.login.is_here(): error = self.page.get_error() if error: if 'code confidentiel à la première connexion' in error: raise BrowserPasswordExpired(error) raise BrowserIncorrectPassword(error) if not self.logged: raise BrowserIncorrectPassword()
def do_login(self): self.login.go() self.page.login(self.username, self.password) if self.login.is_here(): if 'acceptation' in self.url: raise ActionNeeded("Veuillez accepter les conditions générales d'utilisation sur le site.") else: raise BrowserIncorrectPassword("L'identifiant ou le mot de passe est incorrect.") elif self.migration.is_here(): # Usually landing here when customers have to renew their credentials message = self.page.get_error() raise BrowserPasswordExpired(message)
def iter_accounts(self): if not self.accounts: self.acc_home.go() if self.error.is_here(): raise BrowserPasswordExpired() self.page.expand() for acc in self.page.iter_accounts(): if acc.id in [a.id for a in self.accounts]: # TODO apply that id to all accounts acc.id = "%s_%s" % (acc.id, ''.join(acc.label.split())) self.accounts.append(acc) for acc in self.accounts: yield acc
def do_login(self): self.login_cas.go() try: self.page.login(self.username, self.password) except ClientError as e: if e.response.status_code == 401: raise BrowserIncorrectPassword() raise if not self.page.is_logged(): raise BrowserIncorrectPassword(self.page.get_error_message()) self.dashboard.go() if self.password_expired.is_here(): raise BrowserPasswordExpired(self.page.get_error_message())
def do_login(self): assert isinstance(self.username, basestring) assert isinstance(self.password, basestring) try: self.loginpage.stay_or_go().login(self.username, self.password) except ClientError as error: if error.response.status_code == 401: raise BrowserIncorrectPassword() if error.response.status_code == 403: # occur when user try several times with a bad password, orange block his account for a short time raise BrowserIncorrectPassword(error.response.json()) raise if self.password_page.is_here(): error_message = self.page.get_change_password_message() if error_message: raise BrowserPasswordExpired(error_message)
def on_load(self): if self.doc['commun']['statut'].lower() == 'nok': reason = self.doc['commun']['raison'] if reason == 'SYD-COMPTES-UNAUTHORIZED-ACCESS': raise NoAccountsException( "Vous n'avez pas l'autorisation de consulter : {}".format( reason)) elif reason == 'niv_auth_insuff': raise BrowserIncorrectPassword( 'Vos identifiants sont incorrects') elif reason == 'chgt_mdp_oblig': raise BrowserPasswordExpired( 'Veuillez renouveler votre mot de passe') elif reason == 'oob_insc_oblig': raise AuthMethodNotImplemented( "L'authentification par Secure Access n'est pas prise en charge" ) raise BrowserUnavailable(reason)
def on_load(self): if self.doc['commun']['statut'].lower() == 'nok': reason = self.doc['commun']['raison'] if reason == 'SYD-COMPTES-UNAUTHORIZED-ACCESS': raise NoAccountsException( "Vous n'avez pas l'autorisation de consulter : {}".format( reason)) elif reason == 'niv_auth_insuff': return elif reason in ('chgt_mdp_oblig', 'chgt_mdp_init'): raise BrowserPasswordExpired( 'Veuillez vous rendre sur le site de la banque pour renouveler votre mot de passe' ) elif reason == 'oob_insc_oblig': raise AuthMethodNotImplemented( "L'authentification par Secure Access n'est pas prise en charge" ) else: # the BrowserUnavailable was raised for every unknown error, and was masking the real error. # So users and developers didn't know what kind of error it was. assert False, 'Error %s is not handled yet.' % reason
def on_load(self): if self.doc.xpath('//h1[contains(text(), "Erreur")]'): raise BrowserUnavailable(CleanText('//h1[contains(text(), "Erreur")]//span')(self.doc)) msg = CleanText('//div[@class="x-attentionErreur"]/b')(self.doc) if 'vous devez modifier votre code confidentiel' in msg: raise BrowserPasswordExpired(msg)
def do_login(self): """ Attempt to log in. Note: this method does nothing if we are already logged in. """ # Among the parameters used during the login step, there is # a connection type (called typeAccount) that can take the # following values: # WE: espace particulier # WP: espace pro # WM: personnes protégées # EU: Cenet # # A connection can have one connection type as well as many of # them. There is an issue when there is many connection types: # the connection type to use can't be guessed in advance, we # have to test all of them until the login step is successful # (sometimes all connection type can be used for the login, sometimes # only one will work). # # For simplicity's sake, we try each connection type from first to # last (they are returned in a list by the first request) # # Examples of connection types combination that have been seen so far: # [WE] # [WP] # [WE, WP] # [WE, WP, WM] # [WP, WM] # [EU] # [EU, WE] (EU tends to come first when present) if not self.username or not self.password: raise BrowserIncorrectPassword() # Retrieve the list of types: can contain a single type or more # - when there is a single type: all the information are available # - when there are several types: an additional request is needed try: connection = self.login.go(login=self.username) # The website crash sometime when the module is not on caissedepargne (on linebourse, for exemple). # The module think is not connected anymore, so we go to the home logged page. If there are no error # that mean we are already logged and now, on the good website except ValueError: self.home.go() if self.home.is_here(): return # If that not the case, that's an other error that we have to correct raise data = connection.get_response() if data is None: raise BrowserIncorrectPassword() accounts_types = data.get('account', []) if not self.nuser and 'WE' not in accounts_types: raise BrowserIncorrectPassword( "Utilisez Caisse d'Épargne Professionnels et renseignez votre nuser pour connecter vos comptes sur l'epace Professionels ou Entreprises." ) if len(accounts_types) > 1: # Additional request when there is more than one connection type # to "choose" from the list of connection types self.multi_type = True if self.inexttype < len(accounts_types): if accounts_types[self.inexttype] == 'EU' and not self.nuser: # when EU is present and not alone, it tends to come first # if nuser is unset though, user probably doesn't want 'EU' self.inexttype += 1 self.typeAccount = accounts_types[self.inexttype] else: assert False, 'should have logged in with at least one connection type' self.inexttype += 1 data = self.account_login.go( login=self.username, accountType=self.typeAccount).get_response() assert data is not None if data.get( 'authMode', '' ) == 'redirect': # the connection type EU could also be used as a criteria raise SiteSwitch('cenet') typeAccount = data['account'][0] if self.multi_type: assert typeAccount == self.typeAccount id_token_clavier = data['keyboard']['Id'] vk = CaissedepargneKeyboard(data['keyboard']['ImageClavier'], data['keyboard']['Num']['string']) newCodeConf = vk.get_string_code(self.password) playload = { 'idTokenClavier': id_token_clavier, 'newCodeConf': newCodeConf, 'auth_mode': 'ajax', 'nuusager': self.nuser.encode('utf-8'), 'codconf': '', # must be present though empty 'typeAccount': typeAccount, 'step': 'authentification', 'ctx': 'typsrv={}'.format(typeAccount), 'clavierSecurise': '1', 'nuabbd': self.username } try: res = self.location(data['url'], params=playload) except ValueError: raise BrowserUnavailable() if not res.page: raise BrowserUnavailable() response = res.page.get_response() assert response is not None if response['error'] == 'Veuillez changer votre mot de passe': raise BrowserPasswordExpired(response['error']) if not response['action']: # the only possible way to log in w/o nuser is on WE. if we're here no need to go further. if not self.nuser and self.typeAccount == 'WE': raise BrowserIncorrectPassword(response['error']) # we tested all, next iteration will throw the assertion if self.inexttype == len( accounts_types ) and 'Temporairement votre abonnement est bloqué' in response[ 'error']: raise ActionNeeded(response['error']) if self.multi_type: # try to log in with the next connection type's value self.do_login() return raise BrowserIncorrectPassword(response['error']) self.BASEURL = urljoin(data['url'], '/') try: self.home.go() except BrowserHTTPNotFound: raise BrowserIncorrectPassword()
def on_load(self): raise BrowserPasswordExpired( u'Vous avez atteint le seuil de 100 connexions avec le même code secret. Par mesure de sécurité, veuillez le changer.' )
def on_load(self): raise BrowserPasswordExpired('New pass needed')
def on_load(self): raise BrowserPasswordExpired( CleanText('//p[@class="message"]')(self.doc))
def on_load(self): msg = CleanText('//div[@id="errors"]')(self.doc) if msg == 'Your password has expired: you must change it.': raise BrowserPasswordExpired(msg)
def on_load(self): message = CleanText('//h3')(self.doc) or CleanText('//h1')(self.doc) raise BrowserPasswordExpired(message)
def on_load(self): raise BrowserPasswordExpired()
def on_load(self): error_msg = CleanText('//fieldset//font[1]/text()', default='')(self.doc) if 'Le code personnel que vous allez choisir' in error_msg: raise BrowserPasswordExpired() assert False, 'Unhandled error on PasswordExpiredPage: %s' % error_msg
def on_load(self): raise BrowserPasswordExpired("Renouvellement de mot de passe requis.")