diff --git a/auquotidien/auquotidien.py b/auquotidien/auquotidien.py index 11fab03..b847803 100644 --- a/auquotidien/auquotidien.py +++ b/auquotidien/auquotidien.py @@ -8,7 +8,6 @@ from modules import admin from modules import backoffice from modules import categories_admin from modules import payments_ui -from modules import strongbox_ui from modules import formpage from modules import template from modules import root @@ -28,9 +27,6 @@ rdb.items = [] rdb.register_directory('payments', payments_ui.PaymentsDirectory()) rdb.register_menu_item('payments/', _('Payments')) -rdb.register_directory('strongbox', strongbox_ui.StrongboxDirectory()) -rdb.register_menu_item('strongbox/', _('Strongbox')) - rdb.register_directory('settings', admin.SettingsDirectory()) import wcs.admin.forms diff --git a/auquotidien/modules/admin.py b/auquotidien/modules/admin.py index b7ef237..e6317fd 100644 --- a/auquotidien/modules/admin.py +++ b/auquotidien/modules/admin.py @@ -22,8 +22,7 @@ from .abelium_domino_ui import AbeliumDominoDirectory class PanelDirectory(Directory): - _q_exports = ['', 'update', 'permissions', - 'strongbox', 'domino'] + _q_exports = ['', 'update', 'permissions', 'domino'] label = N_('Control Panel') domino = AbeliumDominoDirectory() @@ -47,10 +46,6 @@ class PanelDirectory(Directory): form.add(SingleSelectWidget, 'payments', title = _('Admin role for payments'), value = permissions_cfg.get('payments', None), options = [(None, _('Nobody'), None)] + get_user_roles()) - if get_publisher().has_site_option('auquotidien-strongbox'): - form.add(SingleSelectWidget, 'strongbox', title = _('Admin role for strongbox'), - value = permissions_cfg.get('strongbox', None), - options = [(None, _('Nobody'), None)] + get_user_roles()) form.add_submit('submit', _('Submit')) form.add_submit('cancel', _('Cancel')) @@ -66,41 +61,13 @@ class PanelDirectory(Directory): return r.getvalue() else: from wcs.admin.settings import cfg_submit - cfg_submit(form, 'aq-permissions', - ('forms', 'payments', 'strongbox')) - return redirect('..') - - def strongbox(self): - if not get_publisher().has_site_option('strongbox'): - raise errors.TraversalError() - misc_cfg = get_cfg('misc', {}) - form = Form(enctype='multipart/form-data') - form.add(CheckboxWidget, 'aq-strongbox', title=_('Strongbox Support'), - value=misc_cfg.get('aq-strongbox'), required=False) - - form.add_submit('submit', _('Submit')) - form.add_submit('cancel', _('Cancel')) - - if form.get_widget('cancel').parse(): - return redirect('..') - - if not form.is_submitted() or form.has_errors(): - get_response().breadcrumb.append(('aq/strongbox', _('Strongbox Support'))) - html_top('settings', _('Strongbox Support')) - r = TemplateIO(html=True) - r += htmltext('

%s

') % _('Strongbox Support') - r += form.render() - return r.getvalue() - else: - from wcs.admin.settings import cfg_submit - cfg_submit(form, 'misc', ('aq-strongbox',)) + cfg_submit(form, 'aq-permissions', ('forms', 'payments')) return redirect('..') class SettingsDirectory(wcs.admin.settings.SettingsDirectory): def _q_index(self): - if not (get_publisher().has_site_option('auquotidien-payments') or - get_publisher().has_site_option('auquotidien-strongvox')): + if not get_publisher().has_site_option('auquotidien-payments'): return super(SettingsDirectory, self)._q_index() r = TemplateIO(html=True) r += htmltext(super(SettingsDirectory, self)._q_index()) @@ -109,8 +76,6 @@ class SettingsDirectory(wcs.admin.settings.SettingsDirectory): r += htmltext('

%s

') % _('Extra Options') r += htmltext('') diff --git a/auquotidien/modules/backoffice.py b/auquotidien/modules/backoffice.py index 8a17e85..c4f3659 100644 --- a/auquotidien/modules/backoffice.py +++ b/auquotidien/modules/backoffice.py @@ -28,13 +28,6 @@ def check_visibility(target, user=CURRENT_USER): target = target.strip('/') if target == 'management': target = 'forms' - if target == 'strongbox': - if not get_publisher().has_site_option(target): - # strongbox disabled in site-options.cfg - return False - if not get_cfg('misc', {}).get('aq-strongbox'): - # strongbox disabled in settings panel - return False admin_role = get_cfg('aq-permissions', {}).get(target, None) if not admin_role: return False diff --git a/auquotidien/modules/myspace.py b/auquotidien/modules/myspace.py index 196c45e..948cfca 100644 --- a/auquotidien/modules/myspace.py +++ b/auquotidien/modules/myspace.py @@ -25,7 +25,6 @@ from wcs.qommon.admin.texts import TextsDirectory from wcs.formdef import FormDef import wcs.myspace -from .strongbox import StrongboxItem, StrongboxType from .payments import Invoice, Regie, is_payment_supported class MyInvoicesDirectory(Directory): @@ -108,260 +107,6 @@ class MyInvoicesDirectory(Directory): return r.getvalue() -class StrongboxDirectory(Directory): - _q_exports = ['', 'add', 'download', 'remove', 'pick', 'validate'] - - def _q_traverse(self, path): - if not get_cfg('misc', {}).get('aq-strongbox'): - raise errors.TraversalError() - get_response().breadcrumb.append(('strongbox/', _('Strongbox'))) - return Directory._q_traverse(self, path) - - def get_form(self): - types = [(x.id, x.label) for x in StrongboxType.select()] - form = Form(action='add', enctype='multipart/form-data') - form.add(StringWidget, 'description', title=_('Description'), size=60) - form.add(FileWidget, 'file', title=_('File'), required=True) - form.add(SingleSelectWidget, 'type_id', title=_('Document Type'), - options = [(None, _('Not specified'))] + types) - form.add(DateWidget, 'date_time', title = _('Document Date')) - form.add_submit('submit', _('Upload')) - return form - - def _q_index(self): - template.html_top(_('Strongbox')) - r = TemplateIO(html=True) - - # TODO: a paragraph of explanations here could be useful - - sffiles = list(StrongboxItem.get_with_indexed_value( - str('user_id'), str(get_request().user.id))) - if sffiles: - r += htmltext('') - r += htmltext('') % ( - _('Type'), _('Expiration')) - else: - r += htmltext('

') - r += _('There is currently nothing in your strongbox.') - r += htmltext('

') - has_items_to_validate = False - for i, sffile in enumerate(sffiles): - expired = False - if not sffile.validated_time: - has_items_to_validate = True - continue - if sffile.expiration_time and sffile.expiration_time < time.localtime(): - expired = True - if i%2: - classnames = ['odd'] - else: - classnames = ['even'] - if expired: - classnames.append('expired') - r += htmltext('') % ' '.join(classnames) - r += htmltext('') - if sffile.type_id: - r += htmltext('') % StrongboxType.get(sffile.type_id).label - else: - r += htmltext('') - if sffile.expiration_time: - r += htmltext('') - else: - r += htmltext('') - r += htmltext('') - r += htmltext('') - - if has_items_to_validate: - r += htmltext('') % _('Proposed Items') - for sffile in sffiles: - if sffile.validated_time: - continue - if sffile.expiration_time and sffile.expiration_time < time.localtime(): - expired = True - if i%2: - classnames = ['odd'] - else: - classnames = ['even'] - if expired: - classnames.append('expired') - r += htmltext('') % ' '.join(classnames) - - r += htmltext('') - if sffile.type_id: - r += htmltext('') % StrongboxType.get(sffile.type_id).label - else: - r += htmltext('') - - if sffile.expiration_time: - r += htmltext('') - else: - r += htmltext('') - r += htmltext('') - r += htmltext('') - if sffiles: - r += htmltext('
%s%s
') - r += sffile.get_display_name() - r += htmltext('%s-%s') % strftime(misc.date_format(), sffile.expiration_time) - if expired: - r += ' (%s)' % _('expired') - r += htmltext('-') - r += htmltext(' [%s] ') % (sffile.id, _('download')) - r += htmltext('[%s] ') % (sffile.id, _('remove')) - r += htmltext('

%s

') - r += sffile.get_display_name() - r += htmltext('%s-%s') % strftime(misc.date_format(), sffile.expiration_time) - if expired: - r += ' (%s)' % _('expired') - r += htmltext('-') - r += htmltext(' [%s] ') % (sffile.id, _('download')) - r += htmltext(' [%s] ') % (sffile.id, _('validate')) - r += htmltext(' [%s] ') % (sffile.id, _('reject')) - r += htmltext('
') - - r += htmltext('

%s

') % _('Add a file to the strongbox') - form = self.get_form() - r += form.render() - return r.getvalue() - - def add(self): - form = self.get_form() - if not form.is_submitted(): - if get_request().form.get('mode') == 'pick': - return redirect('pick') - else: - return redirect('.') - - sffile = StrongboxItem() - sffile.user_id = get_request().user.id - sffile.description = form.get_widget('description').parse() - sffile.validated_time = time.localtime() - sffile.type_id = form.get_widget('type_id').parse() - v = form.get_widget('date_time').parse() - sffile.set_expiration_time_from_date(v) - sffile.store() - sffile.set_file(form.get_widget('file').parse()) - sffile.store() - if get_request().form.get('mode') == 'pick': - return redirect('pick') - else: - return redirect('.') - - def download(self): - id = get_request().form.get('id') - if not id: - raise errors.TraversalError() - try: - sffile = StrongboxItem.get(id) - except KeyError: - raise errors.TraversalError() - if str(sffile.user_id) != str(get_request().user.id): - raise errors.TraversalError() - - filename = sffile.file.filename - fd = file(filename) - size = os.path.getsize(filename) - response = get_response() - response.set_content_type('application/octet-stream') - response.set_header('content-disposition', 'attachment; filename="%s"' % sffile.file.base_filename) - return FileStream(fd, size) - - def validate(self): - id = get_request().form.get('id') - if not id: - raise errors.TraversalError() - try: - sffile = StrongboxItem.get(id) - except KeyError: - raise errors.TraversalError() - if str(sffile.user_id) != str(get_request().user.id): - raise errors.TraversalError() - sffile.validated_time = time.time() - sffile.store() - return redirect('.') - - def remove(self): - id = get_request().form.get('id') - if not id: - raise errors.TraversalError() - try: - sffile = StrongboxItem.get(id) - except KeyError: - raise errors.TraversalError() - if str(sffile.user_id) != str(get_request().user.id): - raise errors.TraversalError() - - r = TemplateIO(html=True) - form = Form(enctype='multipart/form-data') - form.add_hidden('id', get_request().form.get('id')) - form.widgets.append(HtmlWidget('

%s

' % _( - 'You are about to irrevocably delete this item from your strongbox.'))) - form.add_submit('submit', _('Submit')) - form.add_submit('cancel', _('Cancel')) - if form.get_submit() == 'cancel': - return redirect('.') - if not form.is_submitted() or form.has_errors(): - if sffile.type_id: - r += htmltext('

%s

') % _('Deleting %(filetype)s: %(filename)s') % { - 'filetype': StrongboxType.get(sffile.type_id).label, - 'filename': sffile.get_display_name() - } - else: - r += htmltext('

%s

') % _('Deleting %(filename)s') % {'filename': sffile.get_display_name()} - r += form.render() - return r.getvalue() - else: - sffile.remove_self() - sffile.remove_file() - return redirect('.') - - def picked_file(self): - get_response().set_content_type('application/json') - sffile = StrongboxItem.get(get_request().form.get('val')) - sffile.file.fp = file(sffile.file.filename) - if sffile.user_id != get_request().user.id: - raise errors.TraversalError() - # XXX: this will copy the file, it would be quite nice if it was - # possible to just make it a symlink to the sffile - token = get_session().add_tempfile(sffile.file) - return json.dumps({'token': token, 'filename': sffile.file.base_filename}) - - def pick(self): - if get_request().form.get('select') == 'true': - return self.picked_file() - r = TemplateIO(html=True) - root_url = get_publisher().get_root_url() - sffiles = list(StrongboxItem.get_with_indexed_value( - str('user_id'), str(get_request().user.id))) - r += htmltext('

%s

') % _('Pick a file') - - if not sffiles: - r += htmltext('

') - r += _('You do not have any file in your strongbox at the moment.') - r += htmltext('

') - r += htmltext('
') - r += htmltext('%s') % (root_url, - _('Open Strongbox Management')) - r += htmltext('
') - else: - r += htmltext('
') - r += htmltext('') - - r += htmltext('
') - r += htmltext('') % _('Cancel') - r += ' ' - r += htmltext('') % _('Pick') - r += htmltext('
') - r += htmltext('
') - return r.getvalue() - - class JsonDirectory(Directory): '''Export of several lists in json, related to the current user or the SAMLv2 NameID we'd get in the URL''' @@ -410,9 +155,8 @@ class JsonDirectory(Directory): class MyspaceDirectory(wcs.myspace.MyspaceDirectory): _q_exports = ['', 'profile', 'new', 'password', 'remove', 'drafts', 'forms', - 'strongbox', 'invoices', 'json'] + 'invoices', 'json'] - strongbox = StrongboxDirectory() invoices = MyInvoicesDirectory() json = JsonDirectory() @@ -457,8 +201,6 @@ class MyspaceDirectory(wcs.myspace.MyspaceDirectory): profile_links.append('%s' % _('My Profile')) if user_forms: profile_links.append('%s' % _('My Forms')) - if get_cfg('misc', {}).get('aq-strongbox'): - profile_links.append('%s' % _('My Strongbox')) if is_payment_supported(): profile_links.append('%s' % _('My Invoices')) diff --git a/auquotidien/modules/strongbox.py b/auquotidien/modules/strongbox.py deleted file mode 100644 index 3f9bd14..0000000 --- a/auquotidien/modules/strongbox.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -import time - -from quixote import get_publisher -from wcs.qommon.storage import StorableObject -from wcs.qommon import misc - -class StrongboxType(StorableObject): - _names = 'strongbox-types' - - id = None - label = None - validation_months = 0 - - -class StrongboxFile(): - id = None - orig_filename = None - base_filename = None - content_type = None - charset = None - - def __init__(self, id, f): - self.id = id - self.orig_filename = f.orig_filename - self.base_filename = f.base_filename - self.content_type = f.content_type - self.charset = f.charset - self.fp = f.fp - - def __getstate__(self): - odict = self.__dict__.copy() - if not odict.has_key('fp'): - return odict - - # XXX: add some locking - del odict['fp'] - dirname = os.path.join(get_publisher().app_dir, 'strongbox-files') - if not os.path.exists(dirname): - os.mkdir(dirname) - odict['filename'] = os.path.join(dirname, str(self.id)) - self.fp.seek(0) - fd = file(odict['filename'], 'w') - fd.write(self.fp.read()) - fd.close() - return odict - - -class StrongboxItem(StorableObject): - _names = 'strongbox-items' - _hashed_indexes = ['user_id'] - - user_id = None - description = None - file = None - type_id = None - expiration_time = None - proposed_by = None - proposed_time = None - validated_time = None - - def get_display_name(self): - if self.description: - return self.description - return self.file.base_filename - - def set_file(self, file): - self.file = StrongboxFile(self.id, file) - - def remove_file(self): - os.unlink(self.file.filename) - - def set_expiration_time_from_date(self, value): - if not value: - self.expiration_time = None - return - if not StrongboxType.has_key(self.type_id): - return - - if not StrongboxType.get(self.type_id).validation_months: - self.expiration_time = None - return - - date = time.strptime(value, misc.date_format()) - year, month, day = date[:3] - month += StrongboxType.get(self.type_id).validation_months - while month > 12: - year += 1 - month -= 12 - while True: - try: - self.expiration_time = time.strptime( - '%04d-%02d-%02d' % (year, month, day), '%Y-%m-%d') - except ValueError: - day -= 1 - continue - break - diff --git a/auquotidien/modules/strongbox_ui.py b/auquotidien/modules/strongbox_ui.py deleted file mode 100644 index 18702ee..0000000 --- a/auquotidien/modules/strongbox_ui.py +++ /dev/null @@ -1,284 +0,0 @@ -import time - -from quixote import get_request, get_response, get_session, redirect -from quixote.directory import Directory, AccessControlled -from quixote.html import TemplateIO, htmltext - -import wcs -import wcs.admin.root - -from wcs.qommon import _ -from wcs.qommon import errors, misc -from wcs.qommon.form import * -from wcs.qommon.backoffice.menu import html_top -from wcs.qommon import get_cfg - -from .strongbox import StrongboxType, StrongboxItem - - - -class StrongboxTypeDirectory(Directory): - _q_exports = ['', 'edit', 'delete'] - - def __init__(self, strongboxtype): - self.strongboxtype = strongboxtype - - def _q_index(self): - html_top('strongbox', title = _('Item Type: %s') % self.strongboxtype.label) - r = TemplateIO(html=True) - r += htmltext('

