From 45de054ba8ecbbcf4082e1f577c3314eb5b0db6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Tue, 26 Nov 2019 14:07:25 +0100
Subject: [PATCH 5/6] remove support for strongbox (#37967)

---
 auquotidien/auquotidien.py          |   4 -
 auquotidien/modules/admin.py        |  41 +---
 auquotidien/modules/backoffice.py   |   7 -
 auquotidien/modules/myspace.py      | 260 +------------------------
 auquotidien/modules/strongbox.py    |  98 ----------
 auquotidien/modules/strongbox_ui.py | 284 ----------------------------
 6 files changed, 4 insertions(+), 690 deletions(-)
 delete mode 100644 auquotidien/modules/strongbox.py
 delete mode 100644 auquotidien/modules/strongbox_ui.py

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('<h2>%s</h2>') % _('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('<h2>%s</h2>') % _('Extra Options')
         r += htmltext('<ul>')
         r += htmltext('<li><a href="aq/permissions">%s</a></li>') % _('Permissions')
-        if get_publisher().has_site_option('strongbox'):
-            r += htmltext('<li><a href="aq/strongbox">%s</a></li>') % _('Strongbox Support')
         if get_publisher().has_site_option('domino'):
             r += htmltext('<li><a href="aq/domino">%s</a></li>') % _('Abelium Domino Integration')
         r += htmltext('</ul>')
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('<table id="strongbox-items">')
-            r += htmltext('<tr><th></th><th>%s</th><th>%s</th><th></th></tr>') % (
-                _('Type'), _('Expiration'))
-        else:
-            r += htmltext('<p>')
-            r += _('There is currently nothing in your strongbox.')
-            r += htmltext('</p>')
-        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('<tr class="%s">') % ' '.join(classnames)
-            r += htmltext('<td class="label">')
-            r += sffile.get_display_name()
-            r += htmltext('</td>')
-            if sffile.type_id:
-                r += htmltext('<td class="type">%s</td>') % StrongboxType.get(sffile.type_id).label
-            else:
-                r += htmltext('<td class="type">-</td>')
-            if sffile.expiration_time:
-                r += htmltext('<td class="expiration">%s') % strftime(misc.date_format(), sffile.expiration_time)
-                if expired:
-                    r += ' (%s)' % _('expired')
-                r += htmltext('</td>')
-            else:
-                r += htmltext('<td class="expiration">-</td>')
-            r += htmltext('<td class="actions">')
-            r += htmltext(' [<a href="download?id=%s">%s</a>] ') % (sffile.id, _('download'))
-            r += htmltext('[<a rel="popup" href="remove?id=%s">%s</a>] ') % (sffile.id, _('remove'))
-            r += htmltext('</td>')
-            r += htmltext('</tr>')
-
-        if has_items_to_validate:
-            r += htmltext('<tr><td colspan="4"><h3>%s</h3></td></tr>') % _('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('<tr class="%s">') % ' '.join(classnames)
-
-                r += htmltext('<td class="label">')
-                r += sffile.get_display_name()
-                r += htmltext('</td>')
-                if sffile.type_id:
-                    r += htmltext('<td class="type">%s</td>') % StrongboxType.get(sffile.type_id).label
-                else:
-                    r += htmltext('<td class="type">-</td>')
-
-                if sffile.expiration_time:
-                    r += htmltext('<td class="expiration">%s') % strftime(misc.date_format(), sffile.expiration_time)
-                    if expired:
-                        r += ' (%s)' % _('expired')
-                    r += htmltext('</td>')
-                else:
-                    r += htmltext('<td class="expiration">-</td>')
-                r += htmltext('<td class="actions">')
-                r += htmltext(' [<a href="download?id=%s">%s</a>] ') % (sffile.id, _('download'))
-                r += htmltext(' [<a href="validate?id=%s">%s</a>] ') % (sffile.id, _('validate'))
-                r += htmltext(' [<a href="remove?id=%s">%s</a>] ') % (sffile.id, _('reject'))
-                r += htmltext('</td>')
-                r += htmltext('</tr>')
-        if sffiles:
-            r += htmltext('</table>')
-
-        r += htmltext('<h3>%s</h3>') % _('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('<p>%s</p>' % _(
-                        '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('<h2>%s</h2>') % _('Deleting %(filetype)s: %(filename)s') % {
-                        'filetype': StrongboxType.get(sffile.type_id).label,
-                        'filename': sffile.get_display_name()
-                    }
-            else:
-                r += htmltext('<h2>%s</h2>') % _('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('<h2>%s</h2>') % _('Pick a file')
-
-        if not sffiles:
-            r += htmltext('<p>')
-            r += _('You do not have any file in your strongbox at the moment.')
-            r += htmltext('</p>')
-            r += htmltext('<div class="buttons">')
-            r += htmltext('<a href="%smyspace/strongbox/" target="_blank">%s</a>') % (root_url,
-                _('Open Strongbox Management'))
-            r += htmltext('</div>')
-        else:
-            r += htmltext('<form id="strongbox-pick">')
-            r += htmltext('<ul>')
-            for sffile in sffiles:
-                r += htmltext('<li><label><input type="radio" name="file" value="%s"/>%s</label>') % (
-                                sffile.id, sffile.get_display_name())
-                r += htmltext(' [<a href="%smyspace/strongbox/download?id=%s">%s</a>] ') % (
-                                root_url, sffile.id, _('view'))
-                r += htmltext('</li>')
-            r += htmltext('</ul>')
-
-            r += htmltext('<div class="buttons">')
-            r += htmltext('<input name="cancel" type="button" value="%s"/>') % _('Cancel')
-            r += ' '
-            r += htmltext('<input name="pick" type="button" value="%s"/>') % _('Pick')
-            r += htmltext('</div>')
-            r += htmltext('</form>')
-        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('<a href="#my-profile">%s</a>' % _('My Profile'))
         if user_forms:
             profile_links.append('<a href="#my-forms">%s</a>' % _('My Forms'))
-        if get_cfg('misc', {}).get('aq-strongbox'):
-            profile_links.append('<a href="strongbox/">%s</a>' % _('My Strongbox'))
         if is_payment_supported():
             profile_links.append('<a href="invoices/">%s</a>' % _('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('<h2>%s</h2>') % _('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('<div class="bo-block">')
-            r += htmltext('<ul>')
-            r += htmltext('<li>')
-            r += _('Number of months of validity:')
-            r += ' '
-            r += self.strongboxtype.validation_months
-            r += htmltext('</li>')
-            r += htmltext('</ul>')
-            r += htmltext('</div>')
-
-        return r.getvalue()
-
-    def get_sidebar(self):
-        r = TemplateIO(html=True)
-        r += htmltext('<ul>')
-        r += htmltext('<li><a href="edit">%s</a></li>') % _('Edit')
-        r += htmltext('<li><a href="delete">%s</a></li>') % _('Delete')
-        r += htmltext('</ul>')
-        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('<h2>%s</h2>') % _('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('<p>%s</p>' % _(
-                        '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('<h2>%s</h2>') % _('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('<h2>%s</h2>') % _('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('<div class="splitcontent-left">')
-        r += htmltext('<div class="bo-block">')
-        r += htmltext('<h2>%s</h2>') % _('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('<ul>')
-                for u in users:
-                    r += htmltext('<li><a href="add_to?user_id=%s">%s</a></li>') % (u.id, u.display_name)
-                r += htmltext('</ul>')
-            else:
-                r += _('No user found.')
-        r += htmltext('</div>')
-        r += htmltext('</div>')
-
-        r += htmltext('<div class="splitcontent-right">')
-        r += htmltext('<div class="bo-block">')
-        types = StrongboxType.select()
-        r += htmltext('<h2>%s</h2>') % _('Item Types')
-        if not types:
-            r += htmltext('<p>')
-            r += _('There is no item types defined at the moment.')
-            r += htmltext('</p>')
-
-        r += htmltext('<ul class="biglist" id="strongbox-list">')
-        for l in types:
-            type_id = l.id
-            r += htmltext('<li class="biglistitem" id="itemId_%s">') % type_id
-            r += htmltext('<strong class="label"><a href="types/%s/">%s</a></strong>') % (type_id, l.label)
-            r += htmltext('</li>')
-        r += htmltext('</ul>')
-        r += htmltext('</div>')
-        r += htmltext('</div>')
-        return r.getvalue()
-
-    def get_sidebar(self):
-        r = TemplateIO(html=True)
-        r += htmltext('<ul id="sidebar-actions">')
-        r += htmltext('  <li><a class="new-item" href="types/new">%s</a></li>') % _('New Item Type')
-        r += htmltext('</ul>')
-        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('<h2>%s %s</h2>') % (_('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()
-- 
2.24.0

