Revision b436bd51

b/ChangeLog
1 1
===========
2 2
1.1.2 RELEASE
3 3
Updates and enhancements. Check documentation for updating from previous versions
4

  
4 5
	- Rest Api
6
	- Use Django signals for notifications
5 7

  
6 8
=======
7 9
1.1.1 RELEASE
b/flowspec/helpers.py
1
from django.core.mail.message import EmailMessage
2
from django.conf import settings
3

  
4

  
5
def send_new_mail(subject, message, from_email, recipient_list, bcc_list):
6
    return EmailMessage(subject, message, from_email, recipient_list, bcc_list).send()
7

  
8

  
9
def get_peer_techc_mails(user):
10
    mail = []
11
    additional_mail = []
12
    techmails_list = []
13
    user_mail = '%s' % user.email
14
    user_mail = user_mail.split(';')
15
    techmails = user.get_profile().peer.techc_emails.all()
16
    if techmails:
17
        for techmail in techmails:
18
            techmails_list.append(techmail.email)
19
    if settings.NOTIFY_ADMIN_MAILS:
20
        additional_mail = settings.NOTIFY_ADMIN_MAILS
21
    mail.extend(additional_mail)
22
    mail.extend(techmails_list)
23
    return mail
b/flowspec/migrations/0006_auto__add_field_route_requesters_address.py
1
# -*- coding: utf-8 -*-
2
import datetime
3
from south.db import db
4
from south.v2 import SchemaMigration
5
from django.db import models
6

  
7

  
8
class Migration(SchemaMigration):
9

  
10
    def forwards(self, orm):
11
        # Adding field 'Route.requesters_address'
12
        db.add_column(u'route', 'requesters_address',
13
                      self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True),
14
                      keep_default=False)
15

  
16

  
17
    def backwards(self, orm):
18
        # Deleting field 'Route.requesters_address'
19
        db.delete_column(u'route', 'requesters_address')
20

  
21

  
22
    models = {
23
        'auth.group': {
24
            'Meta': {'object_name': 'Group'},
25
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
26
            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
27
            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
28
        },
29
        'auth.permission': {
30
            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
31
            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
32
            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
33
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
34
            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
35
        },
36
        'auth.user': {
37
            'Meta': {'object_name': 'User'},
38
            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
39
            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
40
            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
41
            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
42
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
43
            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
44
            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
45
            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
46
            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
47
            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
48
            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
49
            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
50
            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
51
        },
52
        'contenttypes.contenttype': {
53
            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
54
            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
55
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
56
            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
57
            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
58
        },
59
        'flowspec.fragmenttype': {
60
            'Meta': {'object_name': 'FragmentType'},
61
            'fragmenttype': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
62
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
63
        },
64
        'flowspec.matchdscp': {
65
            'Meta': {'object_name': 'MatchDscp', 'db_table': "u'match_dscp'"},
66
            'dscp': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
67
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
68
        },
69
        'flowspec.matchport': {
70
            'Meta': {'object_name': 'MatchPort', 'db_table': "u'match_port'"},
71
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
72
            'port': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '24'})
73
        },
74
        'flowspec.matchprotocol': {
75
            'Meta': {'object_name': 'MatchProtocol', 'db_table': "u'match_protocol'"},
76
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
77
            'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '24'})
78
        },
79
        'flowspec.route': {
80
            'Meta': {'object_name': 'Route', 'db_table': "u'route'"},
81
            'applier': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
82
            'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
83
            'destination': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
84
            'destinationport': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'matchDestinationPort'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['flowspec.MatchPort']"}),
85
            'dscp': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.MatchDscp']", 'null': 'True', 'blank': 'True'}),
86
            'expires': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2015, 1, 15, 0, 0)'}),
87
            'filed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
88
            'fragmenttype': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.FragmentType']", 'null': 'True', 'blank': 'True'}),
89
            'icmpcode': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
90
            'icmptype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
91
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
92
            'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
93
            'name': ('django.db.models.fields.SlugField', [], {'max_length': '128'}),
94
            'packetlength': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
95
            'port': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'matchPort'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['flowspec.MatchPort']"}),
