Project

General

Profile

Download (44.5 KB) Statistics
| Branch: | Tag: | Revision:
from quixote import get_publisher, get_response, get_request, redirect, get_session
from quixote.directory import Directory
from quixote.html import htmltext
from quixote.util import StaticDirectory

from wcs.qommon.misc import get_variadic_url

import os
import re
import string
import urlparse

try:
import lasso
except ImportError:
pass

import wcs
import wcs.root
import qommon
from qommon import get_cfg, get_logger
from qommon import template
from qommon import errors
from qommon.form import *
from qommon import logger
from wcs.roles import logged_users_role

from qommon import emails
from qommon.sms import SMS
from wcs.categories import Category
from wcs.formdef import FormDef
from qommon.tokens import Token
from qommon.admin.emails import EmailsDirectory
from qommon.admin.texts import TextsDirectory

from links import Link
from announces import Announce, AnnounceSubscription
from myspace import MyspaceDirectory
from agenda import AgendaDirectory
from events import Event, get_default_event_tags
from payments import PublicPaymentDirectory
from payments_ui import InvoicesDirectory

import admin

import wcs.forms.root
from wcs.workflows import Workflow

from saml2 import Saml2Directory

OldRootDirectory = wcs.root.RootDirectory

import qommon.ident.password
import qommon.ident.idp

import drupal
import ezldap_ui
import msp_ui

def category_get_homepage_position(self):
if hasattr(self, 'homepage_position') and self.homepage_position:
return self.homepage_position
if self.url_name == 'consultations':
return '2nd'
return '1st'
Category.get_homepage_position = category_get_homepage_position

def category_get_limit(self):
if hasattr(self, 'limit') and self.limit is not None:
return self.limit
return 3
Category.get_limit = category_get_limit


class FormsRootDirectory(wcs.forms.root.RootDirectory):

def _q_index(self, *args):
get_response().filter['is_index'] = True
return wcs.forms.root.RootDirectory._q_index(self, *args)

def user_forms [html] (self, user_forms):
base_url = get_publisher().get_root_url()

draft = [x for x in user_forms if x.is_draft()]
if draft:
'<h4 id="drafts">%s</h4>' % _('My Current Drafts')
'<ul>'
for f in draft:
'<li><a href="%s%s/%s/%s">%s</a>, %s</li>' % (base_url,
f.formdef.category.url_name,
f.formdef.url_name, f.id, f.formdef.name,
misc.localstrftime(f.receipt_time))
'</ul>'

forms_by_status_name = {}
for f in user_forms:
if f.is_draft():
continue
status = f.get_visible_status()
if status:
status_name = status.name
else:
status_name = None
if status_name in forms_by_status_name:
forms_by_status_name[status_name].append(f)
else:
forms_by_status_name[status_name] = [f]
for status_name in forms_by_status_name:
if status_name:
'<h4>%s</h4>' % _('My forms with status "%s"') % status_name
else:
'<h4>%s</h4>' % _('My forms with an unknown status') % status_name
'<ul>'
forms_by_status_name[status_name].sort(lambda x,y: cmp(x.receipt_time, y.receipt_time))
for f in forms_by_status_name[status_name]:
if f.formdef.category_id:
category_url = f.formdef.category.url_name
else:
category_url = '.'
'<li><a href="%s%s/%s/%s/">%s</a>, %s</li>' % (
base_url,
category_url,
f.formdef.url_name, f.id, f.formdef.name,
misc.localstrftime(f.receipt_time))
'</ul>'


class AnnounceDirectory(Directory):
_q_exports = ['', 'edit', 'delete', 'email']

def __init__(self, announce):
self.announce = announce

def _q_index [html] (self):
template.html_top(_('Announces to citizens'))

if self.announce.publication_time:
date_heading = '%s - ' % time.strftime(misc.date_format(), self.announce.publication_time)
else:
date_heading = ''

'<h3>%s%s</h3>' % (date_heading, self.announce.title)

'<p>'
self.announce.text
'</p>'

'<p>'
'<a href="../">%s</a>' % _('Back')
'</p>'


class AnnouncesDirectory(Directory):
_q_exports = ['', 'subscribe', 'email', 'atom', 'sms', 'emailconfirm',
'email_unsubscribe', 'sms_unsubscribe', 'smsconfirm', 'rawlist']

def _q_traverse(self, path):
get_response().breadcrumb.append(('announces/', _('Announces')))
return Directory._q_traverse(self, path)

def _q_index [html] (self):
template.html_top(_('Announces to citizens'))
self.announces_list()
'<ul id="announces-links">'
'<li><a href="subscribe">%s</a></li>' % _('Receiving those Announces')
'</ul>'

