summaryrefslogtreecommitdiffstats
path: root/combo_plugin_subscriptions/models.py
blob: b63ec7dc2ea3d984a94c04fbc78fc604c028c1e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
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 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'<SubscriptionsManagePlugin %s>' % self.passerelle_url

    def is_relevant(self, context):
        # the cell is only relevant for connected users
        return bool(context.get('user').is_authenticated())