96
            'protocol': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.MatchProtocol']", 'null': 'True', 'blank': 'True'}),
97
            'requesters_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
98
            'response': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
99
            'source': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
100
            'sourceport': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'matchSourcePort'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['flowspec.MatchPort']"}),
101
            'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '20', 'null': 'True', 'blank': 'True'}),
102
            'tcpflag': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
103
            'then': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['flowspec.ThenAction']", 'symmetrical': 'False'})
104
        },
105
        'flowspec.thenaction': {
106
            'Meta': {'ordering': "['action', 'action_value']", 'unique_together': "(('action', 'action_value'),)", 'object_name': 'ThenAction', 'db_table': "u'then_action'"},
107
            'action': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
108
            'action_value': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
109
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
110
        }
111
    }
112

  
113
    complete_apps = ['flowspec']
b/flowspec/models.py
20 20
from django.db import models
21 21
from django.conf import settings
22 22
from django.contrib.auth.models import User
23
from django.contrib.sites.models import Site
24
from django.db.models.signals import post_save
23 25
from django.utils.translation import ugettext_lazy as _
26
from django.core.urlresolvers import reverse
27

  
28
from flowspec.helpers import send_new_mail, get_peer_techc_mails
24 29
from utils import proxy as PR
25 30
from ipaddr import *
26 31
import datetime
27 32
import logging
28 33
from time import sleep
29
from junos import create_junos_name, policer_name
34
from junos import create_junos_name
30 35

  
31 36
import beanstalkc
32 37
from utils.randomizer import id_generator as id_gen
......
167 172
    expires = models.DateField(default=days_offset, verbose_name=_("Expires"))
168 173
    response = models.CharField(max_length=512, blank=True, null=True, verbose_name=_("Response"))
169 174
    comments = models.TextField(null=True, blank=True, verbose_name=_("Comments"))
170

  
175
    requesters_address = models.CharField(max_length=255, blank=True, null=True)
171 176

  
172 177
    def __unicode__(self):
173 178
        return self.name
......
183 188
            self.name = "%s_%s" %(self.name, hash)
184 189
        super(Route, self).save(*args, **kwargs) # Call the "real" save() method.
185 190

  
186

  
187 191
    def clean(self, *args, **kwargs):
188 192
        from django.core.exceptions import ValidationError
189 193
        if self.destination:
......
201 205

  
202 206
    def commit_add(self, *args, **kwargs):
203 207
        peer = self.applier.get_profile().peer.peer_tag
204
        send_message("[%s] Adding rule %s. Please wait..." %(self.applier.username, self.name), peer)
208
        send_message("[%s] Adding rule %s. Please wait..." % (self.applier.username, self.name), peer)
205 209
        response = add.delay(self)
206
        logger.info("Got add job id: %s" %response)
210
        logger.info('Got add job id: %s' % response)
211
        fqdn = Site.objects.get_current().domain
212
        admin_url = 'https://%s%s' % (
213
            fqdn,
214
            reverse('edit-route', kwargs={'route_slug': self.name})
215
        )
216
        mail_body = render_to_string(
217
            'rule_action.txt',
218
            {
219
                'route': self,
220
                'address': self.requesters_address,
221
                'action': 'creation',
222
                'url': admin_url
223
            }
224
        )
225
        user_mail = '%s' % self.applier.email
226
        user_mail = user_mail.split(';')
227
        send_new_mail(
228
            settings.EMAIL_SUBJECT_PREFIX + 'Rule %s creation request submitted by %s' % (self.name, self.applier.username),
229
            mail_body,
230
            settings.SERVER_EMAIL, user_mail,
231
            get_peer_techc_mails(self.applier)
232
        )
233
        d = {
234
            'clientip': '%s' % self.requesters_address,
235
            'user': self.applier.username
236
        }
237
        logger.info(mail_body, extra=d)
207 238

  
208 239
    def commit_edit(self, *args, **kwargs):
209 240
        peer = self.applier.get_profile().peer.peer_tag
210
        send_message("[%s] Editing rule %s. Please wait..." %(self.applier.username, self.name), peer)
