trivial: apply black

This commit is contained in:
Frédéric Péters 2021-01-19 22:08:54 +01:00
parent 1fd2171ea2
commit 2663e08e2d
19 changed files with 603 additions and 332 deletions

View File

@ -27,9 +27,17 @@ rdb.register_menu_item('payments/', _('Payments'))
rdb.register_directory('settings', admin.SettingsDirectory()) rdb.register_directory('settings', admin.SettingsDirectory())
import wcs.admin.forms import wcs.admin.forms
wcs.admin.forms.FormsDirectory.categories = categories_admin.CategoriesDirectory() wcs.admin.forms.FormsDirectory.categories = categories_admin.CategoriesDirectory()
import wcs.categories import wcs.categories
wcs.categories.Category.XML_NODES = [('name', 'str'), ('url_name', 'str'),
('description', 'str'), ('position', 'int'), wcs.categories.Category.XML_NODES = [
('homepage_position', 'str'), ('redirect_url', 'str'), ('limit', 'int')] ('name', 'str'),
('url_name', 'str'),
('description', 'str'),
('position', 'int'),
('homepage_position', 'str'),
('redirect_url', 'str'),
('limit', 'int'),
]

View File

@ -1,4 +1,5 @@
from wcs.workflows import WorkflowStatusItem from wcs.workflows import WorkflowStatusItem
class AbeliumDominoRegisterFamilyWorkflowStatusItem(WorkflowStatusItem): class AbeliumDominoRegisterFamilyWorkflowStatusItem(WorkflowStatusItem):
key = 'abelium-domino-register-family' key = 'abelium-domino-register-family'

View File

@ -36,13 +36,21 @@ class PanelDirectory(Directory):
def permissions(self): def permissions(self):
permissions_cfg = get_cfg('aq-permissions', {}) permissions_cfg = get_cfg('aq-permissions', {})
form = Form(enctype='multipart/form-data') form = Form(enctype='multipart/form-data')
form.add(SingleSelectWidget, 'forms', title = _('Admin role for forms'), form.add(
value = permissions_cfg.get('forms', None), SingleSelectWidget,
options = [(None, _('Nobody'), None)] + get_user_roles()) 'forms',
title=_('Admin role for forms'),
value=permissions_cfg.get('forms', None),
options=[(None, _('Nobody'), None)] + get_user_roles(),
)
if get_publisher().has_site_option('auquotidien-payments'): if get_publisher().has_site_option('auquotidien-payments'):
form.add(SingleSelectWidget, 'payments', title = _('Admin role for payments'), form.add(
value = permissions_cfg.get('payments', None), SingleSelectWidget,
options = [(None, _('Nobody'), None)] + get_user_roles()) 'payments',
title=_('Admin role for payments'),
value=permissions_cfg.get('payments', None),
options=[(None, _('Nobody'), None)] + get_user_roles(),
)
form.add_submit('submit', _('Submit')) form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
@ -58,6 +66,7 @@ class PanelDirectory(Directory):
return r.getvalue() return r.getvalue()
else: else:
from wcs.admin.settings import cfg_submit from wcs.admin.settings import cfg_submit
cfg_submit(form, 'aq-permissions', ('forms', 'payments')) cfg_submit(form, 'aq-permissions', ('forms', 'payments'))
return redirect('..') return redirect('..')
@ -83,4 +92,5 @@ class SettingsDirectory(wcs.admin.settings.SettingsDirectory):
return PanelDirectory() return PanelDirectory()
return super(SettingsDirectory, self)._q_lookup(component) return super(SettingsDirectory, self)._q_lookup(component)
from . import categories_admin from . import categories_admin

View File

@ -17,6 +17,7 @@ from wcs.qommon.form import *
CURRENT_USER = object() CURRENT_USER = object()
def check_visibility(target, user=CURRENT_USER): def check_visibility(target, user=CURRENT_USER):
if not get_publisher().has_site_option('auquotidien-%s' % target): if not get_publisher().has_site_option('auquotidien-%s' % target):
# option not explicitely enabled, -> off. # option not explicitely enabled, -> off.
@ -48,4 +49,5 @@ class BackofficeRootDirectory(wcs.backoffice.root.RootDirectory):
def home(self): def home(self):
return redirect('management/') return redirect('management/')
get_publisher_class().backoffice_directory_class = BackofficeRootDirectory get_publisher_class().backoffice_directory_class = BackofficeRootDirectory

View File

@ -26,6 +26,7 @@ from wcs.qommon.backoffice.menu import html_top
from wcs.qommon.admin.menu import command_icon, error_page from wcs.qommon.admin.menu import command_icon, error_page
import wcs.admin.categories import wcs.admin.categories
class CategoryUI: class CategoryUI:
def __init__(self, category): def __init__(self, category):
self.category = category self.category = category
@ -34,28 +35,47 @@ class CategoryUI:
def get_form(self): def get_form(self):
form = Form(enctype='multipart/form-data') form = Form(enctype='multipart/form-data')
form.add(StringWidget, 'name', title = _('Category Name'), required = True, size=30, form.add(
value = self.category.name) StringWidget, 'name', title=_('Category Name'), required=True, size=30, value=self.category.name
form.add(TextWidget, 'description', title = _('Description'), cols = 80, rows = 10, )
value = self.category.description) form.add(
TextWidget,
'description',
title=_('Description'),
cols=80,
rows=10,
value=self.category.description,
)
homepage_redirect_url = get_cfg('misc', {}).get('homepage-redirect-url') homepage_redirect_url = get_cfg('misc', {}).get('homepage-redirect-url')
if not homepage_redirect_url: if not homepage_redirect_url:
form.add(SingleSelectWidget, 'homepage_position', form.add(
title=_('Position on homepage'), SingleSelectWidget,
value=self.category.get_homepage_position(), 'homepage_position',
options = [('1st', _('First Column')), title=_('Position on homepage'),
('2nd', _('Second Column')), value=self.category.get_homepage_position(),
('side', _('Sidebar')), options=[
('none', _('None'))]) ('1st', _('First Column')),
form.add(IntWidget, 'limit', ('2nd', _('Second Column')),
title=_('Limit number of items displayed on homepage'), ('side', _('Sidebar')),
value=self.category.get_limit()) ('none', _('None')),
],
)
form.add(
IntWidget,
'limit',
title=_('Limit number of items displayed on homepage'),
value=self.category.get_limit(),
)
form.add(StringWidget, 'redirect_url', size=32, form.add(
title=_('URL Redirection'), StringWidget,
hint=_('If set, redirect the site category page to the given URL.'), 'redirect_url',
value=self.category.redirect_url) size=32,
title=_('URL Redirection'),
hint=_('If set, redirect the site category page to the given URL.'),
value=self.category.redirect_url,
)
form.add_submit('submit', _('Submit')) form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
@ -66,7 +86,7 @@ class CategoryUI:
self.category.name = form.get_widget('name').parse() self.category.name = form.get_widget('name').parse()
category = self.category category = self.category
else: else:
category = Category(name = form.get_widget('name').parse()) category = Category(name=form.get_widget('name').parse())
name = form.get_widget('name').parse() name = form.get_widget('name').parse()
category_names = [x.name for x in Category.select() if x.id != category.id] category_names = [x.name for x in Category.select() if x.id != category.id]
@ -85,7 +105,6 @@ class CategoryUI:
category.store() category.store()
class CategoryPage(wcs.admin.categories.CategoryPage): class CategoryPage(wcs.admin.categories.CategoryPage):
def __init__(self, component): def __init__(self, component):
self.category = Category.get(component) self.category = Category.get(component)
@ -97,7 +116,7 @@ class CategoriesDirectory(wcs.admin.categories.CategoriesDirectory):
label = N_('Categories') label = N_('Categories')
def new(self): def new(self):
get_response().breadcrumb.append( ('new', _('New')) ) get_response().breadcrumb.append(('new', _('New')))
category_ui = CategoryUI(None) category_ui = CategoryUI(None)
form = category_ui.get_form() form = category_ui.get_form()
if form.get_widget('cancel').parse(): if form.get_widget('cancel').parse():
@ -111,7 +130,7 @@ class CategoriesDirectory(wcs.admin.categories.CategoriesDirectory):
else: else:
return redirect('.') return redirect('.')
html_top('categories', title = _('New Category')) html_top('categories', title=_('New Category'))
r = TemplateIO(html=True) r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('New Category') r += htmltext('<h2>%s</h2>') % _('New Category')
r += form.render() r += form.render()

View File

@ -2,6 +2,7 @@ class AppointmentPart(object):
def view(self): def view(self):
return '' return ''
class AppointmentErrorPart(object): class AppointmentErrorPart(object):
def view(self): def view(self):
return '' return ''

View File

@ -17,6 +17,7 @@ from wcs.qommon import emails
OldFormPage = wcs.forms.root.FormPage OldFormPage = wcs.forms.root.FormPage
class AlternateFormPage(OldFormPage): class AlternateFormPage(OldFormPage):
def __call__(self): def __call__(self):
# Fix missing trailing slash; lose query string on purpose. # Fix missing trailing slash; lose query string on purpose.
@ -31,6 +32,7 @@ class AlternateFormPage(OldFormPage):
get_response().filter['steps'] = form_side_html get_response().filter['steps'] = form_side_html
return return
wcs.forms.root.FormPage = AlternateFormPage wcs.forms.root.FormPage = AlternateFormPage
wcs.forms.root.PublicFormStatusPage.form_page_class = AlternateFormPage wcs.forms.root.PublicFormStatusPage.form_page_class = AlternateFormPage
wcs.forms.preview.PreviewFormPage.__bases__ = (AlternateFormPage,) wcs.forms.preview.PreviewFormPage.__bases__ = (AlternateFormPage,)
@ -38,9 +40,11 @@ wcs.forms.preview.PreviewFormPage.__bases__ = (AlternateFormPage,)
OldFormsRootDirectory = wcs.forms.root.RootDirectory OldFormsRootDirectory = wcs.forms.root.RootDirectory
class AlternateFormsRootDirectory(OldFormsRootDirectory): class AlternateFormsRootDirectory(OldFormsRootDirectory):
def form_list(self, *args, **kwargs): def form_list(self, *args, **kwargs):
form_list = OldFormsRootDirectory.form_list(self, *args, **kwargs) form_list = OldFormsRootDirectory.form_list(self, *args, **kwargs)
return htmltext(str(form_list).replace('h2>', 'h3>')) return htmltext(str(form_list).replace('h2>', 'h3>'))
wcs.forms.root.RootDirectory = AlternateFormsRootDirectory wcs.forms.root.RootDirectory = AlternateFormsRootDirectory

View File