def _get_announce_subscription(self):
""" """
sub = None
if get_request().user:
subs = AnnounceSubscription.select(lambda x: x.user_id == get_request().user.id)
if subs:
sub = subs[0]
return sub

def rawlist [html] (self):
self.announces_list()
get_response().filter = None

def announces_list [html] (self):
announces = Announce.get_published_announces()
if not announces:
raise errors.TraversalError()

# XXX: will need pagination someday
for item in announces:
'<div class="announce-item">\n'
'<h4>'
if item.publication_time:
time.strftime(misc.date_format(), item.publication_time)
' - '
item.title
'</h4>\n'
'<p>\n'
item.text
'\n</p>\n'
'</div>\n'


def sms [html] (self):
sms_mode = get_cfg('sms', {}).get('mode', 'none')

if sms_mode == 'none':
raise errors.TraversalError()

get_response().breadcrumb.append(('sms', _('SMS')))
template.html_top(_('Receiving announces by SMS'))

if sms_mode == 'demo':
TextsDirectory.get_html_text('aq-sms-demo')
else:
announces_cfg = get_cfg('announces',{})
mobile_mask = announces_cfg.get('mobile_mask')
if mobile_mask:
mobile_mask = ' (' + mobile_mask + ')'
else:
mobile_mask = ''
form = Form(enctype='multipart/form-data')
form.add(StringWidget, 'mobile', title = _('Mobile number %s') % mobile_mask, size=12, required=True)
form.add_submit('submit', _('Subscribe'))
form.add_submit('cancel', _('Cancel'))

if form.get_submit() == 'cancel':
return redirect('subscribe')

if form.is_submitted() and not form.has_errors():
s = self.sms_submit(form)
if s == False:
form.render()
else:
return redirect("smsconfirm")
else:
form.render()

def sms_submit(self, form):
mobile = form.get_widget("mobile").parse()
# clean the string, remove any extra character
mobile = re.sub('[^0-9+]','',mobile)
# if a mask was set, validate
announces_cfg = get_cfg('announces',{})
mobile_mask = announces_cfg.get('mobile_mask')
if mobile_mask:
mobile_regexp = re.sub('X','[0-9]', mobile_mask) + '$'
if not re.match(mobile_regexp, mobile):
form.set_error("mobile", _("Phone number invalid ! It must match ") + mobile_mask)
return False
if mobile.startswith('00'):
mobile = '+' + mobile[2:]
else:
# Default to france international prefix
if not mobile.startswith('+'):
mobile = re.sub("^0", "+33", mobile)
sub = self._get_announce_subscription()
if not sub:
sub = AnnounceSubscription()
if get_request().user:
sub.user_id = get_request().user.id

if mobile:
sub.sms = mobile

if not get_request().user:
sub.enabled = False

sub.store()

# Asking sms confirmation
token = Token(3 * 86400, 4, string.digits)
token.type = 'announces-subscription-confirmation'
token.subscription_id = sub.id
token.store()

message = _("Confirmation code : %s") % str(token.id)
sms_cfg = get_cfg('sms', {})
sender = sms_cfg.get('sender', 'AuQuotidien')[:11]
mode = sms_cfg.get('mode', 'none')
sms = SMS.get_sms_class(mode)
try:
sms.send(sender, [mobile], message)
except errors.SMSError, e:
get_logger().error(e)
form.set_error("mobile", _("Send SMS confirmation failed"))
sub.remove("sms")
return False

def smsconfirm [html] (self):
template.html_top(_('Receiving announces by SMS confirmation'))
"<p>%s</p>" % _("You will receive a confirmation code by SMS.")
form = Form(enctype='multipart/form-data')
form.add(StringWidget, 'code', title = _('Confirmation code (4 characters)'), size=12, required=True)
form.add_submit('submit', _('Subscribe'))
form.add_submit('cancel', _('Cancel'))

if form.get_submit() == 'cancel':
return redirect('..')

if form.is_submitted() and not form.has_errors():
token = None
id = form.get_widget("code").parse()
try:
token = Token.get(id)
except KeyError:
form.set_error("code", _('Invalid confirmation code.'))
else:
if token.type != 'announces-subscription-confirmation':
form.set_error("code", _('Invalid confirmation code.'))
else:
sub = AnnounceSubscription.get(token.subscription_id)
token.remove_self()
sub.enabled_sms = True
sub.store()
return redirect('.')
form.render()
else:
form.render()

def sms_unsubscribe [html] (self):
sub = self._get_announce_subscription()

form = Form(enctype='multipart/form-data')
if not sub:
return redirect('..')

form.add_submit('submit', _('Unsubscribe'))
form.add_submit('cancel', _('Cancel'))

if form.get_submit() == 'cancel':
return redirect('..')

get_response().breadcrumb.append(('sms', _('SMS Unsubscription')))
template.html_top()