241
        send_message(
242
            '[%s] Editing rule %s. Please wait...' %
243
            (
244
                self.applier.username,
245
                self.name
246
            ), peer
247
        )
211 248
        response = edit.delay(self)
212
        logger.info("Got edit job id: %s" %response)
249
        logger.info('Got edit job id: %s' % response)
250
        fqdn = Site.objects.get_current().domain
251
        admin_url = 'https://%s%s' % (
252
            fqdn,
253
            reverse(
254
                'edit-route',
255
                kwargs={'route_slug': self.name}
256
            )
257
        )
258
        mail_body = render_to_string(
259
            'rule_action.txt',
260
            {
261
                'route': self,
262
                'address': self.requesters_address,
263
                'action': 'edit',
264
                'url': admin_url
265
            }
266
        )
267
        user_mail = '%s' % self.applier.email
268
        user_mail = user_mail.split(';')
269
        send_new_mail(
270
            settings.EMAIL_SUBJECT_PREFIX + 'Rule %s edit request submitted by %s' % (self.name, self.applier.username),
271
            mail_body, settings.SERVER_EMAIL, user_mail,
272
            get_peer_techc_mails(self.applier)
273
        )
274
        d = {
275
            'clientip': self.requesters_address,
276
            'user': self.applier.username
277
        }
278
        logger.info(mail_body, extra=d)
213 279

  
214 280
    def commit_delete(self, *args, **kwargs):
215 281
        reason_text = ''
216 282
        reason = ''
217 283
        if "reason" in kwargs:
218 284
            reason = kwargs['reason']
219
            reason_text = "Reason: %s. " %reason
285
            reason_text = 'Reason: %s.' % reason
220 286
        peer = self.applier.get_profile().peer.peer_tag
221
        send_message("[%s] Suspending rule %s. %sPlease wait..." %(self.applier.username, self.name, reason_text), peer)
287
        send_message(
288
            '[%s] Suspending rule %s. %sPlease wait...' % (
289
                self.applier.username,
290
                self.name,
291
                reason_text
292
            ), peer
293
        )
222 294
        response = delete.delay(self, reason=reason)
223
        logger.info("Got delete job id: %s" %response)
295
        logger.info('Got delete job id: %s' % response)
296
        fqdn = Site.objects.get_current().domain
297
        admin_url = 'https://%s%s' % (
298
            fqdn,
299
            reverse(
300
                'edit-route',
301
                kwargs={'route_slug': self.name}
302
            )
303
        )
304
        mail_body = render_to_string(
305
            'rule_action.txt',
306
            {
307
                'route': self,
308
                'address': self.requesters_address,
309
                'action': 'removal',
310
                'url': admin_url
311
            }
312
        )
313
        user_mail = '%' % self.applier.email
314
        user_mail = user_mail.split(';')
315
        send_new_mail(
316
            settings.EMAIL_SUBJECT_PREFIX + 'Rule %s removal request submitted by %s' % (self.name, self.applier.username),
317
            mail_body,
318
            settings.SERVER_EMAIL,
319
            user_mail,
320
            get_peer_techc_mails(self.applier)
321
        )
322
        d = {
323
            'clientip': self.requesters_address,
324
            'user': self.applier.username
325
        }
326
        logger.info(mail_body, extra=d)
224 327

  
225 328
    def has_expired(self):
226 329
        today = datetime.date.today()
......
242 345
        except Exception as e:
243 346
            self.status = "EXPIRED"
244 347
            self.save()
245
            logger.error("No routing options on device. Exception: %s" %e)
348
            logger.error('No routing options on device. Exception: %s' % e)
246 349
            return True
247 350
        for route in routes:
248 351
            if route.name == self.name:
......
478 581
    tube_message = json.dumps({'message': str(msg), 'username':peer})
479 582
    b.put(tube_message)
480 583
    b.close()
584

  
585

  
586
def notify_user(sender, instance, created, **kwargs):
587
    if created:
588
        instance.commit_add()
589
    else:
590
        if instance.has_expired():
591
            instance.commit_delete()
592
        else:
593
            instance.commit_edit()
