import requests import requests.exceptions import logging import json from django.conf import settings from django.db import models from django.utils.translation import ugettext_lazy as _ from django.template.defaultfilters import slugify from django.core.cache import cache from django import template from django.forms import models as model_forms, Select logger = logging.getLogger(__name__) from combo.data.models import CellBase from combo.data.library import register_cell_class from .forms import SubscriptionsManageForm @register_cell_class class SubscriptionsManageCell(CellBase): passerelle_url = models.URLField(verbose_name=_('Subscriptions service url'), max_length=128) resources_restrictions = models.TextField(verbose_name=_('resources restrictions'), blank=True) transports_restrictions = models.TextField(verbose_name=_('transports restrictions'), blank=True) __resources_restrictions = None __transports_restrictions = None template_name = 'subscriptions/subscriptions.html' class Meta: verbose_name = _('Manage your subscriptions') def get_default_form_class(self): model_fields = ('passerelle_url', 'resources_restrictions', 'transports_restrictions') try: return model_forms.modelform_factory(self.__class__, fields=model_fields, widgets={'passerelle_url': Select(choices=settings.COMBO_SUBSCRIPTIONS)}) except AttributeError: return model_forms.modelform_factory(self.__class__, fields=model_fields) def simplify(self, name): return slugify(name.strip()) def get_resources_restrictions(self): if self.__resources_restrictions is None: self.__resources_restrictions = [] for name in filter(None, map(self.simplify, self.resources_restrictions.strip().split(','))): self.__resources_restrictions.append(name) return self.__resources_restrictions def get_transports_restrictions(self): if self.__transports_restrictions is None: self.__transports_restrictions = [] for name in filter(None, map(self.simplify, self.transports_restrictions.strip().split(','))): self.__transports_restrictions.append(name) return self.__transports_restrictions def check_resource(self, resource): restrictions = self.get_resources_restrictions() if restrictions and self.simplify(resource) not in restrictions: return False return True def check_transport(self, transport): restrictions = self.get_transports_restrictions() if restrictions and self.simplify(transport) not in restrictions: return False return True def key(self, **kwargs): return 'passerelle_register_subscriptions_'+slugify(self.passerelle_url+repr(sorted(kwargs.iteritems()))) def get_subscriptions(self, **kwargs): key = self.key(**kwargs) early_response = cache.get(key) if early_response is not None: logger.debug('got subscriptions from cache') return early_response http_response = requests.get(self.passerelle_url, params=kwargs) json_response = http_response.json() if json_response['err'] == 0: logger.debug('got subscriptions from %s: %r', self.passerelle_url, json_response['data']) cache.set(key, json_response['data']) return json_response['data'] else: logger.error('got subscriptions from %(url)s failed: %(json)r', { 'url': self.passerelle_url, 'json': json_response }) return [] def set_subscriptions(self, subscriptions, **kwargs): old_subscriptions = self.get_subscriptions(**kwargs) index = {} for subscription in subscriptions: index[subscription['name']] = subscription post = [] for subscription in old_subscriptions: new_defined = set(subscription['transports']['defined']) if self.simplify(subscription['name']) in index: new_subscription = index[subscription['name']] for transport in subscription['transports']['available']: stransport = self.simplify(transport) if self.check_transport(transport): if stransport in new_subscription['transports']: new_defined.add(transport) else: new_defined.discard(transport) post.append(dict(name=subscription['name'], transports=list(new_defined))) headers = {'Content-type': 'application/json', 'Accept': 'application/json'} try: response = requests.post(self.passerelle_url, params=kwargs, data=json.dumps(post), headers=headers) response.raise_for_status() except requests.exceptions.HTTPError: logger.error(u'set subscriptions on %s returned an HTTP error code: %s', response.request.url, response.status_code) except requests.exceptions.RequestException, e: logger.error(u'set subscriptions on %s failed with exception: %s', response.request.url, e) else: logger.debug(u'set subscriptions on %s: post %r', response.request.url, post) logger.debug(u'set subscriptions on %s: response %r', response.request.url, response.content) cache.delete(self.key(**kwargs)) if response.json()['err'] != 0: logger.error(u'set subscriptions on %s returned an error: %r', response.request.url, response.json()) def render(self, context): cell_name = 'subscription_cell_%s' % self.id plugin_template = template.loader.get_template(self.template_name) request = context.get('request') if request.method == 'POST' and cell_name in request.POST: form = SubscriptionsManageForm(request.POST, instance=self, request=request) form.save() else: form = SubscriptionsManageForm(instance=self, request=request) context['instance'] = self context['form'] = form context['submit_name'] = cell_name return plugin_template.render(context) def __unicode__(self): return u'' % self.passerelle_url def is_relevant(self, context): # the cell is only relevant for connected users return bool(context.get('user').is_authenticated())