if form.is_submitted() and not form.has_errors():
if sub:
sub.remove("sms")

def sms_unsub_ok [html] ():
root_url = get_publisher().get_root_url()
'<p>'
_('You have been unsubscribed from announces')
'</p>'
if not get_response().iframe_mode:
'<a href="%s">%s</a>' % (root_url, _('Back Home'))

return sms_unsub_ok()

else:
'<p>'
_('Do you want to stop receiving announces by sms ?')
'</p>'
form.render()


def subscribe [html] (self):
get_response().breadcrumb.append(('subscribe', _('Subscription')))
template.html_top(_('Receiving Announces'))

TextsDirectory.get_html_text('aq-announces-subscription')

sub = self._get_announce_subscription()

'<ul id="announce-modes">'
if sub and sub.email:
' <li>'
'<span id="par_mail">%s</span>' % _('Email (currently subscribed)')
' <a href="email_unsubscribe" rel="popup">%s</a></li>' % _('Unsubscribe')
else:
' <li><a href="email" id="par_mail" rel="popup">%s</a></li>' % _('Email')
if sub and sub.sms:
' <li>'
if sub.enabled_sms:
'<span id="par_sms">%s</span>' % _('SMS %s (currently subscribed)') % sub.sms
else:
'<span id="par_sms">%s</span>' % _('SMS %s (currently not confirmed)') % sub.sms
' <a href="smsconfirm" rel="popup">%s</a> ' % _('Confirmation')
' <a href="sms_unsubscribe" rel="popup">%s</a></li>' % _('Unsubscribe')
elif get_cfg('sms', {}).get('mode', 'none') != 'none':
' <li><a href="sms" id="par_sms">%s</a></li>' % _('SMS')
' <li><a class="feed-link" href="atom" id="par_rss">%s</a>' % _('Feed')
'</ul>'


def email [html] (self):
get_response().breadcrumb.append(('email', _('Email Subscription')))
template.html_top(_('Receiving Announces by email'))

form = Form(enctype='multipart/form-data')
if get_request().user:
if get_request().user.email:
'<p>'
_('You are logged in and your email is %s, ok to subscribe ?') % \
get_request().user.email
'</p>'
form.add_submit('submit', _('Subscribe'))
else:
'<p>'
_("You are logged in but there is no email address in your profile.")
'</p>'
form.add(EmailWidget, 'email', title = _('Email'), required = True)
form.add_submit('submit', _('Subscribe'))
form.add_submit('submit-remember', _('Subscribe and add this email to my profile'))
else:
'<p>'
_('FIXME will only be used for this purpose etc.')
'</p>'
form.add(EmailWidget, 'email', title = _('Email'), required = True)
form.add_submit('submit', _('Subscribe'))
form.add_submit('cancel', _('Cancel'))

if form.get_submit() == 'cancel':
return redirect('subscribe')

if form.is_submitted() and not form.has_errors():
s = self.email_submit(form)
if s is not False:
return s
else:
form.render()

def email_submit(self, form):
sub = self._get_announce_subscription()
if not sub:
sub = AnnounceSubscription()

if get_request().user:
sub.user_id = get_request().user.id

if form.get_widget('email'):
sub.email = form.get_widget('email').parse()
elif get_request().user.email:
sub.email = get_request().user.email

if not get_request().user:
sub.enabled = False

sub.store()

if get_request().user:
def email_submit_ok [html] ():
root_url = get_publisher().get_root_url()
'<p>'
_('You have been subscribed to the announces.')
'</p>'
if not get_response().iframe_mode:
'<a href="%s">%s</a>' % (root_url, _('Back Home'))

return email_submit_ok()

# asking email confirmation before subscribing someone
token = Token(3 * 86400)
token.type = 'announces-subscription-confirmation'
token.subscription_id = sub.id
token.store()
data = {
'confirm_url': get_request().get_url() + 'confirm?t=%s&a=cfm' % token.id,
'cancel_url': get_request().get_url() + 'confirm?t=%s&a=cxl' % token.id,
'time': misc.localstrftime(time.localtime(token.expiration)),
}

emails.custom_ezt_email('announces-subscription-confirmation',
data, sub.email, exclude_current_user = False)

def email_submit_ok [html] ():
root_url = get_publisher().get_root_url()
'<p>'
_('You have been sent an email for confirmation')
'</p>'
if not get_response().iframe_mode:
'<a href="%s">%s</a>' % (root_url, _('Back Home'))

return email_submit_ok()

def emailconfirm(self):
tokenv = get_request().form.get('t')
action = get_request().form.get('a')

root_url = get_publisher().get_root_url()

try:
token = Token.get(tokenv)
except KeyError:
return template.error_page(
_('The token you submitted does not exist, has expired, or has been cancelled.'),
continue_to = (root_url, _('home page')))

