Source code for ciowarehouse.views.warehouse

# -*- coding: utf-8 -*-
"""View callables to manage warehouses."""

from os.path import join, exists
from shutil import rmtree
from collections import OrderedDict
from json import loads

from sqlalchemy import desc
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.exc import FlushError

from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPNotFound
from pyramid.security import NO_PERMISSION_REQUIRED

from chrysalio.lib.log import log_info
from chrysalio.lib.utils import make_id
from chrysalio.lib.form import get_action, Form
from chrysalio.lib.filter import Filter
from chrysalio.lib.paging import PAGE_SIZES, Paging
from chrysalio.lib.attachment import attachment_url, attachment_update
from chrysalio.lib.tabset import Tabset
from chrysalio.lib.restful import restful_login
from chrysalio.includes.themes import theme_static_prefix
from chrysalio.models.dbuser import DBUser
from chrysalio.models.dbgroup import DBGroup
from chrysalio.models.populate import web2db, db2web
from chrysalio.views import BaseView
from cioservice.models.dbjob import DBJob
from ..lib.i18n import _
from ..lib.utils import flag_image
from ..lib.warehouse import Warehouse
from ..relaxng import RELAXNG_CIOWAREHOUSE
from ..models.populate import xml2db
from ..models.dbwarehouse import WAREHOUSE_ACCESSES
from ..models.dbwarehouse import THUMBNAIL_SIZE_LARGE_DEFAULT
from ..models.dbwarehouse import THUMBNAIL_SIZE_SMALL_DEFAULT
from ..models.dbwarehouse import DBWarehouse, DBWarehouseUser, DBWarehouseJob
from ..models.dbwarehouse import DBWarehouseGroup, DBWarehouseHandler


