# combo - content management system # Copyright (C) 2020 Entr'ouvert # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from django.utils.http import urlencode from requests.exceptions import RequestException from combo.apps.wcs.utils import get_wcs_services from combo.utils import requests def get_default_wcs_service_key(): services = get_wcs_services() for key, service in services.items(): if not service.get('secondary', False): # if secondary is not set or not set to True, return this one return key return None class LazyCardDefObjectsManager: def __init__(self, service_key, card_id, custom_view_id=None, filters=None, user=Ellipsis): self._service_key = service_key self._card_id = card_id self._custom_view_id = custom_view_id self._filters = filters or {} self._user = user self._cached_resultset = None def _clone(self): return LazyCardDefObjectsManager( service_key=self._service_key, card_id=self._card_id, custom_view_id=self._custom_view_id, filters=self._filters, user=self._user, ) def order_by(self, attribute): qs = self._clone() qs._filters['order_by'] = attribute if not attribute: del qs._filters['order_by'] return qs def with_custom_view(self, custom_view_id): qs = self._clone() qs._custom_view_id = custom_view_id return qs def get_full(self): qs = self._clone() qs._filters['full'] = 'on' return qs def access_control(self, user): qs = self._clone() qs._user = user return qs @property def count(self): return len(self) def filter_by(self, attribute): qs = self._clone() qs.pending_attr = attribute return qs def apply_filter_value(self, value): assert self.pending_attr qs = self._clone() if value is None: value = '' if isinstance(value, bool): value = str(value).lower() qs._filters['filter-%s' % self.pending_attr] = value return qs def filter_by_internal_id(self, internal_id): qs = self._clone() if internal_id: qs._filters['filter-internal-id'] = internal_id return qs def filter_by_number(self, number): qs = self._clone() if number: qs._filters['filter-number'] = number return qs def filter_by_user(self, user): qs = self._clone() if user and user.is_authenticated and user.get_name_id(): qs._filters['filter-user-uuid'] = user.get_name_id() return qs def filter_by_status(self, status): qs = self._clone() if status: qs._filters['filter'] = status return qs def _get_results_from_wcs(self): service = get_wcs_services().get(self._service_key) if not service: return [] api_url = 'api/cards/%s/list' % self._card_id if self._custom_view_id: api_url += '/%s' % self._custom_view_id if self._filters: query = urlencode(self._filters) api_url += '?%s' % query without_user = self._user is Ellipsis # not set try: response = requests.get( api_url, remote_service=service, user=None if without_user else self._user, without_user=without_user, log_errors=False, ) response.raise_for_status() except RequestException: return [] if response.json().get('err') == 1: return [] return response.json().get('data') or [] def _populate_cache(self): if self._cached_resultset is not None: return self._cached_resultset = self._get_results_from_wcs() def __len__(self): self._populate_cache() return len(self._cached_resultset) def __getitem__(self, key): try: if not isinstance(key, slice): int(key) except ValueError: raise TypeError self._populate_cache() return self._cached_resultset[key] def __iter__(self): self._populate_cache() yield from self._cached_resultset def __nonzero__(self): return any(self) class LazyCardDef: def __init__(self, slug): if ':' in slug: self.service_key, self.card_id = slug.split(':')[:2] else: self.card_id = slug self.service_key = get_default_wcs_service_key() @property def objects(self): return LazyCardDefObjectsManager(self.service_key, self.card_id) class Cards: def __getattr__(self, attr): try: return LazyCardDef(attr) except KeyError: raise AttributeError(attr) def cards(request): return {'cards': Cards()}