if token.type != 'announces-subscription-confirmation':
return template.error_page(
_('The token you submitted is not appropriate for the requested task.'),
continue_to = (root_url, _('home page')))

sub = AnnounceSubscription.get(token.subscription_id)

if action == 'cxl':
def cancel [html]():
root_url = get_publisher().get_root_url()
template.html_top(_('Email Subscription'))
'<h1>%s</h1>' % _('Request Cancelled')
'<p>%s</p>' % _('The request for subscription has been cancelled.')
'<p>'
htmltext(_('Continue to <a href="%s">home page</a>') % root_url)
'</p>'
token.remove_self()
sub.remove_self()
return cancel()

if action == 'cfm':
token.remove_self()
sub.enabled = True
sub.store()
def sub [html] ():
root_url = get_publisher().get_root_url()
template.html_top(_('Email Subscription'))
'<h1>%s</h1>' % _('Subscription Confirmation')
'<p>%s</p>' % _('Your subscription to announces is now effective.')
'<p>'
htmltext(_('Continue to <a href="%s">home page</a>') % root_url)
'</p>'
return sub()


def atom [plain] (self):
response = get_response()
response.set_content_type('application/atom+xml')

from pyatom import pyatom
xmldoc = pyatom.XMLDoc()
feed = pyatom.Feed()
xmldoc.root_element = feed
feed.title = get_cfg('misc', {}).get('sitename') or 'Au Quotidien'
feed.id = get_request().get_url()

author_email = get_cfg('emails', {}).get('reply_to')
if not author_email:
author_email = get_cfg('emails', {}).get('from')
if author_email:
feed.authors.append(pyatom.Author(author_email))

announces = Announce.get_published_announces()

if announces and announces[0].modification_time:
feed.updated = misc.format_time(announces[0].modification_time,
'%(year)s-%(month)02d-%(day)02dT%(hour)02d:%(minute)02d:%(second)02dZ',
gmtime = True)
feed.links.append(pyatom.Link(get_request().get_url(1) + '/'))

for item in announces:
entry = item.get_atom_entry()
if entry:
feed.entries.append(entry)

str(feed)

def email_unsubscribe [html] (self):
sub = self._get_announce_subscription()

form = Form(enctype='multipart/form-data')
if not sub:
form.add(EmailWidget, 'email', title = _('Email'), required = True)

form.add_submit('submit', _('Unsubscribe'))
form.add_submit('cancel', _('Cancel'))

if form.get_submit() == 'cancel':
return redirect('..')

get_response().breadcrumb.append(('email', _('Email Unsubscription')))
template.html_top()

if form.is_submitted() and not form.has_errors():
if sub:
sub.remove("email")
else:
email = form.get_widget('email').parse()
for s in AnnounceSubscription.select():
if s.email == email:
s.remove("email")

def email_unsub_ok [html] ():
root_url = get_publisher().get_root_url()
'<p>'
_('You have been unsubscribed from announces')
'</p>'
if not get_response().iframe_mode:
'<a href="%s">%s</a>' % (root_url, _('Back Home'))

return email_unsub_ok()

else:
'<p>'
_('Do you want to stop receiving announces by email?')
'</p>'
form.render()

def _q_lookup(self, component):
try:
announce = Announce.get(component)
except KeyError:
raise errors.TraversalError()

if announce.hidden:
raise errors.TraversalError()

get_response().breadcrumb.append((str(announce.id), announce.title))
return AnnounceDirectory(announce)

OldRegisterDirectory = wcs.root.RegisterDirectory

class AlternateRegisterDirectory(OldRegisterDirectory):
def _q_traverse(self, path):
get_response().filter['bigdiv'] = 'new_member'
return OldRegisterDirectory._q_traverse(self, path)

def _q_index [html] (self):
get_logger().info('register')
ident_methods = get_cfg('identification', {}).get('methods', [])

if len(ident_methods) == 0:
idps = get_cfg('idp', {})
if len(idps) == 0:
return template.error_page(_('Authentication subsystem is not yet configured.'))
ident_methods = ['idp'] # fallback to old behaviour; liberty.

if len(ident_methods) == 1:
method = ident_methods[0]
else:
method = 'password'

return qommon.ident.register(method)

OldLoginDirectory = wcs.root.LoginDirectory

class AlternateLoginDirectory(OldLoginDirectory):
def _q_traverse(self, path):
get_response().filter['bigdiv'] = 'member'
return OldLoginDirectory._q_traverse(self, path)

def _q_index [html] (self):
get_logger().info('login')
ident_methods = get_cfg('identification', {}).get('methods', [])

