Improve README and finish duonet support
* mandaye/auth/authform.py: update to support duonet replay * README.rst: improve the quick launch text * mandaye/filters/vincennes.py: filters for Duonet * mandaye/models.py: add birthdate for duonet * mandayectl: improve the cmd line management
This commit is contained in:
parent
b316506ed2
commit
85141684d0
|
@ -68,11 +68,15 @@ or easy_install::
|
|||
Quick Start
|
||||
-----------
|
||||
|
||||
Configure mandaye/config.py
|
||||
|
||||
Then launch the following commands::
|
||||
|
||||
TODO
|
||||
./mandayectl --createdb
|
||||
./mandayectl --start
|
||||
|
||||
You should see the following output::
|
||||
|
||||
TODO
|
||||
Database created
|
||||
Starting Mandaye x.x.x.x:xx ...
|
||||
|
||||
|
|
|
@ -49,24 +49,26 @@ this keys: form_url, form_attrs, username_field and password_field")
|
|||
self.form_url = form_values['form_url']
|
||||
self.form_values = form_values
|
||||
|
||||
def replay(self, env, username, password, **kwargs):
|
||||
def replay(self, env, username, password, extra_values={}):
|
||||
""" replay the login / password
|
||||
env: WSGI env with beaker session and the target
|
||||
extra_values: dict with the field name (key) and the field value (value)
|
||||
"""
|
||||
if not "://" in self.form_url:
|
||||
self.form_url = env['target'].geturl() + 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_attrs'])
|
||||
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
|
||||
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))
|
||||
|
@ -77,32 +79,33 @@ this keys: form_url, form_attrs, username_field and password_field")
|
|||
headers.load_from_dict(self.form_values['form_headers'])
|
||||
params = {}
|
||||
for input in form.findAll('input'):
|
||||
if input['type'] != "submit" and input['type'] != 'button' \
|
||||
and input.has_key('name'):
|
||||
if input.has_key('name'):
|
||||
if input.has_key('value'):
|
||||
params[input['name']] = input['value']
|
||||
else:
|
||||
params[input['name']] = ''
|
||||
params[self.form_values['username_field']] = username
|
||||
params[self.form_values['password_field']] = password
|
||||
for key, value in kwargs:
|
||||
for key, value in extra_values.iteritems():
|
||||
params[key] = value
|
||||
params = urllib.urlencode(params)
|
||||
request = HTTPRequest(cookies, headers, "POST", params)
|
||||
return get_response(env, request, action, cj)
|
||||
|
||||
def associate(self, env, values, request):
|
||||
""" Render the associate page
|
||||
"""
|
||||
return template_response(values['template'], values)
|
||||
|
||||
def associate_submit(self, env, values, condition, request, response):
|
||||
""" Associate your login / password with Mandaye
|
||||
"""
|
||||
pseudo = env['beaker.session'].get('pseudo')
|
||||
if request.msg:
|
||||
post = parse_qs(request.msg.read(), request)
|
||||
response = self.replay(env, post['username'][0], post['password'][0])
|
||||
if not post.has_key('username') or not post.has_key('password'):
|
||||
return get_response(env, HTTPRequest(), values.get('failed_url'))
|
||||
# TODO: generized this part (use a generic key / value table)
|
||||
extra_values = {}
|
||||
if post.has_key('birthdate'):
|
||||
birthdate_field = self.form_values['birthdate_field']
|
||||
extra_values = {birthdate_field: post['birthdate'][0]}
|
||||
response = self.replay(env, post['username'][0], post['password'][0], extra_values)
|
||||
if eval(condition):
|
||||
if not pseudo:
|
||||
return _302(values.get('connection_url'))
|
||||
|
@ -125,6 +128,9 @@ this keys: form_url, form_attrs, username_field and password_field")
|
|||
ext_user.login = post['username'][0]
|
||||
ext_user.password = post['password'][0]
|
||||
ext_user.local_user = local_user
|
||||
# TODO: generalize this
|
||||
if post.has_key('birthdate'):
|
||||
ext_user.birthdate = post['birthdate'][0]
|
||||
mandaye.sql_session.commit()
|
||||
return _302(values.get('connection_url'))
|
||||
|
||||
|
@ -145,7 +151,11 @@ this keys: form_url, form_attrs, username_field and password_field")
|
|||
if not ext_user.login or not ext_user.password:
|
||||
return _500(env['PATH_INFO'],
|
||||
'Invalid values for AuthFormDispatcher.login')
|
||||
response = self.replay(env, ext_user.login, ext_user.password)
|
||||
# TODO: generized this condition
|
||||
extra_values = {}
|
||||
if ext_user.birthdate:
|
||||
extra_values = { self.form_values['birthdate_field']: ext_user.birthdate }
|
||||
response = self.replay(env, ext_user.login, ext_user.password, extra_values)
|
||||
if condition and eval(condition):
|
||||
return response
|
||||
else:
|
||||
|
|
|
@ -11,12 +11,13 @@ filters = Duonet()
|
|||
|
||||
form_values = {
|
||||
'form_url': 'Connect.aspx?key=CV4j27Em0dM%3d',
|
||||
'form_attrs': { 'name': 'form1', },
|
||||
'form_attrs': { 'name': 'form1' },
|
||||
'username_field': 'txtNomFoyer',
|
||||
'birthdate_field': 'txtDateNaissance',
|
||||
'password_field': 'txtCode',
|
||||
}
|
||||
|
||||
|
||||
authform = AuthForm(auth_vincennes, form_values)
|
||||
|
||||
|
||||
|
@ -26,7 +27,7 @@ duonet_mapping = [
|
|||
'method': 'GET',
|
||||
'response': [{
|
||||
'filter': authform.login,
|
||||
'values': { 'associate_url': '/vincennes/associate' },
|
||||
'values': { 'associate_url': '/associate' },
|
||||
'condition': 'response.code==302',
|
||||
},]
|
||||
},
|
||||
|
@ -42,29 +43,29 @@ duonet_mapping = [
|
|||
},
|
||||
}]
|
||||
},
|
||||
# {
|
||||
# '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'/associate$',
|
||||
'method': 'POST',
|
||||
'response': [
|
||||
{
|
||||
'filter': authform.associate_submit,
|
||||
'values': {
|
||||
'site_name': 'conservatoire',
|
||||
'connection_url': '/vincennes/connection',
|
||||
'failed_url': 'https://extranet.duonet.fr/Connect.aspx?key=CV4j27Em0dM%3d'
|
||||
},
|
||||
'condition': "response.code==302"
|
||||
},
|
||||
{
|
||||
'filter': filters.resp_associate,
|
||||
'values': {
|
||||
'action': '/associate',
|
||||
'template': 'duonet_associate.html',
|
||||
'error_msg': "Identifiants incorrects",
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
'path': r'/vincennes/connection$',
|
||||
'method': 'GET',
|
||||
|
@ -84,6 +85,14 @@ duonet_mapping = [
|
|||
'filter': filters.resp_login_page,
|
||||
'values': {'connection_url': '/vincennes/connection'}}]
|
||||
},
|
||||
{
|
||||
'path': r'/$',
|
||||
'method': 'GET',
|
||||
'target': 'https://extranet.duonet.fr/Connect.aspx?key=CV4j27Em0dM%3d',
|
||||
'on_response': [{
|
||||
'filter': filters.resp_login_page,
|
||||
'values': {'connection_url': '/vincennes/connection'}}]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import ipdb
|
||||
|
||||
import mandaye
|
||||
import re
|
||||
|
||||
from urlparse import parse_qs
|
||||
from BeautifulSoup import BeautifulSoup
|
||||
|
||||
from mandaye.models import Site, ExtUser, LocalUser
|
||||
from mandaye.server import get_response
|
||||
from mandaye.response import serve_template
|
||||
from mandaye.http import HTTPRequest
|
||||
from mandaye.response import _500, _302, _401
|
||||
|
||||
def biblio_html_login_page(env, values, request, response):
|
||||
""" msg: response message body
|
||||
|
@ -83,5 +88,3 @@ class Duonet:
|
|||
response.msg = str(soup)
|
||||
return response
|
||||
|
||||
def associate_submit(self, env, values, request, response):
|
||||
pass
|
||||
|
|
|
@ -26,7 +26,7 @@ class LocalUser(Base):
|
|||
|
||||
id = Column(Integer, primary_key=True)
|
||||
login = Column(String(150), nullable=True, unique=True)
|
||||
password = Column(String, nullable=True)
|
||||
password = Column(String(25), nullable=True)
|
||||
fullname = Column(String(150), nullable=True)
|
||||
|
||||
def __init__(self, login=None, password=None, fullname=None):
|
||||
|
@ -48,7 +48,8 @@ class ExtUser(Base):
|
|||
|
||||
id = Column(Integer, primary_key=True)
|
||||
login = Column(String(80), nullable=True)
|
||||
password = Column(String, nullable=True)
|
||||
password = Column(String(25), nullable=True)
|
||||
birthdate = Column(String(15), nullable=True)
|
||||
local_user_id = Column(Integer, ForeignKey('local_users.id'))
|
||||
site_id = Column(Integer, ForeignKey('sites.id'))
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ from mandaye import config
|
|||
from mandaye import server
|
||||
|
||||
def get_cmd_options():
|
||||
parser = OptionParser()
|
||||
usage = "usage: %prog [-d, --daemon] start|stop|createdb"
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("--start",
|
||||
dest="start",
|
||||
default=False,
|
||||
|
@ -42,6 +43,8 @@ def get_cmd_options():
|
|||
parser.error("you can't use options start and stop at the same time")
|
||||
if options.daemon and not options.start and not options.stop:
|
||||
parser.error("You must use option start or stop")
|
||||
if not options.start and not options.stop and not options.createdb:
|
||||
parser.error("You must use option start | stop | createdb")
|
||||
return options
|
||||
|
||||
def main():
|
||||
|
@ -53,9 +56,10 @@ def main():
|
|||
from sqlalchemy import create_engine
|
||||
engine = create_engine(config.db_url)
|
||||
Base.metadata.create_all(engine)
|
||||
print "Database created"
|
||||
|
||||
if options.start:
|
||||
logging.info("Starting Mandaye %s:%d .." % (config.host, config.port))
|
||||
print "Starting Mandaye %s:%d .." % (config.host, config.port)
|
||||
server.serve()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Reference in New Issue