Пример #1
0
 def do_login(self):
     self.login_page.go()
     self.page.login(self.username, self.password)
     if self.term_page.is_here():
         raise ActionNeeded()
     if self.error_page.is_here() or self.error_page2.is_here():
         alert = self.page.get_error()
         if "account has not been activated" in alert:
             raise ActionNeeded(alert)
         elif "unexpected" in alert:
             raise BrowserUnavailable(alert)
         elif "password" in alert:
             raise BrowserIncorrectPassword(alert)
         else:
             assert False
Пример #2
0
    def check_recipient_status(self):
        transaction_status = Dict('donnees/transaction_status')(self.doc)

        # check add new recipient status
        assert transaction_status in ('available', 'in_progress', 'aborted', 'rejected'), \
            'transaction_status is %s' % transaction_status
        if transaction_status == 'aborted':
            raise AddRecipientTimeout()
        elif transaction_status == 'rejected':
            raise ActionNeeded(
                "La demande d'ajout de bénéficiaire a été annulée.")
        elif transaction_status == 'in_progress':
            raise ActionNeeded(
                'Veuillez valider le bénéficiaire sur votre application bancaire.'
            )
Пример #3
0
 def on_load(self):
     if self.doc.xpath(
             u'//form//h1[contains(text(), "Accusé de reception du chéquier")]'
     ):
         form = self.get_form(name='Alert')
         form['command'] = 'validateAlertMessage'
         form['radioValide_1_2_40003039944'] = 'Non'
         form.submit()
     elif self.doc.xpath(u'//p[@class="cddErrorMessage"]'):
         error_message = CleanText(u'//p[@class="cddErrorMessage"]')(
             self.doc)
         # TODO python2 handles unicode exceptions badly, fix when passing to python3
         raise ActionNeeded(error_message.encode('ascii', 'replace'))
     else:
         raise ActionNeeded(CleanText(u'//form//h1[1]')(self.doc))
Пример #4
0
    def process_action_needed(self):
        # we have to go in an iframe to know if there are CGUs
        url = self.page.get_iframe_url()
        if url:
            self.location(
                self.absurl(url, base=True)
            )  # beware, the landing page might vary according to the referer page. So far I didn't figure out how the landing page is chosen.

            if self.security_page.is_here():
                # Some connections require reinforced security and we cannot bypass the OTP in order
                # to get to the account information. Users have to provide a phone number in order to
                # validate an OTP, so we must raise an ActionNeeded with the appropriate message.
                raise ActionNeeded(
                    'Cette opération sensible doit être validée par un code sécurité envoyé par SMS ou serveur vocal. '
                    'Veuillez contacter le Service Clients pour renseigner vos coordonnées téléphoniques.'
                )

            # if there are skippable CGUs, skip them
            if self.accounts_page.is_here() and self.page.has_action_needed():
                # Look for the request in the event listener registered to the button
                # can be harcoded, no variable part. It is a POST request without data.
                self.location(self.absurl('ReloadContext?action=1&',
                                          base=True),
                              method='POST')
            self.accounts_page.go(
            )  # go back to the accounts page whenever there was an iframe or not

        self.action_needed_processed = True
Пример #5
0
    def do_security_check(self):
        try:
            form = self.get_security_form()
            self.security_check.go(data=form)
        except ServerError as exc:
            # Wrongpass returns a 500 server error...
            exc_json = exc.response.json()
            error = exc_json.get('error')
            if error:
                message = error.get('message', '')
                wrongpass_messages = ("Votre identification est incorrecte", "Vous n'avez plus droit")
                if any(value in message for value in wrongpass_messages):
                    raise BrowserIncorrectPassword()
                if 'obtenir un nouveau code' in message:
                    raise ActionNeeded(message)

                code = error.get('code', '')
                technical_error_messages = ('Un incident technique', 'identifiant et votre code personnel')
                # Sometimes there is no error message, so we try to use the code as well
                technical_error_codes = ('technical_error',)
                if any(value in message for value in technical_error_messages) or \
                   any(value in code for value in technical_error_codes):
                    raise BrowserUnavailable(message)

            # When a PSD2 SCA is required it also returns a 500, hopefully we can detect it
            if (
                exc_json.get('url') == 'dsp2/informations.html'
                or exc_json.get('redirection', '').endswith('dsp2/informations.html')
            ):
                return self.handle_sca()

            raise