if len(ident_methods) > 1 and 'idp' in ident_methods:
# if there is more than one identification method, and there is a
# possibility of SSO, if we got there as a consequence of an access
# unauthorized url on admin/ or backoffice/, then idp auth method
# is chosen forcefully.
after_url = get_session().after_url
if after_url:
root_url = get_publisher().get_root_url()
after_path = urlparse.urlparse(after_url)[2]
after_path = after_path[len(root_url):]
if after_path.startswith(str('admin')) or \
after_path.startswith(str('backoffice')):
ident_methods = ['idp']

# don't display authentication system choice
if len(ident_methods) == 1:
method = ident_methods[0]
try:
return qommon.ident.login(method)
except KeyError:
get_logger().error('failed to login with method %s' % method)
return errors.TraversalError()

if sorted(ident_methods) == ['idp', 'password']:
get_response().breadcrumb.append(('login', _('Login')))
identities_cfg = get_cfg('identities', {})
form = Form(enctype = 'multipart/form-data', id = 'login-form', use_tokens = False)
if identities_cfg.get('email-as-username', False):
form.add(StringWidget, 'username', title = _('Email'), size=25, required=True)
else:
form.add(StringWidget, 'username', title = _('Username'), size=25, required=True)
form.add(PasswordWidget, 'password', title = _('Password'), size=25, required=True)
form.add_submit('submit', _('Connect'))
if form.is_submitted() and not form.has_errors():
tmp = qommon.ident.password.MethodDirectory().login_submit(form)
if not form.has_errors():
return tmp

'<div id="login-password">'
get_session().display_message()
form.render()

base_url = get_publisher().get_root_url()
'<p><a href="%sident/password/forgotten">%s</a></p>' % (
base_url, _('Forgotten password ?'))

'</div>'

# XXX: this part only supports a single IdP
'<div id="login-sso">'
TextsDirectory.get_html_text('aq-sso-text')
form = Form(enctype='multipart/form-data',
action = '%sident/idp/login' % base_url)
form.add_hidden('method', 'idp')
for kidp, idp in get_cfg('idp', {}).items():
p = lasso.Provider(lasso.PROVIDER_ROLE_IDP,
misc.get_abs_path(idp['metadata']),
misc.get_abs_path(idp.get('publickey')), None)
form.add_hidden('idp', p.providerId)
break
form.add_submit('submit', _('Connect'))
form.render()
'</div>'

get_request().environ['REQUEST_METHOD'] = 'GET'

"""<script type="text/javascript">
document.getElementById('login-form')['username'].focus();
</script>"""

else:
return OldLoginDirectory._q_index(self)


OldIdentDirectory = wcs.root.IdentDirectory
class AlternateIdentDirectory(OldIdentDirectory):
def _q_traverse(self, path):
get_response().filter['bigdiv'] = 'member'
return OldIdentDirectory._q_traverse(self, path)


class AlternateRootDirectory(OldRootDirectory):
_q_exports = ['', 'admin', 'backoffice', 'forms', 'login', 'logout',
'liberty', 'token', 'saml', 'register', 'ident', 'afterjobs',
('informations-editeur', 'informations_editeur'), 'index2',
('announces', 'announces_dir'),
'accessibility', 'contact', 'help',
'myspace', 'services', 'agenda', 'categories', 'user',
('tmp-upload', 'tmp_upload'), 'json', '__version__',
'themes', 'pages', 'payment', 'invoices', 'accesscode', 'roles',
'msp']

admin = admin.AdminRootDirectory()
announces_dir = AnnouncesDirectory()
register = AlternateRegisterDirectory()
login = AlternateLoginDirectory()
ident = AlternateIdentDirectory()
myspace = MyspaceDirectory()
agenda = AgendaDirectory()
saml = Saml2Directory()
payment = PublicPaymentDirectory()
invoices = InvoicesDirectory()
msp = msp_ui.MSPDirectory()

def get_substitution_variables(self):
d = {}
def print_links(fd):
fd.write(str(self.links()))
d['links'] = print_links
return d

def _q_traverse(self, path):
if get_publisher().has_site_option('drupal'):
drupal.try_auth()
if get_publisher().has_site_option('ezldap'):
ezldap_ui.try_auth(self)

session = get_session()
if session:
get_request().user = session.get_user()
else:
get_request().user = None

get_publisher().substitutions.feed(get_request().user)

response = get_response()
if not hasattr(response, 'filter'):
response.filter = {}

response.filter['gauche'] = self.box_side(path)
response.filter['keywords'] = template.get_current_theme().get('keywords')
get_publisher().substitutions.feed(self)

response.breadcrumb = [ ('', _('Home')) ]

if not self.admin:
self.admin = get_publisher().admin_directory_class()

if not self.backoffice:
self.backoffice = get_publisher().backoffice_directory_class()

