Improve authform and begin duonet support

* mandaye/auth/authform.py: add action auto detection
 * mandaye/configs/duonet_vincennes.py: begin duonet mapping
 * mandaye/server.py: improve cookiejar support in get_response
 * mandaye/templates/duonet_associate.html: the associate template
 * mandaye/filters/vincennes.py: begin duonet support
This commit is contained in:
Jérôme Schneider 2011-09-22 12:31:46 +02:00
parent 133a9a931f
commit b316506ed2
8 changed files with 279 additions and 37 deletions

View File

@ -18,31 +18,55 @@ from mandaye.server import get_response
class AuthForm(object):
def __init__(self, local_auth, form_action, form_url, form_headers,
form_values, username_field, password_field):
def __init__(self, local_auth, form_values):
""" local_auth: instance of your local authentification system
form_values: dict example :
{
'form_action': '/myform',
'form_url': '/myform',
'form_attrs': { 'name': 'form40', },
'username_field': 'user',
'password_field': 'pwd'
}
"""
self.local_auth = local_auth
self.form_action = form_action
self.form_url = form_url
self.form_headers = form_headers
if not form_values.has_key('form_headers'):
form_values['form_headers'] = {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 Mandaye/0.0'
}
if not form_values.has_key('form_url') or \
not form_values.has_key('form_attrs') or \
not form_values.has_key('username_field') or \
not form_values.has_key('password_field'):
logging.critical("Bad configuration: AuthForm form_values dict must have \
this keys: form_url, form_attrs, username_field and password_field")
# TODO: manage Mandaye exceptions
raise BaseException, 'AuthForm bad configuration'
self.form_url = form_values['form_url']
self.form_values = form_values
self.username_field = username_field
self.password_field = password_field
def replay(self, env, username, password, **kwargs):
""" replay the login / password
"""
cj = CookieJar()
request = HTTPRequest()
if not "://" in self.form_url:
self.form_url = env['target'].geturl() + self.form_url
cj = CookieJar()
request = HTTPRequest()
login = get_response(env, request, self.form_url, cj)
if login.code == 502:
return login
soup = BeautifulSoup(login.msg)
form = soup.find('form', **self.form_values)
form = soup.find('form', **self.form_values['form_attrs'])
if not self.form_values.has_key('from_action'):
action = form['action']
else:
action = self.form_values['form_action']
if not "://" in action:
action = env['target'].geturl() + action
if not form:
logging.warning("%s %s: can't find login form on %s" %
(self.env['HTTP_HOST'], self.env['PATH_INFO'], self.form_url))
@ -50,7 +74,7 @@ class AuthForm(object):
cookies = login.cookies
headers = HTTPHeader()
headers.load_from_dict(self.form_headers)
headers.load_from_dict(self.form_values['form_headers'])
params = {}
for input in form.findAll('input'):
if input['type'] != "submit" and input['type'] != 'button' \
@ -59,15 +83,13 @@ class AuthForm(object):
params[input['name']] = input['value']
else:
params[input['name']] = ''
params[self.username_field] = username
params[self.password_field] = password
params[self.form_values['username_field']] = username
params[self.form_values['password_field']] = password
for key, value in kwargs:
params[key] = value
params = urllib.urlencode(params)
request = HTTPRequest(cookies, headers, "POST", params)
if not "://" in self.form_action:
self.form_action = env['target'].geturl() + self.form_action
return get_response(env, request, self.form_action, cj)
return get_response(env, request, action, cj)
def associate(self, env, values, request):
""" Render the associate page

View File

@ -9,14 +9,12 @@ from mandaye.configs.vincennes import auth_vincennes
form_values = {
'form_url': '/sezhame/page/connexion-abonne',
'form_action': '/sezhame/page/connexion-abonne?destination=user',
'form_headers': { 'Content-Type': 'application/x-www-form-urlencoded' },
'form_values': { 'id': 'dk-opac15-login-form', },
'form_attrs': { 'id': 'dk-opac15-login-form', },
'username_field': 'user',
'password_field': 'password'
}
authform = AuthForm(auth_vincennes, **form_values)
authform = AuthForm(auth_vincennes, form_values)
biblio_mapping = [

View File

@ -0,0 +1,89 @@
from mandaye.auth.authform import AuthForm
from mandaye.auth.vincennes import VincennesAuth
from mandaye.filters.vincennes import Duonet
from mandaye.filters.default import MandayeFilter
from mandaye.configs.vincennes import auth_vincennes
filters = Duonet()
form_values = {
'form_url': 'Connect.aspx?key=CV4j27Em0dM%3d',
'form_attrs': { 'name': 'form1', },
'username_field': 'txtNomFoyer',
'birthdate_field': 'txtDateNaissance',
'password_field': 'txtCode',
}
authform = AuthForm(auth_vincennes, form_values)
duonet_mapping = [
{
'path': r'/vincennes/login$',
'method': 'GET',
'response': [{
'filter': authform.login,
'values': { 'associate_url': '/vincennes/associate' },
'condition': 'response.code==302',
},]
},
{
'path': r'/associate$',
'method': 'GET',
'target': 'https://extranet.duonet.fr/Connect.aspx?key=CV4j27Em0dM%3d',
'on_response': [{
'filter': filters.resp_associate,
'values': {
'action': '/associate',
'template': 'duonet_associate.html',
},
}]
},
# {
# 'path': r'/vincennes/associate$',
# 'method': 'POST',
# 'response': [
# {
# 'filter': authform.associate_submit,
# 'values': {
# 'site_name': 'espace_famille',
# 'connection_url': '/vincennes/connection',
# 'failed_url': 'https://vincennes.espace-famille.net/vincennes/index.do'
# },
# 'condition': "response.code==302"
# },
# {
# 'filter': filters.resp_associate,
# 'values': {
# 'action': '/vincennes/associate',
# 'template': 'famille_associate.html',
# 'error_msg': "Code famille et/ou mot de passe incorrects",
# },
# },
# ]
# },
{
'path': r'/vincennes/connection$',
'method': 'GET',
'response': [{
'filter': auth_vincennes.connection,
'values': {
'destination': 'https://test.vincennes.fr/comptecitoyen/auth',
'next_url': '/vincennes/login',
'service_name': 'biblio'
}
}]
},
{
'path': r'/Connect.aspx$',
'method': 'GET',
'on_response': [{
'filter': filters.resp_login_page,
'values': {'connection_url': '/vincennes/connection'}}]
},
]

View File

@ -10,25 +10,13 @@ from mandaye.configs.vincennes import auth_vincennes
filters = EspaceFamille()
form_values = {
'form_action': '/vincennes/index.do',
'form_url': '/vincennes/index.do',
'form_headers': { 'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
'Accept-language': 'fr-FR,en-US;q=0.8,en;q=0.6',
'Accept-encoding': 'gzip,deflate,sdch',
'Accept': 'text/css,*/*;q=0.1',
'Accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Origin': 'https://vincennes.espace-famille.net',
'Referer': 'https://vincennes.espace-famille.net/vincennes/login.do',
'Cache-control': 'no-cache',},
'form_values': { 'action': 'login.do', },
'form_attrs': { 'action': 'login.do', },
'username_field': 'codeFamille',
'password_field': 'motDePasse'
}
authform = AuthForm(auth_vincennes, **form_values)
authform = AuthForm(auth_vincennes, form_values)
famille_mapping = [

View File

@ -1,3 +1,4 @@
import ipdb
import re
@ -47,7 +48,6 @@ class EspaceFamille:
def resp_associate(self, env, values, request, response):
"""docstring for resp_associate_login"""
if response.msg:
#response.msg = response.msg.replace('./config/', '/vincennes/config/')
soup = BeautifulSoup(response.msg)
div = soup.find('div', {'class': 'bloc-model-1'})
if div:
@ -58,3 +58,30 @@ class EspaceFamille:
return response
class Duonet:
def resp_login_page(self, env, values, request, response):
"""docstring for resp_login_page"""
if response.msg:
soup = BeautifulSoup(response.msg)
table = soup.find('table', {'id': 'tbConnect'})
input = table.find('input', type='submit')
input.append('<a href=\"%s\">Connection via mon compte citoyen</a>' % \
values['connection_url'])
response.msg = str(soup)
return response
def resp_associate(self, env, values, request, response):
"""docstring for resp_associate_login"""
if response.msg:
soup = BeautifulSoup(response.msg)
form = soup.find('form', {'name': 'form1'})
if form:
new_form = serve_template(values.get('template'), **values)
new_form.encode('utf-8')
form.replaceWith(new_form)
response.msg = str(soup)
return response
def associate_submit(self, env, values, request, response):
pass

View File

@ -54,15 +54,16 @@ def get_response(env, request, url, cookiejar=None):
if cookiejar:
response.cookies = Cookie.SimpleCookie()
for cookie in cookiejar:
if response.cookies.has_key(cookie.name):
del response.cookies[cookie.name]
response.cookies[cookie.name] = cookie.value
if cookie.expires:
response.cookies[cookie.name]['expires'] = cookie.expires
else:
del response.cookies[cookie.name]['expires']
if cookie.domain:
response.cookies[cookie.name]['domain'] = cookie.domain
if cookie.path:
response.cookies[cookie.name]['path'] = cookie.path
# TODO: add the other RFC 2109 cookie values
resp.close()
return response

View File

@ -0,0 +1,97 @@
<form name="form1" method="post" action="${action}" id="form1">
<center>
<div id="divMargin" style="height:100px"></div>
<div id="pnlLogin" style="text-align:center;">
<input type="hidden" name="hd" id="hd" value="800;1000" />
<table width="100%" align="center">
<tr >
<td colspan="2" align="center">
<img id="imgMain" src="http://www.parapharmacie-defrance.fr/lien/logo_mairie_vincennes.gif" style="height:120px;border-width:0px;" />
</td>
</tr>
<tr>
<td colspan="2" style="padding-top:10px;padding-bottom:15px">
<div style="border:solid 1px black" >
<span id="lblSchoolName" style="font-size:XX-Large;">Associer votre compte</span>
</div>
</td>
</tr>
<tr>
<td colspan="2" align="center" lang="fr">
<table>
<tr valign="top">
<td style="display:none">
<a id="hlkExt" title="Nouveaux élève(s)/Consultation/Espace publique de l&#39;établissement" href="External/Default.aspx" style="font-weight:bold;">Pas encore inscrit(e)?</a>
</td>
<td>
<div id="pnlLog" style="background-color:LightGrey;">
<table align="center" id="tbConnect" style="padding:10px 10px 10px 10px">
<tr>
<td align="right">
<span id="lblPassword">Nom de famille</span>
</td>
<td align="left">
<input name="username" type="text" id="txtNomFoyer" autocomplete="off" style="font-weight:bold;" />
</td>
</tr>
<tr>
<td align="right">
<span id="lblDateDeNaissance">Date de Naissance</span>
</td>
<td align="left">
<input name="birthdate" type="text" id="txtDateNaissance" autocomplete="off" style="font-weight:bold;" />
<span id="lblPassword1" style="font-size:XX-Small;font-style:italic;">(Ex: 16/06/2008)</span>
</td>
</tr>
<tr>
<td align="right">
<span id="lblLogin">Code DuoNET</span>
</td>
<td align="left" style="padding-left:3px">
<input name="password" type="password" maxlength="13" id="txtCode" autocomplete="off" style="font-weight:bold;width:121px;" />
<span id="lblPassword2" style="font-size:XX-Small;font-style:italic;">(Ex: 1994000001001)</span>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="submit" name="btnConnect" value="Associer" id="btnConnect" style="font-weight:bold;" />
<div id="upChooseRole">
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<center>
% if error_msg:
<span id="lblError" style="color:Red;font-weight:bold;">${error_msg}</span>
% endif
</center>
</div>
</center>
<div id="pnlLoadModal" style="background-color:White;border:solid 1px black;padding:3px 3px 3px 3px;display:none">
<img id="imgLoadModal" src="Images/loading1.gif" style="border-width:0px;" />
</div>
</form>

View File

@ -0,0 +1,20 @@
<div class="bloc-model-1">
<h2>Associer votre compte au compte citoyen</h2>
<div class="bloc-gris">
<form action="${action}" method="post">
<div class="form">
% if error_msg:
<div id="list-errors">
<p class="errors"><b>${error_msg}</b><br></p>
</div>
% endif
<div class="firstline">
<label for="cdfmll" class="first"><b></b> Code famille</label> :
<input type="text" id="cdfmll" class="txt" name="username" title="Indiquez votre code famille"><br>
<label for="mtdpss"><b></b> Mot de passe</label> :
<input type="password" id="mtdpss" class="txt" name="password" title="Indiquez votre mot de passe"></div>
<input type="submit" class="submit" value="Associer"><br>
</div>
</form>
</div>
</div>