Пример #6
0
    def on_load(self):
        if Dict('commun/statut')(self.doc).upper() == 'NOK':
            reason = Dict('commun/raison')(self.doc)
            action = Dict('commun/action')(self.doc)

            if action and 'BLOCAGE' in action:
                raise ActionNeeded()

            if reason and 'err_tech' in reason:
                # This error is temporary and usually do not happens on the next try
                raise TemporaryBrowserUnavailable()

            if ('le service est momentanement indisponible' in reason
                    and Dict('commun/origine')(self.doc) != 'cbo'):
                raise BrowserUnavailable()

            if reason == "niv_auth_insuff":
                return

            conditions = (
                'pas encore géré'
                in reason,  # this page is not handled by SG api website
                'le service est momentanement indisponible'
                in reason,  # can't access new website
            )
            assert any(conditions), 'Error %s is not handled yet' % reason
            self.logger.warning('Handled Error "%s"', reason)
Пример #7
0
 def on_load(self):
     if self.doc.xpath('//div[@class="validation"]'):
         # There is no complete message to fetch on the website but this node appears
         # when we land on a perimeter that has never been visited before.
         raise ActionNeeded("Certains de vos périmètres n'ont encore jamais été visités.\
                             Merci de parcourir tous les périmètres disponibles sur le site \
                             Crédit Agricole et de réaliser les réglages requis pour chaque périmètre.")
Пример #8
0
    def do_login(self):
        if not self.password.isdigit() or len(self.password) not in (6, 7):
            raise BrowserIncorrectPassword()
        if not self.username.isdigit() or len(self.username) < 8:
            raise BrowserIncorrectPassword()
        self.username = self.username[:8]

        self.main_page.go()
        try:
            self.page.login(self.username, self.password)
        except BrowserHTTPNotFound:
            raise BrowserIncorrectPassword()

        assert self.login.is_here()
        reason, action = self.page.get_error()
        if reason == 'echec_authent':
            raise BrowserIncorrectPassword()
        elif reason in (
                'acces_bloq',
                'acces_susp',
                'pas_acces_bad',
        ):
            raise ActionNeeded()
        elif reason == 'err_tech':
            # there is message "Service momentanément indisponible. Veuillez réessayer."
            # in SG website in that case ...
            raise BrowserUnavailable()
Пример #9
0
 def handle_sca(self):
     """
     The ActionNeeded is temporary: we are waiting for an account to implement the SCA.
     We can raise an ActionNeed because a validated SCA is cross web browser: if user performs
     the SCA on its side there will be no SCA anymore on weboob.
     """
     raise ActionNeeded('Vous devez réaliser la double authentification sur le portail internet')
Пример #10
0
    def get_subscription_list(self):
        self.liresite.go(
            json={
                "numPremierSitePage": 0,
                "pageSize": 100000,
                "idTdg": None,
                "critereFiltre": [],
                "critereTri": []
            })
        id_site_list = self.page.get_id_site_list()
        if not id_site_list:
            raise ActionNeeded(
                "Vous ne disposez d'aucun contrat actif relatif à vos sites")

        data = {
            'critereFiltre': [],
            'critereTri': [],
            'idTdg': None,
            'pageSize': 100000,
            'startRowNum': 0
        }

        sub_page = self.subscriptions.go(json=data)
        self.contracts.go(json={
            'refDevisOMList': [],
            'refDevisOHList': id_site_list
        })

        for sub in sub_page.get_subscriptions():
            self.page.update_subscription(sub)
            yield sub
Пример #11
0
    def init_login(self):
        self.login.go()

        # 2FA already done, if valid, login() redirects to home page
        if self.twofa_auth_state:
            self.session.cookies.set('auth_client_state', self.twofa_auth_state['value'])
            self.page.login(self.username, self.password, redirect=True)

        if not self.page.logged:
            # 302 redirect to catch to know if polling
            self.page.login(self.username, self.password)
            self.check_redirections()
            # for cic, there is two redirections
            self.check_redirections()
            if self.twofa_unabled_page.is_here():
                raise ActionNeeded(self.page.get_error_msg())

            # when people try to log in but there are on a sub site of creditmutuel
            if not self.page and not self.url.startswith(self.BASEURL):
                raise BrowserIncorrectPassword()

            if self.login_error.is_here():
                raise BrowserIncorrectPassword()

        if self.verify_pass.is_here():
            raise AuthMethodNotImplemented("L'identification renforcée avec la carte n'est pas supportée.")

        self.check_auth_methods()

        self.getCurrentSubBank()