%s

') % _('Item Type: %s') % self.strongboxtype.label - get_response().filter['sidebar'] = self.get_sidebar() - r += get_session().display_message() - - if self.strongboxtype.validation_months: - r += htmltext('
') - r += htmltext('') - r += htmltext('
') - - return r.getvalue() - - def get_sidebar(self): - r = TemplateIO(html=True) - r += htmltext('') - return r.getvalue() - - def edit(self): - form = self.form() - if form.get_submit() == 'cancel': - return redirect('.') - - if form.is_submitted() and not form.has_errors(): - self.submit(form) - return redirect('..') - - html_top('strongbox', title = _('Edit Item Type: %s') % self.strongboxtype.label) - r = TemplateIO(html=True) - r += htmltext('

%s

') % _('Edit Item Type: %s') % self.strongboxtype.label - r += form.render() - return r.getvalue() - - def form(self): - form = Form(enctype='multipart/form-data') - form.add(StringWidget, 'label', title = _('Label'), required = True, - value = self.strongboxtype.label) - form.add(IntWidget, 'validation_months', title=_('Number of months of validity'), - value=self.strongboxtype.validation_months, - hint=_('Use 0 if there is no expiration')) - form.add_submit('submit', _('Submit')) - form.add_submit('cancel', _('Cancel')) - return form - - def submit(self, form): - for k in ('label', 'validation_months'): - widget = form.get_widget(k) - if widget: - setattr(self.strongboxtype, k, widget.parse()) - self.strongboxtype.store() - - def delete(self): - form = Form(enctype='multipart/form-data') - form.widgets.append(HtmlWidget('