try:
return Directory._q_traverse(self, path)
except errors.TraversalError, e:
try:
f = FormDef.get_by_urlname(path[0])
except KeyError:
pass
else:
base_url = get_publisher().get_root_url()

uri_rest = get_request().environ.get('REQUEST_URI')
if not uri_rest:
uri_rest = get_request().get_path()
if uri_rest.startswith(base_url):
uri_rest = uri_rest[len(base_url):]
elif uri_rest.startswith('/'):
# dirty hack, ezldap reverseproxy uses a fake base_url
uri_rest = uri_rest[1:]
if f.category_id:
return redirect('%s%s/%s' % (base_url, f.category.url_name, uri_rest))

raise e


def _q_lookup(self, component):
if component == 'qo':
dirname = os.path.join(get_publisher().data_dir, 'qommon')
return StaticDirectory(dirname, follow_symlinks = True)

if component == 'aq':
dirname = os.path.join(get_publisher().data_dir, 'qommon', 'auquotidien')
return StaticDirectory(dirname, follow_symlinks = True)

if component in ('css','images'):
return OldRootDirectory._q_lookup(self, component)

# is this a category ?
try:
category = Category.get_by_urlname(component)
except KeyError:
pass
else:
return FormsRootDirectory(category)

# is this a formdef ?
try:
formdef = FormDef.get_by_urlname(component)
except KeyError:
pass
else:
if formdef.category_id is None:
get_response().filter['bigdiv'] = 'rub_service'
return FormsRootDirectory()._q_lookup(component)
# if there is category, let it fall back to raise TraversalError,
# it will get caught in _q_traverse that will redirect it to an
# URL embedding the category

return None

def json(self):
return FormsRootDirectory().json()

def categories(self):
return FormsRootDirectory().categories()

def _q_index [html] (self):
if get_request().is_json():
return FormsRootDirectory().json()

root_url = get_publisher().get_root_url()
if get_request().user and get_request().user.anonymous and get_request().user.lasso_dump:
return redirect('%smyspace/new' % root_url)

if get_response().iframe_mode:
# never display home page in an iframe
return redirect('%sservices' % root_url)

template.html_top()
get_response().filter['is_index'] = True

if not 'auquotidien-welcome-in-services' in get_response().filter.get('keywords', []):
t = TextsDirectory.get_html_text('aq-home-page')
if not t:
if get_request().user:
t = TextsDirectory.get_html_text('welcome-logged')
else:
t = TextsDirectory.get_html_text('welcome-unlogged')
if t:
'<div id="home-page-intro">'
t
'</div>'

'<div id="centre">'
self.box_services(position='1st')
'</div>'
'<div id="droite">'
self.myspace_snippet()
self.box_services(position='2nd')
self.consultations()
self.announces()
'</div>'

user = get_request().user
if user and user.can_go_in_backoffice():
get_response().filter['backoffice'] = True

def services [html] (self):
template.html_top()
get_response().filter['bigdiv'] = 'rub_service'
self.box_services(level = 2)

def box_services [html] (self, level=3, position=None):
## Services
if get_request().user and get_request().user.roles:
accepted_roles = get_request().user.roles
else:
accepted_roles = []

cats = Category.select(order_by = 'name')
cats = [x for x in cats if x.url_name != 'consultations']
Category.sort_by_position(cats)

all_formdefs = FormDef.select(lambda x: not x.is_disabled() or x.disabled_redirection,
order_by = 'name')

if position:
t = self.display_list_of_formdefs(
[x for x in cats if x.get_homepage_position() == position],
all_formdefs, accepted_roles)
else:
t = self.display_list_of_formdefs(cats, all_formdefs, accepted_roles)

if not t:
return

if position == '2nd':
'<div id="services-2nd">'
else:
'<div id="services">'
if level == 2:
'<h2>%s</h2>' % _('Services')
else:
'<h3>%s</h3>' % _('Services')

if get_response().iframe_mode:
if get_request().user:
message = TextsDirectory.get_html_text('welcome-logged')
else:
message = TextsDirectory.get_html_text('welcome-unlogged')

if message:
'<div id="welcome-message">'
message
'</div>'
elif 'auquotidien-welcome-in-services' in get_response().filter.get('keywords', []):
homepage_text = TextsDirectory.get_html_text('aq-home-page')
if homepage_text:
'<div id="home-page-intro">'
homepage_text
'</div>'

'<ul>'
t
'</ul>'

'</div>'

def display_list_of_formdefs [html] (self, cats, all_formdefs, accepted_roles):
for category in cats:
if category.url_name == 'consultations':
self.consultations_category = category
continue
formdefs = [x for x in all_formdefs if x.category_id == category.id]
formdefs_advertise = []