Пример #12
0
    def do_login(self):
        self.pre_login.go()
        self.wait_until_is_here(self.pre_login)

        self.page.go_login()
        self.wait_until_is_here(self.login)
        self.page.login(self.username, self.password)

        self.wait_until(
            AnyCondition(
                IsHereCondition(self.accueil),
                VisibleXPath('//div[@id="labelQuestion"]'),
                VisibleXPath(
                    '//div[contains(@class, "Notification-error-message")]'),
            ))

        if not self.accueil.is_here():
            assert self.login.is_here(), 'We landed on an unknown page'
            error = self.page.get_error()
            if any((
                    'Votre compte a été désactivé' in error,
                    'Votre compte est bloqué' in error,
            )):
                raise ActionNeeded(error)
            raise BrowserIncorrectPassword(error)
Пример #13
0
    def do_login(self):
        # due to the website change, login changed too, this is for don't try to login with the wrong login
        if self.username.isdigit() and len(self.username) > 7:
            raise ActionNeeded()

        if self.password.isdigit():
            self.account_space_login.go()
            if self.page.get_error_link():
                # Go on information page to get possible error message
                self.location(self.page.get_error_link())

            vk_passwd = self.keyboard.go().get_password(self.password)

            login_data = {
                'email': self.username,
                'password': vk_passwd,
                'rememberIdenfiant': False,
            }

            self.location('https://connect.axa.fr')
            self.login.go(data=login_data, headers={'X-XSRF-TOKEN': self.session.cookies['XSRF-TOKEN']})

        if not self.password.isdigit() or self.page.check_error():
            raise BrowserIncorrectPassword()

        # home page to finish login
        self.location('https://espaceclient.axa.fr/')
Пример #14
0
 def on_load(self):
     if CleanText(
             '//a//span[contains(text(), "J\'ACCEPTE LES CONDITIONS GENERALES D\'UTILISATION") or'
             '          contains(text(), "I ACCEPT THE GENERAL CONDITIONS OF USE")]'
     )(self.doc):
         raise ActionNeeded(
             "Veuillez valider les conditions générales d'utilisation")
Пример #15
0
 def on_load(self):
     if self.doc.xpath(
             '//span[contains(text(), "VO(S) DOCUMENT(S) A SIGNER")]'):
         raise ActionNeeded(
             CleanText(
                 '//div[@class="block"]/p[contains(text(), "Vous avez un ou plusieurs document(s) à signer")]'
             )(self.doc))
Пример #16
0
    def on_load(self):
        HTMLPage.on_load(self)

        msg = CleanText('//div[has-class("form-input-label")]',
                        default='')(self.doc)
        if "prendre connaissance des nouvelles conditions" in msg:
            raise ActionNeeded(msg)

        msg = CleanText('//span[@id="txtErrorAccesBase"]')(self.doc)
        if 'Merci de nous envoyer' in msg:
            raise ActionNeeded(msg)

        # website sometime crash
        if self.doc.xpath(
                u'//div[@id="divError"]/span[contains(text(),"Une erreur est survenue")]'
        ):
            raise BrowserUnavailable()
Пример #17
0
 def on_load(self):
     err_msgs = [
         "vos informations personnelles n'ayant pas été modifiées récemment, nous vous remercions de bien vouloir les compléter",
         "nous vous remercions de mettre à jour et/ou de compléter vos informations personnelles",
     ]
     text = CleanText('//div[@class="block_cadre"]//div/p')(self.doc)
     if any(err_msg in text for err_msg in err_msgs):
         raise ActionNeeded(text)
Пример #18
0
    def get_profile(self):
        if CleanText(Dict('commun/statut', default=''))(self.doc) == 'nok':
            reason = CleanText(Dict('commun/raison', default=''))(self.doc)
            assert reason == 'GDPR', 'Unhandled error : %s' % reason
            raise ActionNeeded(reason)

        profile = Profile()
        profile.name = Format('%s %s', CleanText(Dict('donnees/nom')), CleanText(Dict('donnees/prenom'), default=''))(self.doc)
        return profile
Пример #19
0
 def on_load(self):
     error = (Attr(
         '//input[@required][@id="profile_lei_type_identifier"]',
         'data-message',
         default=None)(self.doc) or CleanText(
             '//h2[@class="page-title"][contains(text(), "Actualisation")]',
             default=None)(self.doc))
     if error:
         raise ActionNeeded(error)