594

  
595

  
596
post_save.connect(notify_user, sender=Route)
b/flowspec/views.py
54 54

  
55 55
from django.views.decorators.cache import never_cache
56 56
from django.conf import settings
57
from django.core.mail.message import EmailMessage
58 57
from django.template.defaultfilters import slugify
58
from flowspec.helpers import send_new_mail, get_peer_techc_mails
59 59
import datetime
60 60
import os
61 61

  
......
127 127
    jresp['aaData'] = routes
128 128
    return HttpResponse(json.dumps(jresp), mimetype='application/json')
129 129

  
130

  
130 131
@login_required
131 132
@never_cache
132 133
def overview_routes_ajax(request):
......
147 148
    jresp['aaData'] = routes
148 149
    return HttpResponse(json.dumps(jresp), mimetype='application/json')
149 150

  
151

  
150 152
def build_routes_json(groutes):
151 153
    routes = []
152 154
    for r in groutes:
......
170 172
        routes.append(rd)
171 173
    return routes
172 174

  
175

  
173 176
@login_required
174 177
@never_cache
175 178
def add_route(request):
......
178 181
    if request.user.is_superuser:
179 182
        applier_peer_networks = PeerRange.objects.all()
180 183
    if not applier_peer_networks:
181
         messages.add_message(request, messages.WARNING,
182
                             _("Insufficient rights on administrative networks. Cannot add rule. Contact your administrator"))
183
         return HttpResponseRedirect(reverse("group-routes"))
184
        messages.add_message(
185
            request,
186
            messages.WARNING,
187
            ('Insufficient rights on administrative networks. Cannot add rule. Contact your administrator')
188
        )
189
        return HttpResponseRedirect(reverse("group-routes"))
184 190
    if request.method == "GET":
185 191
        form = RouteForm(initial={'applier': applier})
186 192
        if not request.user.is_superuser:
......
201 207
                pass
202 208
        form = RouteForm(request_data)
203 209
        if form.is_valid():
204
            route=form.save(commit=False)
210
            route = form.save(commit=False)
205 211
            if not request.user.is_superuser:
206 212
                route.applier = request.user
207 213
            route.status = "PENDING"
208 214
            route.response = "Applying"