%s

' % _( - 'You are about to irrevocably delete this item type.'))) - form.add_submit('submit', _('Submit')) - form.add_submit('cancel', _('Cancel')) - if form.get_submit() == 'cancel': - return redirect('..') - if not form.is_submitted() or form.has_errors(): - get_response().breadcrumb.append(('delete', _('Delete'))) - html_top('strongbox', title = _('Delete Item Type')) - r = TemplateIO(html=True) - r += htmltext('

%s

') % _('Deleting Item Type: %s') % self.strongboxtype.label - r += form.render() - return r.getvalue() - else: - self.strongboxtype.remove_self() - return redirect('..') - - -class StrongboxTypesDirectory(Directory): - _q_exports = ['', 'new'] - - def _q_traverse(self, path): - get_response().breadcrumb.append(('types/', _('Item Types'))) - return Directory._q_traverse(self, path) - - def _q_index(self): - return redirect('..') - - def new(self): - type_ui = StrongboxTypeDirectory(StrongboxType()) - - form = type_ui.form() - if form.get_submit() == 'cancel': - return redirect('.') - - if form.is_submitted() and not form.has_errors(): - type_ui.submit(form) - return redirect('%s/' % type_ui.strongboxtype.id) - - get_response().breadcrumb.append(('new', _('New Item Type'))) - html_top('strongbox', title = _('New Item Type')) - r = TemplateIO(html=True) - r += htmltext('