for formdef in formdefs[:]:
if formdef.is_disabled(): # is a redirection
continue
if not formdef.roles:
continue
if not get_request().user:
if formdef.always_advertise:
formdefs_advertise.append(formdef)
formdefs.remove(formdef)
continue
if logged_users_role().id in formdef.roles:
continue
for q in accepted_roles:
if q in formdef.roles:
break
else:
if formdef.always_advertise:
formdefs_advertise.append(formdef)
formdefs.remove(formdef)

if not formdefs and not formdefs_advertise:
continue

'<li>'
'<strong>'
'<a href="%s/">' % category.url_name
category.name
'</a></strong>\n'
if category.description:
if category.description[0] == '<':
htmltext(category.description)
else:
'<p>'
category.description
'</p>'
'<ul>'
limit = category.get_limit()
for formdef in formdefs[:limit]:
'<li>'
'<a href="%s/%s/">%s</a>' % (category.url_name, formdef.url_name, formdef.name)
'</li>\n'
if len(formdefs) < limit:
for formdef in formdefs_advertise[:limit-len(formdefs)]:
'<li>'
'<a href="%s/%s/">%s</a>' % (category.url_name, formdef.url_name, formdef.name)
' (%s)' % _('authentication required')
'</li>\n'
if (len(formdefs)+len(formdefs_advertise)) > limit:
'<li class="all-forms"><a href="%s/" title="%s">%s</a></li>' % (category.url_name,
_('Access to all forms of the "%s" category') % category.name,
_('Access to all forms in this category'))
'</ul>'
'</li>\n'

def consultations [html] (self):
cats = [x for x in Category.select() if x.url_name == 'consultations']
if not cats:
return
consultations_category = cats[0]
formdefs = FormDef.select(lambda x: (
x.category_id == consultations_category.id and
(not x.is_disabled() or x.disabled_redirection)),
order_by = 'name')
if not formdefs:
return
## Consultations
'<div id="consultations">'
'<h3>%s</h3>' % _('Consultations')
if consultations_category.description:
if consultations_category.description[0] == '<':
htmltext(consultations_category.description)
else:
'<p>'
consultations_category.description
'</p>'
'<ul>'
for formdef in formdefs:
'<li>'
'<a href="%s/%s/">%s</a>' % (consultations_category.url_name,
formdef.url_name, formdef.name)
'</li>'
'</ul>'
'</div>'

def box_side [html] (self, path):
'<div id="sidebox">'
root_url = get_publisher().get_root_url()

if self.has_anonymous_access_codes():
'<form id="follow-form" action="%saccesscode">' % root_url
'<h3>%s</h3>' % _('Tracking')
'<label>%s</label> ' % _('Code:')
'<input name="code" size="10"/>'
'</form>'

self.links()

cats = Category.select(order_by = 'name')
cats = [x for x in cats if x.url_name != 'consultations' and x.get_homepage_position() == 'side']
Category.sort_by_position(cats)
if cats:
'<div id="side-services">'
'<h3>%s</h3>' % _('Services')
'<ul>'
for cat in cats:
'<li><a href="%s/">%s</a></li>' % (cat.url_name, cat.name)
'</ul>'
'</div>'

if Event.keys(): # if there are events, add a link to the agenda
tags = get_cfg('misc', {}).get('event_tags')
if not tags:
tags = get_default_event_tags()
'<h3 id="agenda-link"><a href="%sagenda/">%s</a></h3>' % (root_url, _('Agenda'))

if path and path[0] == 'agenda':
'<p class="tags">'
for tag in tags:
'<a href="%sagenda/tag/%s">%s</a> ' % (root_url, tag, tag)
'</p>'
self.agenda.display_remote_calendars()

'<p>'
' <a href="%sagenda/filter">%s</a>' % (root_url, _('Advanced Filter'))
'</p>'

'</div>'

def has_anonymous_access_codes(self):
for workflow in Workflow.select():
for wfstatus in workflow.possible_status:
for wfitem in wfstatus.items:
if wfitem.key == 'create-anonymous-access-code':
return True
return False

def accesscode(self):
code = get_request().form.get('code')
if not code:
return redirect(get_publisher().get_root_url())
try:
token = Token.get(code)
except KeyError:
return redirect(get_publisher().get_root_url())
if token.type != 'anonymous-access-code':
return redirect(get_publisher().get_root_url())
formdef_urlname, formdata_id = token.formdata_reference
try:
formdata = FormDef.get_by_urlname(formdef_urlname).data_class().get(formdata_id)
except KeyError:
return redirect(get_publisher().get_root_url())
session = get_session()
if not hasattr(session, '_wf_anonymous_access_authorized'):
session._wf_anonymous_access_authorized = []
session._wf_anonymous_access_authorized.append(formdata.get_url())
return redirect(formdata.get_url() + 'access/')