Пример #20
0
 def on_load(self):
     warn = self.doc.xpath(
         u'//div[@id="message_renouvellement_mot_passe"] | \
                            //span[contains(text(), "Votre identifiant change")] | \
                            //span[contains(text(), "Nouveau mot de passe")] | \
                            //span[contains(text(), "Renouvellement de votre mot de passe")] |\
                            //span[contains(text(), "Mieux vous connaître")]'
     )
     if len(warn) > 0:
         raise ActionNeeded(warn[0].text)
Пример #21
0
    def on_load(self):
        # Need to update mail. Try to skip
        msg = "Merci de renseigner votre adresse e-mail"
        if CleanText('//p[@role="heading" and contains(text(), "%s")]' % msg)(self.doc):
            url = Link('//a[contains(., "PASSER CETTE ETAPE")]', default=None)(self.doc)
            if url:
                self.browser.location(url)
            else:
                raise ActionNeeded(msg)

        # Mobile phone update can not be skipped
        msg = "Merci de renseigner votre numéro de téléphone mobile"
        if CleanText('//p[@role="heading" and contains(text(), "%s")]' % msg)(self.doc):
            raise ActionNeeded(msg)

        # CGU, can not bypass
        msg = "Veuillez accepter les conditions générales d'utilisation"
        if CleanText('//p[@role="heading" and contains(text(), "%s")]' % msg)(self.doc):
            raise ActionNeeded(msg)
Пример #22
0
 def on_load(self):
     if self.doc.xpath(
             u'//form//h1[contains(text(), "Accusé de reception du chéquier")]'
     ):
         form = self.get_form(name='Alert')
         form['command'] = 'validateAlertMessage'
         form['radioValide_1_2_40003039944'] = 'Non'
         form.submit()
     else:
         raise ActionNeeded(CleanText(u'//form//h1[1]')(self.doc))
Пример #23
0
 def is_recipient_validated(self):
     authent_state = self.doc['data']['verifAuthentForte'][
         'authentForteDone']
     assert authent_state in (0, 1, 2,
                              3), 'State of authent is %s' % authent_state
     if authent_state == 2:
         raise ActionNeeded(
             "La demande d'ajout de bénéficiaire a été annulée.")
     elif authent_state == 3:
         raise AddRecipientTimeout()
     return authent_state
Пример #24
0
 def do_login(self):
     r = self.do_post_auth()
     if 'gestion-des-erreurs/erreur-pwd' in r.url:
         raise BrowserIncorrectPassword('Bad login/password.')
     if 'gestion-des-erreurs/opposition' in r.url:
         raise BrowserIncorrectPassword('Your account is disabled')
     if '/pages-gestion-des-erreurs/erreur-technique' in r.url:
         errmsg = re.search(r'<h4>(.*)</h4>', r.text).group(1)
         raise BrowserUnavailable(errmsg)
     if '/pages-gestion-des-erreurs/message-tiers-oppose' in r.url:
         raise ActionNeeded('Cannot connect to account because 2-factor authentication is enabled')
Пример #25
0
    def handle_login_error(self, r):
        error_page = r.response.json()
        assert 'error' in error_page, "Something went wrong in login"
        error = error_page['error']

        if error['code'] in self.WRONGPASS_CODES:
            raise BrowserIncorrectPassword(error['message'])
        elif error['code'] in self.ACTIONNEEDED_CODES:
            raise ActionNeeded(error['message'])

        raise Exception("%r code isn't handled yet: %s" % (error['code'], error['message']))
Пример #26
0
 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)
Пример #27
0
    def do_login(self):
        self.login.go().login(self.username, self.password)

        if self.login.is_here():
            error = self.page.get_error()
            if error and 'mot de passe' in error:
                raise BrowserIncorrectPassword(error)
            elif error and any((
                'Votre compte a été bloqué / clôturé' in error,
                'Votre compte est bloqué, veuillez contacter le Service Clients' in error,
            )):
                raise ActionNeeded(error)
            raise AssertionError('Unhandled behavior at login: error is "{}"'.format(error))