# =============================================================================
[docs]class WarehouseView(BaseView): """Class to manage warehouse views. :type request: pyramid.request.Request :param request: Current request. """ # ------------------------------------------------------------------------- def __init__(self, request): """Constructor method.""" super(WarehouseView, self).__init__(request) if 'modules_off' not in self._request.registry or \ 'ciowarehouse' in self._request.registry['modules_off']: raise HTTPForbidden(comment=_( 'The module "CioWarehouse" is not activated.')) # -------------------------------------------------------------------------
[docs] @view_config( route_name='warehouse_index', renderer='ciowarehouse:Templates/warehouse_index.pt', permission='warehouse-view') @view_config(route_name='warehouse_index', renderer='json', xhr=True) def index(self): """List all authorized warehouses.""" # Ajax i_creator = self._request.has_permission('warehouse-create') \ or self._request.has_permission('warehouse-configure') if self._request.is_xhr: if i_creator: self._import_warehouses() return {} # Action action, items = self._index_action(i_creator) if action[:4] == 'exp!': action = self._warehouses2response(items) if action: return action # Filter paging_id = 'warehouse_index' if i_creator: pfilter = Filter( self._request, paging_id, ( ('i18n_label', _('Label'), False, ''), ('warehouse_id', _('Identifier'), False, ''), ('access', _('Access'), False, [('', ' ')] + list(WAREHOUSE_ACCESSES.items()))), remove=action[:4] == 'crm!' and action[4:] or None) else: pfilter = Filter( self._request, paging_id, ( ('i18n_label', _('Label'), False, ''), ('warehouse_id', _('Identifier'), False, '')), remove=action[:4] == 'crm!' and action[4:] or None) # Favorites user_id = self._request.session['user']['user_id'] if 'ciowarehouse' not in self._request.session: self._request.session['ciowarehouse'] = {} if self._request.POST: self._request.session['ciowarehouse']['favorite_only'] = bool( self._request.POST.get('favorite')) favorites = [ k[0] for k in self._request.dbsession.query( DBWarehouseUser.warehouse_id).filter_by( user_id=user_id, favorite=True)] # Paging defaults = Paging.params(self._request, paging_id, '+warehouse_id') defaults['favorite'] = favorites and \ self._request.session['ciowarehouse'].get('favorite_only', True) dbquery = pfilter.sql( self._request.dbsession.query(DBWarehouse), 'wrh_warehouses') if not i_creator: dbquery = dbquery.filter(DBWarehouse.warehouse_id.in_( self._my_warehouse_ids())) if defaults['favorite']: dbquery = dbquery.filter(DBWarehouse.warehouse_id.in_(favorites)) oby = getattr(DBWarehouse, defaults['sort'][1:]) dbquery = dbquery.order_by( desc(oby) if defaults['sort'][0] == '-' else oby) paging = Paging(self._request, paging_id, dbquery, defaults) paging.set_current_ids('warehouse_id') if not defaults['favorite'] and pfilter.is_empty() \ and not self._request.has_permission('warehouse-edit') \ and not self._request.has_permission('warehouse-configure') \ and len(paging) == 1: return HTTPFound(self._request.route_path( 'browse_directory_root', warehouse_id=paging[0].warehouse_id)) # Form & completed action form = Form(self._request, defaults=defaults) form.forget('filter_value') if action and action[3] == '!': action = '' self._request.breadcrumbs(_('Warehouses'), 1) return { 'action': action, 'items': items, 'form': form, 'pfilter': pfilter, 'paging': paging, 'favorites': favorites, 'i_creator': i_creator, 'i_editor': self._request.has_permission('warehouse-edit'), 'flag_image': flag_image, 'PAGE_SIZES': PAGE_SIZES, 'attachment_url': attachment_url, 'has_attachments': bool( self._request.registry.settings.get('attachments')), 'download_max_size': self._request.registry['settings'][ 'download-max-size']}
# -------------------------------------------------------------------------
[docs] @view_config( route_name='warehouse_index_filter', renderer='json', xhr=True) def index_filter(self): """Return a dictionary to autocomplete a filter field.""" return Filter.sql_autocomplete(self._request, DBWarehouse)
# -------------------------------------------------------------------------
[docs] @view_config( route_name='warehouse_view', renderer='ciowarehouse:Templates/warehouse_view.pt', permission='warehouse-view') def view(self): """Show warehouse configuration.""" # Warehouse i_creator = self._request.has_permission('warehouse-create') i_configurator = self._request.has_permission('warehouse-configure') dbwarehouse = self._get_dbwarehouse(i_creator or i_configurator) picture = self._request.registry.settings.get('attachments') and ( attachment_url( self._request, dbwarehouse.attachments_dir, dbwarehouse.attachments_key, dbwarehouse.picture) or '{0}/ciowarehouse/images/warehouse_picture.png'.format( theme_static_prefix(self._request))) # Action action = get_action(self._request)[0] i_editor = self._request.has_permission('warehouse-edit') if action == 'exp!': action = self._warehouses2response((dbwarehouse.warehouse_id,)) if action: return action elif action == 'bld!' and i_creator: self._force_full_refresh(dbwarehouse, i_configurator, True) elif action == 'rfh!' and i_editor: self._force_full_refresh(dbwarehouse, i_configurator, False) # User paging user_paging, defaults, user_filter = self._user_paging( action, dbwarehouse) # Form form = Form(self._request, defaults=defaults) form.forget('filter_value') # Breadcrumbs label = dbwarehouse.label(self._request) self._request.breadcrumbs( _('Warehouse "${l}"', {'l': label}), replace=self._request.route_path( 'warehouse_edit', warehouse_id=dbwarehouse.warehouse_id)) return { 'form': form, 'label': label, 'user_filter': user_filter, 'user_paging': user_paging, 'tabset': Tabset( self._request, 'tabWarehouse', dbwarehouse.settings_tabs(self._request)), 'dbwarehouse': dbwarehouse, 'picture': picture, 'navigator': Paging.navigator( self._request, 'warehouse_index', dbwarehouse.warehouse_id, self._request.route_path( 'warehouse_view', warehouse_id='_ID_')), 'i_editor': i_editor, 'i_creator': i_creator}
# -------------------------------------------------------------------------
[docs] @view_config( route_name='warehouse_full_refresh', renderer='json', permission=NO_PERMISSION_REQUIRED, require_csrf=False) def full_refresh(self): """Launch a full refresh action to pull, index and create thumbnails on the whole warehouse.""" warehouse, error = self._restful_warehouse() if error is not None: return {'error': error} error = warehouse.full_refresh( self._request, reindex=self._request.params.get('reindex') == 'True', recreate_thumbnails=self._request.params.get( 'recreate_thumbnails') == 'True', in_thread=self._request.params.get('in_thread') == 'True') if error: return {'error': self._request.localizer.translate(error)} return {'error': None, 'label': warehouse.label(self._request)}
# -------------------------------------------------------------------------
[docs] @view_config( route_name='warehouse_refresh', renderer='json', permission=NO_PERMISSION_REQUIRED, require_csrf=False) def refresh(self): """Launch a refresh action to index and create thumbnails for some files.""" warehouse, error = self._restful_warehouse() if error is not None: return {'error': error} error = warehouse.refresh( self._request, files=loads(self._request.params.get('files', '[]')), recursive=self._request.params.get('recursive') == 'True', in_thread=self._request.params.get('in_thread') == 'True') if error: return {'error': self._request.localizer.translate(error)} return {'error': None, 'label': warehouse.label(self._request)}
# -------------------------------------------------------------------------
[docs] @view_config( route_name='warehouse_create', renderer='ciowarehouse:Templates/warehouse_edit.pt', permission='warehouse-edit') @view_config( route_name='warehouse_edit', renderer='ciowarehouse:Templates/warehouse_edit.pt', permission='warehouse-edit') @view_config( route_name='warehouse_edit', renderer='json', xhr=True, permission='warehouse-edit') def edit(self): """Create or edit a warehouse.""" # Rights i_creator = self._request.has_permission('warehouse-create') i_configurator = self._request.has_permission('warehouse-configure') dbwarehouse = self._get_dbwarehouse(i_creator or i_configurator) \ if 'warehouse_id' in self._request.matchdict else None if dbwarehouse is None and not i_creator and not i_configurator: raise HTTPForbidden() # Ajax if self._request.is_xhr: if dbwarehouse is not None: dbwarehouse.attachments_key, dbwarehouse.picture = \ attachment_update( self._request, dbwarehouse.attachments_dir, dbwarehouse.attachments_key, self._request.POST['picture'], replace=dbwarehouse.picture, prefix=dbwarehouse.warehouse_id[:12]) log_info( self._request, 'warehouse_update_picture', dbwarehouse.warehouse_id) return {} # User paging action = get_action(self._request)[0] user_paging, defaults, user_filter = self._user_paging(action) # Form jobs = OrderedDict([ (k.job_id, (k.label(self._request), k.description(self._request))) for k in self._request.dbsession.query( DBJob).order_by(desc('priority')) if not k.areas or 'ciowarehouse.browse' in [i.area_id for i in k.areas]]) groups = { k.group_id: ( k.label(self._request), k.description(self._request)) for k in self._request.dbsession.query(DBGroup)} form = Form( self._request, *DBWarehouse.settings_schema( self._request, defaults, groups, jobs, dbwarehouse), obj=dbwarehouse, force_defaults=dbwarehouse is not None) form.forget('filter_value') # Action if action == 'pct!' and dbwarehouse is not None: dbwarehouse.attachments_key, dbwarehouse.picture = \ attachment_update( self._request, dbwarehouse.attachments_dir, dbwarehouse.attachments_key, self._request.POST['picture'], replace=dbwarehouse.picture, prefix=dbwarehouse.warehouse_id[:12]) log_info( self._request, 'warehouse_update_picture', dbwarehouse.warehouse_id) elif action == 'sav!' and form.validate(): dbwarehouse = self._save(dbwarehouse, groups, jobs, form.values) if dbwarehouse is not None: if 'warehouse_id' not in self._request.matchdict: self._request.breadcrumbs.pop() log_info( self._request, 'warehouse_id' in self._request.matchdict and 'warehouse_edit' or 'warehouse_create', dbwarehouse.warehouse_id) return HTTPFound(self._request.route_path( 'warehouse_view', warehouse_id=dbwarehouse.warehouse_id)) if form.has_error(): self._request.session.flash(_('Correct errors.'), 'alert') # Picture if dbwarehouse and self._request.registry.settings.get('attachments'): picture = attachment_url( self._request, dbwarehouse.attachments_dir, dbwarehouse.attachments_key, dbwarehouse.picture) or \ '{0}/ciowarehouse/images/warehouse_picture.png'.format( theme_static_prefix(self._request)) else: picture = None # Breadcrumbs label = dbwarehouse and dbwarehouse.label(self._request) if not dbwarehouse: self._request.breadcrumbs(_('Warehouse Creation')) else: self._request.breadcrumbs( _('Warehouse "${l}" Edition', {'l': label}), replace=self._request.route_path( 'warehouse_view', warehouse_id=dbwarehouse.warehouse_id)) return { 'form': form, 'dbwarehouse': dbwarehouse or DBWarehouse, 'action': action, 'picture': picture, 'label': label, 'user_filter': user_filter, 'user_paging': user_paging, 'groups': groups, 'jobs': jobs, 'tabset': Tabset( self._request, 'tabWarehouse', DBWarehouse.settings_tabs(self._request))}
# ------------------------------------------------------------------------- def _get_dbwarehouse(self, i_creator): """Return the SqlAlchemy object of the selected warehouse or raise an HTTPNotFound exception. :param bool i_creator: ``True`` if the user can create a warehouse. :rtype: .models.dbwarehouse.DBWarehouse """ dbwarehouse = self._request.dbsession.query(DBWarehouse).filter_by( warehouse_id=self._request.matchdict['warehouse_id']).first() if dbwarehouse is None: raise HTTPNotFound() if not i_creator and \ dbwarehouse.warehouse_id not in self._my_warehouse_ids(): raise HTTPForbidden() return dbwarehouse # ------------------------------------------------------------------------- def _delete_warehouses(self, warehouse_ids): """Delete warehouses. :param list warehouse_ids: List of warehouse IDs to delete. """ deleted = [] attachments = self._request.registry.settings.get('attachments') ciowarehouse = self._request.registry['modules']['ciowarehouse'] for dbwarehouse in self._request.dbsession.query(DBWarehouse).filter( DBWarehouse.warehouse_id.in_(warehouse_ids)): # Remove files warehouse = ciowarehouse.warehouse( self._request, dbwarehouse.warehouse_id) if warehouse is not None: if exists(warehouse.root): rmtree(warehouse.root) ciowarehouse.warehouse_forget( self._request, dbwarehouse.warehouse_id) # Remove attachments if attachments and dbwarehouse.attachments_key: attachment = join( attachments, dbwarehouse.attachments_dir, dbwarehouse.attachments_key) if exists(attachment): rmtree(attachment) # Remove from database deleted.append(dbwarehouse.warehouse_id) self._request.dbsession.delete(dbwarehouse) if deleted: log_info(self._request, 'warehouse_delete', ' '.join(deleted)) # ------------------------------------------------------------------------- def _import_warehouses(self): """Import warehouses.""" # Get current IDs warehouse_ids = {k[0] for k in self._request.dbsession.query( DBWarehouse.warehouse_id)} # Update database web2db(self._request, xml2db, 'warehouse', relaxngs={ '{{{0}}}{1}'.format( RELAXNG_CIOWAREHOUSE['namespace'], RELAXNG_CIOWAREHOUSE['root']): RELAXNG_CIOWAREHOUSE['file']}) # Get new IDs warehouse_ids = {k[0] for k in self._request.dbsession.query( DBWarehouse.warehouse_id)} - warehouse_ids if not warehouse_ids: return log_info(self._request, 'warehouse_import', ' '.join(warehouse_ids)) # Clone warehouses ciowarehouse = self._request.registry['modules']['ciowarehouse'] for warehouse_id in warehouse_ids: dbwarehouse = self._request.dbsession.query(DBWarehouse).filter_by( warehouse_id=warehouse_id).first() if dbwarehouse is None: continue warehouse = Warehouse( self._request.registry, dbwarehouse, ciowarehouse.locations) error = warehouse.vcs.clone() if error: self._request.session.flash(error, 'alert') else: warehouse.full_refresh(self._request, in_thread=True) # ------------------------------------------------------------------------- def _restful_warehouse(self): """Return a warehouse called by a restful request. :rtype: tuple :return: A tuple like ``(warehouse, error)``. """ ciowarehouse = self._request.registry['modules']['ciowarehouse'] error = restful_login( self._request, ciowarehouse.restful.get('key', '-'), ciowarehouse.restful.get('token_ttl')) if error is not None: return None, error warehouse_id = self._request.matchdict['warehouse_id'] warehouse = ciowarehouse.warehouse(self._request, warehouse_id) if warehouse is None: return None, self._request.localizer.translate( _('Unknown warehouse "${w}"', {'w': warehouse_id})) return warehouse, None # ------------------------------------------------------------------------- def _warehouses2response(self, warehouse_ids): """Export warehouses as an XML file embedded in a Pyramid response. :param list warehouse_ids: List of warehouse IDs to export. :rtype: :class:`pyramid.response.Response` or ``''`` """ dbitems = tuple(self._request.dbsession.query(DBWarehouse).filter( DBWarehouse.warehouse_id.in_(warehouse_ids)).order_by( 'warehouse_id')) if not dbitems: return '' filename = '{0}.{1}.xml'.format( len(dbitems) == 1 and dbitems[0].warehouse_id or make_id(self._request.registry['settings']['title'], 'token'), DBWarehouse.suffix) log_info( self._request, 'warehouse_export', ' '.join([k.warehouse_id for k in dbitems])) return db2web(self._request, dbitems, filename, RELAXNG_CIOWAREHOUSE) # ------------------------------------------------------------------------- def _toggle_favorite(self, warehouse_id): """Toggle the favorite state of the warehouse. :param str warehouse_id: ID of the warehouse. """ dbsession = self._request.dbsession user_id = self._request.session['user']['user_id'] dbwarehouse_user = dbsession.query(DBWarehouseUser).filter_by( warehouse_id=warehouse_id, user_id=user_id).first() if dbwarehouse_user is None: dbsession.add(DBWarehouseUser( warehouse_id=warehouse_id, user_id=user_id, favorite=True)) elif dbwarehouse_user.favorite \ and dbwarehouse_user.file_rights is None \ and dbwarehouse_user.meta_rights is None: dbsession.delete(dbwarehouse_user) else: dbwarehouse_user.favorite = not dbwarehouse_user.favorite # ------------------------------------------------------------------------- def _force_full_refresh(self, dbwarehouse, i_configurator, clear): """Launch warehouse indexation and thumbnail creation. :type dbwarehouse: .models.dbwarehouse.DBWarehouse :param dbwarehouse: SQLAlchemy object for the warehouse. :param bool i_configurator: ``True`` if the user can configure the warehouse. :param bool clear: If ``True``, erase existing thumbnails and index. """ ciowarehouse = self._request.registry['modules']['ciowarehouse'] warehouse = ciowarehouse.warehouse( self._request, dbwarehouse.warehouse_id) if warehouse is None and (clear or not i_configurator): self._request.session.flash(_('Unable to refresh!'), 'alert') return if warehouse is None: warehouse = Warehouse( self._request.registry, dbwarehouse, ciowarehouse.locations) error = warehouse.full_refresh( self._request, reindex=clear, recreate_thumbnails=clear, in_thread=True, force=True) if error is not None: self._request.session.flash(error, 'alert') else: self._request.session.flash( _('Full rebuild fired...') if clear else _('Refreshment fired...')) self._request.registry['modules']['ciowarehouse'].cache_clear( self._request, warehouse.uid) # ------------------------------------------------------------------------- def _index_action(self, i_creator): """Execute actions for index view. :param bool i_creator: ``True`` if the user can create a warehouse. :rtype: tuple :return: A tuple such as ``(action, items)``. """ action, items = get_action(self._request) if action == 'imp!' and i_creator: self._import_warehouses() elif action[:4] == 'del!' and i_creator: self._delete_warehouses(items) elif action[:4] == 'fav!': self._toggle_favorite(action[4:]) return action, items # ------------------------------------------------------------------------- def _my_warehouse_ids(self): """Return a list of authorized warehouse IDs. :rtype: list """ user_id = self._request.session['user']['user_id'] warehouse_ids = {k[0] for k in self._request.dbsession.query( DBWarehouse.warehouse_id).filter( DBWarehouse.access.in_(('free', 'readonly')))} warehouse_ids |= {k[0] for k in self._request.dbsession.query( DBWarehouseUser.warehouse_id).filter_by( user_id=user_id).filter( DBWarehouseUser.file_rights.isnot(None))} warehouse_ids |= {k[0] for k in self._request.dbsession.query( DBWarehouseGroup.warehouse_id).filter( DBWarehouseGroup.group_id.in_( self._request.session['user']['groups']))} return warehouse_ids # ------------------------------------------------------------------------- def _save(self, dbwarehouse, groups, jobs, values): """Save a warehouse. :type dbwarehouse: .models.dbwarehouse.DBWarehouse :param dbwarehouse: Warehouse to save. :param dict groups: A dictionary such as ``{group_id: (label, description),...}``. :param dict jobs: A dictionary such as ``{job_id: (label, description),...}``. :param dict values: Form values. :rtype: :class:`~.models.dbwarehouse.DBWarehouse` instance or ``None`` """ creation = dbwarehouse is None dbwarehouse = dbwarehouse or DBWarehouse() thumbnails = ( dbwarehouse.thumbnail_large, dbwarehouse.thumbnail_small) \ if dbwarehouse else None # Update warehouse record = {k: values[k] for k in values if k[:4] not in ( 'usr:', 'vbl', 'fil:', 'mta', 'fav:', 'grp:', 'gfil', 'gmta', 'hdl:', 'job:')} if not creation: record['warehouse_id'] = dbwarehouse.warehouse_id record['location'] = dbwarehouse.location error = dbwarehouse.record_format(record) if error: self._request.session.flash(error, 'alert') return None record.update({ k: None for k in values if not values[k] and hasattr(DBWarehouse, k)}) record['thumbnail_large'] = record.get( 'thumbnail_large') or THUMBNAIL_SIZE_LARGE_DEFAULT record['thumbnail_small'] = record.get( 'thumbnail_small') or THUMBNAIL_SIZE_SMALL_DEFAULT if not record.get('download_max_size'): record['download_max_size'] = 0 for field in record: if getattr(dbwarehouse, field) != record[field]: setattr(dbwarehouse, field, record[field]) # Save if creation: try: self._request.dbsession.add(dbwarehouse) self._request.dbsession.flush() except (IntegrityError, FlushError): self._request.session.flash( _('This warehouse already exists.'), 'alert') return None warehouse = Warehouse( self._request.registry, dbwarehouse, self._request.registry['modules']['ciowarehouse'].locations) error = warehouse.vcs.clone() if error: self._request.session.flash(error, 'alert') # Update users self._users_update(dbwarehouse) # Update groups self._groups_update(dbwarehouse, groups, values) # Update handlers self._handlers_update(dbwarehouse, values) # Update jobs self._jobs_update(dbwarehouse, jobs, values) # Clean up session self._request.registry['modules']['ciowarehouse'].warehouse_forget( self._request, dbwarehouse.warehouse_id) # Thumbnail generation if thumbnails and ( dbwarehouse.thumbnail_large != thumbnails[0] or dbwarehouse.thumbnail_small != thumbnails[1]): warehouse = self._request.registry['modules']['ciowarehouse']\ .warehouse(self._request, dbwarehouse.warehouse_id) warehouse.full_refresh( self._request, recreate_thumbnails=True, in_thread=True) self._request.registry['modules']['ciowarehouse'].warehouse_forget( self._request, dbwarehouse.warehouse_id) return dbwarehouse # ------------------------------------------------------------------------- def _users_update(self, dbwarehouse): """Update the list of warehouse users. :type dbwarehouse: .models.dbwarhouse.DBWarehouse :param dbwarehouse: SQLAlchemy object for the current warehouse. """ values = {} for value in self._request.POST: if value[:4] in ('set:', 'usr:', 'fav:'): user_id = int(value[4:]) value = value[:3] else: continue if user_id not in values: values[user_id] = [] if value != 'set': values[user_id].append(value) for user_id, value_list in values.items(): dbwarehouse_user = self._request.dbsession.query( DBWarehouseUser).filter_by( warehouse_id=dbwarehouse.warehouse_id, user_id=user_id).first() if 'usr' not in value_list and 'fav' not in value_list: if dbwarehouse_user is not None: self._request.dbsession.delete(dbwarehouse_user) continue if dbwarehouse_user is None: dbwarehouse_user = DBWarehouseUser( warehouse_id=dbwarehouse.warehouse_id, user_id=user_id) self._request.dbsession.add(dbwarehouse_user) file_rights = self._request.POST.get('fil:{0}'.format(user_id)) \ if 'usr' in value_list else None file_rights = 'reader' \ if not file_rights and 'usr' in value_list \ else file_rights meta_rights = 'writer' if file_rights == 'writer-admin' else ( self._request.POST.get('mta:{0}'.format(user_id)) if file_rights else None) meta_rights = 'reader' if file_rights and not meta_rights \ else meta_rights dbwarehouse_user.file_rights = file_rights or None dbwarehouse_user.meta_rights = meta_rights or None dbwarehouse_user.favorite = 'fav' in value_list # ------------------------------------------------------------------------- def _groups_update(self, dbwarehouse, groups, values): """Update the list of groups. :type dbwarehouse: .models.dbwarhouse.DBWarehouse :param dbwarehouse: SQLAlchemy object for the current warehouse. :param dict groups: A dictionary such as ``{group_id: (label, description),...}``. :param dict values: Form values. """ warehouse_groups = {k.group_id: k for k in dbwarehouse.groups} for group_id in sorted(groups): value = values['grp:{0}'.format(group_id)] if not value: if group_id in warehouse_groups: self._request.dbsession.delete( self._request.dbsession.query(DBWarehouseGroup) .filter_by(warehouse_id=dbwarehouse.warehouse_id, group_id=group_id) .first()) continue dbwarehouse_group = warehouse_groups.get(group_id) if dbwarehouse_group is None: dbwarehouse_group = DBWarehouseGroup( warehouse_id=dbwarehouse.warehouse_id, group_id=group_id) self._request.dbsession.add(dbwarehouse_group) file_rights = self._request.POST.get( 'gfil:{0}'.format(group_id)) or 'reader' dbwarehouse_group.file_rights = file_rights dbwarehouse_group.meta_rights = \ 'writer' if file_rights == 'writer-admin' else \ self._request.POST.get( 'gmta:{0}'.format(group_id)) or 'reader' # ------------------------------------------------------------------------- def _user_paging(self, action, dbwarehouse=None): """Return a paging object for users. :param str action: Current action. :type dbwarehouse: .models.dbwarhouse.DBWarehouse :param dbwarehouse: (optional) If not ``None``, users are only users of the warehouse. :rtype: tuple :return: A tuple such as ``(user_paging, defaults, user_filter)``. """ # Filter paging_id = 'warehouse_users' ufilter = Filter( self._request, paging_id, ( ('login', _('Login'), False, None), ('last_name', _('Last name'), False, None), ('email', _('Email'), False, None), ('status', _('Status'), False, [('', ' ')] + list(DBUser.status_labels.items()))), (('status', '=', 'active'),), remove=action[:4] == 'crm!' and action[4:] or None) # Database query defaults = Paging.params( self._request, paging_id, '+last_name', default_display='list') dbquery = ufilter.sql( self._request.dbsession.query( DBUser.user_id, DBUser.login, DBUser.first_name, DBUser.last_name, DBUser.honorific, DBUser.email, DBUser.email_hidden, DBUser.status, DBUser.last_login, DBUser.attachments_key, DBUser.picture), 'users') if dbwarehouse is not None: dbquery = dbquery.filter(DBUser.user_id.in_( [k.user_id for k in dbwarehouse.users])) oby = getattr(DBUser, defaults['sort'][1:]) dbquery = dbquery.order_by( desc(oby) if defaults['sort'][0] == '-' else oby) return Paging(self._request, paging_id, dbquery, defaults), \ dict(defaults), ufilter # ------------------------------------------------------------------------- def _handlers_update(self, dbwarehouse, values): """Update warehouse handlers. :type dbwarehouse: .models.dbwarehouse.DBWarehouse :param dbwarehouse: Warehouse to save. :param dict values: Form values. """ if len([None for k in values if k[:4] == 'hdl:' and values[k]]) == len( self._request.registry.get('handlers', '')): self._request.dbsession.query(DBWarehouseHandler).filter_by( warehouse_id=dbwarehouse.warehouse_id).delete() return warehouse_handlers = [k.handler_id for k in dbwarehouse.handlers] for handler in self._request.registry.get('handlers', ()): value = values['hdl:{0}'.format(handler.uid)] if value and handler.uid not in warehouse_handlers: self._request.dbsession.add(DBWarehouseHandler( warehouse_id=dbwarehouse.warehouse_id, handler_id=handler.uid)) elif not value and handler.uid in warehouse_handlers: self._request.dbsession.delete(self._request.dbsession.query( DBWarehouseHandler).filter_by( warehouse_id=dbwarehouse.warehouse_id, handler_id=handler.uid).first()) # ------------------------------------------------------------------------- def _jobs_update(self, dbwarehouse, jobs, values): """Uupdate warehouse jobs. :type dbwarehouse: .models.dbwarehouse.DBWarehouse :param dbwarehouse: Warehouse to save. :param dict jobs: A dictionary such as ``{job_id: (label, description),...}``. :param dict values: Form values. """ warehouse_jobs = {k.job_id: k for k in dbwarehouse.jobs} for job_id in jobs: value = values['job:{0}'.format(job_id)] if value and job_id not in warehouse_jobs: self._request.dbsession.add(DBWarehouseJob( warehouse_id=dbwarehouse.warehouse_id, job_id=job_id)) elif not value and job_id in warehouse_jobs: self._request.dbsession.delete( self._request.dbsession.query(DBWarehouseJob).filter_by( warehouse_id=dbwarehouse.warehouse_id, job_id=job_id) .first())