%s

') % _('New Item Type') - r += form.render() - return r.getvalue() - - def _q_lookup(self, component): - try: - strongboxtype = StrongboxType.get(component) - except KeyError: - raise errors.TraversalError() - get_response().breadcrumb.append((str(strongboxtype.id), strongboxtype.label)) - return StrongboxTypeDirectory(strongboxtype) - - -class StrongboxDirectory(AccessControlled, Directory): - _q_exports = ['', 'types', 'add', 'add_to'] - label = N_('Strongbox') - - types = StrongboxTypesDirectory() - - def is_accessible(self, user): - from .backoffice import check_visibility - return check_visibility('strongbox', user) - - def _q_access(self): - user = get_request().user - if not user: - raise errors.AccessUnauthorizedError() - - if not self.is_accessible(user): - raise errors.AccessForbiddenError( - public_msg = _('You are not allowed to access Strongbox Management'), - location_hint = 'backoffice') - - get_response().breadcrumb.append(('strongbox/', _('Strongbox'))) - - - def _q_index(self): - html_top('strongbox', _('Strongbox')) - r = TemplateIO(html=True) - get_response().filter['sidebar'] = self.get_sidebar() - - r += get_session().display_message() - - r += htmltext('
') - r += htmltext('
') - r += htmltext('