Пример #28
0
    def do_login(self):
        if not self.username or not self.password:
            raise BrowserIncorrectPassword()

        # First we try to connect to the new website: if the connection
        # is on the old website, we will automatically redirected.
        website = self.website.replace('.fr', '')
        region_domain = re.sub(r'^www\.', 'www.credit-agricole.fr/', website)
        self.BASEURL = 'https://%s/' % region_domain
        self.login_page.go()
        if self.old_website.is_here():
            self.BASEURL = 'https://%s/' % self.website
            self.logger.warning(
                'This is a regional connection, switching to old website with URL %s',
                self.BASEURL)
            raise SiteSwitch('region')

        form = self.get_security_form()
        try:
            self.security_check.go(data=form)
        except ServerError as exc:
            # Wrongpass returns a 500 server error...
            error = exc.response.json().get('error')
            if error:
                message = error.get('message', '')
                wrongpass_messages = ("Votre identification est incorrecte",
                                      "Vous n'avez plus droit")
                if any(value in message for value in wrongpass_messages):
                    raise BrowserIncorrectPassword()
                if 'obtenir un nouveau code' in message:
                    raise ActionNeeded(message)
                technical_errors = ('Un incident technique',
                                    'identifiant et votre code personnel')
                if any(value in message for value in technical_errors):
                    # If it is a technical error, we try login again
                    form = self.get_security_form()
                    try:
                        self.security_check.go(data=form)
                    except ServerError as exc:
                        error = exc.response.json().get('error')
                        if error:
                            message = error.get('message', '')
                            if 'Un incident technique' in message:
                                raise BrowserUnavailable(message)

        # accounts_url may contain '/particulier', '/professionnel', '/entreprise', '/agriculteur' or '/association'
        self.accounts_url = self.page.get_accounts_url()
        assert self.accounts_url, 'Could not get accounts url from security check'
        self.location(self.accounts_url)
        assert self.accounts_page.is_here(
        ), 'We failed to login after the security check: response URL is %s' % self.url
Пример #29
0
    def get_subscription_list(self):
        try:
            self.profile.go()

            assert self.profile.is_here() or self.manage_cgi.is_here()

            # we land on manage_cgi page when there is cgu to validate
            if self.manage_cgi.is_here():
                # but they are not in this page, we have to go to home_page to get message
                self.home_page.go()
                msg = self.page.get_error_message()
                assert "Nos Conditions Générales d'Utilisation ont évolué" in msg, msg
                raise ActionNeeded(msg)
            else:
                profile = self.page.get_profile()
        except ConnectTimeout:
            # sometimes server just doesn't answer
            raise BrowserUnavailable()

        # this only works when there are pro subs.
        nb_sub = 0
        try:
            for sub in self.contracts.go().iter_subscriptions():
                sub.subscriber = profile.name
                yield sub
            nb_sub = self.page.doc['totalContracts']
            # assert pagination is not needed
            assert nb_sub < 15
        except ServerError:
            pass

        if nb_sub > 0:
            return
        # if nb_sub is 0, we continue, because we can get them in next url

        for sub in self._iter_subscriptions_by_type(profile.name, 'sosh'):
            nb_sub += 1
            yield sub
        for sub in self._iter_subscriptions_by_type(profile.name, 'orange'):
            nb_sub += 1
            yield sub

        if nb_sub == 0:
            # No subscriptions found, trying with the API.
            headers = {
                'X-Orange-Caller-Id': 'ECQ',
            }
            self.subscriptions_api.go(headers=headers)
            for sub in self.page.iter_subscription():
                sub.subscriber = profile.name
                yield sub
Пример #30
0
    def do_login(self):
        # Due to the website change, login changed too.
        # This is for avoiding to log-in with the wrong login
        if self.username.isdigit() and len(self.username) > 7:
            raise ActionNeeded()

        if self.password.isdigit():
            self.account_space_login.go()
            if self.page.get_error_link():
                # Go on information page to get possible error message
                self.location(self.page.get_error_link())

            vk_passwd = self.keyboard.go().get_password(self.password)

            login_data = {
                'email': self.username,
                'password': vk_passwd,
                'rememberIdenfiant': False,
            }

            self.location('https://connect.axa.fr')
            self.login.go(
                data=login_data,
                headers={'X-XSRF-TOKEN': self.session.cookies['XSRF-TOKEN']})

        if not self.password.isdigit() or self.page.check_error():
            raise BrowserIncorrectPassword()

        url = self.page.get_url()
        if 'bank-otp' in url:
            # The SCA is Cross-Browser so the user can do the SMS validation on the website
            # and then try to synchronize the connection again.
            raise ActionNeeded(
                'Vous devez réaliser la double authentification sur le portail internet'
            )

        # home page to finish login
        self.location('https://espaceclient.axa.fr/')