# Copyright(C) 2017 Tony Malto
#
# flake8: compatible
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see .
from woob.browser import LoginBrowser, URL, need_login
from woob.capabilities.bank import Account
from woob.browser.exceptions import ServerError
from woob.exceptions import BrowserIncorrectPassword, ActionNeeded
from .pages import (
LoginPage, AccountsPage, TransactionsInvestmentsPage, AllTransactionsPage,
DocumentsSignaturePage, RedirectToUserAgreementPage, UserAgreementPage,
RedirectionPage, AuthCodePage,
)
class GmfBrowser(LoginBrowser):
BASEURL = 'https://mon-espace-societaire.gmf.fr'
login_post = URL(r'/connexion/CAP-US_AccesEC/api/accounts/authentication', LoginPage)
auth_page = URL(r'https://coveauth.gmf.fr/coveauth-server/oauth2/authorization',)
redirection_page = URL(r'/homepage\?code=(?P.+)&state=.*', RedirectionPage)
auth_code_page = URL(r'/cap-mx-espacesocietaire-internet/api/users/authorizationCode', AuthCodePage)
redirect_to_user_agreement = URL('^$', RedirectToUserAgreementPage)
user_agreement = URL(r'/restreint/pages/securite/IC9.faces', UserAgreementPage)
accounts = URL(r'/cap-mx-espacesocietaire-internet/api/prestation', AccountsPage)
transactions_investments = URL(
r'https://espace-assure.gmf.fr/pointentree/contratvie/detailsContrats',
TransactionsInvestmentsPage
)
all_transactions = URL(
r'https://espace-assure.gmf.fr/pages/contratvie/detailscontrats/.*\.faces',
AllTransactionsPage
)
documents_signature = URL(r'/public/pages/authentification/.*\.faces', DocumentsSignaturePage)
def __init__(self, config, *args, **kwargs):
kwargs['username'] = config['login'].get()
kwargs['password'] = config['password'].get()
super().__init__(*args, **kwargs)
self.config = config
def do_login(self):
try:
self.login_post.go(
json={
'id': self.username,
'motDePasse': self.password,
},
params={'marque': 'GMF'}
)
except ServerError as e:
if e.response.status_code == 502:
# When credentials are incorrect we get a 502 without any error message
raise BrowserIncorrectPassword()
status = self.page.get_status()
if status == 'M':
raise ActionNeeded(
'''Pour garantir la sécurité de votre espace client, votre compte nécessite une mise à jour.
Veuillez vous connecter sur votre portail internet.'''
)
id = self.page.get_id()
self.auth_page.go(
data={
'username': id,
'password': self.password,
'client_id': 'acces-ec-gmf-PROD',
'state': 'eyJwIjoiU1RBVEUifQ==',
'profile': 'accesec',
'population': '51',
'ttl': '240',
'response_type': 'code',
'redirect_uri': f'{self.BASEURL}/homepage',
}
)
if not self.redirection_page.is_here():
raise AssertionError('Should be on redirection page')
# csrf token is needed for accounts page
code = self.page.params['code']
self.auth_code_page.go(json={'code': code})
self.session.headers['covea-csrf-token'] = self.page.get_csrf_token()
@need_login
def iter_accounts(self):
self.accounts.go()
return self.page.iter_accounts()
@need_login
def iter_history(self, account):
self.accounts.stay_or_go()
data = self.page.get_details_page_form_data(account)
self.transactions_investments.go(data=data)
self.page.show_all_transactions()
return self.page.iter_history()
@need_login
def iter_investment(self, account):
self.accounts.stay_or_go()
data = self.page.get_details_page_form_data(account)
self.transactions_investments.go(data=data)
if self.page.has_investments():
return self.page.iter_investments()
elif account.label == 'Epargne Compte Libre Croissance' and account.type == Account.TYPE_LIFE_INSURANCE:
# This type of life insurance is very specific and contains only one invest of type 'Fond en euros' with no more information available on detail page.
return self.page.create_investment(account)
return []