%s

') % _('Propose a file to a user') - form = Form(enctype='multipart/form-data') - form.add(StringWidget, 'q', title = _('User'), required=True) - form.add_submit('search', _('Search')) - r += form.render() - if form.is_submitted() and not form.has_errors(): - q = form.get_widget('q').parse() - users = self.search_for_users(q) - if users: - if len(users) == 1: - return redirect('add_to?user_id=%s' % users[0].id) - if len(users) < 50: - r += _('(first 50 users only)') - r += htmltext('') - else: - r += _('No user found.') - r += htmltext('
') - r += htmltext('
') - - r += htmltext('
') - r += htmltext('
') - types = StrongboxType.select() - r += htmltext('

%s

') % _('Item Types') - if not types: - r += htmltext('

') - r += _('There is no item types defined at the moment.') - r += htmltext('

') - - r += htmltext('') - r += htmltext('
') - r += htmltext('
') - return r.getvalue() - - def get_sidebar(self): - r = TemplateIO(html=True) - r += htmltext('') - return r.getvalue() - - def search_for_users(self, q): - if hasattr(get_publisher().user_class, 'search'): - return get_publisher().user_class.search(q) - if q: - users = [x for x in get_publisher().user_class.select() - if q in (x.name or '') or q in (x.email or '')] - return users - else: - return [] - - def get_form(self): - types = [(x.id, x.label) for x in StrongboxType.select()] - form = Form(action='add', enctype='multipart/form-data') - form.add(StringWidget, 'description', title=_('Description'), size=60) - form.add(FileWidget, 'file', title=_('File'), required=True) - form.add(SingleSelectWidget, 'type_id', title=_('Document Type'), - options = [(None, _('Not specified'))] + types) - form.add(DateWidget, 'date_time', title = _('Document Date')) - form.add_submit('submit', _('Upload')) - return form - - def add(self): - form = self.get_form() - form.add(StringWidget, 'user_id', title=_('User')) - if not form.is_submitted(): - return redirect('.') - - sffile = StrongboxItem() - sffile.user_id = form.get_widget('user_id').parse() - sffile.description = form.get_widget('description').parse() - sffile.proposed_time = time.localtime() - sffile.proposed_id = get_request().user.id - sffile.type_id = form.get_widget('type_id').parse() - v = form.get_widget('date_time').parse() - sffile.set_expiration_time_from_date(v) - sffile.store() - sffile.set_file(form.get_widget('file').parse()) - sffile.store() - return redirect('.') - - def add_to(self): - form = Form(enctype='multipart/form-data', action='add_to') - form.add(StringWidget, 'user_id', title = _('User'), required=True) - try: - user_id = form.get_widget('user_id').parse() - user = get_publisher().user_class.get(user_id) - except: - return redirect('.') - if not user: - return redirect('.') - get_request().form = {} - get_request().environ['REQUEST_METHOD'] = 'GET' - - html_top('strongbox', _('Strongbox')) - r = TemplateIO(html=True) - r += htmltext('

%s %s

') % (_('Propose a file to:'), user.display_name) - form = self.get_form() - form.add(HiddenWidget, 'user_id', title=_('User'), value=user.id) - r += form.render() - return r.getvalue()