--- /dev/null
+import os
+import sys
+
+sys.path.append('/home/leopoul/projects/')
+sys.path.append('/home/leopoul/projects/flowspy')
+
+os.environ['DJANGO_SETTINGS_MODULE'] = 'flowspy.settings'
+
+from gevent import monkey; monkey.patch_all()
+
+
+import django.core.handlers.wsgi
+application = django.core.handlers.wsgi.WSGIHandler()
--- /dev/null
+# -*- coding: utf-8 -*- vim:encoding=utf-8:
+# vim: tabstop=4:shiftwidth=4:softtabstop=4:expandtab
+
+from django.contrib.auth.models import User, UserManager, Permission, Group
+from django.conf import settings
+from flowspy.peers.models import *
+from flowspy.accounts.models import *
+
+class shibauthBackend:
+ def authenticate(self, **kwargs):
+
+ username = kwargs.get('username')
+ firstname = kwargs.get('firstname')
+ lastname = kwargs.get('lastname')
+ mail = kwargs.get('mail')
+ affiliation = kwargs.get('affiliation')
+ organization = kwargs.get('organization')
+ user = self._auth_user(username, firstname, lastname, mail, affiliation, organization)
+ if not user:
+ return None
+ return user
+
+ def _auth_user(self, username, firstname, lastname, mail, affiliation, organization):
+
+ try:
+ user = User.objects.get(username__exact=username)
+ # The user did not exist. Create one with no privileges
+ except:
+ user = User.objects.create_user(username, mail, None)
+ user.first_name = firstname
+ user.last_name = lastname
+ user.is_staff = False
+ user.is_superuser = False
+# if organization == settings.SHIB_ADMIN_DOMAIN:
+# user.is_staff = True
+# user.is_superuser = True
+ user.is_active = True
+ try:
+ peer = Peer.objects.get(domain_name=organization)
+ up = UserProfile.objects.get_or_create(user=user,peer=peer)
+ except:
+ pass
+ return user
+
+ def get_user(self, user_id):
+ try:
+ return User.objects.get(pk=user_id)
+ except User.DoesNotExist:
+ return None
from flowspy.accounts.models import *
from utils import proxy as PR
-class RouteAdmin(admin.ModelAdmin):
-
- actions = ['deactivate']
-
- def deactivate(self, request, queryset):
- applier = PR.Applier(route_objects=queryset)
- commit, response = applier.apply(configuration=applier.delete_routes())
- if commit:
- rows = queryset.update(is_online=False, is_active=False)
- queryset.update(response="Successfully removed route from network")
- self.message_user(request, "Successfully removed %s routes from network" % rows)
- else:
- self.message_user(request, "Could not remove routes from network")
- deactivate.short_description = "Deactivate selected routes from network"
-
- list_display = ('name', 'is_online', 'applier', 'get_match', 'get_then', 'response')
- fieldsets = [
- (None, {'fields': ['name','applier']}),
- ("Match", {'fields': ['source', 'sourceport', 'destination', 'destinationport', 'port']}),
- ('Advanced Match Statements', {'fields': ['dscp', 'fragmenttype', 'icmpcode', 'icmptype', 'packetlength', 'protocol', 'tcpflag'], 'classes': ['collapse']}),
- ("Then", {'fields': ['then' ]}),
- (None, {'fields': ['comments',]}),
-
- ]
+#class RouteAdmin(admin.ModelAdmin):
+#
+# actions = ['deactivate']
+#
+# def deactivate(self, request, queryset):
+# applier = PR.Applier(route_objects=queryset)
+# commit, response = applier.apply(configuration=applier.delete_routes())
+# if commit:
+# rows = queryset.update(is_online=False, is_active=False)
+# queryset.update(response="Successfully removed route from network")
+# self.message_user(request, "Successfully removed %s routes from network" % rows)
+# else:
+# self.message_user(request, "Could not remove routes from network")
+# deactivate.short_description = "Deactivate selected routes from network"
+#
+# list_display = ('name', 'is_online', 'applier', 'get_match', 'get_then', 'response')
+# fieldsets = [
+# (None, {'fields': ['name','applier']}),
+# ("Match", {'fields': ['source', 'sourceport', 'destination', 'destinationport', 'port']}),
+# ('Advanced Match Statements', {'fields': ['dscp', 'fragmenttype', 'icmpcode', 'icmptype', 'packetlength', 'protocol', 'tcpflag'], 'classes': ['collapse']}),
+# ("Then", {'fields': ['then' ]}),
+# (None, {'fields': ['comments',]}),
+#
+# ]
# fields = ('name', 'applier', 'expires')
#def formfield_for_dbfield(self, db_field, **kwargs):
admin.site.register(ThenAction)
#admin.site.register(ThenStatement)
#admin.site.register(MatchStatement)
-admin.site.register(Route, RouteAdmin)
+admin.site.register(Route)
admin.site.disable_action('delete_selected')
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
from django.template.defaultfilters import filesizeformat
-
from flowspy.flowspec.models import *
from ipaddr import *
+from django.contrib.auth.models import User
class RouteForm(forms.ModelForm):
# name = forms.CharField(help_text=ugettext_lazy("A unique route name,"
ports = self.cleaned_data.get('port', None)
destination = self.cleaned_data.get('destination', None)
destinationports = self.cleaned_data.get('destinationport', None)
+ user = self.cleaned_data.get('applier', None)
+ networks = user.get_profile().peer.networks.all()
+ mynetwork = False
+ if destination:
+ for network in networks:
+ net = IPNetwork(network.network)
+ if IPNetwork(destination) in net:
+ mynetwork = True
+ if not mynetwork:
+ raise forms.ValidationError('Destination address/network should belong to your administrative address space. Check My Profile to review your networks')
if (sourceports and ports):
raise forms.ValidationError('Cannot create rule for source ports and ports at the same time. Select either ports or source ports')
if (destinationports and ports):
raise forms.ValidationError('Once destination port is matched, destination has to be filled as well. Either deselect destination port or fill destination address')
if not (source or sourceports or ports or destination or destinationports):
raise forms.ValidationError('Fill at least a Route Match Condition')
- return self.cleaned_data
\ No newline at end of file
+ return self.cleaned_data
+
+class ThenPlainForm(forms.ModelForm):
+# action = forms.CharField(initial='rate-limit')
+ class Meta:
+ model = ThenAction
+
+ def clean_action_value(self):
+ action_value = self.cleaned_data['action_value']
+ if action_value:
+ try:
+ assert(int(action_value))
+ return "%s" %self.cleaned_data["action_value"]
+ except:
+ raise forms.ValidationError('Rate-limiting should be an integer')
+ if int(action_value) < 50:
+ raise forms.ValidationError('Rate-limiting cannot be < 50kbps')
+ else:
+ raise forms.ValidationError('Cannot be empty')
+
+ def clean_action(self):
+ action = self.cleaned_data['action']
+ if action != 'rate-limit':
+ raise forms.ValidationError('Cannot select something other than rate-limit')
+ else:
+ return self.cleaned_data["action"]
+
+class PortPlainForm(forms.ModelForm):
+# action = forms.CharField(initial='rate-limit')
+ class Meta:
+ model = MatchPort
+
+ def clean_port(self):
+ port = self.cleaned_data['port']
+ if port:
+ try:
+ assert(int(port))
+ return "%s" %self.cleaned_data["port"]
+ except:
+ raise forms.ValidationError('Port should be an integer')
+ else:
+ raise forms.ValidationError('Cannot be empty')
from time import sleep
from flowspy.utils import beanstalkc
+from flowspy.utils.randomizer import id_generator as id_gen
FORMAT = '%(asctime)s %(levelname)s: %(message)s'
("sample", "Sample")
)
+ROUTE_STATES = (
+ ("ACTIVE", "ACTIVE"),
+ ("ERROR", "ERROR"),
+ ("EXPIRED", "EXPIRED"),
+ ("PENDING", "PENDING"),
+ ("OUTOFSYNC", "OUTOFSYNC"),
+ ("INACTIVE", "INACTIVE"),
+)
+
def days_offset(): return datetime.now() + timedelta(days = settings.EXPIRATION_DAYS_OFFSET)
class MatchPort(models.Model):
- port = models.CharField(max_length=24)
+ port = models.CharField(max_length=24, unique=True)
def __unicode__(self):
return self.port
class Meta:
action = models.CharField(max_length=60, choices=THEN_CHOICES, verbose_name="Action")
action_value = models.CharField(max_length=255, blank=True, null=True, verbose_name="Action Value")
def __unicode__(self):
- return "%s: %s" %(self.action, self.action_value)
+ ret = "%s:%s" %(self.action, self.action_value)
+ return ret.rstrip(":")
class Meta:
db_table = u'then_action'
then = models.ManyToManyField(ThenAction, verbose_name="Then")
filed = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
- is_online = models.BooleanField(default=False)
- is_active = models.BooleanField(default=False)
+ status = models.CharField(max_length=20, choices=ROUTE_STATES, blank=True, null=True, verbose_name="Status", default="PENDING")
+# is_online = models.BooleanField(default=False)
+# is_active = models.BooleanField(default=False)
expires = models.DateField(default=days_offset, blank=True, null=True,)
response = models.CharField(max_length=512, blank=True, null=True)
comments = models.TextField(null=True, blank=True, verbose_name="Comments")
return self.name
class Meta:
- unique_together = (("name", "is_active"),)
db_table = u'route'
+ def save(self, *args, **kwargs):
+ if not self.pk:
+ hash = id_gen()
+ self.name = "%s_%s" %(self.name, hash)
+ super(Route, self).save(*args, **kwargs) # Call the "real" save() method.
+
+
def clean(self, *args, **kwargs):
from django.core.exceptions import ValidationError
if self.destination:
# logger.info("Got save job id: %s" %response)
def commit_add(self, *args, **kwargs):
- send_message("Adding route %s. Please wait..." %self.name, self.applier)
+ peer = self.applier.get_profile().peer.domain_name
+ send_message("[%s] Adding route %s. Please wait..." %(self.applier.username, self.name), peer)
response = add.delay(self)
logger.info("Got save job id: %s" %response)
def deactivate(self):
- self.is_online = False
- self.is_active = False
+ self.status = "INACTIVE"
self.save()
# def delete(self, *args, **kwargs):
# response = delete.delay(self)
# logger.info("Got delete job id: %s" %response)
def commit_edit(self, *args, **kwargs):
- send_message("Editing route %s. Please wait..." %self.name, self.applier)
+ peer = self.applier.get_profile().peer.domain_name
+ send_message("[%s] Editing route %s. Please wait..." %(self.applier.username, self.name), peer)
response = edit.delay(self)
logger.info("Got edit job id: %s" %response)
def commit_delete(self, *args, **kwargs):
- send_message("Removing route %s. Please wait..." %self.name, self.applier)
+ peer = self.applier.get_profile().peer.domain_name
+ send_message("[%s] Removing route %s. Please wait..." %(self.applier.username, self.name), peer)
response = delete.delay(self)
logger.info("Got edit job id: %s" %response)
#
# def delete(self, *args, **kwargs):
# response = delete.delay(self)
# logger.info("Got delete job id: %s" %response)
- def is_synced(self):
-
+
+ def is_synced(self):
found = False
get_device = PR.Retriever()
device = get_device.fetch_device()
try:
routes = device.routing_options[0].routes
except Exception as e:
- self.is_online = False
+ self.status = "EXPIRED"
self.save()
logger.error("No routing options on device. Exception: %s" %e)
return False
logger.info('Protocol fields do not match')
except:
pass
- if found and not self.is_online:
+ if found and self.status != "ACTIVE":
logger.error('Rule is applied on device but appears as offline')
found = False
def get_match(self):
ret = ''
if self.destination:
- ret = '%s Destination Address:<strong>%s</strong><br/>' %(ret, self.destination)
+ ret = '%s Dst Addr:<strong>%s</strong><br/>' %(ret, self.destination)
if self.fragmenttype:
ret = "%s Fragment Type:<strong>%s</strong><br/>" %(ret, self.fragmenttype)
if self.icmpcode:
if self.protocol:
ret = "%s Protocol:<strong>%s</strong><br/>" %(ret, self.protocol)
if self.source:
- ret = "%s Source Address:<strong>%s</strong><br/>" %(ret, self.source)
+ ret = "%s Src Addr:<strong>%s</strong><br/>" %(ret, self.source)
if self.tcpflag:
ret = "%s TCP flag:<strong>%s</strong><br/>" %(ret, self.tcpflag)
if self.port:
ret = ret + "Port:<strong>%s</strong><br/>" %(port)
if self.destinationport:
for port in self.destinationport.all():
- ret = ret + "Destination Port:<strong>%s</strong><br/>" %(port)
+ ret = ret + "Dst Port:<strong>%s</strong><br/>" %(port)
if self.sourceport:
for port in self.sourceport.all():
- ret = ret +"Source Port:<strong>%s</strong><br/>" %(port)
+ ret = ret +"Src Port:<strong>%s</strong><br/>" %(port)
if self.dscp:
for dscp in self.dscp.all():
ret = ret + "%s Port:<strong>%s</strong><br/>" %(ret, dscp)
get_match.allow_tags = True
def send_message(msg, user):
- username = user.username
+# username = user.username
+ peer = user
b = beanstalkc.Connection()
b.use(settings.POLLS_TUBE)
- tube_message = json.dumps({'message': str(msg), 'username':username})
+ tube_message = json.dumps({'message': str(msg), 'username':peer})
b.put(tube_message)
b.close()
--- /dev/null
+INSERT INTO `then_action` (`id`, `action`, `action_value`) VALUES
+(1, 'accept', ''),
+(2, 'discard', '');
\ No newline at end of file
applier = PR.Applier(route_object=route)
commit, response = applier.apply()
if commit:
- is_online = True
- is_active = True
+ status = "ACTIVE"
else:
- is_online = False
- is_active = True
- route.is_online = is_online
- route.is_active = is_active
+ status = "ERROR"
+ route.status = status
route.response = response
- subtask(announce).delay("Route add: %s - Result: %s" %(route.name, response), route.applier)
+ subtask(announce).delay("[%s] Route add: %s - Result: %s" %(route.applier, route.name, response), route.applier)
route.save()
@task
applier = PR.Applier(route_object=route)
commit, response = applier.apply(operation="replace")
if commit:
- is_online = True
+ status = "ACTIVE"
else:
- is_online = False
- route.is_active = True
- route.is_online = is_online
+ status = "ERROR"
+ route.status = status
route.response = response
route.save()
- subtask(announce).delay("Route edit: %s - Result: %s" %(route.name, response), route.applier)
+ subtask(announce).delay("[%s] Route edit: %s - Result: %s"%(route.applier, route.name, response), route.applier)
applier = PR.Applier(route_object=route)
commit, response = applier.apply(operation="delete")
if commit:
- is_online = False
- is_active = False
+ status = "INACTIVE"
else:
- is_online = route.is_online
- is_active = route.is_active
- route.is_online = is_online
- route.is_active = is_active
+ status = "ERROR"
+ route.status = status
route.response = response
route.save()
- subtask(announce).delay("Route delete: %s - Result %s" %(route.name, response), route.applier)
+ subtask(announce).delay("[%s] Route delete: %s - Result %s" %(route.applier, route.name, response), route.applier)
@task
def announce(messg, user):
messg = str(messg)
- username = user.username
+# username = user.username
+ username = user.get_profile().peer.domain_name
b = beanstalkc.Connection()
b.use(settings.POLLS_TUBE)
tube_message = json.dumps({'message': messg, 'username':username})
b.put(tube_message)
b.close()
-
+@task
+def check_sync(route_name=None, selected_routes = []):
+ if not selected_routes:
+ routes = Route.objects.all()
+ else:
+ routes = selected_routes
+ if route_name:
+ routes = routes.filter(name=route_name)
+ for route in roures:
+ if route.is_synced():
+ logger.info("Route %s is synced" %route.name)
+ else:
+ logger.warn("Route %s is out of sync" %route.name)
#def delete(route):
#
# applier = PR.Applier(route_object=route)
import urllib2
import re
import socket
+import json
from django import forms
from django.views.decorators.csrf import csrf_exempt
from django.core import urlresolvers
+from django.core import serializers
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponseForbidden, HttpResponse
from django.shortcuts import get_object_or_404, render_to_response
from django.contrib import messages
from flowspy.accounts.models import *
+from django.contrib.auth import authenticate, login
+
from django.forms.models import model_to_dict
from flowspy.flowspec.forms import *
from flowspy.flowspec.models import *
from copy import deepcopy
+from flowspy.utils.decorators import shib_required
def days_offset(): return datetime.now() + timedelta(days = settings.EXPIRATION_DAYS_OFFSET)
@login_required
def user_routes(request):
- if request.user.is_anonymous():
- return HttpResponseRedirect(reverse('login'))
user_routes = Route.objects.filter(applier=request.user)
return render_to_response('user_routes.html', {'routes': user_routes},
context_instance=RequestContext(request))
@login_required
def group_routes(request):
- if request.user.is_anonymous():
- return HttpResponseRedirect(reverse('login'))
+ group_routes = []
peer = request.user.get_profile().peer
if peer:
peer_members = UserProfile.objects.filter(peer=peer)
@login_required
def add_route(request):
+ applier = request.user.pk
if request.method == "GET":
form = RouteForm()
- return render_to_response('apply.html', {'form': form},
+ return render_to_response('apply.html', {'form': form, 'applier': applier},
context_instance=RequestContext(request))
else:
route=form.save(commit=False)
route.applier = request.user
route.expires = days_offset()
+ route.status = "PENDING"
route.save()
form.save_m2m()
route.commit_add()
- return HttpResponseRedirect(urlresolvers.reverse("user-routes"))
+ return HttpResponseRedirect(reverse("group-routes"))
else:
- return render_to_response('apply.html', {'form': form},
+ return render_to_response('apply.html', {'form': form, 'applier':applier},
context_instance=RequestContext(request))
+
+@login_required
+def add_then(request):
+ applier = request.user.pk
+ if request.method == "GET":
+ form = RouteForm()
+ return render_to_response('apply.html', {'form': form, 'applier': applier},
+ context_instance=RequestContext(request))
+
+ else:
+ form = RouteForm(request.POST)
+ if form.is_valid():
+ route=form.save(commit=False)
+ route.applier = request.user
+ route.expires = days_offset()
+ route.save()
+ form.save_m2m()
+ route.commit_add()
+ return HttpResponseRedirect(reverse("group-routes"))
+ else:
+ return render_to_response('apply.html', {'form': form, 'applier':applier},
+ context_instance=RequestContext(request))
+
@login_required
def edit_route(request, route_slug):
+ applier = request.user.pk
route_edit = get_object_or_404(Route, name=route_slug)
route_original = deepcopy(route_edit)
if request.POST:
if form.is_valid():
route=form.save(commit=False)
route.name = route_original.name
- route.applier = route_original.applier
+ route.applier = request.user
route.expires = route_original.expires
- route.is_active = route_original.is_active
+ route.status = "PENDING"
route.save()
form.save_m2m()
route.commit_edit()
- return HttpResponseRedirect(urlresolvers.reverse("user-routes"))
+ return HttpResponseRedirect(reverse("group-routes"))
else:
- return render_to_response('apply.html', {'form': form, 'edit':True},
+ return render_to_response('apply.html', {'form': form, 'edit':True, 'applier': applier},
context_instance=RequestContext(request))
else:
dictionary = model_to_dict(route_edit, fields=[], exclude=[])
+ #form = RouteForm(instance=route_edit)
form = RouteForm(dictionary)
- return render_to_response('apply.html', {'form': form, 'edit':True},
+ return render_to_response('apply.html', {'form': form, 'edit':True, 'applier': applier},
context_instance=RequestContext(request))
@login_required
def delete_route(request, route_slug):
if request.is_ajax():
route = get_object_or_404(Route, name=route_slug)
- if route.applier == request.user:
+ applier_peer = route.applier.get_profile().peer
+ requester_peer = request.user.get_profile().peer
+ if applier_peer == requester_peer:
route.deactivate()
route.commit_delete()
- return HttpResponseRedirect(urlresolvers.reverse("user-routes"))
+ html = "<html><body>Done</body></html>"
+ return HttpResponse(html)
+ else:
+ return HttpResponseRedirect(reverse("group-routes"))
+
+@login_required
+def user_profile(request):
+ user = request.user
+ peer = request.user.get_profile().peer
+
+ return render_to_response('profile.html', {'user': user, 'peer':peer},
+ context_instance=RequestContext(request))
+
+
+def user_login(request):
+ try:
+ error_username = None
+ error_orgname = None
+ username = request.META['HTTP_EPPN']
+ if not username:
+ error_username = True
+ firstname = request.META['HTTP_SHIB_INETORGPERSON_GIVENNAME']
+ lastname = request.META['HTTP_SHIB_PERSON_SURNAME']
+ mail = request.META['HTTP_SHIB_INETORGPERSON_MAIL']
+ organization = request.META['HTTP_SHIB_HOMEORGANIZATION']
+ if not organization:
+ error_orgname = True
+
+ if error_orgname or error_username:
+ error = "Your idP should release the HTTP_EPPN, HTTP_SHIB_HOMEORGANIZATION attributes towards this service"
+ return render_to_response('error.html', {'error': error,},
+ context_instance=RequestContext(request))
+ user = authenticate(username=username, firstname=firstname, lastname=lastname, mail=mail, organization=organization, affiliation=None)
+ if user is not None:
+ login(request, user)
+ return HttpResponseRedirect(reverse("group-routes"))
+ # Redirect to a success page.
+ # Return a 'disabled account' error message
+ else:
+ html = "<html><body>Invalid User</body></html>"
+ return HttpResponse(html)
+ except Exception as e:
+ html = "<html><body>Invalid Login Procedure %s </body></html>" %e
+ return HttpResponse(html)
+ # Return an 'invalid login' error message.
+# return HttpResponseRedirect(reverse("user-routes"))
+
+@login_required
+def add_rate_limit(request):
+ if request.method == "GET":
+ form = ThenPlainForm()
+ return render_to_response('add_rate_limit.html', {'form': form,},
+ context_instance=RequestContext(request))
+
+ else:
+ form = ThenPlainForm(request.POST)
+ if form.is_valid():
+ then=form.save(commit=False)
+ then.action_value = "%sk"%then.action_value
+ then.save()
+ response_data = {}
+ response_data['pk'] = "%s" %then.pk
+ response_data['value'] = "%s:%s" %(then.action, then.action_value)
+ return HttpResponse(simplejson.dumps(response_data), mimetype='application/json')
+ else:
+ return render_to_response('add_rate_limit.html', {'form': form,},
+ context_instance=RequestContext(request))
+
+@login_required
+def add_port(request):
+ if request.method == "GET":
+ form = PortPlainForm()
+ return render_to_response('add_port.html', {'form': form,},
+ context_instance=RequestContext(request))
+
+ else:
+ form = PortPlainForm(request.POST)
+ if form.is_valid():
+ port=form.save()
+ response_data = {}
+ response_data['value'] = "%s" %port.pk
+ response_data['text'] = "%s" %port.port
+ return HttpResponse(simplejson.dumps(response_data), mimetype='application/json')
+ else:
+ return render_to_response('add_port.html', {'form': form,},
+ context_instance=RequestContext(request))
+
+@login_required
+def user_logout(request):
+ return HttpResponseRedirect(settings.SHIB_LOGOUT_URL)
+
+
+def load_jscript(request, file):
+ return render_to_response('%s.js' % file, context_instance=RequestContext(request), mimetype="text/javascript")
--- /dev/null
+from django.contrib.auth.models import User
+from django.core.validators import MaxLengthValidator
+
+NEW_USERNAME_LENGTH = 255
+
+def monkey_patch_username():
+ username = User._meta.get_field("username")
+ username.max_length = NEW_USERNAME_LENGTH
+ for v in username.validators:
+ if isinstance(v, MaxLengthValidator):
+ v.limit_value = NEW_USERNAME_LENGTH
+
+monkey_patch_username()
urlpatterns = patterns('flowspy.poller.views',
('^$', 'main'),
- ('^a/message/existing$', 'message_existing'),
- ('^a/message/new$', 'message_new'),
- ('^a/message/updates$', 'message_updates'))
+ url('^a/message/existing$', 'message_existing', name='fetch-existing'),
+ url('^a/message/new$', 'message_new',name='fetch-new'),
+ url('^a/message/updates$', 'message_updates', name='fetch-updates'))
urlpatterns += patterns('',
(r'^static/(?P<path>.*)', 'django.views.static.serve',\
from gevent.event import Event
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
+from django.http import HttpResponseRedirect
+from django.core.urlresolvers import reverse
+
from flowspy.utils import beanstalkc
cache_size = 200
def __init__(self):
+ self.user = None
self.user_cache = {}
self.user_cursor = {}
self.cache = []
if self.user_cache:
request.session['cursor'] = self.user_cache[-1]['id']
return render_to_response('poll.html', {'messages': self.user_cache})
-
+
@csrf_exempt
def message_existing(self, request):
-
- try:
- user = request.user.username
- except:
- user = None
- self.new_message_user_event[user] = Event()
- try:
- if self.user_cache[user]:
- self.user_cursor[user] = self.user_cache[user][-1]['id']
- except:
- self.user_cache[user] = []
- self.user_cursor[user] = ''
- return json_response({'messages': self.user_cache[user]})
+ if request.is_ajax():
+ try:
+ user = request.user.get_profile().peer.domain_name
+ except:
+ user = None
+ return False
+ try:
+ assert(self.new_message_user_event[user])
+ except:
+ self.new_message_user_event[user] = Event()
+ # self.new_message_user_event[user] = Event()
+ try:
+ if self.user_cache[user]:
+ self.user_cursor[user] = self.user_cache[user][-1]['id']
+ except:
+ self.user_cache[user] = []
+ self.user_cursor[user] = ''
+ return json_response({'messages': self.user_cache[user]})
+ return HttpResponseRedirect(reverse('login'))
@csrf_exempt
def message_new(self, mesg=None):
@csrf_exempt
def message_updates(self, request):
- cursor = {}
- try:
- user = request.user.username
- except:
- user = None
-
- cursor[user] = self.user_cursor[user]
-
- try:
- if not isinstance(self.user_cache[user], list):
+ if request.is_ajax():
+ cursor = {}
+ try:
+ # user = request.user.username
+ user = request.user.get_profile().peer.domain_name
+ except:
+ user = None
+ return False
+ cursor[user] = self.user_cursor[user]
+
+ try:
+ if not isinstance(self.user_cache[user], list):
+ self.user_cache[user] = []
+ except:
self.user_cache[user] = []
- except:
- self.user_cache[user] = []
- if not self.user_cache[user] or cursor[user] == self.user_cache[user][-1]['id']:
- self.new_message_user_event[user].wait()
-# self.new_message_event.wait()
-# assert cursor[user] != self.user_cache[user][-1]['id'], cursor[user]
- try:
- for index, m in enumerate(self.user_cache[user]):
- if m['id'] == cursor[user]:
- return json_response({'messages': self.user_cache[user][index + 1:]})
- return json_response({'messages': self.user_cache[user]})
- finally:
- if self.user_cache[user]:
- self.user_cursor[user] = self.user_cache[user][-1]['id']
-# else:
-# request.session.pop('cursor', None)
+ if not self.user_cache[user] or cursor[user] == self.user_cache[user][-1]['id']:
+ self.new_message_user_event[user].wait()
+ # self.new_message_event.wait()
+ # assert cursor[user] != self.user_cache[user][-1]['id'], cursor[user]
+ try:
+ for index, m in enumerate(self.user_cache[user]):
+ if m['id'] == cursor[user]:
+ return json_response({'messages': self.user_cache[user][index + 1:]})
+ return json_response({'messages': self.user_cache[user]})
+ finally:
+ if self.user_cache[user]:
+ self.user_cursor[user] = self.user_cache[user][-1]['id']
+ return HttpResponseRedirect(reverse('login'))
+ # else:
+ # request.session.pop('cursor', None)
def monitor_polls(self, polls=None):
b = beanstalkc.Connection()
b.watch(settings.POLLS_TUBE)
while True:
job = b.reserve()
- print job.body
msg = json.loads(job.body)
job.bury()
self.message_new(msg)
#!/usr/bin/python
from gevent.wsgi import WSGIServer
from poller.application import application
-print 'Serving on 8000...'
-WSGIServer(('netdev.grnet.gr', 9090), application).serve_forever()
+server="localhost"
+port=8081
+print 'Serving on port %s...' % port
+WSGIServer((server,port ), application).serve_forever()
#cluster_overview_table_wrapper{
width: 100%;
}
-
+/*
+ * jQuery UI specific styling
+ */
.paging_two_button .ui-button {
float: left;
}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Everything below this line is the same as demo_table.css. This file is
+ * required for 'cleanliness' of the markup
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables features
+ */
+
.dataTables_wrapper {
position: relative;
min-height: 302px;
- float: left;
- clear: both;
_height: 302px;
- width: 100%;
- zoom: 1; /* Feeling sorry for IE */
+ clear: both;
}
.dataTables_processing {
position: absolute;
- top: 50%;
+ top: 0px;
left: 50%;
width: 250px;
- height: 30px;
margin-left: -125px;
- margin-top: -15px;
- padding: 14px 0 2px 0;
border: 1px solid #ddd;
text-align: center;
color: #999;
- font-size: 14px;
- background-color: white;
+ font-size: 11px;
+ padding: 2px 0;
}
.dataTables_length {
}
.dataTables_info {
- width: 60%;
+ width: 50%;
float: left;
}
.dataTables_paginate {
- width: 44px;
- * width: 50px;
float: right;
text-align: right;
}
-
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables display
+ */
table.display {
margin: 0 auto;
- clear: both;
width: 100%;
+ clear: both;
border-collapse: collapse;
-
-}
-
-table.display thead th {
- padding: 3px 18px 3px 10px;
- font-weight: normal;
- cursor: pointer;
- * cursor: hand;
}
table.display tfoot th {
- padding: 3px 18px 3px 10px;
- border-top: 1px solid black;
+ padding: 3px 0px 3px 10px;
font-weight: bold;
+ font-weight: normal;
}
table.display tr.heading2 td {
padding: 3px 10px;
}
-table.display td a {
- font-weight: normal;
-}
-
table.display td.center {
text-align: center;
}
-table.display tfoot th {
- padding: 3px 0px 3px 10px;
- font-weight: bold;
- font-weight: normal;
-}
-table.display tr.heading2 td {
- border-bottom: 1px solid #aaa;
-}
-
-table.display td {
- padding: 3px 10px;
-}
-table.display td.center {
- text-align: center;
-}
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables sorting
+ */
.sorting_asc {
background: url('../images/sort_asc.png') no-repeat center right;
background: url('../images/sort_desc_disabled.png') no-repeat center right;
}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables row classes
+ */
table.display tr.odd.gradeA {
- background-color: #EEEEEE;
+ background-color: #ddffdd;
}
table.display tr.even.gradeA {
- background-color: #F6F6F6;
+ background-color: #eeffee;
+}
+
+
+
+
+table.display tr.odd.gradeA {
+ background-color: #ddffdd;
+}
+
+table.display tr.even.gradeA {
+ background-color: #eeffee;
}
table.display tr.odd.gradeC {
background-color: white;
}
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Misc
+ */
.dataTables_scroll {
clear: both;
}
-.dataTables_scrollBody {
- *margin-top: -1px;
-}
-
.top, .bottom {
padding: 15px;
background-color: #F5F5F5;
width: 40%;
}
-.paging_full_numbers {
- width: 400px;
- height: 22px;
- line-height: 22px;
-}
-
.paging_full_numbers span.paginate_button,
.paging_full_numbers span.paginate_active {
border: 1px solid #aaa;
background-color: #9FAFD1;
}
+
+/*
+ * Sorting classes for columns
+ */
+/* For the standard odd/even */
tr.odd td.sorting_1 {
background-color: #D3D6FF;
}
background-color: #F9F9FF;
}
+
+/* For the Conditional-CSS grading rows */
+/*
+ Colour calculations (based off the main row colours)
+ Level 1:
+ dd > c4
+ ee > d5
+ Level 2:
+ dd > d1
+ ee > e2
+ */
tr.odd.gradeA td.sorting_1 {
- background-color: #E1E1E1;
+ background-color: #c4ffc4;
}
tr.odd.gradeA td.sorting_2 {
- background-color: #E8E8E8;
+ background-color: #d1ffd1;
}
tr.odd.gradeA td.sorting_3 {
- background-color: #E8E8E8;
+ background-color: #d1ffd1;
}
tr.even.gradeA td.sorting_1 {
- background-color: #EAEAEA;
+ background-color: #d5ffd5;
}
tr.even.gradeA td.sorting_2 {
- background-color: #F0F0F0;
+ background-color: #e2ffe2;
}
tr.even.gradeA td.sorting_3 {
- background-color: #F0F0F0;
+ background-color: #e2ffe2;
}
tr.odd.gradeC td.sorting_1 {
background-color: #e2e2e2;
}
+
+/*
+ * Row highlighting example
+ */
.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
background-color: #ECFFB3;
}
background-color: #E6FF99;
}
-.ex_highlight_row #example tr.even:hover {
- background-color: #ECFFB3;
-}
-
-.ex_highlight_row #example tr.even:hover td.sorting_1 {
- background-color: #DDFF75;
-}
-
-.ex_highlight_row #example tr.even:hover td.sorting_2 {
- background-color: #E7FF9E;
-}
-
-.ex_highlight_row #example tr.even:hover td.sorting_3 {
- background-color: #E2FF89;
-}
-
-.ex_highlight_row #example tr.odd:hover {
- background-color: #E6FF99;
-}
-
-.ex_highlight_row #example tr.odd:hover td.sorting_1 {
- background-color: #D6FF5C;
-}
-
-.ex_highlight_row #example tr.odd:hover td.sorting_2 {
- background-color: #E0FF84;
-}
-
-.ex_highlight_row #example tr.odd:hover td.sorting_3 {
- background-color: #DBFF70;
-}
-
-table.KeyTable td {
- border: 3px solid transparent;
-}
-
-table.KeyTable td.focus {
- border: 3px solid #3366FF;
-}
-
-table.display tr.gradeA {
- background-color: #eeffee;
-}
-
-table.display tr.gradeC {
- background-color: #ddddff;
-}
-
-table.display tr.gradeX {
- background-color: #ffdddd;
-}
-
-table.display tr.gradeU {
- background-color: #ddd;
-}
-
div.box {
height: 100px;
padding: 10px;
--- /dev/null
+<form id="add_port_form" method="POST">
+ {% csrf_token %}
+<table>
+<tr><th>Port</th><td>{{ form.port }}<span class="error" id='rl_error'>{{ form.port.errors|join:", " }}</span></td></tr>
+</table>
+</form>
\ No newline at end of file
--- /dev/null
+<form id="add_rl_form" method="POST">
+ {% csrf_token %}
+<table>
+<input type="hidden" id="id_action" name="action" value="rate-limit"/>
+<tr><th>Value</th><td>{{ form.action_value }}Kbps<span class="error" id='rl_error'>{{ form.action_value.errors|join:", " }}</span></td></tr>
+<tr class="help"><td></td><td>Value should be >50Kbps</td></tr>
+</table>
+</form>
\ No newline at end of file
{% extends "base.html" %}
{% load i18n %}
-
+
{% block title %}
{% if edit %}
{% trans "Edit Route" %} {{form.data.name}}
{% trans "Create route" %}
{% endif %}
{% endblock %}
-
+{% block extrahead %}
+<script>
+ $(document).ready( function(){
+
+ $("#id_sourceport").css('width', '100px').attr('size', '5');
+ $("#id_port").css('width', '100px').attr('size', '5');
+ $("#id_destinationport").css('width', '100px').attr('size', '5');
+ $('#id_then').attr("multiple", "");
+ $('#then_diag').dialog({
+ height: 220,
+ width: 340,
+ modal: true,
+ autoOpen: false,
+ buttons: {
+ 'Add': function() {
+ console.log($("#add_rl_form").serialize());
+ $.ajax({
+ url:"{% url add-rate-limit %}",
+ data:$("#add_rl_form").serialize(),
+ type: "POST",
+ cache: false,
+ success:function(data){
+ try {
+ value = data.pk;
+ text = data.value;
+ $('#id_then').append($("<option></option>").attr("value",value).text(text));
+ $('#then_diag').dialog('close');
+ }
+ catch (exception) {
+ $('#then_diag').html(data);
+ }
+ }
+ });
+ },
+ Cancel: function() {
+ $('#then_diag').dialog('close');
+ }
+ }
+ });
+
+ $('#port_diag').dialog({
+ height: 220,
+ width: 340,
+ modal: true,
+ autoOpen: false,
+ buttons: {
+ 'Add': function() {
+ console.log($("#add_port_form").serialize());
+ $.ajax({
+ url:"{% url add-port %}",
+ data:$("#add_port_form").serialize(),
+ type: "POST",
+ cache: false,
+ success:function(data){
+ try {
+ value = data.value;
+ text = data.text;
+ $('#id_port').append($("<option></option>").attr("value",value).text(text));
+ $('#id_destinationport').append($("<option></option>").attr("value",value).text(text));
+ $('#id_sourceport').append($("<option></option>").attr("value",value).text(text));
+ $('#port_diag').dialog('close');
+ }
+ catch (exception) {
+ $('#port_diag').html(data);
+ }
+ }
+ });
+ },
+ Cancel: function() {
+ $('#port_diag').dialog('close');
+ }
+ }
+ });
+
+
+ $("#new_then_actions").button({
+ icons: {
+ primary: "ui-icon-plusthick"
+ },
+ })
+ .click(function(){
+ $.ajax({
+ url: "{% url add-rate-limit %}",
+ cache: false,
+ success: function(data){
+ $("#then_diag").html(data);
+ }
+ });
+ $('#then_diag').dialog('open');
+ return false;
+ });
+
+
+ $(".new_port").button({
+ icons: {
+ primary: "ui-icon-plusthick"
+ },
+ })
+ .click(function(){
+ $.ajax({
+ url: "{% url add-port %}",
+ cache: false,
+ success: function(data){
+ $("#port_diag").html(data);
+ }
+ });
+ $('#port_diag').dialog('open');
+ return false;
+ });
+ });
+
+</script>
+{% endblock %}
{% block content %}
<style type="text/css">
th {
}
</style>
-
<div align="center">
{% if edit %}
<h3>{% trans "Edit route" %}: {{form.data.name}}</h3>
<legend>{% trans "Route Basic Info" %}</legend>
<table>
<tr><th>{{ form.name.label_tag }}</th><td>{{ form.name }}<span class="error">{{ form.name.errors|join:", " }}</span></td></tr>
-<tr class="help"><td></td><td>{{ form.name.help_text }}</td></tr>
+<tr class="help"><td></td><td>A unique identifier will be added as a name_suffix</td></tr>
</table>
</fieldset>
<fieldset>
<legend>{% trans "Route Match Conditions" %}</legend>
<table>
+<input type="hidden" id="id_applier" name="applier" value="{{applier}}"/>
<tr><th>{{ form.source.label_tag }}</th><td>{{ form.source }}<span class="error">{{ form.source.errors|join:", " }}</span></td></tr>
<tr class="help"><td></td><td>{{ form.source.help_text }}</td></tr>
-<tr><th>{{ form.sourceport.label_tag }}</th><td>{{ form.sourceport }}<span class="error">{{ form.sourceport.errors|join:", " }}</span></td></tr>
+<tr><th>{{ form.sourceport.label_tag }}</th><td>{{ form.sourceport }} <button class="new_port">Port</button><span class="error">{{ form.sourceport.errors|join:", " }}</span></td></tr>
<tr class="help"><td></td><td>{{ form.sourceport.help_text }}</td></tr>
<tr><th>{{ form.destination.label_tag }}</th><td>{{ form.destination }}<span class="error">{{ form.destination.errors|join:", " }}</span></td></tr>
<tr class="help"><td></td><td>{{ form.destination.help_text }}</td></tr>
-<tr><th>{{ form.destinationport.label_tag }}</th><td>{{ form.destinationport }}<span class="error">{{ form.destinationport.errors|join:", " }}</span></td></tr>
+<tr><th>{{ form.destinationport.label_tag }}</th><td>{{ form.destinationport }} <button class="new_port">Port</button><span class="error">{{ form.destinationport.errors|join:", " }}</span></td></tr>
<tr class="help"><td></td><td>{{ form.destinationport.help_text }}</td></tr>
-<tr><th>{{ form.port.label_tag }}</th><td>{{ form.port }}<span class="error">{{ form.port.errors|join:", " }}</span></td></tr>
+<tr><th>{{ form.port.label_tag }}</th><td>{{ form.port }} <button class="new_port">Port</button><span class="error">{{ form.port.errors|join:", " }}</span></td></tr>
<tr class="help"><td></td><td>{{ form.port.help_text }}</td></tr>
</table>
</fieldset>
<fieldset>
<legend>{% trans "Route Actions" %}</legend>
<table>
-<tr><th>{{ form.then.label_tag }}</th><td>{{ form.then }}<span class="error">{{ form.then.errors|join:", " }}</span></td></tr>
-<tr class="help"><td></td><td>{{ form.then.help_text }}</td></tr>
+<tr><th>{{ form.then.label_tag }}</th><td>{{ form.then }} <button id="new_then_actions">Rate-limit</button><span class="error">{{ form.then.errors|join:", " }}</span></td></tr>
</table>
</fieldset>
<fieldset>
</form>
</div>
+<div id="then_diag" title="Add new rate-limit value">
+</div>
+
+<div id="port_diag" title="Add new port">
+</div>
+
{% endblock %}
<link rel="stylesheet" type="text/css" href="/static/css/base.css">
<link rel="stylesheet" type="text/css" href="/static/css/smoothness/jquery-ui-1.8.13.custom.css">
<script type="text/javascript" src="/static/js/jquery-ui-1.8.12.custom.min.js"></script>
-<script type="text/javascript" src="/static/js/poller.js"></script>
+<script type="text/javascript" src="{% url load-js 'poller' %}"></script>
<script type="text/javascript">
function setlang(lang){
<body>
<div id="main">
<div id="header">
- <a class="grnetlogo" href="/">
+ <a class="grnetlogo" href="{% url group-routes %}">
<img class="logoimg" src="/static/grnet_logo.png">
</a>
<div id="title">
{% if user.is_authenticated %}
<span class="topmenuuser">{% trans "Welcome" %} <strong>{{user}}</strong></span>
{% endif %}
+ {% comment %}
<span {% if user.is_authenticated %}class="topmenuaction"{% else %}class="topmenuuser"{% endif %} >
<form action="{% url django.views.i18n.set_language %}" method="post" style="display:inline;" id="langform">
{% csrf_token %}
{% endfor %}
</form>
</span>
+ {% endcomment %}
{% if user.is_authenticated %}
- <span class="topmenuaction"><a href="">{% trans "My profile" %}</a></span>
-{% if user.is_superuser %}
+ <span class="topmenuaction"><a href="{% url user-profile %}">{% trans "My profile" %}</a></span>
+ {% if user.is_superuser %}
<span class="topmenuaction"><a href="{% url admin:index %}">{% trans "Admin" %}</a></span>
-{% endif %}
+ {% endif %}
<span class="topmenuaction"><a href="{% url logout %}">{% trans "Logout" %}</a></span>
{% else %}
<span class="topmenuaction"><a href="{% url login %}">{% trans "Login" %}</a></span>
</div>
<div id="content">
{% block brcrmb_container %}
- <div class="info_content_title">{% if user.is_authenticated %}<a href="/">{% trans "My routes" %}</a>{% endif %}
+ <div class="info_content_title">{% if user.is_authenticated %}<a href="{% url group-routes %}">{% trans "My routes" %}</a>{% endif %}
{% block breadcrumbs %}{% endblock %}
</div>
--- /dev/null
+{% load i18n %}
+<html>
+<head>
+<title>Error</title>
+<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+<META HTTP-EQUIV="Expires" CONTENT="-1">
+<script src="/static/js/jquery.min.js" type="text/javascript"></script>
+<link rel="stylesheet" type="text/css" href="/static/css/base.css">
+<link rel="stylesheet" type="text/css" href="/static/css/smoothness/jquery-ui-1.8.13.custom.css">
+<script type="text/javascript" src="/static/js/jquery-ui-1.8.12.custom.min.js"></script>
+
+</head>
+
+
+
+<body>
+ <div id="main">
+ <div id="header">
+ <a class="grnetlogo" href="{% url group-routes %}">
+ <img class="logoimg" src="/static/grnet_logo.png">
+ </a>
+ <div id="title">
+ <a href="/">Firewall on Demand</a>
+ </div>
+ <div class="loginform">
+ <div id="formcontent">
+ {% if user.is_authenticated %}
+ <span class="topmenuuser">{% trans "Welcome" %} <strong>{{user}}</strong></span>
+ {% endif %}
+ <span {% if user.is_authenticated %}class="topmenuaction"{% else %}class="topmenuuser"{% endif %} >
+ <form action="{% url django.views.i18n.set_language %}" method="post" style="display:inline;" id="langform">
+ {% csrf_token %}
+ <input name="next" type="hidden" value="{{ next }}" />
+ <input id="langsel" name="language" type="hidden" value="" />
+ {% for lang in LANGUAGES %}<a class="select_lang" href="#" onclick="setlang('{{ lang.0 }}'); return false;" title="{{lang.1}}">{% ifnotequal LANGUAGE_CODE lang.0 %}<font style="font-weight:normal;">{% endifnotequal %}{% trans lang.1 %}{% ifnotequal LANGUAGE_CODE lang.0 %}</font>{% endifnotequal %}</a>{% if not forloop.last %} -{% endif %}
+ {% endfor %}
+ </form>
+ </span>
+ {% if user.is_authenticated %}
+ <span class="topmenuaction"><a href="{% url user-profile %}">{% trans "My profile" %}</a></span>
+{% if user.is_superuser %}
+ <span class="topmenuaction"><a href="{% url admin:index %}">{% trans "Admin" %}</a></span>
+{% endif %}
+ <span class="topmenuaction"><a href="{% url logout %}">{% trans "Logout" %}</a></span>
+ {% else %}
+ <span class="topmenuaction"><a href="{% url login %}">{% trans "Login" %}</a></span>
+ {% endif %}
+ </div>
+
+ </div>
+ </div>
+ <div id="content">
+ {% block brcrmb_container %}
+ <div class="info_content_title">{% if user.is_authenticated %}<a href="{% url group-routes %}">{% trans "My routes" %}</a>{% endif %}
+ {% block breadcrumbs %}{% endblock %}
+ </div>
+
+ {% endblock %}
+ {% block content %}
+ A required shibboleth attribute was not released towards this service<br>
+ Required shibboleth attributes:<br>
+ <strong>HTTP_EPPN</strong><br>
+ <strong>HTTP_SHIB_HOMEORGANIZATION</strong>
+ <br><br>
+ Optional Attributes:<br>
+ <strong>HTTP_SHIB_INETORGPERSON_GIVENNAME</strong><br>
+ <strong>HTTP_SHIB_PERSON_SURNAME</strong><br>
+ <strong>HTTP_SHIB_INETORGPERSON_MAIL</strong><br>
+
+ {% endblock %}
+
+ </div>
+ <div id="footer">
+ {% if user.is_authenticated %}
+ {% trans "If you have any questions or need help, contact GRNET Helpdesk at <a href='mailto:helpdesk@grnet.gr'>helpdesk@grnet.gr</a> or 800-11-47638." %}<br />
+ {% endif %}
+ <a href="http://www.grnet.gr">{% trans "GRNET" %} NOC</a> | <a href="/about/info/">{% trans "Info" %}</a> | <a href="/about/terms-of-service">{% trans "Service Terms" %}</a>
+ </div>
+ </div>
+</body>
+</html>
--- /dev/null
+// Copyright 2009 FriendFeed
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+$(document).ready(function() {
+ if (!window.console) window.console = {};
+ if (!window.console.log) window.console.log = function() {};
+
+ $("#messageform").live("submit", function() {
+ newMessage($(this));
+ return false;
+ });
+ $("#messageform").live("keypress", function(e) {
+ if (e.keyCode == 13) {
+ newMessage($(this));
+ return false;
+ }
+ });
+ $("#message").select();
+ updater.start();
+ updater.poll();
+});
+
+function newMessage(form) {
+ var message = form.formToDict();
+ var disabled = form.find("input[type=submit]");
+ disabled.disable();
+ $.postJSON("{% url fetch-new %}", message, function(response) {
+ updater.showMessage(response);
+ if (message.id) {
+ form.parent().remove();
+ } else {
+ form.find("input[type=text]").val("").select();
+ disabled.enable();
+ }
+ });
+}
+
+function getCookie(name) {
+ var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
+ return r ? r[1] : undefined;
+}
+
+jQuery.postJSON = function(url, args, callback) {
+ args._xsrf = getCookie("_xsrf");
+ $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
+ success: function(response) {
+ if (callback) callback(eval("(" + response + ")"));
+ }, error: function(response) {
+ console.log("ERROR:", response)
+ }});
+};
+
+jQuery.fn.formToDict = function() {
+ var fields = this.serializeArray();
+ var json = {}
+ for (var i = 0; i < fields.length; i++) {
+ json[fields[i].name] = fields[i].value;
+ }
+ if (json.next) delete json.next;
+ return json;
+};
+
+jQuery.fn.disable = function() {
+ this.enable(false);
+ return this;
+};
+
+jQuery.fn.enable = function(opt_enable) {
+ if (arguments.length && !opt_enable) {
+ this.attr("disabled", "disabled");
+ } else {
+ this.removeAttr("disabled");
+ }
+ return this;
+};
+
+var updater = {
+ errorSleepTime: 500,
+ cursor: null,
+
+ start: function() {
+ var args = {"_xsrf": getCookie("_xsrf")};
+ if (updater.cursor) args.cursor = updater.cursor;
+ $.ajax({url: "{% url fetch-existing %}", type: "POST", dataType: "text",
+ data: $.param(args), success: updater.onFetchExisting,
+ error: updater.onError});
+ },
+
+ poll: function() {
+ var args = {"_xsrf": getCookie("_xsrf")};
+ if (updater.cursor) args.cursor = updater.cursor;
+ $.ajax({url: "{% url fetch-updates %}", type: "POST", dataType: "text",
+ data: $.param(args), success: updater.onSuccess,
+ error: updater.onError});
+ },
+
+ onSuccess: function(response) {
+ try {
+ updater.newMessages(eval("(" + response + ")"));
+ } catch (e) {
+ updater.onError();
+ return;
+ }
+ updater.errorSleepTime = 500;
+ window.setTimeout(updater.poll, 0);
+ },
+
+ onFetchExisting: function(response) {
+ try {
+ updater.existingMessages(eval("(" + response + ")"));
+ } catch (e) {
+// updater.onError();
+ return;
+ }
+ },
+
+ onError: function(response) {
+ updater.errorSleepTime *= 2;
+ console.log("Poll error; sleeping for", updater.errorSleepTime, "ms");
+ window.setTimeout(updater.poll, updater.errorSleepTime);
+ },
+
+ newMessages: function(response) {
+ if (!response.messages) return;
+ updater.cursor = response.cursor;
+ var messages = response.messages;
+ updater.cursor = messages[messages.length - 1].id;
+// console.log(messages.length, "new messages, cursor:", updater.cursor);
+
+ for (var i = 0; i < messages.length; i++) {
+ updater.showMessage(messages[i]);
+ }
+ if (($('#console').dialog('isOpen')) == false){
+ blink("#consolebutton");
+ }
+ },
+
+ existingMessages: function(response) {
+ if (!response.messages) return;
+ updater.cursor = response.cursor;
+ var messages = response.messages;
+ updater.cursor = messages[messages.length - 1].id;
+ for (var i = 0; i < messages.length; i++) {
+ updater.showMessage(messages[i]);
+ }
+ },
+
+ showMessage: function(message) {
+ var existing = $("#m" + message.id);
+ if (existing.length > 0) return;
+ var node = $(message.html);
+ node.hide();
+// $('#inbox').val($('#inbox').val()+message.text);
+ $("#inbox").append(node);
+ node.slideDown();
+ }
+};
+
+function blink(selector){
+ $(selector).animate({ color: "red" }, 500, function(){
+ $(this).animate({ color: "#555555" }, 500, function(){
+ blink(this);
+ });
+ });
+}
+
{% extends "base.html" %}
{% load i18n %}
-{% block extrahead %}
- <script>
-$(document).ready(function () {
- $('#accordion').accordion({
- active: false,
- collapsible: true,
- autoHeight: false,
- create: function () {
-// load password change form
- $('#pass_change_placeholder').load("{% url pass_change %}");
-// load ssh keys manager
- $('#manage_sshkeys_placeholder').load("{% url user-keys %}");
-// change user mail
- $('#change_email_placeholder').load("{% url mail-change %}");
-// change user full name
- $('#change_name_placeholder').load("{% url name-change %}");
-
- }
- });
-});
- </script>
-
-{% endblock %}
{% block title %}{% trans "My profile" %}{% endblock %}
{% block content %}
<h3>{% trans "My profile" %}</h3>
-<div id="accordion">
- <h3><a href="#" style="color: #4183C4;">{% trans "Change Name" %}</a></h3>
- <div id="change_name_placeholder"></div>
- <h3><a href="#" style="color: #4183C4;">{% trans "Change Password" %}</a></h3>
- <div id="pass_change_placeholder"></div>
- <h3><a href="#" style="color: #4183C4;">{% trans "Change Email" %}</a></h3>
- <div id="change_email_placeholder"></div>
- <h3><a href="#" style="color: #4183C4;">{% trans "Manage SSH Keys" %}</a></h3>
- <div id="manage_sshkeys_placeholder"></div>
+<div id="profile">
+ My data:<br>
+ <strong>First name:</strong> {{user.first_name}} <br>
+ <strong>Last name:</strong> {{user.last_name}} <br>
+ <strong>Email:</strong> {{user.email}}<br>
+ <strong>Organization:</strong> {{peer}} <br>
+ <strong>Admin Networks:</strong> <br>
+ {% for network in peer.networks.all %}
+ {{network}}<br>
+ {% endfor %}
+
</div>
'Delete': function() {
route = $('#route_to_delete').text();
route_url_id = '#del_route_'+route;
- console.log(route_url_id);
url = $(route_url_id).attr('href');
- console.log(route, url);
$.ajax({
url: url ,
cache: false,
$('#dialog').dialog('close');
}
});
-// $('#dialog').dialog('close');
},
Cancel: function() {
$('#dialog').dialog('close');
});
$('#console').dialog({
height: 250,
- width: 500,
+ width: 800,
modal: true,
autoOpen: false
});
<th style="text-align: center;">{% trans "Applier" %}</th>
<th style="text-align: center;">{% trans "Expires" %}</th>
<th style="text-align: center;">{% trans "Response" %}</th>
- <th style="text-align: center; width:120px;">{% trans "Actions" %}</th>
+ <th style="text-align: center; width:140px;">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for route in routes %}
-<tr {% if route.is_online %} class="GradeA" {% else %} class="GradeX" {% endif %}>
+<tr {% ifequal route.status 'ACTIVE' %} class="GradeA" {% else %} class="GradeX" {% endifequal %}>
<td>{{ route.name }}</td>
<td>{{ route.get_match|safe|escape }}</td>
<td style="text-align: center;">{{route.get_then|safe|escape}}</td>
- <td style="text-align: center;">{% if route.is_online %}Online{% else %}Offline{% endif %}</td>
+ <td style="text-align: center;">{{route.status}}</td>
{% comment %}<td style="text-align: center;">{{ route.response }}</td>{% endcomment %}
<td style="text-align: center;">{{ route.applier }}</td>
<td style="text-align: center;">{{ route.expires }}</td>
<td style="text-align: center;">{{ route.response }}</td>
<td style="text-align: center;">
- {% if route.is_active %}
+ {% ifequal route.status 'ACTIVE' %}
<a href="{% url edit-route route.name %}" class="edit_button" id="edit_button_{{route.pk}}">Edit</a>
<button class="del_button" id="{{route.name}}" onclick="javascript:delete_route(this.id)">Del</button>
<a href="{% url delete-route route.name %}" style="display:none" id="del_route_{{route.name}}"></a>
{% else %}
+ {% ifequal route.status 'INACTIVE' %}
+ <a href="{% url edit-route route.name %}" class="edit_button" id="edit_button_{{route.pk}}">Reactivate</a>
+ {% else %}
-
- {% endif %}</td>
+ {% endifequal %}
+ {% endifequal %}</td>
</tr>
{% endfor %}
urlpatterns = patterns('',
# Example:
- # (r'^flowspy/', include('flowspy.foo.urls')),
- (r'^poll/', include('flowspy.poller.urls')),
- url(r'^/?$', 'flowspy.flowspec.views.group_routes', name="group-routes"),
- url(r'^add/?$', 'flowspy.flowspec.views.add_route', name="add-route"),
- url(r'^edit/(?P<route_slug>\w+)/$', 'flowspy.flowspec.views.edit_route', name="edit-route"),
- url(r'^delete/(?P<route_slug>\w+)/$', 'flowspy.flowspec.views.delete_route', name="delete-route"),
- url(r'^user/login/?', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name="login"),
- url(r'^user/logout/?', 'django.contrib.auth.views.logout', {'next_page': '/'}, name="logout"),
- (r'^setlang/?$', 'django.views.i18n.set_language'),
+ # (r'^fod/flowspy/', include('flowspy.foo.urls')),
+ (r'^fod/poll/', include('flowspy.poller.urls')),
+# url(r'^fod/?$', 'flowspy.flowspec.views.user_routes', name="user-routes"),
+ url(r'^fod/?$', 'flowspy.flowspec.views.group_routes', name="group-routes"),
+ url(r'^fod/profile/?$', 'flowspy.flowspec.views.user_profile', name="user-profile"),
+ url(r'^fod/add/?$', 'flowspy.flowspec.views.add_route', name="add-route"),
+ url(r'^fod/addrl/?$', 'flowspy.flowspec.views.add_rate_limit', name="add-rate-limit"),
+ url(r'^fod/addport/?$', 'flowspy.flowspec.views.add_port', name="add-port"),
+ url(r'^fod/edit/(?P<route_slug>\w+)/$', 'flowspy.flowspec.views.edit_route', name="edit-route"),
+ url(r'^fod/delete/(?P<route_slug>\w+)/$', 'flowspy.flowspec.views.delete_route', name="delete-route"),
+ url(r'^fod/login/?', 'flowspy.flowspec.views.user_login', name="login"),
+ url(r'^fod/logout/?', 'flowspy.flowspec.views.user_logout', name="logout"),
+ (r'^fod/setlang/?$', 'django.views.i18n.set_language'),
# Uncomment the admin/doc line below to enable admin documentation:
- (r'^admin/doc/', include('django.contrib.admindocs.urls')),
-
+ (r'^fod/admin/doc/', include('django.contrib.admindocs.urls')),
+ url(r'^fod/load_js/(?P<file>[\w\s\d_-]+)/$', 'flowspy.flowspec.views.load_jscript', name="load-js"),
# Uncomment the next line to enable the admin:
- (r'^admin/', include(admin.site.urls)),
+ (r'^fod/admin/', include(admin.site.urls)),
)
if settings.DEBUG:
urlpatterns += patterns('',
- (r'^static/(?P<path>.*)', 'django.views.static.serve',\
+ (r'^fod/static/(?P<path>.*)', 'django.views.static.serve',\
{'document_root': settings.STATIC_URL}),
)
\ No newline at end of file
--- /dev/null
+from django.http import HttpResponseRedirect
+from django.core.urlresolvers import reverse
+
+
+def shib_required(f):
+ def wrap(request, *args, **kwargs):
+ if 'HTTP_SHIB_SESSION_ID' not in request.META or not request.META['HTTP_SHIB_SESSION_ID']:
+ return HttpResponseRedirect(reverse('login'))
+ return f(request, *args, **kwargs)
+
+ wrap.__doc__=f.__doc__
+ wrap.__name__=f.__name__
+ return wrap
--- /dev/null
+import string
+import random
+
+def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
+ return ''.join(random.choice(chars) for x in range(size))