209
            route.source = IPNetwork("%s/%s" %(IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed
210
            route.destination = IPNetwork("%s/%s" %(IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed
215
            route.source = IPNetwork('%s/%s' % (IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed
216
            route.destination = IPNetwork('%s/%s' % (IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed
217
            route.requesters_address = request.META['HTTP_X_FORWARDED_FOR']
211 218
            route.save()
212 219
            form.save_m2m()
213
            route.commit_add()
214
            requesters_address = request.META['HTTP_X_FORWARDED_FOR']
215
            fqdn = Site.objects.get_current().domain
216
            admin_url = "https://%s%s" % (fqdn, reverse("edit-route", kwargs={'route_slug': route.name }))
217
            mail_body = render_to_string("rule_action.txt",
218
                                             {"route": route, "address": requesters_address, "action": "creation", "url": admin_url})
219
            user_mail = "%s" %route.applier.email
220
            user_mail = user_mail.split(';')
221
            send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s creation request submitted by %s" %(route.name, route.applier.username),
222
                              mail_body, settings.SERVER_EMAIL, user_mail,
223
                              get_peer_techc_mails(route.applier))
224
            d = { 'clientip' : "%s"%requesters_address, 'user' : route.applier.username }
225
            logger.info(mail_body, extra=d)
226 220
            return HttpResponseRedirect(reverse("group-routes"))
227 221
        else:
228 222
            if not request.user.is_superuser:
229 223
                form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True)
230 224
                form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False)
231
            return render_to_response('apply.html', {'form': form, 'applier':applier},
232
                                      context_instance=RequestContext(request))
225
            return render_to_response(
226
                'apply.html',
227
                {
228
                    'form': form,
229
                    'applier': applier
230
                },
231
                context_instance=RequestContext(request)
232
            )
233

  
233 234

  
234 235
@login_required
235 236
@never_cache
......
239 240
    route_edit = get_object_or_404(Route, name=route_slug)
240 241
    route_edit_applier_peer = route_edit.applier.get_profile().peer
241 242
    if applier_peer != route_edit_applier_peer and (not request.user.is_superuser):
242
        messages.add_message(request, messages.WARNING,
243
                             _("Insufficient rights to edit rule %s") %(route_slug))
243
        messages.add_message(
244
            request,
245
            messages.WARNING,
246
            ('Insufficient rights to edit rule %s') % (route_slug)
247
        )
244 248
        return HttpResponseRedirect(reverse("group-routes"))
245 249
#    if route_edit.status == "ADMININACTIVE" :
246 250
#        messages.add_message(request, messages.WARNING,
......
250 254
#        messages.add_message(request, messages.WARNING,
251 255
#                             "Cannot edit the expired rule %s. Contact helpdesk to enable it" %(route_slug))
252 256
#        return HttpResponseRedirect(reverse("group-routes"))
253
    if route_edit.status == "PENDING" :
254
        messages.add_message(request, messages.WARNING,
255
                             _("Cannot edit a pending rule: %s.") %(route_slug))
257
    if route_edit.status == 'PENDING':
258
        messages.add_message(
259
            request,
260
            messages.WARNING,
261
            ('Cannot edit a pending rule: %s.') % (route_slug)
262
        )
256 263
        return HttpResponseRedirect(reverse("group-routes"))
257 264
    route_original = deepcopy(route_edit)
258 265
    if request.POST:
......
265 272
                del request_data['issuperuser']
266 273
            except:
267 274
                pass
268
        form = RouteForm(request_data, instance = route_edit)
275
        form = RouteForm(
276
            request_data,
277
            instance=route_edit
278
        )
269 279
        critical_changed_values = ['source', 'destination', 'sourceport', 'destinationport', 'port', 'protocol', 'then', 'fragmenttype']
270 280
        if form.is_valid():
271 281
            changed_data = form.changed_data
272
            route=form.save(commit=False)
282
            route = form.save(commit=False)
273 283
            route.name = route_original.name
274 284
            route.status = route_original.status
275 285
            route.response = route_original.response
......
278 288
            if bool(set(changed_data) & set(critical_changed_values)) or (not route_original.status == 'ACTIVE'):
279 289
                route.status = "PENDING"
280 290
                route.response = "Applying"
281
                route.source = IPNetwork("%s/%s" %(IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed
282
                route.destination = IPNetwork("%s/%s" %(IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed
291
                route.source = IPNetwork('%s/%s' % (IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed
292
                route.destination = IPNetwork('%s/%s' % (IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed
293
                route.requesters_address = self.request.META['HTTP_X_FORWARDED_FOR']
283 294
            route.save()
284 295
            if bool(set(changed_data) & set(critical_changed_values)) or (not route_original.status == 'ACTIVE'):
285 296
                form.save_m2m()
286
                route.commit_edit()
287
                requesters_address = request.META['HTTP_X_FORWARDED_FOR']
288
                fqdn = Site.objects.get_current().domain
289
                admin_url = "https://%s%s" % (fqdn, reverse("edit-route", kwargs={'route_slug': route.name }))
290
                mail_body = render_to_string("rule_action.txt",
291
                                             {"route": route, "address": requesters_address, "action": "edit", "url": admin_url})
292
                user_mail = "%s" %route.applier.email
293
                user_mail = user_mail.split(';')
294
                send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s edit request submitted by %s" %(route.name, route.applier.username),
295
                              mail_body, settings.SERVER_EMAIL, user_mail,
296
                              get_peer_techc_mails(route.applier))
297
                d = { 'clientip' : requesters_address, 'user' : route.applier.username }
298
                logger.info(mail_body, extra=d)
297
                # route.commit_edit()
299 298
            return HttpResponseRedirect(reverse("group-routes"))
300 299
        else:
301 300
            if not request.user.is_superuser:
302 301
                form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True)
303 302
                form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False)
304
            return render_to_response('apply.html', {'form': form, 'edit':True, 'applier': applier},
305
                                      context_instance=RequestContext(request))
303
            return render_to_response(
304
                'apply.html',
305
                {
306
                    'form': form,
307
                    'edit': True,
308
                    'applier': applier
309
                },
310
                context_instance=RequestContext(request)
311
            )
306 312
    else:
307 313
        if (not route_original.status == 'ACTIVE'):
308
            route_edit.expires = datetime.date.today() + datetime.timedelta(days = settings.EXPIRATION_DAYS_OFFSET)
314
            route_edit.expires = datetime.date.today() + datetime.timedelta(days=settings.EXPIRATION_DAYS_OFFSET)
309 315
        dictionary = model_to_dict(route_edit, fields=[], exclude=[])
310 316
        if request.user.is_superuser:
311 317
            dictionary['issuperuser'] = request.user.username
......
318 324
        if not request.user.is_superuser:
319 325
            form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True)
320 326
            form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False)
321
        return render_to_response('apply.html', {'form': form, 'edit':True, 'applier': applier},
322
                                  context_instance=RequestContext(request))
327
        return render_to_response(
328
            'apply.html',
329
            {
330
                'form': form,
331
                'edit': True,
332
                'applier': applier
333
            },
334
            context_instance=RequestContext(request)
335
        )
336

  
323 337

  
324 338
@login_required
325 339
@never_cache
......
334 348
            if not request.user.is_superuser:
335 349
                route.applier = request.user
336 350
            route.response = "Deactivating"
351
            route.requesters_address = request.META['HTTP_X_FORWARDED_FOR']
337 352
            route.save()
338
            route.commit_delete()
339
            requesters_address = request.META['HTTP_X_FORWARDED_FOR']
340
            fqdn = Site.objects.get_current().domain
341
            admin_url = "https://%s%s" % (fqdn, reverse("edit-route", kwargs={'route_slug': route.name }))
342
            mail_body = render_to_string("rule_action.txt",
343
                                             {"route": route, "address": requesters_address, "action": "removal", "url": admin_url})
344
            user_mail = "%s" %route.applier.email
345
            user_mail = user_mail.split(';')
346
            send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s removal request submitted by %s" %(route.name, route.applier.username),
347
                              mail_body, settings.SERVER_EMAIL, user_mail,
348
                             get_peer_techc_mails(route.applier))
349
            d = { 'clientip' : requesters_address, 'user' : route.applier.username }
350
            logger.info(mail_body, extra=d)
353
            # route.commit_delete()
351 354
        html = "<html><body>Done</body></html>"
352 355
        return HttpResponse(html)
353 356
    else:
354 357
        return HttpResponseRedirect(reverse("group-routes"))
355 358

  
359

  
356 360
@login_required
357 361
@never_cache
358 362
def user_profile(request):
......
577 581
    return render_to_response('%s.js' % file, {'timeout': long_polling_timeout}, context_instance=RequestContext(request), mimetype="text/javascript")
578 582

  
579 583

  
580
def get_peer_techc_mails(user):
581
    mail = []
582
    additional_mail = []
583
    techmails_list = []
584
    user_mail = "%s" %user.email
585
    user_mail = user_mail.split(';')
586
    techmails = user.get_profile().peer.techc_emails.all()
587
    if techmails:
588
        for techmail in techmails:
589
            techmails_list.append(techmail.email)
590
    if settings.NOTIFY_ADMIN_MAILS:
591
        additional_mail = settings.NOTIFY_ADMIN_MAILS
592
    mail.extend(additional_mail)
593
    mail.extend(techmails_list)
594
    return mail
595

  
596
def send_new_mail(subject, message, from_email, recipient_list, bcc_list):
597
    return EmailMessage(subject, message, from_email, recipient_list, bcc_list).send()
598

  
599

  
600 584
def lookupShibAttr(attrmap, requestMeta):
601 585
    for attr in attrmap:
602 586
        if (attr in requestMeta.keys()):
b/flowspec/viewsets.py
36 36
    queryset = Route.objects.all()
37 37
    serializer_class = RouteSerializer
38 38

  
39
    def pre_save(self, obj):
40
        obj.requesters_address = self.request.META['HTTP_X_FORWARDED_FOR']
41

  
39 42

  
40 43
class PortViewSet(viewsets.ModelViewSet):
41 44
    queryset = MatchPort.objects.all()

Also available in: Unified diff