This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
ifef-registration/extra/modules/root.ptl

319 lines
14 KiB
Plaintext

from qommon import get_cfg, get_logger
from quixote import redirect, get_session
from authentic.form import *
from quixote.html import htmltext
import qommon.errors as errors
import qommon.template as template
import authentic.identities as identities
import authentic.root
import authentic.publisher
import authentic.admin.configuration as configuration
import urllib2
import captcha
from callback import BatchJob, XmlRpcAction
import lasso
import authentic.misc as misc
from qommon.admin.texts import TextsDirectory
schema = (('PART_EMP', _('Particulier-employeur')),
(_('Salarie du Particulier-employeur'),
('SAL_EMP_INS', _('inscrit')),
('SAL_EMP_NONINS', _('pas inscrit en formation'))),
(_('Assistante(e) maternel(le)'),
('ASS_MAT_INS', _('inscrit')),
('ASS_MAT_NOINS', _('pas inscrit en formation'))),
(_('Formateur ou directeur d\'un organisme de formation'),
('FOF_LAB', _('''labellise par l'Institut-Fepem''')),
('FOF_SOUH_LAB', _('souhaitant etre labellise')),
('FOF_NOLAB', _('pas encore labellise'))),
('FC_SOUH_PART', _('Formateur consultant souhaitant entrer dans la communaute')),
(_('Salarie d\'un organisme public, d\'une association ou d\'une organisation'),
('SOP_PART', _('partenaire de l\'Institut-Fepem')),
('SOP_SOUH_PART', _('souhaitant devenir partenaire')),
('SOP_NOPART', _('pas encore partenaire'))),
('PRO_FOR', _('Un professionnel de la formation')),
('PERS_PRO_FAM', _('Une personne interessee par le sujet de la professionnalisation de l\'emploi familial')))
def check_classification(classification):
# Check classification
classification_ok = False
for q in schema:
if isinstance(q[1], tuple):
for r in q[1:]:
if r[0] == classification:
classification_ok = True
break
else:
if q[0] == classification:
classification_ok = True
break
if classification_ok:
break
return classification_ok
class IfefRootDirectory(authentic.root.RootDirectory):
_q_exports = authentic.root.RootDirectory._q_exports + [ 'register2', 'erp_change_password' ]
def _q_traverse(self, path):
request = get_request()
if request.form and request.form.get('service'):
service = request.form['service']
get_session().service = service
request.service = service
return super(IfefRootDirectory, self)._q_traverse(path)
def register2 (self):
return self.register(version=2)
def register (self, version=1):
identities_cfg = get_cfg('identities', {})
session = get_session()
if not identities_cfg.get('creation') in ('self', 'moderated'):
raise errors.TraversalError()
form = Form(enctype="multipart/form-data")
fields = identities.get_store_class().fields
keys = []
if getattr(session, 'service', None):
keys = get_cfg('providers',{}).get(session.service, {}) \
.get('registration_fields')
if keys:
fields = [ field for field in fields \
if field.key in keys ]
for field in fields:
if getattr(field, str('on_register'), True):
field.add_to_form(form) and None
has_email = 'email' in [x.key for x in identities.get_store_class().fields]
if not has_email or not identities_cfg.get('email-as-username', False):
form.add(ValidatedStringWidget, "username", title=_("Username"),
size=30,
hint=_("The identifier can only contain letters and digits."),
required=True, regex=identities.get_store().username_regex)
passwords_cfg = configuration.get_configuration('passwords')
if passwords_cfg.get('can_change') and not passwords_cfg.get('generate'):
form.add(PasswordWidget, "password", title=_("Password"), size=30, required=True)
else:
form.add(HtmlWidget, htmltext('<p>%s</p>') % _('A password will be mailed to you.'))
add_classification = True
if keys and 'classification' not in keys:
add_classification = False
if add_classification:
classification = get_request().form.get('classification')
if classification:
if not check_classification(classification):
classification = None
if version == 1:
s='<label><p><em>%s:</em></p></label><select name="classification" size="18">' % _('You are')
for q in schema:
if isinstance(q[1], tuple):
s += '<optgroup label="%s">' % q[0]
for r in q[1:]:
code, text = r
if code == classification:
selected = 'selected="1"'
else:
selected = ''
s += '<option %s value="%s">%s</option>\n' % (selected, code, text)
s += '</optgroup>\n'
else:
code, text = q
if code == classification:
selected = 'selected="1"'
else:
selected = ''
s += '<option %s value="%s">%s</option>\n' % (selected, code, text)
s += '</select>'
else:
s='<label><p><em>%s:</em></p></label><cite style="display: block; margin: 1em; font-size: 70%%">' % _('You are')
for i, q in enumerate(schema):
if isinstance(q, tuple):
s += '<p>%s' % q[0]
for j, q in enumerate(q[1:]):
s += '<input id="s%s-%s" value="%s-%s" type="radio" name="RadioGroup">%s</input>' % (i, j, i, j, q)
s += '</p>\n'
else:
s += '<p><input id="s%s" value="%s" type="radio" name="RadioGroup">%s</input></p>' % (i, i, q)
s+='</cite>'
if add_classification and get_request().get_method() == 'POST' \
and not classification:
form.set_error('username', ' ')
form.add(HtmlWidget, 'erreur', htmltext('<div class="error"><strong>%s</strong></div>') % _('You must choose a class'))
elif get_request().get_method() == 'GET':
get_request().form = {}
if add_classification:
form.add(HtmlWidget, 'classification', htmltext(s))
# domain name: fepem
re_captcha_public_key = '6LcIULoSAAAAAIbUohbBeHCcUeWAt74sjvjK6w5W'
re_captcha_private_key = '6LcIULoSAAAAADfaFk2E9x9G2FgpSsnNIfUV1rlS'
re_captcha = '''
<script type="text/javascript">
RecaptchaOptions = { "theme" : "white", "lang" : "fr" };
</script>
<script type="text/javascript" src="http://api.recaptcha.net/challenge?k=%(pkey)s">
</script>
<noscript>
<iframe src="http://api.recaptcha.net/noscript?k=%(pkey)s"
height="300" width="500" frameborder="0"></iframe><br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
</textarea>
<input type="hidden" name="recaptcha_response_field"
value="manual_challenge">
</noscript>''' % { 'pkey' : re_captcha_public_key }
identities_configuration = configuration.get_configuration('identities')
form.add(HtmlWidget, htmltext('<div id="conditions">%s</div>' %
TextsDirectory.get_html_text('terms-of-use')))
form.add(CheckboxWidget, 'validation',
title=htmltext(_('''I accept the terms of use''')),
required = True)
if 0:
form.add(HtmlWidget, htmltext(re_captcha))
form.add_captcha()
form.add(HtmlWidget, htmltext('<p id="cnil">%s</p>' %
TextsDirectory.get_html_text('cnil-disclaimer')))
form.add_submit("submit", _("Submit"))
form.add_submit("cancel", _("Cancel"))
request = get_request()
if 0 and request.form and \
request.form.has_key('recaptcha_challenge_field') and \
request.form.has_key('recaptcha_response_field'):
print captcha.submit(request.form['recaptcha_challenge_field'],
request.form['recaptcha_response_field'],
re_captcha_private_key, request.environ['REMOTE_ADDR'])
if form.get_submit() == 'cancel':
return redirect('.')
if form.is_submitted():
if not form.has_errors():
try:
return self.register_submit(form)
except authentic.root.RegistrationError:
pass
template.html_top(_('Registration'))
get_response().breadcrumb.append( ('register', _('Registration')) )
vars = {
'register_form': str(form.render())
}
return authentic.root.TextsDirectory.get_html_text('register', vars)
def pre_registration_callback(self, identity):
identity.userClass = [ 'GRAND.PUBLIC' ]
identity.name = identity.givenName + ' ' + identity.sn
def registration_callback(self, identity):
email = identity.email
uid = identity.accounts[0].username
if 'classification' in get_request().form:
classification = get_request().form['classification']
action = XmlRpcAction.create_ldap_classification(uid, email, classification)
get_response().add_after_job('''Send registration to Neogia, email = %r,\
classification = %r''' % (email, classification), BatchJob(action))
def get_idp_sso_list [html] (self):
if not get_cfg('providers', {}).items():
return ''
'<ul>'
for klp, lp in get_cfg('providers', {}).items():
if lp['role'] == lasso.PROVIDER_ROLE_IDP:
continue # only allows initiated login to service providers
if lp.get('idp_initiated_sso', True) is False:
continue
try:
provider, label = misc.get_provider_and_label(klp)
except KeyError:
continue
if hasattr(provider, str('getProtocolConformance')) and \
provider.getProtocolConformance() == lasso.PROTOCOL_SAML_2_0:
url = 'saml/sp/%s/login' % klp
else:
url = 'liberty/sp/%s/login' % klp
'<li class="%s"><a href="%s">%s</a></li>' % (
klp,
url, htmltext(_('Log on %s') % label))
'</ul>'
def erp_change_password_get [html] (self):
template.html_top(title = _('ERP Change Password'))
'<p>This service expects a POST-ed form with the following fields'
'<dl>'
'<dt>secret</dtd><dd>The secret giving access to this service</dd>'
'<dt>uid</dtd><dd>The uid for which we want to change password</dd>'
'<dt>password</dt><dd>(optional) the password to set</dd>'
'</dl>'
'<h2>Behaviour</h2>'
'<p>If secret or uid are missing or if an unknown field is given, an error 400 is returned.</p>'
'<p>If secret is wrong, an error 403 is returned,</p>'
'<p>If uid is unknown, an error 400 is returned.</p>'
'<p>If a password is given, it is set and sent by mail, if the account has an email.</p>'
'<p>If no password is given, one is generated and sent by mail.</p>'
'<p>If no password is given and no email is present, an error 400 is returned.</p>'
'<h2>Result</h2>'
'<p>If no error occured, a document containing the string "ok" of content-type text/plain is returned</p>'
def erp_change_password(self):
request = get_request()
store = identities.get_store()
if request.get_method() != 'POST':
return self.erp_change_password_get()
form = request.form
if 'secret' not in form or 'uid' not in form:
raise errors.QueryError('%s' % form)
secret = form['secret']
uid = form['uid']
password = form.get('password')
# Verify the secret
if secret != configuration.get_configuration('identities').get('erp_secret'):
raise errors.AccessError()
# Check the uid exists
identity = identities.get_store().get_identity_for_username(uid)
if not identity:
raise errors.QueryError('User %r not found' % uid)
# Suppose there is only one account object
account = identity.accounts[0]
if password:
# Check the password is acceptable
pass
else:
# Check that the identity has an email
if not identity.email:
raise errors.QueryError('User %r has no email, we cannot generate a new password' % uid)
password = store.create_password(for_account=uid)
if identity.email:
self.email_password(identity, password=password)
account.password = store.hash_password(password)
store.save(identity)
response = get_response()
response.set_content_type('text/plain')
return 'ok'
from qommon.publisher import get_publisher_class
get_publisher_class().root_directory_class = IfefRootDirectory
TextsDirectory.register('terms-of-use',
N_("Terms of use"),
hint = '',
default = 'Terms of use')
TextsDirectory.register('cnil-disclaimer',
N_("CNIL disclaimer"),
hint = '',
default = 'CNIL disclaimer')