def links [html] (self):
links = Link.select()
if not links:
return

Link.sort_by_position(links)

'<div id="links">'
if links[0].url:
# first link has an URL, so it's not a title, so we display a
# generic title
'<h3>%s</h3>' % _('Useful links')
has_ul = False
vars = get_publisher().substitutions.get_context_variables()
for link in links:
if not link.url:
# acting title
if has_ul:
'</ul>'
'<h3>%s</h3>' % link.title
'<ul>'
has_ul = True
else:
if not has_ul:
'<ul>'
has_ul = True
'<li><a href="%s">%s</a></li>' % (get_variadic_url(link.url, vars), link.title)
if has_ul:
'</ul>'
'</div>'


def announces [html] (self):
announces = Announce.get_published_announces()
if not announces:
return

'<div id="announces">'
'<h3>%s</h3>' % _('Announces to citizens')
for item in announces[:3]:
'<div class="announce-item">'
'<h4>'
if item.publication_time:
time.strftime(misc.date_format(), item.publication_time)
' - '
item.title
'</h4>'
'<p>'
item.text
'</p>'
'</div>'

'<ul id="announces-links">'
'<li><a href="announces/subscribe">%s</a></li>' % _('Receiving those Announces')
'<li><a href="announces/">%s</a></li>' % _('Previous Announces')
'</ul>'
'</div>'

def myspace_snippet [html] (self):
'<div id="myspace">'
'<h3>%s</h3>' % _('My Space')
'<ul>'
if get_request().user and not get_request().user.anonymous:
' <li><a href="myspace/" id="member">%s</a></li>' % _('Access to your personal space')
' <li><a href="logout" id="logout">%s</a></li>' % _('Logout')
else:
' <li><a href="register/" id="inscr">%s</a></li>' % _('Registration')
' <li><a href="login/" id="login">%s</a></li>' % _('Login')
'</ul>'
'</div>'


def page_view [html] (self, key, title, urlname = None):
if not urlname:
urlname = key[3:].replace(str('_'), str('-'))
get_response().breadcrumb.append((urlname, title))
template.html_top(title)
'<div class="article">'
htmltext(TextsDirectory.get_html_text(key))
'</div>'

def informations_editeur [html] (self):
get_response().filter['bigdiv'] = 'info'
return self.page_view('aq-editor-info', _('Editor Informations'),
urlname = 'informations_editeur')

def accessibility(self):
get_response().filter['bigdiv'] = 'accessibility'
return self.page_view('aq-accessibility', _('Accessibility Statement'))

def contact(self):
get_response().filter['bigdiv'] = 'contact'
return self.page_view('aq-contact', _('Contact'))

def help(self):
get_response().filter['bigdiv'] = 'help'
return self.page_view('aq-help', _('Help'))


from qommon.publisher import get_publisher_class
get_publisher_class().root_directory_class = AlternateRootDirectory
get_publisher_class().after_login_url = 'myspace/'
get_publisher_class().use_sms_feature = True

# help links
get_publisher_class().backoffice_help_url = {
'fr': 'https://doc.entrouvert.org/au-quotidien/stable/guide-gestionnaire.html',
}
get_publisher_class().admin_help_url = {
'fr': 'https://doc.entrouvert.org/auquotidien/dev/',
}


EmailsDirectory.register('announces-subscription-confirmation',
N_('Confirmation of Announces Subscription'),
N_('Available variables: change_url, cancel_url, time, sitename'),
default_subject = N_('Announce Subscription Request'),
default_body = N_("""\
You have (or someone impersonating you has) requested to subscribe to
announces from [sitename]. To confirm this request, visit the
following link:

[confirm_url]

If you are not the person who made this request, or you wish to cancel
this request, visit the following link:

[cancel_url]

If you do nothing, the request will lapse after 3 days (precisely on
[time]).
"""))


TextsDirectory.register('aq-announces-subscription',
N_('Text on announces subscription page'),
default = N_('''\
<p>
FIXME
'</p>'''))

TextsDirectory.register('aq-sms-demo',
N_('Text when subscribing to announces SMS and configured as demo'),
default = N_('''
<p>
Receiving announces by SMS is not possible in this demo
</p>'''))

TextsDirectory.register('aq-editor-info', N_('Editor Informations'))
TextsDirectory.register('aq-accessibility', N_('Accessibility Statement'))
TextsDirectory.register('aq-contact', N_('Contact Information'))
TextsDirectory.register('aq-help', N_('Help'))
TextsDirectory.register('aq-sso-text', N_('Connecting with Identity Provider'),
default = N_('''<h3>Connecting with Identity Provider</h3>
<p>You can also use your identity provider to connect.
</p>'''))

TextsDirectory.register('aq-home-page', N_('Home Page'), wysiwyg = True)
(29-29/33)