@ -28,6 +28,7 @@ import wcs.myspace
from .payments import Invoice, Regie, is_payment_supported from .payments import Invoice, Regie, is_payment_supported
class MyInvoicesDirectory(Directory): class MyInvoicesDirectory(Directory):
_q_exports = [''] _q_exports = ['']
@ -49,8 +50,7 @@ class MyInvoicesDirectory(Directory):
r += get_session().display_message() r += get_session().display_message()
invoices = [] invoices = []
invoices.extend(Invoice.get_with_indexed_value( invoices.extend(Invoice.get_with_indexed_value(str('user_id'), str(user.id)))
str('user_id'), str(user.id)))
invoices.sort(key=lambda x: (str(x.regie_id), -x.date.toordinal())) invoices.sort(key=lambda x: (str(x.regie_id), -x.date.toordinal()))
last_regie_id = None last_regie_id = None
@ -88,8 +88,10 @@ class MyInvoicesDirectory(Directory):
r += _('paid on %s') % misc.localstrftime(invoice.paid_date) r += _('paid on %s') % misc.localstrftime(invoice.paid_date)
r += ' - ' r += ' - '
button = _('Details') button = _('Details')
r += htmltext('<a href="%s/invoices/%s">%s</a>' % (get_publisher().get_frontoffice_url(), r += htmltext(
invoice.id, button)) '<a href="%s/invoices/%s">%s</a>'
% (get_publisher().get_frontoffice_url(), invoice.id, button)
)
r += htmltext('</li>') r += htmltext('</li>')
if last_regie_id: if last_regie_id:
@ -102,8 +104,8 @@ class MyInvoicesDirectory(Directory):
class JsonDirectory(Directory): class JsonDirectory(Directory):
'''Export of several lists in json, related to the current user or the """Export of several lists in json, related to the current user or the
SAMLv2 NameID we'd get in the URL''' SAMLv2 NameID we'd get in the URL"""
_q_exports = ['forms'] _q_exports = ['forms']
@ -119,14 +121,12 @@ class JsonDirectory(Directory):
formdefs = FormDef.select(order_by='name', ignore_errors=True) formdefs = FormDef.select(order_by='name', ignore_errors=True)
user_forms = [] user_forms = []
for formdef in formdefs: for formdef in formdefs:
user_forms.extend(formdef.data_class().get_with_indexed_value( user_forms.extend(formdef.data_class().get_with_indexed_value('user_id', self.user.id))
'user_id', self.user.id))
epoch = time.localtime(1970) epoch = time.localtime(1970)
user_forms.sort(key=lambda x: x.receipt_time or epoch) user_forms.sort(key=lambda x: x.receipt_time or epoch)
get_response().set_content_type('application/json') get_response().set_content_type('application/json')
forms_output = [] forms_output = []
for form in user_forms: for form in user_forms:
visible_status = form.get_visible_status(user=self.user) visible_status = form.get_visible_status(user=self.user)
@ -136,21 +136,16 @@ class JsonDirectory(Directory):
name = form.formdef.name name = form.formdef.name
id = form.get_display_id() id = form.get_display_id()
status = visible_status.name status = visible_status.name
title = _('%(name)s #%(id)s (%(status)s)') % { title = _('%(name)s #%(id)s (%(status)s)') % {'name': name, 'id': id, 'status': status}
'name': name,
'id': id,
'status': status
}
url = form.get_url() url = form.get_url()
d = { 'title': title, 'url': url } d = {'title': title, 'url': url}
d.update(form.get_substitution_variables(minimal=True)) d.update(form.get_substitution_variables(minimal=True))
forms_output.append(d) forms_output.append(d)
return json.dumps(forms_output, cls=misc.JSONEncoder) return json.dumps(forms_output, cls=misc.JSONEncoder)
class MyspaceDirectory(wcs.myspace.MyspaceDirectory): class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
_q_exports = ['', 'profile', 'new', 'password', 'remove', 'drafts', 'forms', _q_exports = ['', 'profile', 'new', 'password', 'remove', 'drafts', 'forms', 'invoices', 'json']
'invoices', 'json']
invoices = MyInvoicesDirectory() invoices = MyInvoicesDirectory()
json = JsonDirectory() json = JsonDirectory()
@ -161,15 +156,13 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
# Migrate custom text settings # Migrate custom text settings
texts_cfg = get_cfg('texts', {}) texts_cfg = get_cfg('texts', {})
if 'text-aq-top-of-profile' in texts_cfg and ( if 'text-aq-top-of-profile' in texts_cfg and (not 'text-top-of-profile' in texts_cfg):
not 'text-top-of-profile' in texts_cfg):
texts_cfg['text-top-of-profile'] = texts_cfg['text-aq-top-of-profile'] texts_cfg['text-top-of-profile'] = texts_cfg['text-aq-top-of-profile']
del texts_cfg['text-aq-top-of-profile'] del texts_cfg['text-aq-top-of-profile']
get_publisher().write_cfg() get_publisher().write_cfg()
return Directory._q_traverse(self, path) return Directory._q_traverse(self, path)
def _q_index(self): def _q_index(self):
user = get_request().user user = get_request().user
if not user: if not user:
@ -186,8 +179,7 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
formdefs = FormDef.select(order_by='name', ignore_errors=True) formdefs = FormDef.select(order_by='name', ignore_errors=True)
user_forms = [] user_forms = []
for formdef in formdefs: for formdef in formdefs:
user_forms.extend(formdef.data_class().get_with_indexed_value( user_forms.extend(formdef.data_class().get_with_indexed_value('user_id', user.id))
'user_id', user.id))
epoch = time.localtime(1970) epoch = time.localtime(1970)
user_forms.sort(key=lambda x: x.receipt_time or epoch) user_forms.sort(key=lambda x: x.receipt_time or epoch)
@ -223,15 +215,20 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
pass pass
else: else:
r += htmltext('<p>') r += htmltext('<p>')
r += _('You can delete your account freely from the services portal. ' r += _(
'This action is irreversible; it will destruct your personal ' 'You can delete your account freely from the services portal. '
'datas and destruct the access to your request history.') 'This action is irreversible; it will destruct your personal '
r += htmltext(' <strong><a href="remove" rel="popup">%s</a></strong>.') % _('Delete My Account') 'datas and destruct the access to your request history.'
)
r += htmltext(' <strong><a href="remove" rel="popup">%s</a></strong>.') % _(
'Delete My Account'
)
r += htmltext('</p>') r += htmltext('</p>')
if user_forms: if user_forms:
r += htmltext('<h3 id="my-forms">%s</h3>') % _('My Forms') r += htmltext('<h3 id="my-forms">%s</h3>') % _('My Forms')
from . import root from . import root
r += root.FormsRootDirectory().user_forms(user_forms) r += root.FormsRootDirectory().user_forms(user_forms)
return r.getvalue() return r.getvalue()
@ -267,10 +264,14 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
ident_method = 'idp' ident_method = 'idp'
if form_data and ident_method != 'idp': if form_data and ident_method != 'idp':
r += htmltext('<p class="command"><a href="profile" rel="popup">%s</a></p>') % _('Edit My Profile') r += htmltext('<p class="command"><a href="profile" rel="popup">%s</a></p>') % _(
'Edit My Profile'
)
if ident_method == 'password' and passwords_cfg.get('can_change', False): if ident_method == 'password' and passwords_cfg.get('can_change', False):
r += htmltext('<p class="command"><a href="password" rel="popup">%s</a></p>') % _('Change My Password') r += htmltext('<p class="command"><a href="password" rel="popup">%s</a></p>') % _(
'Change My Password'
)
return r.getvalue() return r.getvalue()
@ -279,9 +280,9 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
if not user or user.anonymous: if not user or user.anonymous:
raise errors.AccessUnauthorizedError() raise errors.AccessUnauthorizedError()
form = Form(enctype = 'multipart/form-data') form = Form(enctype='multipart/form-data')
formdef = user.get_formdef() formdef = user.get_formdef()
formdef.add_fields_to_form(form, form_data = user.form_data) formdef.add_fields_to_form(form, form_data=user.form_data)
form.add_submit('submit', _('Apply Changes')) form.add_submit('submit', _('Apply Changes'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
@ -314,11 +315,9 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
if not user or user.anonymous: if not user or user.anonymous:
raise errors.AccessUnauthorizedError() raise errors.AccessUnauthorizedError()
form = Form(enctype = 'multipart/form-data') form = Form(enctype='multipart/form-data')
form.add(PasswordWidget, 'new_password', title = _('New Password'), form.add(PasswordWidget, 'new_password', title=_('New Password'), required=True)
required=True) form.add(PasswordWidget, 'new2_password', title=_('New Password (confirm)'), required=True)
form.add(PasswordWidget, 'new2_password', title = _('New Password (confirm)'),
required=True)
form.add_submit('submit', _('Change Password')) form.add_submit('submit', _('Change Password'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
@ -351,7 +350,7 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
if not get_request().user or not get_request().user.anonymous: if not get_request().user or not get_request().user.anonymous:
raise errors.AccessUnauthorizedError() raise errors.AccessUnauthorizedError()
form = Form(enctype = 'multipart/form-data') form = Form(enctype='multipart/form-data')
formdef = get_publisher().user_class.get_formdef() formdef = get_publisher().user_class.get_formdef()
if formdef: if formdef:
formdef.add_fields_to_form(form) formdef.add_fields_to_form(form)
@ -376,15 +375,15 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
template.html_top(_('Welcome')) template.html_top(_('Welcome'))
return form.render() return form.render()
def remove(self): def remove(self):
user = get_request().user user = get_request().user
if not user or user.anonymous: if not user or user.anonymous:
raise errors.AccessUnauthorizedError() raise errors.AccessUnauthorizedError()
form = Form(enctype = 'multipart/form-data') form = Form(enctype='multipart/form-data')
form.widgets.append(HtmlWidget('<p>%s</p>' % _( form.widgets.append(
'Are you really sure you want to remove your account?'))) HtmlWidget('<p>%s</p>' % _('Are you really sure you want to remove your account?'))
)
form.add_submit('submit', _('Remove my account')) form.add_submit('submit', _('Remove my account'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
@ -394,7 +393,7 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
if form.is_submitted() and not form.has_errors(): if form.is_submitted() and not form.has_errors():
user = get_request().user user = get_request().user
account = PasswordAccount.get_on_index(user.id, str('user_id')) account = PasswordAccount.get_on_index(user.id, str('user_id'))
get_session_manager().expire_session() get_session_manager().expire_session()
account.remove_self() account.remove_self()
return redirect(get_publisher().get_root_url()) return redirect(get_publisher().get_root_url())
@ -402,7 +401,4 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
return form.render() return form.render()
TextsDirectory.register('aq-myspace-invoice', TextsDirectory.register('aq-myspace-invoice', N_('Message on top of invoices page'), category=N_('Invoices'))
N_('Message on top of invoices page'),
category = N_('Invoices'))

View File

@ -8,8 +8,7 @@ from decimal import Decimal
from django.utils.six.moves.urllib import parse as urllib from django.utils.six.moves.urllib import parse as urllib
from quixote import (redirect, get_publisher, get_request, get_session, from quixote import redirect, get_publisher, get_request, get_session, get_response
get_response)
from quixote.directory import Directory from quixote.directory import Directory
from quixote.html import TemplateIO, htmltext from quixote.html import TemplateIO, htmltext
@ -26,14 +25,14 @@ from wcs.qommon import _, N_
from wcs.qommon import force_str from wcs.qommon import force_str
from wcs.qommon import errors, get_logger, get_cfg, emails from wcs.qommon import errors, get_logger, get_cfg, emails
from wcs.qommon.storage import StorableObject from wcs.qommon.storage import StorableObject
from wcs.qommon.form import htmltext, StringWidget, TextWidget, SingleSelectWidget, \ from wcs.qommon.form import htmltext, StringWidget, TextWidget, SingleSelectWidget, WidgetDict
WidgetDict
from wcs.qommon.misc import simplify from wcs.qommon.misc import simplify
from wcs.formdef import FormDef from wcs.formdef import FormDef
from wcs.formdata import Evolution from wcs.formdata import Evolution
from wcs.workflows import WorkflowStatusItem, register_item_class, template_on_formdata from wcs.workflows import WorkflowStatusItem, register_item_class, template_on_formdata
def is_payment_supported(): def is_payment_supported():
if not eopayment: if not eopayment:
return False return False
@ -49,8 +48,7 @@ class Regie(StorableObject):
service_options = None service_options = None
def get_payment_object(self): def get_payment_object(self):
return eopayment.Payment(kind=self.service, return eopayment.Payment(kind=self.service, options=self.service_options)
options=self.service_options)
class Invoice(StorableObject): class Invoice(StorableObject):
@ -97,12 +95,14 @@ class Invoice(StorableObject):
r = random.SystemRandom() r = random.SystemRandom()
self.fresh = True self.fresh = True
while True: while True:
id = '-'.join([ id = '-'.join(
dt.now().strftime('%Y%m%d'), [
'r%s' % (self.regie_id or 'x'), dt.now().strftime('%Y%m%d'),
'f%s' % (self.formdef_id or 'x'), 'r%s' % (self.regie_id or 'x'),
''.join([r.choice(string.digits) for x in range(5)]) 'f%s' % (self.formdef_id or 'x'),
]) ''.join([r.choice(string.digits) for x in range(5)]),
]
)
crc = '%0.2d' % (hashlib.md5(id.encode('utf-8')).digest()[0] % 100) crc = '%0.2d' % (hashlib.md5(id.encode('utf-8')).digest()[0] % 100)
id = id + '-' + crc id = id + '-' + crc
if not self.has_key(id): if not self.has_key(id):
@ -119,6 +119,7 @@ class Invoice(StorableObject):
return int(id[-2:]) == (hashlib.md5(id[:-3].encode('utf-8')).digest()[0] % 100) return int(id[-2:]) == (hashlib.md5(id[:-3].encode('utf-8')).digest()[0] % 100)
except: except:
return False return False
check_crc = classmethod(check_crc) check_crc = classmethod(check_crc)
def pay(self): def pay(self):
@ -150,11 +151,16 @@ class Invoice(StorableObject):
INVOICE_EVO_VIEW = { INVOICE_EVO_VIEW = {
'create': N_('Create Invoice <a href="%(url)s">%(id)s</a>: %(subject)s - %(amount)s &euro;'), 'create': N_('Create Invoice <a href="%(url)s">%(id)s</a>: %(subject)s - %(amount)s &euro;'),
'pay': N_('Invoice <a href="%(url)s">%(id)s</a> is paid with transaction number %(transaction_order_id)s'), 'pay': N_(
'Invoice <a href="%(url)s">%(id)s</a> is paid with transaction number %(transaction_order_id)s'
),
'cancel': N_('Cancel Invoice <a href="%(url)s">%(id)s</a>'), 'cancel': N_('Cancel Invoice <a href="%(url)s">%(id)s</a>'),
'try': N_('Try paying invoice <a href="%(url)s">%(id)s</a> with transaction number %(transaction_order_id)s'), 'try': N_(
'Try paying invoice <a href="%(url)s">%(id)s</a> with transaction number %(transaction_order_id)s'
),
} }
class InvoiceEvolutionPart: class InvoiceEvolutionPart:
action = None action = None
id = None id = None
@ -180,8 +186,9 @@ class InvoiceEvolutionPart:
return '' return ''
if self.transaction: if self.transaction:
vars['transaction_order_id'] = self.transaction.order_id vars['transaction_order_id'] = self.transaction.order_id
return htmltext('<p class="invoice-%s">' % self.action + \ return htmltext(
_(INVOICE_EVO_VIEW[self.action]) % vars + '</p>') '<p class="invoice-%s">' % self.action + _(INVOICE_EVO_VIEW[self.action]) % vars + '</p>'
)
class Transaction(StorableObject): class Transaction(StorableObject):
@ -206,8 +213,10 @@ class Transaction(StorableObject):
id = ''.join([r.choice(string.digits) for x in range(16)]) id = ''.join([r.choice(string.digits) for x in range(16)])
if not cls.has_key(id): if not cls.has_key(id):
return id return id
get_new_id = classmethod(get_new_id) get_new_id = classmethod(get_new_id)
class PaymentWorkflowStatusItem(WorkflowStatusItem): class PaymentWorkflowStatusItem(WorkflowStatusItem):
description = N_('Payment Creation') description = N_('Payment Creation')
key = 'payment' key = 'payment'
@ -224,6 +233,7 @@ class PaymentWorkflowStatusItem(WorkflowStatusItem):
def is_available(self, workflow=None): def is_available(self, workflow=None):
return is_payment_supported() return is_payment_supported()
is_available = classmethod(is_available) is_available = classmethod(is_available)
def render_as_line(self): def render_as_line(self):
@ -236,38 +246,49 @@ class PaymentWorkflowStatusItem(WorkflowStatusItem):
return _('Payable (not completed)') return _('Payable (not completed)')
def get_parameters(self): def get_parameters(self):
return ('subject', 'details', 'amount', 'regie_id', 'next_status', return ('subject', 'details', 'amount', 'regie_id', 'next_status', 'request_kwargs')
'request_kwargs')
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
if 'subject' in parameters: if 'subject' in parameters:
form.add(StringWidget, '%ssubject' % prefix, title=_('Subject'), form.add(StringWidget, '%ssubject' % prefix, title=_('Subject'), value=self.subject, size=40)
value=self.subject, size=40)
if 'details' in parameters: if 'details' in parameters:
form.add(TextWidget, '%sdetails' % prefix, title=_('Details'), form.add(
value=self.details, cols=80, rows=10) TextWidget, '%sdetails' % prefix, title=_('Details'), value=self.details, cols=80, rows=10
)
if 'amount' in parameters: if 'amount' in parameters:
form.add(StringWidget, '%samount' % prefix, title=_('Amount'), value=self.amount) form.add(StringWidget, '%samount' % prefix, title=_('Amount'), value=self.amount)
if 'regie_id' in parameters: if 'regie_id' in parameters:
form.add(SingleSelectWidget, '%sregie_id' % prefix, form.add(
title=_('Regie'), value=self.regie_id, SingleSelectWidget,
options = [(None, '---')] + [(x.id, x.label) for x in Regie.select()]) '%sregie_id' % prefix,
title=_('Regie'),
value=self.regie_id,
options=[(None, '---')] + [(x.id, x.label) for x in Regie.select()],
)
if 'next_status' in parameters: if 'next_status' in parameters:
form.add(SingleSelectWidget, '%snext_status' % prefix, form.add(
title=_('Status after validation'), value = self.next_status, SingleSelectWidget,
hint=_('Used only if the current status of the form does not contain any "Payment Validation" item'), '%snext_status' % prefix,
options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status]) title=_('Status after validation'),
value=self.next_status,
hint=_(
'Used only if the current status of the form does not contain any "Payment Validation" item'
),
options=[(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status],
)
if 'request_kwargs' in parameters: if 'request_kwargs' in parameters:
keys = ['name', 'email', 'address', 'phone', 'info1', 'info2', 'info3'] keys = ['name', 'email', 'address', 'phone', 'info1', 'info2', 'info3']
hint = '' hint = ''
hint +=_('If the value starts by = it will be ' hint += _('If the value starts by = it will be ' 'interpreted as a Python expression.')
'interpreted as a Python expression.')
hint += ' ' hint += ' '
hint += _('Standard keys are: %s.') % (', '.join(keys)) hint += _('Standard keys are: %s.') % (', '.join(keys))
form.add(WidgetDict, 'request_kwargs', form.add(
WidgetDict,
'request_kwargs',
title=_('Parameters for the payment system'), title=_('Parameters for the payment system'),
hint=hint, hint=hint,
value = self.request_kwargs) value=self.request_kwargs,
)
def perform(self, formdata): def perform(self, formdata):
invoice = Invoice(regie_id=self.regie_id, formdef_id=formdata.formdef.id) invoice = Invoice(regie_id=self.regie_id, formdef_id=formdata.formdef.id)
@ -278,8 +299,9 @@ class PaymentWorkflowStatusItem(WorkflowStatusItem):
invoice.subject = template_on_formdata(formdata, self.compute(self.subject)) invoice.subject = template_on_formdata(formdata, self.compute(self.subject))
else: else:
invoice.subject = _('%(form_name)s #%(formdata_id)s') % { invoice.subject = _('%(form_name)s #%(formdata_id)s') % {
'form_name': formdata.formdef.name, 'form_name': formdata.formdef.name,
'formdata_id': formdata.id } 'formdata_id': formdata.id,
}
invoice.details = template_on_formdata(formdata, self.compute(self.details)) invoice.details = template_on_formdata(formdata, self.compute(self.details))
invoice.amount = Decimal(self.compute(self.amount)) invoice.amount = Decimal(self.compute(self.amount))
invoice.date = dt.now() invoice.date = dt.now()
@ -300,8 +322,10 @@ class PaymentWorkflowStatusItem(WorkflowStatusItem):
# redirect the user to "my invoices" # redirect the user to "my invoices"
return get_publisher().get_frontoffice_url() + '/myspace/invoices/' return get_publisher().get_frontoffice_url() + '/myspace/invoices/'
register_item_class(PaymentWorkflowStatusItem) register_item_class(PaymentWorkflowStatusItem)
class PaymentCancelWorkflowStatusItem(WorkflowStatusItem): class PaymentCancelWorkflowStatusItem(WorkflowStatusItem):
description = N_('Payment Cancel') description = N_('Payment Cancel')
key = 'payment-cancel' key = 'payment-cancel'
@ -313,6 +337,7 @@ class PaymentCancelWorkflowStatusItem(WorkflowStatusItem):
def is_available(self, workflow=None): def is_available(self, workflow=None):
return is_payment_supported() return is_payment_supported()
is_available = classmethod(is_available) is_available = classmethod(is_available)
def render_as_line(self): def render_as_line(self):
@ -332,13 +357,16 @@ class PaymentCancelWorkflowStatusItem(WorkflowStatusItem):
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
if 'reason' in parameters: if 'reason' in parameters:
form.add(StringWidget, '%sreason' % prefix, title=_('Reason'), form.add(StringWidget, '%sreason' % prefix, title=_('Reason'), value=self.reason, size=40)
value=self.reason, size=40)
if 'regie_id' in parameters: if 'regie_id' in parameters:
form.add(SingleSelectWidget, '%sregie_id' % prefix, form.add(
title=_('Regie'), value=self.regie_id, SingleSelectWidget,
options = [(None, '---'), ('_all', _('All Regies'))] + \ '%sregie_id' % prefix,
[(x.id, x.label) for x in Regie.select()]) title=_('Regie'),
value=self.regie_id,
options=[(None, '---'), ('_all', _('All Regies'))]
+ [(x.id, x.label) for x in Regie.select()],
)
def perform(self, formdata): def perform(self, formdata):
invoices_id = [] invoices_id = []
@ -356,8 +384,9 @@ class PaymentCancelWorkflowStatusItem(WorkflowStatusItem):
# security filter: check user # security filter: check user
invoices = [i for i in invoices if i.user_id == formdata.user_id] invoices = [i for i in invoices if i.user_id == formdata.user_id]
# security filter: check formdata & formdef # security filter: check formdata & formdef
invoices = [i for i in invoices if (i.formdata_id == formdata.id) \ invoices = [
and (i.formdef_id == formdata.formdef.id)] i for i in invoices if (i.formdata_id == formdata.id) and (i.formdef_id == formdata.formdef.id)
]
evo = Evolution() evo = Evolution()
evo.time = time.localtime() evo.time = time.localtime()
for invoice in invoices: for invoice in invoices:
@ -370,6 +399,7 @@ class PaymentCancelWorkflowStatusItem(WorkflowStatusItem):
formdata.store() formdata.store()
return get_publisher().get_frontoffice_url() + '/myspace/invoices/' return get_publisher().get_frontoffice_url() + '/myspace/invoices/'
register_item_class(PaymentCancelWorkflowStatusItem) register_item_class(PaymentCancelWorkflowStatusItem)
@ -377,8 +407,8 @@ def request_payment(invoice_ids, url, add_regie=True):
for invoice_id in invoice_ids: for invoice_id in invoice_ids:
if not Invoice.check_crc(invoice_id): if not Invoice.check_crc(invoice_id):
raise errors.QueryError() raise errors.QueryError()
invoices = [ Invoice.get(invoice_id) for invoice_id in invoice_ids ] invoices = [Invoice.get(invoice_id) for invoice_id in invoice_ids]
invoices = [ i for i in invoices if not (i.paid or i.canceled) ] invoices = [i for i in invoices if not (i.paid or i.canceled)]
regie_ids = set([invoice.regie_id for invoice in invoices]) regie_ids = set([invoice.regie_id for invoice in invoices])
# Do not apply if more than one regie is used or no invoice is not paid or canceled # Do not apply if more than one regie is used or no invoice is not paid or canceled
if len(invoices) == 0 or len(regie_ids) != 1: if len(invoices) == 0 or len(regie_ids) != 1:
@ -420,8 +450,7 @@ def request_payment(invoice_ids, url, add_regie=True):
evo = Evolution() evo = Evolution()
evo.time = time.localtime() evo.time = time.localtime()
evo.status = formdata.status evo.status = formdata.status
evo.add_part(InvoiceEvolutionPart('try', invoice, evo.add_part(InvoiceEvolutionPart('try', invoice, transaction=transaction))
transaction=transaction))
if not formdata.evolution: if not formdata.evolution:
formdata.evolution = [] formdata.evolution = []
formdata.evolution.append(evo) formdata.evolution.append(evo)
@ -434,15 +463,20 @@ def request_payment(invoice_ids, url, add_regie=True):
else: else:
raise NotImplementedError() raise NotImplementedError()
def return_eopayment_form(form): def return_eopayment_form(form):
r = TemplateIO(html=True) r = TemplateIO(html=True)
r += htmltext('<html><body onload="document.payform.submit()">') r += htmltext('<html><body onload="document.payform.submit()">')
r += htmltext('<form action="%s" method="%s" name="payform">') % (force_str(form.url), force_str(form.method)) r += htmltext('<form action="%s" method="%s" name="payform">') % (
force_str(form.url),
force_str(form.method),
)
for field in form.fields: for field in form.fields:
r += htmltext('<input type="%s" name="%s" value="%s"/>') % ( r += htmltext('<input type="%s" name="%s" value="%s"/>') % (
force_str(field['type']), force_str(field['type']),
force_str(field['name']), force_str(field['name']),
force_str(field['value'])) force_str(field['value']),
)
r += htmltext('<input type="submit" name="submit" value="%s"/>') % _('Pay') r += htmltext('<input type="submit" name="submit" value="%s"/>') % _('Pay')
r += htmltext('</body></html>') r += htmltext('</body></html>')
return r.getvalue() return r.getvalue()
@ -458,6 +492,7 @@ class PaymentValidationWorkflowStatusItem(WorkflowStatusItem):
def is_available(self, workflow=None): def is_available(self, workflow=None):
return is_payment_supported() return is_payment_supported()
is_available = classmethod(is_available) is_available = classmethod(is_available)
def render_as_line(self): def render_as_line(self):
@ -468,9 +503,14 @@ class PaymentValidationWorkflowStatusItem(WorkflowStatusItem):
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
if 'next_status' in parameters: if 'next_status' in parameters:
form.add(SingleSelectWidget, '%snext_status' % prefix, form.add(
title=_('Status once validated'), value = self.next_status, SingleSelectWidget,
options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status]) '%snext_status' % prefix,
title=_('Status once validated'),
value=self.next_status,
options=[(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status],
)
register_item_class(PaymentValidationWorkflowStatusItem) register_item_class(PaymentValidationWorkflowStatusItem)
@ -507,8 +547,10 @@ class PublicPaymentRegieBackDirectory(Directory):
transaction.bank_data = bank_data transaction.bank_data = bank_data
transaction.store() transaction.store()
if payment_response.signed and payment_response.is_paid() and commit: if payment_response.signed and payment_response.is_paid() and commit:
logger.info('transaction %s successful, bankd_id:%s bank_data:%s' % ( logger.info(
order_id, payment_response.transaction_id, bank_data)) 'transaction %s successful, bankd_id:%s bank_data:%s'
% (order_id, payment_response.transaction_id, bank_data)
)
for invoice_id in transaction.invoice_ids: for invoice_id in transaction.invoice_ids:
# all invoices are now paid # all invoices are now paid
@ -530,8 +572,7 @@ class PublicPaymentRegieBackDirectory(Directory):
evo = Evolution() evo = Evolution()
evo.time = time.localtime() evo.time = time.localtime()
evo.status = formdata.status evo.status = formdata.status
evo.add_part(InvoiceEvolutionPart('pay', invoice, evo.add_part(InvoiceEvolutionPart('pay', invoice, transaction=transaction))
transaction=transaction))
if not formdata.evolution: if not formdata.evolution:
formdata.evolution = [] formdata.evolution = []
formdata.evolution.append(evo) formdata.evolution.append(evo)
@ -540,11 +581,9 @@ class PublicPaymentRegieBackDirectory(Directory):
formdata.perform_workflow() formdata.perform_workflow()
elif payment_response.is_error() and commit: elif payment_response.is_error() and commit:
logger.info('transaction %s finished with failure, bank_data:%s' % ( logger.info('transaction %s finished with failure, bank_data:%s' % (order_id, bank_data))
order_id, bank_data))
elif commit: elif commit:
logger.info('transaction %s is in intermediate state, bank_data:%s' % ( logger.info('transaction %s is in intermediate state, bank_data:%s' % (order_id, bank_data))
order_id, bank_data))
if payment_response.return_content != None and self.asynchronous: if payment_response.return_content != None and self.asynchronous:
get_response().set_content_type('text/plain') get_response().set_content_type('text/plain')
return payment_response.return_content return payment_response.return_content
@ -560,6 +599,7 @@ class PublicPaymentRegieBackDirectory(Directory):
url += '/myspace/invoices/' url += '/myspace/invoices/'
return redirect(url) return redirect(url)
class PublicPaymentDirectory(Directory): class PublicPaymentDirectory(Directory):
_q_exports = ['init', 'back', 'back_asynchronous'] _q_exports = ['init', 'back', 'back_asynchronous']
@ -579,23 +619,26 @@ class PublicPaymentDirectory(Directory):
return request_payment(invoice_ids, url) return request_payment(invoice_ids, url)
def notify_new_invoice(invoice): def notify_new_invoice(invoice):
notify_invoice(invoice, 'payment-new-invoice-email') notify_invoice(invoice, 'payment-new-invoice-email')
def notify_paid_invoice(invoice): def notify_paid_invoice(invoice):
notify_invoice(invoice, 'payment-invoice-paid-email') notify_invoice(invoice, 'payment-invoice-paid-email')
def notify_canceled_invoice(invoice): def notify_canceled_invoice(invoice):
notify_invoice(invoice, 'payment-invoice-canceled-email') notify_invoice(invoice, 'payment-invoice-canceled-email')
def notify_invoice(invoice, template): def notify_invoice(invoice, template):
user = invoice.get_user() user = invoice.get_user()
assert user is not None assert user is not None
regie = Regie.get(id=invoice.regie_id) regie = Regie.get(id=invoice.regie_id)
emails.custom_template_email(template, { emails.custom_template_email(
'user': user, template,
'invoice': invoice, {'user': user, 'invoice': invoice, 'regie': regie, 'invoice_url': invoice.payment_url()},
'regie': regie, user.email,
'invoice_url': invoice.payment_url() fire_and_forget=True,
}, user.email, fire_and_forget = True) )

View File

@ -19,14 +19,14 @@ from wcs.qommon.admin.emails import EmailsDirectory
from wcs.qommon.backoffice.menu import html_top from wcs.qommon.backoffice.menu import html_top
from wcs.qommon import get_cfg from wcs.qommon import get_cfg
from .payments import (eopayment, Regie, is_payment_supported, Invoice, from .payments import eopayment, Regie, is_payment_supported, Invoice, Transaction, notify_paid_invoice
Transaction, notify_paid_invoice)
from wcs.qommon.admin.texts import TextsDirectory from wcs.qommon.admin.texts import TextsDirectory
if not set: if not set:
from sets import Set as set from sets import Set as set
def invoice_as_html(invoice): def invoice_as_html(invoice):
r = TemplateIO(html=True) r = TemplateIO(html=True)
r += htmltext('<div id="invoice">') r += htmltext('<div id="invoice">')
@ -40,16 +40,20 @@ def invoice_as_html(invoice):
r += '\nTransaction:\n' r += '\nTransaction:\n'
r += pprint.pformat(transaction.__dict__) r += pprint.pformat(transaction.__dict__)
r += htmltext('\n-->') r += htmltext('\n-->')
if invoice.formdef_id and invoice.formdata_id and \ if invoice.formdef_id and invoice.formdata_id and get_session().user == invoice.user_id:
get_session().user == invoice.user_id:
formdef = FormDef.get(invoice.formdef_id) formdef = FormDef.get(invoice.formdef_id)
if formdef: if formdef:
formdata = formdef.data_class().get(invoice.formdata_id, ignore_errors=True) formdata = formdef.data_class().get(invoice.formdata_id, ignore_errors=True)
if formdata: if formdata:
name = _('%(form_name)s #%(formdata_id)s') % { name = _('%(form_name)s #%(formdata_id)s') % {
'form_name': formdata.formdef.name, 'form_name': formdata.formdef.name,
'formdata_id': formdata.id } 'formdata_id': formdata.id,
r += htmltext('<p class="from">%s <a href="%s">%s</a></p>') % (_('From:'), formdata.get_url(), name) }
r += htmltext('<p class="from">%s <a href="%s">%s</a></p>') % (
_('From:'),
formdata.get_url(),
name,
)
r += htmltext('<p class="regie">%s</p>') % _('Regie: %s') % Regie.get(invoice.regie_id).label r += htmltext('<p class="regie">%s</p>') % _('Regie: %s') % Regie.get(invoice.regie_id).label
r += htmltext('<p class="date">%s</p>') % _('Created on: %s') % misc.localstrftime(invoice.date) r += htmltext('<p class="date">%s</p>') % _('Created on: %s') % misc.localstrftime(invoice.date)
if invoice.details: if invoice.details:
@ -114,7 +118,9 @@ class InvoicesDirectory(Directory):
if len(regies_id) == 1: if len(regies_id) == 1:
r += htmltext('<p class="command">') r += htmltext('<p class="command">')
r += htmltext('<a href="%s/payment/init?invoice_ids=%s">') % ( r += htmltext('<a href="%s/payment/init?invoice_ids=%s">') % (
get_publisher().get_frontoffice_url(), component) get_publisher().get_frontoffice_url(),
component,
)
if len(invoice_ids) > 1: if len(invoice_ids) > 1:
r += _('Pay Selected Invoices') r += _('Pay Selected Invoices')
else: else:
@ -136,7 +142,7 @@ class RegieDirectory(Directory):
self.regie = regie self.regie = regie
def _q_index(self): def _q_index(self):
html_top('payments', title = _('Regie: %s') % self.regie.label) html_top('payments', title=_('Regie: %s') % self.regie.label)
r = TemplateIO(html=True) r = TemplateIO(html=True)
get_response().filter['sidebar'] = self.get_sidebar() get_response().filter['sidebar'] = self.get_sidebar()
r += htmltext('<h2>%s</h2>') % _('Regie: %s') % self.regie.label r += htmltext('<h2>%s</h2>') % _('Regie: %s') % self.regie.label
@ -182,26 +188,31 @@ class RegieDirectory(Directory):
self.submit(form) self.submit(form)
return redirect('..') return redirect('..')
html_top('payments', title = _('Edit Regie: %s') % self.regie.label) html_top('payments', title=_('Edit Regie: %s') % self.regie.label)
r = TemplateIO(html=True) r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('Edit Regie: %s') % self.regie.label r += htmltext('<h2>%s</h2>') % _('Edit Regie: %s') % self.regie.label
r += form.render() r += form.render()
return r.getvalue() return r.getvalue()
def form(self): def form(self):
form = Form(enctype='multipart/form-data') form = Form(enctype='multipart/form-data')
form.add(StringWidget, 'label', title=_('Label'), required=True, form.add(StringWidget, 'label', title=_('Label'), required=True, value=self.regie.label)
value=self.regie.label) form.add(
form.add(TextWidget, 'description', title=_('Description'), TextWidget, 'description', title=_('Description'), value=self.regie.description, rows=5, cols=60
value=self.regie.description, rows=5, cols=60) )
form.add(SingleSelectWidget, 'service', title=_('Banking Service'), form.add(
value=self.regie.service, required=True, SingleSelectWidget,
options = [ 'service',
('dummy', _('Dummy (for tests)')), title=_('Banking Service'),
('sips', 'SIPS'), value=self.regie.service,
('systempayv2', 'systempay (Banque Populaire)'), required=True,
('spplus', _('SP+ (Caisse d\'epargne)'))]) options=[
('dummy', _('Dummy (for tests)')),
('sips', 'SIPS'),
('systempayv2', 'systempay (Banque Populaire)'),
('spplus', _('SP+ (Caisse d\'epargne)')),
],
)
form.add_submit('submit', _('Submit')) form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
return form return form
@ -215,8 +226,7 @@ class RegieDirectory(Directory):
def delete(self): def delete(self):
form = Form(enctype='multipart/form-data') form = Form(enctype='multipart/form-data')
form.widgets.append(HtmlWidget('<p>%s</p>' % _( form.widgets.append(HtmlWidget('<p>%s</p>' % _('You are about to irrevocably delete this regie.')))
'You are about to irrevocably delete this regie.')))
form.add_submit('submit', _('Submit')) form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
if form.get_submit() == 'cancel': if form.get_submit() == 'cancel':
@ -224,7 +234,7 @@ class RegieDirectory(Directory):
if not form.is_submitted() or form.has_errors(): if not form.is_submitted() or form.has_errors():
get_response().breadcrumb.append(('delete', _('Delete'))) get_response().breadcrumb.append(('delete', _('Delete')))
r = TemplateIO(html=True) r = TemplateIO(html=True)
html_top('payments', title = _('Delete Regie')) html_top('payments', title=_('Delete Regie'))
r += htmltext('<h2>%s</h2>') % _('Deleting Regie: %s') % self.regie.label r += htmltext('<h2>%s</h2>') % _('Deleting Regie: %s') % self.regie.label
r += form.render() r += form.render()
return r.getvalue() return r.getvalue()
@ -267,11 +277,9 @@ class RegieDirectory(Directory):
kwargs['cols'] = 80 kwargs['cols'] = 80
kwargs['rows'] = 5 kwargs['rows'] = 5
if 'type' not in infos or infos['type'] is str: if 'type' not in infos or infos['type'] is str:
form.add(widget, name, title=_(title), form.add(widget, name, title=_(title), value=service_options.get(name), **kwargs)
value=service_options.get(name), **kwargs)
elif infos['type'] is bool: elif infos['type'] is bool:
form.add(CheckboxWidget, name, title=title, form.add(CheckboxWidget, name, title=title, value=service_options.get(name), **kwargs)
value=service_options.get(name), **kwargs)
form.add_submit('submit', _('Submit')) form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel')) form.add_submit('cancel', _('Cancel'))
return form return form
@ -297,7 +305,7 @@ class RegieDirectory(Directory):
return redirect('.') return redirect('.')
if form.is_submitted() and not form.has_errors(): if form.is_submitted() and not form.has_errors():
if self.submit_options(form, module): if self.submit_options(form, module):
return redirect('..') return redirect('..')
html_top('payments', title=_('Edit Service Options')) html_top('payments', title=_('Edit Service Options'))
@ -360,8 +368,7 @@ class RegieDirectory(Directory):
def get_invoices(self): def get_invoices(self):
sort_by = self.get_sort_by() sort_by = self.get_sort_by()
invoices = list(Invoice.get_with_indexed_value('regie_id', self.regie.id, invoices = list(Invoice.get_with_indexed_value('regie_id', self.regie.id, ignore_errors=True))
ignore_errors=True))
if 'date' in sort_by: if 'date' in sort_by:
reverse = True reverse = True
key = lambda i: getattr(i, sort_by) or datetime.datetime.now() key = lambda i: getattr(i, sort_by) or datetime.datetime.now()
@ -372,31 +379,35 @@ class RegieDirectory(Directory):
return invoices return invoices
def unpay(self, request, invoice): def unpay(self, request, invoice):
get_logger().info(_('manually set unpaid invoice %(invoice_id)s in regie %(regie)s') get_logger().info(
% dict(invoice_id=invoice.id, regie=self.regie.id)) _('manually set unpaid invoice %(invoice_id)s in regie %(regie)s')
% dict(invoice_id=invoice.id, regie=self.regie.id)
)
transaction = Transaction() transaction = Transaction()
transaction.invoice_ids = [ invoice.id ] transaction.invoice_ids = [invoice.id]
transaction.order_id = 'Manual action' transaction.order_id = 'Manual action'
transaction.start = datetime.datetime.now() transaction.start = datetime.datetime.now()
transaction.end = transaction.start transaction.end = transaction.start
transaction.bank_data = { transaction.bank_data = {
'action': 'Set unpaid', 'action': 'Set unpaid',
'by': request.user.get_display_name() + ' (%s)' % request.user.id 'by': request.user.get_display_name() + ' (%s)' % request.user.id,
} }
transaction.store() transaction.store()
invoice.unpay() invoice.unpay()
def pay(self, request, invoice): def pay(self, request, invoice):
get_logger().info(_('manually set paid invoice %(invoice_id)s in regie %(regie)s') get_logger().info(
% dict(invoice_id=invoice.id, regie=self.regie.id)) _('manually set paid invoice %(invoice_id)s in regie %(regie)s')
% dict(invoice_id=invoice.id, regie=self.regie.id)
)
transaction = Transaction() transaction = Transaction()
transaction.invoice_ids = [ invoice.id ] transaction.invoice_ids = [invoice.id]
transaction.order_id = 'Manual action' transaction.order_id = 'Manual action'
transaction.start = datetime.datetime.now() transaction.start = datetime.datetime.now()
transaction.end = transaction.start transaction.end = transaction.start
transaction.bank_data = { transaction.bank_data = {
'action': 'Set paid', 'action': 'Set paid',
'by': request.user.get_display_name() + ' (%s)' % request.user.id 'by': request.user.get_display_name() + ' (%s)' % request.user.id,
} }
transaction.store() transaction.store()
invoice.pay() invoice.pay()
@ -430,7 +441,7 @@ class RegieDirectory(Directory):
r += htmltext('</tr>') r += htmltext('</tr>')
r += htmltext('</thead>') r += htmltext('</thead>')
invoices = self.get_invoices() invoices = self.get_invoices()
for invoice in invoices[offset:offset+self.PAGINATION]: for invoice in invoices[offset : offset + self.PAGINATION]:
r += htmltext('<tbody class="invoice-rows">') r += htmltext('<tbody class="invoice-rows">')
r += htmltext('<tr class="invoice-row"><td>') r += htmltext('<tr class="invoice-row"><td>')
r += misc.localstrftime(invoice.date) r += misc.localstrftime(invoice.date)
@ -456,8 +467,7 @@ class RegieDirectory(Directory):
r += htmltext('</form>') r += htmltext('</form>')
r += htmltext('</td></tr>') r += htmltext('</td></tr>')
transactions = list(Transaction.get_with_indexed_value('invoice_ids', transactions = list(Transaction.get_with_indexed_value('invoice_ids', invoice.id))
invoice.id))
for transaction in sorted(transactions, key=lambda x: x.start): for transaction in sorted(transactions, key=lambda x: x.start):
r += htmltext('<tr>') r += htmltext('<tr>')
r += htmltext('<td></td>') r += htmltext('<td></td>')
@ -473,11 +483,9 @@ class RegieDirectory(Directory):
r += htmltext('</tbody>') r += htmltext('</tbody>')
r += htmltext('</tbody></table>') r += htmltext('</tbody></table>')
if offset != 0: if offset != 0:
r += htmltext('<a href="?offset=%d>%s</a> ') % ( r += htmltext('<a href="?offset=%d>%s</a> ') % (max(0, offset - self.PAGINATION), _('Previous'))
max(0, offset-self.PAGINATION), _('Previous'))
if offset + self.PAGINATION < len(invoices): if offset + self.PAGINATION < len(invoices):
r += htmltext('<a href="?offset=%d>%s</a> ') % ( r += htmltext('<a href="?offset=%d>%s</a> ') % (max(0, offset - self.PAGINATION), _('Previous'))
max(0, offset-self.PAGINATION), _('Previous'))
return r.getvalue() return r.getvalue()
@ -503,7 +511,7 @@ class RegiesDirectory(Directory):
return redirect('%s/' % regie_ui.regie.id) return redirect('%s/' % regie_ui.regie.id)
get_response().breadcrumb.append(('new', _('New Regie'))) get_response().breadcrumb.append(('new', _('New Regie')))
html_top('payments', title = _('New Regie')) html_top('payments', title=_('New Regie'))
r = TemplateIO(html=True) r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('New Regie') r += htmltext('<h2>%s</h2>') % _('New Regie')
r += form.render() r += form.render()
@ -526,6 +534,7 @@ class PaymentsDirectory(AccessControlled, Directory):
def is_accessible(self, user): def is_accessible(self, user):
from .backoffice import check_visibility from .backoffice import check_visibility
return check_visibility('payments', user) return check_visibility('payments', user)
def _q_access(self): def _q_access(self):
@ -535,8 +544,8 @@ class PaymentsDirectory(AccessControlled, Directory):
if not self.is_accessible(user): if not self.is_accessible(user):
raise errors.AccessForbiddenError( raise errors.AccessForbiddenError(
public_msg = _('You are not allowed to access Payments Management'), public_msg=_('You are not allowed to access Payments Management'), location_hint='backoffice'
location_hint = 'backoffice') )
get_response().breadcrumb.append(('payments/', _('Payments'))) get_response().breadcrumb.append(('payments/', _('Payments')))
@ -573,33 +582,43 @@ class PaymentsDirectory(AccessControlled, Directory):
return r.getvalue() return r.getvalue()
TextsDirectory.register('aq-invoice', TextsDirectory.register('aq-invoice', N_('Message on top of an invoice'), category=N_('Invoices'))
N_('Message on top of an invoice'),
category = N_('Invoices'))
EmailsDirectory.register('payment-new-invoice-email', EmailsDirectory.register(
N_('New invoice'), 'payment-new-invoice-email',
N_('Available variables: user, regie, invoice, invoice_url'), N_('New invoice'),
category = N_('Invoices'), N_('Available variables: user, regie, invoice, invoice_url'),
default_subject = N_('New invoice'), category=N_('Invoices'),
default_body = N_(''' default_subject=N_('New invoice'),
default_body=N_(
'''
A new invoice is available at [invoice_url]. A new invoice is available at [invoice_url].
''')) '''
),
)
EmailsDirectory.register('payment-invoice-paid-email', EmailsDirectory.register(
N_('Paid invoice'), 'payment-invoice-paid-email',
N_('Available variables: user, regie, invoice, invoice_url'), N_('Paid invoice'),
category = N_('Invoices'), N_('Available variables: user, regie, invoice, invoice_url'),
default_subject = N_('Paid invoice'), category=N_('Invoices'),
default_body = N_(''' default_subject=N_('Paid invoice'),
default_body=N_(
'''
The invoice [invoice_url] has been paid. The invoice [invoice_url] has been paid.
''')) '''
),
)
EmailsDirectory.register('payment-invoice-canceled-email', EmailsDirectory.register(
N_('Canceled invoice'), 'payment-invoice-canceled-email',
N_('Available variables: user, regie, invoice, invoice_url'), N_('Canceled invoice'),
category = N_('Invoices'), N_('Available variables: user, regie, invoice, invoice_url'),
default_subject = N_('Canceled invoice'), category=N_('Invoices'),
default_body = N_(''' default_subject=N_('Canceled invoice'),
default_body=N_(
'''
The invoice [invoice.id] has been canceled. The invoice [invoice.id] has been canceled.
''')) '''
),
)

View File

@ -62,12 +62,17 @@ def category_get_homepage_position(self):
if self.url_name == 'consultations': if self.url_name == 'consultations':
return '2nd' return '2nd'
return '1st' return '1st'
Category.get_homepage_position = category_get_homepage_position Category.get_homepage_position = category_get_homepage_position
def category_get_limit(self): def category_get_limit(self):
if hasattr(self, 'limit') and self.limit is not None: if hasattr(self, 'limit') and self.limit is not None:
return self.limit return self.limit
return 7 return 7
Category.get_limit = category_get_limit Category.get_limit = category_get_limit
Category.TEXT_ATTRIBUTES = ['name', 'url_name', 'description', 'homepage_position'] Category.TEXT_ATTRIBUTES = ['name', 'url_name', 'description', 'homepage_position']
@ -75,6 +80,7 @@ Category.INT_ATTRIBUTES = ['position', 'limit']
OldRegisterDirectory = wcs.root.RegisterDirectory OldRegisterDirectory = wcs.root.RegisterDirectory
class AlternateRegisterDirectory(OldRegisterDirectory): class AlternateRegisterDirectory(OldRegisterDirectory):
def _q_traverse(self, path): def _q_traverse(self, path):
get_response().filter['bigdiv'] = 'new_member' get_response().filter['bigdiv'] = 'new_member'
@ -88,7 +94,7 @@ class AlternateRegisterDirectory(OldRegisterDirectory):
idps = get_cfg('idp', {}) idps = get_cfg('idp', {})
if len(idps) == 0: if len(idps) == 0:
return template.error_page(_('Authentication subsystem is not yet configured.')) return template.error_page(_('Authentication subsystem is not yet configured.'))
ident_methods = ['idp'] # fallback to old behaviour; saml. ident_methods = ['idp'] # fallback to old behaviour; saml.
if len(ident_methods) == 1: if len(ident_methods) == 1:
method = ident_methods[0] method = ident_methods[0]
@ -97,8 +103,10 @@ class AlternateRegisterDirectory(OldRegisterDirectory):
return wcs.qommon.ident.register(method) return wcs.qommon.ident.register(method)
OldLoginDirectory = wcs.root.LoginDirectory OldLoginDirectory = wcs.root.LoginDirectory
class AlternateLoginDirectory(OldLoginDirectory): class AlternateLoginDirectory(OldLoginDirectory):
def _q_traverse(self, path): def _q_traverse(self, path):
get_response().filter['bigdiv'] = 'member' get_response().filter['bigdiv'] = 'member'
@ -125,9 +133,8 @@ class AlternateLoginDirectory(OldLoginDirectory):
if after_url: if after_url:
root_url = get_publisher().get_root_url() root_url = get_publisher().get_root_url()
after_path = urlparse.urlparse(after_url)[2] after_path = urlparse.urlparse(after_url)[2]
after_path = after_path[len(root_url):] after_path = after_path[len(root_url) :]
if after_path.startswith(str('admin')) or \ if after_path.startswith(str('admin')) or after_path.startswith(str('backoffice')):
after_path.startswith(str('backoffice')):
ident_methods = ['idp'] ident_methods = ['idp']
# don't display authentication system choice # don't display authentication system choice
@ -143,12 +150,12 @@ class AlternateLoginDirectory(OldLoginDirectory):
r = TemplateIO(html=True) r = TemplateIO(html=True)
get_response().breadcrumb.append(('login', _('Login'))) get_response().breadcrumb.append(('login', _('Login')))
identities_cfg = get_cfg('identities', {}) identities_cfg = get_cfg('identities', {})
form = Form(enctype = 'multipart/form-data', id = 'login-form', use_tokens = False) form = Form(enctype='multipart/form-data', id='login-form', use_tokens=False)
if identities_cfg.get('email-as-username', False): if identities_cfg.get('email-as-username', False):
form.add(StringWidget, 'username', title = _('Email'), size=25, required=True) form.add(StringWidget, 'username', title=_('Email'), size=25, required=True)
else: else:
form.add(StringWidget, 'username', title = _('Username'), size=25, required=True) form.add(StringWidget, 'username', title=_('Username'), size=25, required=True)
form.add(PasswordWidget, 'password', title = _('Password'), size=25, required=True) form.add(PasswordWidget, 'password', title=_('Password'), size=25, required=True)
form.add_submit('submit', _('Connect')) form.add_submit('submit', _('Connect'))
if form.is_submitted() and not form.has_errors(): if form.is_submitted() and not form.has_errors():
tmp = wcs.qommon.ident.password.MethodDirectory().login_submit(form) tmp = wcs.qommon.ident.password.MethodDirectory().login_submit(form)
@ -161,20 +168,24 @@ class AlternateLoginDirectory(OldLoginDirectory):
base_url = get_publisher().get_root_url() base_url = get_publisher().get_root_url()
r += htmltext('<p><a href="%sident/password/forgotten">%s</a></p>') % ( r += htmltext('<p><a href="%sident/password/forgotten">%s</a></p>') % (
base_url, _('Forgotten password ?')) base_url,
_('Forgotten password ?'),
)
r += htmltext('</div>') r += htmltext('</div>')
# XXX: this part only supports a single IdP # XXX: this part only supports a single IdP
r += htmltext('<div id="login-sso">') r += htmltext('<div id="login-sso">')
r += TextsDirectory.get_html_text('aq-sso-text') r += TextsDirectory.get_html_text('aq-sso-text')
form = Form(enctype='multipart/form-data', form = Form(enctype='multipart/form-data', action='%sident/idp/login' % base_url)
action = '%sident/idp/login' % base_url)
form.add_hidden('method', 'idp') form.add_hidden('method', 'idp')
for kidp, idp in get_cfg('idp', {}).items(): for kidp, idp in get_cfg('idp', {}).items():
p = lasso.Provider(lasso.PROVIDER_ROLE_IDP, p = lasso.Provider(
misc.get_abs_path(idp['metadata']), lasso.PROVIDER_ROLE_IDP,
misc.get_abs_path(idp.get('publickey')), None) misc.get_abs_path(idp['metadata']),
misc.get_abs_path(idp.get('publickey')),
None,
)
form.add_hidden('idp', p.providerId) form.add_hidden('idp', p.providerId)
break break
form.add_submit('submit', _('Connect')) form.add_submit('submit', _('Connect'))
@ -184,15 +195,19 @@ class AlternateLoginDirectory(OldLoginDirectory):
get_request().environ['REQUEST_METHOD'] = 'GET' get_request().environ['REQUEST_METHOD'] = 'GET'
r += htmltext("""<script type="text/javascript"> r += htmltext(
"""<script type="text/javascript">
document.getElementById('login-form')['username'].focus(); document.getElementById('login-form')['username'].focus();
</script>""") </script>"""
)
return r.getvalue() return r.getvalue()
else: else:
return OldLoginDirectory._q_index(self) return OldLoginDirectory._q_index(self)
OldIdentDirectory = wcs.root.IdentDirectory OldIdentDirectory = wcs.root.IdentDirectory
class AlternateIdentDirectory(OldIdentDirectory): class AlternateIdentDirectory(OldIdentDirectory):
def _q_traverse(self, path): def _q_traverse(self, path):
get_response().filter['bigdiv'] = 'member' get_response().filter['bigdiv'] = 'member'
@ -206,15 +221,41 @@ class AlternatePreviewDirectory(PreviewDirectory):
class AlternateRootDirectory(OldRootDirectory): class AlternateRootDirectory(OldRootDirectory):
_q_exports = ['', 'admin', 'backoffice', 'forms', 'login', 'logout', _q_exports = [
'saml', 'register', 'ident', 'afterjobs', '',
('informations-editeur', 'informations_editeur'), 'admin',
'myspace', 'services', 'categories', 'user', 'backoffice',
('tmp-upload', 'tmp_upload'), 'json', '__version__', 'forms',
'themes', 'pages', 'payment', 'invoices', 'roles', 'login',
'api', 'code', 'fargo', 'tryauth', 'auth', 'preview', 'logout',
('reload-top', 'reload_top'), 'static', 'saml',
('i18n.js', 'i18n_js'), 'actions',] 'register',
'ident',
'afterjobs',
('informations-editeur', 'informations_editeur'),
'myspace',
'services',
'categories',
'user',
('tmp-upload', 'tmp_upload'),
'json',
'__version__',
'themes',
'pages',
'payment',
'invoices',
'roles',
'api',
'code',
'fargo',
'tryauth',
'auth',
'preview',
('reload-top', 'reload_top'),
'static',
('i18n.js', 'i18n_js'),
'actions',
]
register = AlternateRegisterDirectory() register = AlternateRegisterDirectory()
login = AlternateLoginDirectory() login = AlternateLoginDirectory()
@ -250,7 +291,7 @@ class AlternateRootDirectory(OldRootDirectory):
response.filter['keywords'] = template.get_current_theme().get('keywords') response.filter['keywords'] = template.get_current_theme().get('keywords')
get_publisher().substitutions.feed(self) get_publisher().substitutions.feed(self)
response.breadcrumb = [ ('', _('Home')) ] response.breadcrumb = [('', _('Home'))]
if not self.admin: if not self.admin:
self.admin = get_publisher().admin_directory_class() self.admin = get_publisher().admin_directory_class()
@ -279,7 +320,7 @@ class AlternateRootDirectory(OldRootDirectory):
if get_request().get_query(): if get_request().get_query():
uri_rest += '?' + get_request().get_query() uri_rest += '?' + get_request().get_query()
if uri_rest.startswith(base_url): if uri_rest.startswith(base_url):
uri_rest = uri_rest[len(base_url):] uri_rest = uri_rest[len(base_url) :]
if f.category: if f.category:
if f.category.url_name == f.url_name: if f.category.url_name == f.url_name:
return FormsRootDirectory(f.category)._q_traverse(path[1:]) return FormsRootDirectory(f.category)._q_traverse(path[1:])
@ -298,7 +339,6 @@ class AlternateRootDirectory(OldRootDirectory):
raise e raise e
def _q_lookup(self, component): def _q_lookup(self, component):
# is this a category ? # is this a category ?
try: try:
@ -316,8 +356,7 @@ class AlternateRootDirectory(OldRootDirectory):
# if the form has no category, or the request is a POST, or the # if the form has no category, or the request is a POST, or the
# slug matches both a category and a formdef, directly call # slug matches both a category and a formdef, directly call
# into FormsRootDirectory. # into FormsRootDirectory.
if formdef.category_id is None or get_request().get_method() == 'POST' or ( if formdef.category_id is None or get_request().get_method() == 'POST' or (formdef and category):
formdef and category):
get_response().filter['bigdiv'] = 'rub_service' get_response().filter['bigdiv'] = 'rub_service'
return FormsRootDirectory()._q_lookup(component) return FormsRootDirectory()._q_lookup(component)
@ -347,8 +386,9 @@ class AlternateRootDirectory(OldRootDirectory):
redirect_url = get_cfg('misc', {}).get('homepage-redirect-url') redirect_url = get_cfg('misc', {}).get('homepage-redirect-url')
if redirect_url: if redirect_url:
return redirect(misc.get_variadic_url(redirect_url, return redirect(
get_publisher().substitutions.get_context_variables())) misc.get_variadic_url(redirect_url, get_publisher().substitutions.get_context_variables())
)
template.html_top() template.html_top()
r = TemplateIO(html=True) r = TemplateIO(html=True)
@ -384,7 +424,7 @@ class AlternateRootDirectory(OldRootDirectory):
def services(self): def services(self):
template.html_top() template.html_top()
get_response().filter['bigdiv'] = 'rub_service' get_response().filter['bigdiv'] = 'rub_service'
return self.box_services(level = 2) return self.box_services(level=2)
def box_services(self, level=3, position=None): def box_services(self, level=3, position=None):
## Services ## Services
@ -393,17 +433,18 @@ class AlternateRootDirectory(OldRootDirectory):
else: else:
accepted_roles = [] accepted_roles = []
cats = Category.select(order_by = 'name') cats = Category.select(order_by='name')
cats = [x for x in cats if x.url_name != 'consultations'] cats = [x for x in cats if x.url_name != 'consultations']
Category.sort_by_position(cats) Category.sort_by_position(cats)
all_formdefs = FormDef.select(lambda x: not x.is_disabled() or x.disabled_redirection, all_formdefs = FormDef.select(
order_by = 'name') lambda x: not x.is_disabled() or x.disabled_redirection, order_by='name'
)
if position: if position:
t = self.display_list_of_formdefs( t = self.display_list_of_formdefs(
[x for x in cats if x.get_homepage_position() == position], [x for x in cats if x.get_homepage_position() == position], all_formdefs, accepted_roles
all_formdefs, accepted_roles) )
else: else:
t = self.display_list_of_formdefs(cats, all_formdefs, accepted_roles) t = self.display_list_of_formdefs(cats, all_formdefs, accepted_roles)
@ -445,7 +486,7 @@ class AlternateRootDirectory(OldRootDirectory):
formdefs_advertise = [] formdefs_advertise = []
for formdef in formdefs[:]: for formdef in formdefs[:]:
if formdef.is_disabled(): # is a redirection if formdef.is_disabled(): # is a redirection
continue continue
if not formdef.roles: if not formdef.roles:
continue continue
@ -473,7 +514,9 @@ class AlternateRootDirectory(OldRootDirectory):
keywords[keyword] = True keywords[keyword] = True
r += htmltext('<li id="category-%s" data-keywords="%s">') % ( r += htmltext('<li id="category-%s" data-keywords="%s">') % (
category.url_name, ' '.join(keywords)) category.url_name,
' '.join(keywords),
)
r += htmltext('<strong>') r += htmltext('<strong>')
r += htmltext('<a href="%s/">') % category.url_name r += htmltext('<a href="%s/">') % category.url_name
r += category.name r += category.name
@ -487,18 +530,28 @@ class AlternateRootDirectory(OldRootDirectory):
if formdef.is_disabled() and formdef.disabled_redirection: if formdef.is_disabled() and formdef.disabled_redirection:
classes.append('redirection') classes.append('redirection')
r += htmltext('<a class="%s" href="%s/%s/">%s</a>') % ( r += htmltext('<a class="%s" href="%s/%s/">%s</a>') % (
' '.join(classes), category.url_name, formdef.url_name, formdef.name) ' '.join(classes),
category.url_name,
formdef.url_name,
formdef.name,
)
r += htmltext('</li>\n') r += htmltext('</li>\n')
if len(formdefs) < limit: if len(formdefs) < limit:
for formdef in formdefs_advertise[:limit-len(formdefs)]: for formdef in formdefs_advertise[: limit - len(formdefs)]:
r += htmltext('<li class="required-authentication">') r += htmltext('<li class="required-authentication">')
r += htmltext('<a href="%s/%s/">%s</a>') % (category.url_name, formdef.url_name, formdef.name) r += htmltext('<a href="%s/%s/">%s</a>') % (
category.url_name,
formdef.url_name,
formdef.name,
)
r += htmltext('<span> (%s)</span>') % _('authentication required') r += htmltext('<span> (%s)</span>') % _('authentication required')
r += htmltext('</li>\n') r += htmltext('</li>\n')
if (len(formdefs)+len(formdefs_advertise)) > limit: if (len(formdefs) + len(formdefs_advertise)) > limit:
r += htmltext('<li class="all-forms"><a href="%s/" title="%s">%s</a></li>') % (category.url_name, r += htmltext('<li class="all-forms"><a href="%s/" title="%s">%s</a></li>') % (
_('Access to all forms of the "%s" category') % category.name, category.url_name,
_('Access to all forms in this category')) _('Access to all forms of the "%s" category') % category.name,
_('Access to all forms in this category'),
)
r += htmltext('</ul>') r += htmltext('</ul>')
r += htmltext('</li>\n') r += htmltext('</li>\n')
@ -509,10 +562,13 @@ class AlternateRootDirectory(OldRootDirectory):
if not cats: if not cats:
return return
consultations_category = cats[0] consultations_category = cats[0]
formdefs = FormDef.select(lambda x: ( formdefs = FormDef.select(
str(x.category_id) == str(consultations_category.id) and lambda x: (
(not x.is_disabled() or x.disabled_redirection)), str(x.category_id) == str(consultations_category.id)
order_by = 'name') and (not x.is_disabled() or x.disabled_redirection)
),
order_by='name',
)
if not formdefs: if not formdefs:
return return
## Consultations ## Consultations
@ -523,8 +579,11 @@ class AlternateRootDirectory(OldRootDirectory):
r += htmltext('<ul>') r += htmltext('<ul>')
for formdef in formdefs: for formdef in formdefs:
r += htmltext('<li>') r += htmltext('<li>')
r += htmltext('<a href="%s/%s/">%s</a>') % (consultations_category.url_name, r += htmltext('<a href="%s/%s/">%s</a>') % (
formdef.url_name, formdef.name) consultations_category.url_name,
formdef.url_name,
formdef.name,
)
r += htmltext('</li>') r += htmltext('</li>')
r += htmltext('</ul>') r += htmltext('</ul>')
r += htmltext('</div>') r += htmltext('</div>')
@ -534,16 +593,18 @@ class AlternateRootDirectory(OldRootDirectory):
r = TemplateIO(html=True) r = TemplateIO(html=True)
root_url = get_publisher().get_root_url() root_url = get_publisher().get_root_url()
if (path == [''] and if (
'include-tracking-code-form' in get_response().filter.get('keywords', []) and path == ['']
self.has_anonymous_access_codes()): and 'include-tracking-code-form' in get_response().filter.get('keywords', [])
and self.has_anonymous_access_codes()
):
r += htmltext('<form id="follow-form" action="%scode/load">') % root_url r += htmltext('<form id="follow-form" action="%scode/load">') % root_url
r += htmltext('<h3>%s</h3>') % _('Tracking code') r += htmltext('<h3>%s</h3>') % _('Tracking code')
r += htmltext('<input size="12" name="code" placeholder="%s"/>') % _('ex: RPQDFVCD') r += htmltext('<input size="12" name="code" placeholder="%s"/>') % _('ex: RPQDFVCD')
r += htmltext('<input type="submit" value="%s"/>') % _('Load') r += htmltext('<input type="submit" value="%s"/>') % _('Load')
r += htmltext('</form>') r += htmltext('</form>')
cats = Category.select(order_by = 'name') cats = Category.select(order_by='name')
cats = [x for x in cats if x.url_name != 'consultations' and x.get_homepage_position() == 'side'] cats = [x for x in cats if x.url_name != 'consultations' and x.get_homepage_position() == 'side']
Category.sort_by_position(cats) Category.sort_by_position(cats)
if cats: if cats:
@ -574,7 +635,9 @@ class AlternateRootDirectory(OldRootDirectory):
r += htmltext('<h3>%s</h3>') % _('My Space') r += htmltext('<h3>%s</h3>') % _('My Space')
r += htmltext('<ul>') r += htmltext('<ul>')
if get_request().user and not get_request().user.anonymous: if get_request().user and not get_request().user.anonymous:
r += htmltext(' <li><a href="myspace/" id="member">%s</a></li>') % _('Access to your personal space') r += htmltext(' <li><a href="myspace/" id="member">%s</a></li>') % _(
'Access to your personal space'
)
r += htmltext(' <li><a href="logout" id="logout">%s</a></li>') % _('Logout') r += htmltext(' <li><a href="logout" id="logout">%s</a></li>') % _('Logout')
else: else:
r += htmltext(' <li><a href="register/" id="inscr">%s</a></li>') % _('Registration') r += htmltext(' <li><a href="register/" id="inscr">%s</a></li>') % _('Registration')
@ -583,7 +646,7 @@ class AlternateRootDirectory(OldRootDirectory):
r += htmltext('</div>') r += htmltext('</div>')
return r.getvalue() return r.getvalue()
def page_view(self, key, title, urlname = None): def page_view(self, key, title, urlname=None):
if not urlname: if not urlname:
urlname = key[3:].replace(str('_'), str('-')) urlname = key[3:].replace(str('_'), str('-'))
get_response().breadcrumb.append((urlname, title)) get_response().breadcrumb.append((urlname, title))
@ -596,8 +659,7 @@ class AlternateRootDirectory(OldRootDirectory):
def informations_editeur(self): def informations_editeur(self):
get_response().filter['bigdiv'] = 'info' get_response().filter['bigdiv'] = 'info'
return self.page_view('aq-editor-info', _('Editor Informations'), return self.page_view('aq-editor-info', _('Editor Informations'), urlname='informations_editeur')
urlname = 'informations_editeur')
def accessibility(self): def accessibility(self):
get_response().filter['bigdiv'] = 'accessibility' get_response().filter['bigdiv'] = 'accessibility'
@ -613,6 +675,7 @@ class AlternateRootDirectory(OldRootDirectory):
from qommon.publisher import get_publisher_class from qommon.publisher import get_publisher_class
get_publisher_class().root_directory_class = AlternateRootDirectory get_publisher_class().root_directory_class = AlternateRootDirectory
get_publisher_class().after_login_url = 'myspace/' get_publisher_class().after_login_url = 'myspace/'
get_publisher_class().use_sms_feature = True get_publisher_class().use_sms_feature = True
@ -622,9 +685,14 @@ TextsDirectory.register('aq-editor-info', N_('Editor Informations'))
TextsDirectory.register('aq-accessibility', N_('Accessibility Statement')) TextsDirectory.register('aq-accessibility', N_('Accessibility Statement'))
TextsDirectory.register('aq-contact', N_('Contact Information')) TextsDirectory.register('aq-contact', N_('Contact Information'))
TextsDirectory.register('aq-help', N_('Help')) TextsDirectory.register('aq-help', N_('Help'))
TextsDirectory.register('aq-sso-text', N_('Connecting with Identity Provider'), TextsDirectory.register(
default = N_('''<h3>Connecting with Identity Provider</h3> '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>You can also use your identity provider to connect.
</p>''')) </p>'''
),
)
TextsDirectory.register('aq-home-page', N_('Home Page'), wysiwyg = True) TextsDirectory.register('aq-home-page', N_('Home Page'), wysiwyg=True)

View File

@ -9,8 +9,8 @@ import wcs.qommon.saml2
class Saml2Directory(wcs.qommon.saml2.Saml2Directory): class Saml2Directory(wcs.qommon.saml2.Saml2Directory):
def extract_attributes(self, session, login): def extract_attributes(self, session, login):
'''Separate attributes as two dictionaries: one for last value, one for """Separate attributes as two dictionaries: one for last value, one for
the list of values.''' the list of values."""
d = {} d = {}
m = {} m = {}
@ -59,7 +59,7 @@ class Saml2Directory(wcs.qommon.saml2.Saml2Directory):
# name field, this only works if there's a single field for the name # name field, this only works if there's a single field for the name
field_name_values = users_cfg.get('field_name') field_name_values = users_cfg.get('field_name')
if field_name_values: if field_name_values:
if type(field_name_values) is str: # it was a string in previous versions if type(field_name_values) is str: # it was a string in previous versions
field_name_values = [field_name_values] field_name_values = [field_name_values]
if len(field_name_values) == 1: if len(field_name_values) == 1:
user.form_data[field_name_values[0]] = d.get('cn') user.form_data[field_name_values[0]] = d.get('cn')
@ -67,18 +67,81 @@ class Saml2Directory(wcs.qommon.saml2.Saml2Directory):
# other fields, matching is done on known LDAP attribute names and # other fields, matching is done on known LDAP attribute names and
# common variable names # common variable names
extra_field_mappings = [ extra_field_mappings = [
('gn', ('firstname', 'prenom')), ('gn', ('firstname', 'prenom')),
('givenName', ('firstname', 'prenom')), ('givenName', ('firstname', 'prenom')),
('surname', ('surname', 'name', 'nom',)), (
('sn', ('surname', 'name', 'nom',)), 'surname',
('personalTitle', ('personalTitle', 'civilite',)), (
('l', ('location', 'commune', 'ville',)), 'surname',
('streetAddress', ('streetAddress', 'address', 'adresse', 'street',)), 'name',
('street', ('streetAddress', 'address', 'adresse', 'street',)), 'nom',
('postalCode', ('postalCode', 'codepostal', 'cp',)), ),
('telephoneNumber', ('telephoneNumber', 'telephonefixe', 'telephone',)), ),
('mobile', ('mobile', 'telephonemobile',)), (
('faxNumber', ('faxNumber', 'fax')), 'sn',
(
'surname',
'name',
'nom',
),
),
(
'personalTitle',
(
'personalTitle',
'civilite',
),
),
(
'l',
(
'location',
'commune',
'ville',
),
),
(
'streetAddress',
(
'streetAddress',
'address',
'adresse',
'street',
),
),
(
'street',
(
'streetAddress',
'address',
'adresse',
'street',
),
),
(
'postalCode',
(
'postalCode',
'codepostal',
'cp',
),
),
(
'telephoneNumber',
(
'telephoneNumber',
'telephonefixe',
'telephone',
),
),
(
'mobile',
(
'mobile',
'telephonemobile',
),
),
('faxNumber', ('faxNumber', 'fax')),
] ]
for attribute_key, field_varnames in extra_field_mappings: for attribute_key, field_varnames in extra_field_mappings:

View File

@ -10,6 +10,7 @@ from wcs.categories import Category
wcs_error_page = template.error_page wcs_error_page = template.error_page
wcs_get_decorate_vars = template.get_decorate_vars wcs_get_decorate_vars = template.get_decorate_vars
def get_decorate_vars(body, response, generate_breadcrumb=True, template_context=None, **kwargs): def get_decorate_vars(body, response, generate_breadcrumb=True, template_context=None, **kwargs):
if template_context and 'form_side' in template_context: if template_context and 'form_side' in template_context:
# force rendering as it will put new variables in the context # force rendering as it will put new variables in the context
@ -30,7 +31,7 @@ def render_response(publisher, body):
body = str(body) body = str(body)
root_url = publisher.get_root_url() root_url = publisher.get_root_url()
wcs_path = publisher.get_request().get_path()[len(root_url):] wcs_path = publisher.get_request().get_path()[len(root_url) :]
section = wcs_path.split('/')[0] section = wcs_path.split('/')[0]
if section in ('backoffice', 'admin'): if section in ('backoffice', 'admin'):
@ -78,6 +79,7 @@ def error_page(*args, **kwargs):
get_response().filter['title'] = None get_response().filter['title'] = None
return htmltext('<div id="info"><h2>%s</h2>' % title) + error_page + htmltext('</div>') return htmltext('<div id="info"><h2>%s</h2>' % title) + error_page + htmltext('</div>')
template.error_page = error_page template.error_page = error_page
template.get_decorate_vars = get_decorate_vars template.get_decorate_vars = get_decorate_vars
get_publisher_class().render_response = render_response get_publisher_class().render_response = render_response

View File

@ -12,16 +12,17 @@ from setuptools import setup
def get_version(): def get_version():
'''Use the VERSION, if absent generates a version with git describe, if not """Use the VERSION, if absent generates a version with git describe, if not
tag exists, take 0.0- and add the length of the commit log. tag exists, take 0.0- and add the length of the commit log.
''' """
if os.path.exists('VERSION'): if os.path.exists('VERSION'):
with open('VERSION', 'r') as v: with open('VERSION', 'r') as v:
return v.read() return v.read()
if os.path.exists('.git'): if os.path.exists('.git'):
p = subprocess.Popen( p = subprocess.Popen(
['git', 'describe', '--dirty=.dirty', '--match=v*'], ['git', 'describe', '--dirty=.dirty', '--match=v*'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
) )
result = p.communicate()[0] result = p.communicate()[0]
if p.returncode == 0: if p.returncode == 0:
@ -33,9 +34,7 @@ def get_version():
version = result version = result
return version return version
else: else:
return '0.0.post%s' % len( return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
subprocess.check_output(
['git', 'rev-list', 'HEAD']).splitlines())
return '0.0' return '0.0'
@ -44,7 +43,7 @@ def data_tree(destdir, sourcedir):
r = [] r = []
for root, dirs, files in os.walk(sourcedir): for root, dirs, files in os.walk(sourcedir):
l = [os.path.join(root, x) for x in files if os.path.splitext(x)[1] in extensions] l = [os.path.join(root, x) for x in files if os.path.splitext(x)[1] in extensions]
r.append( (root.replace(sourcedir, destdir, 1), l) ) r.append((root.replace(sourcedir, destdir, 1), l))
if 'CVS' in dirs: if 'CVS' in dirs:
dirs.remove('CVS') dirs.remove('CVS')
if '.svn' in dirs: if '.svn' in dirs:
@ -65,6 +64,7 @@ class compile_translations(Command):
def run(self): def run(self):
try: try:
from django.core.management import call_command from django.core.management import call_command
for path, dirs, files in os.walk('auquotidien'): for path, dirs, files in os.walk('auquotidien'):
if 'locale' not in dirs: if 'locale' not in dirs:
continue continue
@ -87,7 +87,6 @@ class install_lib(_install_lib):
class eo_sdist(sdist): class eo_sdist(sdist):
def run(self): def run(self):
print("creating VERSION file") print("creating VERSION file")
if os.path.exists('VERSION'): if os.path.exists('VERSION'):
@ -101,21 +100,31 @@ class eo_sdist(sdist):
if os.path.exists('VERSION'): if os.path.exists('VERSION'):
os.remove('VERSION') os.remove('VERSION')
setup( setup(
name = 'wcs-au-quotidien', name='wcs-au-quotidien',
version = get_version(), version=get_version(),
maintainer = 'Frederic Peters', maintainer='Frederic Peters',
maintainer_email = 'fpeters@entrouvert.com', maintainer_email='fpeters@entrouvert.com',
package_dir = {'auquotidien': 'auquotidien'}, package_dir={'auquotidien': 'auquotidien'},
packages = ['auquotidien', 'auquotidien.modules'], packages=['auquotidien', 'auquotidien.modules'],
cmdclass={'build': build, cmdclass={
'compile_translations': compile_translations, 'build': build,
'install_lib': install_lib, 'compile_translations': compile_translations,
'sdist': eo_sdist}, 'install_lib': install_lib,
include_package_data=True, 'sdist': eo_sdist,
data_files = data_tree('share/wcs/texts', 'texts') +\ },
data_tree('share/wcs/themes/auquotidien', 'theme') +\ include_package_data=True,
data_tree('share/wcs/themes/', 'data/themes/') + \ data_files=data_tree('share/wcs/texts', 'texts')
data_tree('share/auquotidien/apache-errors', 'apache-errors') +\ + data_tree('share/wcs/themes/auquotidien', 'theme')
[('share/wcs/', ['au-quotidien-wcs-settings.xml',])] + data_tree('share/wcs/themes/', 'data/themes/')
) + data_tree('share/auquotidien/apache-errors', 'apache-errors')
+ [
(
'share/wcs/',
[
'au-quotidien-wcs-settings.xml',
],
)
],
)

View File

@ -23,6 +23,7 @@ from wcs import fields
from utilities import get_app, login, create_temporary_pub from utilities import get_app, login, create_temporary_pub
def setup_module(module): def setup_module(module):
cleanup() cleanup()
@ -35,6 +36,7 @@ def setup_module(module):
pub.cfg['identification'] = {'methods': ['password']} pub.cfg['identification'] = {'methods': ['password']}
pub.write_cfg() pub.write_cfg()
def create_superuser(): def create_superuser():
global user1 global user1
if pub.user_class.has_key('admin'): if pub.user_class.has_key('admin'):
@ -56,19 +58,23 @@ def create_superuser():
pub.cfg['identification'] = {'methods': ['password']} pub.cfg['identification'] = {'methods': ['password']}
pub.write_cfg() pub.write_cfg()
def create_role(): def create_role():
Role.wipe() Role.wipe()
role = Role(name='foobar') role = Role(name='foobar')
role.store() role.store()
return role return role
def teardown_module(module): def teardown_module(module):
shutil.rmtree(pub.APP_DIR) shutil.rmtree(pub.APP_DIR)
@pytest.fixture @pytest.fixture
def empty_siteoptions(): def empty_siteoptions():
open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w').close() open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w').close()
def test_with_superuser(): def test_with_superuser():
create_superuser() create_superuser()
app = login(get_app(pub)) app = login(get_app(pub))
@ -76,6 +82,7 @@ def test_with_superuser():
# this makes sure the extension loaded properly # this makes sure the extension loaded properly
assert '<span id="applabel">Publik</span>' in resp.text assert '<span id="applabel">Publik</span>' in resp.text
def test_general_admin_permissions(): def test_general_admin_permissions():
create_superuser() create_superuser()
app = login(get_app(pub)) app = login(get_app(pub))
@ -89,6 +96,7 @@ def test_general_admin_permissions():
del pub.cfg['admin-permissions'] del pub.cfg['admin-permissions']
pub.write_cfg() pub.write_cfg()
def test_aq_permissions_panel(empty_siteoptions): def test_aq_permissions_panel(empty_siteoptions):
create_superuser() create_superuser()
app = login(get_app(pub)) app = login(get_app(pub))
@ -105,6 +113,7 @@ def test_aq_permissions_panel(empty_siteoptions):
assert 'aq/permissions' in resp.text assert 'aq/permissions' in resp.text
resp = app.get('/backoffice/settings/aq/permissions') resp = app.get('/backoffice/settings/aq/permissions')
def test_menu_items(empty_siteoptions): def test_menu_items(empty_siteoptions):
create_superuser() create_superuser()
role = create_role() role = create_role()

View File

@ -18,6 +18,7 @@ from wcs import fields
from utilities import get_app, login, create_temporary_pub from utilities import get_app, login, create_temporary_pub
def setup_module(module): def setup_module(module):
cleanup() cleanup()
@ -30,6 +31,7 @@ def setup_module(module):
pub.cfg['identification'] = {'methods': ['password']} pub.cfg['identification'] = {'methods': ['password']}
pub.write_cfg() pub.write_cfg()
def create_agent(): def create_agent():
if pub.user_class.has_key('agent'): if pub.user_class.has_key('agent'):
return return
@ -48,6 +50,7 @@ def create_agent():
return user1 return user1
def create_role(): def create_role():
Role.wipe() Role.wipe()
role = Role(name='foobar') role = Role(name='foobar')
@ -55,9 +58,11 @@ def create_role():
role.store() role.store()
return role return role
def teardown_module(module): def teardown_module(module):
shutil.rmtree(pub.APP_DIR) shutil.rmtree(pub.APP_DIR)
def test_with_agent(): def test_with_agent():
user = create_agent() user = create_agent()
app = login(get_app(pub), username='agent', password='agent') app = login(get_app(pub), username='agent', password='agent')
@ -71,6 +76,7 @@ def test_with_agent():
# check user is automatically redirected to management/ # check user is automatically redirected to management/
assert resp.location == 'http://example.net/backoffice/management/' assert resp.location == 'http://example.net/backoffice/management/'
def test_with_agent_submitter(): def test_with_agent_submitter():
user = create_agent() user = create_agent()
role = create_role() role = create_role()
@ -89,7 +95,7 @@ def test_with_agent_submitter():
formdef.backoffice_submission_roles = [role.id] formdef.backoffice_submission_roles = [role.id]
formdef.store() formdef.store()
resp = app.get('/backoffice/', status=200) # no redirect resp = app.get('/backoffice/', status=200) # no redirect
# check the management and submission links are presend twice, once in the # check the management and submission links are presend twice, once in the
# sidebar and once in the page body # sidebar and once in the page body
assert resp.text.count('//example.net/backoffice/management/') == 2 assert resp.text.count('//example.net/backoffice/management/') == 2

View File

@ -6,6 +6,7 @@ from auquotidien.modules import payments
from utilities import get_app, login, create_temporary_pub from utilities import get_app, login, create_temporary_pub
def setup_module(module): def setup_module(module):
cleanup() cleanup()

View File

@ -18,6 +18,7 @@ from wcs import fields
from utilities import get_app, login, create_temporary_pub from utilities import get_app, login, create_temporary_pub
def setup_module(module): def setup_module(module):
cleanup() cleanup()
@ -30,6 +31,7 @@ def setup_module(module):
pub.cfg['identification'] = {'methods': ['password']} pub.cfg['identification'] = {'methods': ['password']}
pub.write_cfg() pub.write_cfg()
def create_user(): def create_user():
if pub.user_class.has_key('user'): if pub.user_class.has_key('user'):
return return
@ -48,6 +50,7 @@ def create_user():
return user1 return user1
def create_formdef(): def create_formdef():
FormDef.wipe() FormDef.wipe()
formdef = FormDef() formdef = FormDef()
@ -56,15 +59,18 @@ def create_formdef():
formdef.store() formdef.store()
return formdef return formdef
def teardown_module(module): def teardown_module(module):
shutil.rmtree(pub.APP_DIR) shutil.rmtree(pub.APP_DIR)
def test_with_user(): def test_with_user():
user = create_user() user = create_user()
app = login(get_app(pub), username='user', password='user') app = login(get_app(pub), username='user', password='user')
resp = app.get('/', status=200) resp = app.get('/', status=200)
resp = app.get('/myspace/', status=200) resp = app.get('/myspace/', status=200)
def test_myspace_with_user_forms(): def test_myspace_with_user_forms():
user = create_user() user = create_user()
formdef = create_formdef() formdef = create_formdef()

View File

@ -16,12 +16,14 @@ import wcs.middleware
wcs.middleware.AfterJobsMiddleware.ASYNC = False wcs.middleware.AfterJobsMiddleware.ASYNC = False
def create_temporary_pub(): def create_temporary_pub():
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
APP_DIR = tempfile.mkdtemp() APP_DIR = tempfile.mkdtemp()
compat.CompatWcsPublisher.APP_DIR = APP_DIR compat.CompatWcsPublisher.APP_DIR = APP_DIR
compat.CompatWcsPublisher.DATA_DIR = os.path.abspath( compat.CompatWcsPublisher.DATA_DIR = os.path.abspath(
os.path.join(os.path.dirname(wcs.__file__), '..', 'data')) os.path.join(os.path.dirname(wcs.__file__), '..', 'data')
)
compat.CompatWcsPublisher.cronjobs = None compat.CompatWcsPublisher.cronjobs = None
config.add_section('extra') config.add_section('extra')
config.set('extra', 'auquotidien', os.path.join(os.path.dirname(__file__), '..', 'auquotidien')) config.set('extra', 'auquotidien', os.path.join(os.path.dirname(__file__), '..', 'auquotidien'))
@ -34,6 +36,7 @@ def create_temporary_pub():
os.mkdir(pub.app_dir) os.mkdir(pub.app_dir)
return pub return pub
def get_app(pub, https=False): def get_app(pub, https=False):
extra_environ = {'HTTP_HOST': 'example.net', 'REMOTE_ADDR': '127.0.0.1'} extra_environ = {'HTTP_HOST': 'example.net', 'REMOTE_ADDR': '127.0.0.1'}
if https: if https:
@ -43,6 +46,7 @@ def get_app(pub, https=False):
extra_environ['HTTPS'] = 'off' extra_environ['HTTPS'] = 'off'
return TestApp(wcs.wsgi.application, extra_environ=extra_environ) return TestApp(wcs.wsgi.application, extra_environ=extra_environ)
def login(app, username='admin', password='admin'): def login(app, username='admin', password='admin'):
login_page = app.get('/login/') login_page = app.get('/login/')
login_form = login_page.forms['login-form'] login_form = login_page.forms['login-form']