Commit 101d86ee authored by Leonidas Poulopoulos's avatar Leonidas Poulopoulos
Browse files

Aligned branch internationalization with latest changes in master

parents be9ee8b3 cc0c4fcf
===========
0.8.7 RELEASE
Minor enhancements
Enhancements:
- Merged all mail txt files into one
- Added all routes in form cleaning (initially, EXPIRED, ADMININACTIVE and ERROR were excluded)
===========
0.8.6 RELEASE
Minor UI enhancements/Bug fix
Fixes:
- Fixed issue where rules in ERROR state would cause check_sync to check them
Enhancements:
- Added small dots to ongoing response field to indicate activity
===========
0.8.5 RELEASE
Feature enhancement release/Minor UI fixes/Cleanup
Fixes:
- Changed javascript order to prevent unformated content in datatables
- Un-needed files cleanup
- Error template is now based on base.html template
Enhancements:
- Administrator privileges apply on UI as well
- Enhanced application security
===========
0.8.4 RELEASE
Vulnerability prevention/bug fixes release
Fixes:
- Fixed a bug where the shib auth backend erased non-shibboleth users info
- Added an authsource variable to prevent authentication backend overlapping
- Added exception handling for non-Shibboleth users that do not belong to a peer
===========
0.8.3 RELEASE
Feature enhancement release
......
......@@ -73,7 +73,19 @@ In settings.py set the following according to your configuration:
* PRIMARY_WHOIS
* ALTERNATE_WHOIS
4.2 Installation
4.2 Branding
4.2.1 Logos
Inside the static folder you will find two empty png files: logo.dist.png (172x80) and shib_login.dist.png (98x80).
Edit those two with your favourite image processing software and save them as logo.png and shib_login.png under the same folder. Image sizes are optimized to operate without any
other code changes. In case you want to incorporate images of different sizes you have to fine tune css and/or html as well.
4.2.2 Footer
Under the templates folder (templates), you can alter the footer.html file to include your own footer messages, badges, etc.
4.3 Installation
* Run:
./manage.py syncdb
......
......@@ -10,6 +10,9 @@ class shibauthBackend:
firstname = kwargs.get('firstname')
lastname = kwargs.get('lastname')
mail = kwargs.get('mail')
authsource = kwargs.get('authsource')
if authsource != 'shibboleth':
return None
try:
user = self._auth_user(username, firstname, lastname, mail)
except:
......@@ -22,10 +25,6 @@ class shibauthBackend:
try:
user = User.objects.get(username__exact=username)
user.email = mail
user.first_name = firstname
user.last_name = lastname
user.save()
# The user did not exist. Create one with no privileges
except:
user = User.objects.create_user(username, mail, None)
......
......@@ -4,6 +4,7 @@ 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 flowspy.peers.models import *
from ipaddr import *
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
......@@ -25,7 +26,14 @@ class RouteForm(forms.ModelForm):
class Meta:
model = Route
def clean_applier(self):
applier = self.cleaned_data['applier']
if applier:
return self.cleaned_data["applier"]
else:
raise forms.ValidationError('This field is required.')
def clean_source(self):
user = User.objects.get(pk=self.data['applier'])
peer = user.get_profile().peer
......@@ -106,8 +114,15 @@ class RouteForm(forms.ModelForm):
destinationports = self.cleaned_data.get('destinationport', None)
protocols = self.cleaned_data.get('protocol', None)
user = self.cleaned_data.get('applier', None)
try:
issuperuser = self.data['issuperuser']
su = User.objects.get(username=issuperuser)
except:
issuperuser = None
peer = user.get_profile().peer
networks = peer.networks.all()
if issuperuser:
networks = PeerRange.objects.filter(peer__in=Peer.objects.all()).distinct()
mynetwork = False
route_pk_list = []
if destination:
......@@ -116,7 +131,7 @@ class RouteForm(forms.ModelForm):
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'))
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):
......@@ -129,7 +144,7 @@ class RouteForm(forms.ModelForm):
raise forms.ValidationError(_('Fill at least a Rule Match Condition'))
if not user.is_superuser and then[0].action not in settings.UI_USER_THEN_ACTIONS:
raise forms.ValidationError(_('This action "%s" is not permitted') %(then[0].action))
existing_routes = Route.objects.exclude(status='EXPIRED').exclude(status='ERROR').exclude(status='ADMININACTIVE')
existing_routes = Route.objects.all()
existing_routes = existing_routes.filter(applier__userprofile__peer=peer)
if source:
source = IPNetwork(source).compressed
......
......@@ -123,8 +123,9 @@ def check_sync(route_name=None, selected_routes = []):
routes = routes.filter(name=route_name)
for route in routes:
if route.has_expired() and (route.status != 'EXPIRED' and route.status != 'ADMININACTIVE' and route.status != 'INACTIVE'):
logger.info('Expiring route %s' %route.name)
subtask(delete).delay(route, reason="EXPIRED")
if route.status != 'ERROR':
logger.info('Expiring %s route %s' %(route.status, route.name))
subtask(delete).delay(route, reason="EXPIRED")
# elif route.has_expired() and (route.status == 'ADMININACTIVE' or route.status == 'INACTIVE'):
# route.status = 'EXPIRED'
# route.response = 'Rule Expired'
......@@ -149,8 +150,8 @@ def notify_expired():
admin_url = "https://%s%s" % \
(fqdn,
"/fod/edit/%s"%route.name)
mail_body = render_to_string("rule_expiration.txt",
{"route": route, 'expiration_days':expiration_days, 'url':admin_url})
mail_body = render_to_string("rule_action.txt",
{"route": route, 'expiration_days':expiration_days, 'action':'expires', 'url':admin_url})
days_num = ' days'
expiration_days_text = "%s %s" %('in',expiration_days)
if expiration_days == 0:
......
......@@ -64,12 +64,18 @@ def welcome(request):
@never_cache
def group_routes(request):
group_routes = []
peer = request.user.get_profile().peer
try:
peer = request.user.get_profile().peer
except UserProfile.DoesNotExist:
error = "User <strong>%s</strong> does not belong to any peer or organization. It is not possible to create new firewall rules.<br>Please contact Helpdesk to resolve this issue" % request.user.username
return render_to_response('error.html', {'error': error})
if peer:
peer_members = UserProfile.objects.filter(peer=peer)
users = [prof.user for prof in peer_members]
group_routes = Route.objects.filter(applier__in=users)
return render_to_response('user_routes.html', {'routes': group_routes},
if request.user.is_superuser:
group_routes = Route.objects.all()
return render_to_response('user_routes.html', {'routes': group_routes},
context_instance=RequestContext(request))
......@@ -83,7 +89,7 @@ def add_route(request):
_("Insufficient rights on administrative networks. Cannot add rule. Contact your administrator"))
return HttpResponseRedirect(reverse("group-routes"))
if request.method == "GET":
form = RouteForm()
form = RouteForm(initial={'applier': applier})
if not request.user.is_superuser:
form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True)
form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False)
......@@ -91,19 +97,32 @@ def add_route(request):
context_instance=RequestContext(request))
else:
form = RouteForm(request.POST)
request_data = request.POST.copy()
if request.user.is_superuser:
request_data['issuperuser'] = request.user.username
else:
request_data['applier'] = applier
try:
del requset_data['issuperuser']
except:
pass
form = RouteForm(request_data)
if form.is_valid():
route=form.save(commit=False)
route.applier = request.user
if not request.user.is_superuser:
route.applier = request.user
route.status = "PENDING"
route.response = "Applying"
route.source = IPNetwork("%s/%s" %(IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed
route.destination = IPNetwork("%s/%s" %(IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed
route.save()
form.save_m2m()
route.commit_add()
requesters_address = request.META['HTTP_X_FORWARDED_FOR']
mail_body = render_to_string("rule_add_mail.txt",
{"route": route, "address": requesters_address})
fqdn = Site.objects.get_current().domain
admin_url = "https://%s%s" % (fqdn, "/fod/edit/%s"%route.name)
mail_body = render_to_string("rule_action.txt",
{"route": route, "address": requesters_address, "action": "creation", "url": admin_url})
user_mail = "%s" %route.applier.email
user_mail = user_mail.split(';')
send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s creation request submitted by %s" %(route.name, route.applier.username),
......@@ -113,6 +132,9 @@ def add_route(request):
logger.info(mail_body, extra=d)
return HttpResponseRedirect(reverse("group-routes"))
else:
if not request.user.is_superuser:
form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True)
form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False)
return render_to_response('apply.html', {'form': form, 'applier':applier},
context_instance=RequestContext(request))
......@@ -123,7 +145,7 @@ def edit_route(request, route_slug):
applier_peer = request.user.get_profile().peer
route_edit = get_object_or_404(Route, name=route_slug)
route_edit_applier_peer = route_edit.applier.get_profile().peer
if applier_peer != route_edit_applier_peer:
if applier_peer != route_edit_applier_peer and (not request.user.is_superuser):
messages.add_message(request, messages.WARNING,
_("Insufficient rights to edit rule %s") %(route_slug))
return HttpResponseRedirect(reverse("group-routes"))
......@@ -141,34 +163,64 @@ def edit_route(request, route_slug):
return HttpResponseRedirect(reverse("group-routes"))
route_original = deepcopy(route_edit)
if request.POST:
form = RouteForm(request.POST, instance = route_edit)
request_data = request.POST.copy()
if request.user.is_superuser:
request_data['issuperuser'] = request.user.username
else:
request_data['applier'] = applier
try:
del request_data['issuperuser']
except:
pass
form = RouteForm(request_data, instance = route_edit)
critical_changed_values = ['source', 'destination', 'sourceport', 'destinationport', 'port', 'protocol', 'then']
if form.is_valid():
changed_data = form.changed_data
route=form.save(commit=False)
route.name = route_original.name
route.applier = request.user
route.status = "PENDING"
route.source = IPNetwork("%s/%s" %(IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed
route.destination = IPNetwork("%s/%s" %(IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed
route.status = route_original.status
route.response = route_original.response
if not request.user.is_superuser:
route.applier = request.user
if bool(set(changed_data) & set(critical_changed_values)) or (not route_original.status == 'ACTIVE'):
route.status = "PENDING"
route.response = "Applying"
route.source = IPNetwork("%s/%s" %(IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed
route.destination = IPNetwork("%s/%s" %(IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed
route.save()
form.save_m2m()
route.commit_edit()
requesters_address = request.META['HTTP_X_FORWARDED_FOR']
mail_body = render_to_string("rule_edit_mail.txt",
{"route": route, "address": requesters_address})
user_mail = "%s" %route.applier.email
user_mail = user_mail.split(';')
send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s edit request submitted by %s" %(route.name, route.applier.username),
if bool(set(changed_data) & set(critical_changed_values)) or (not route_original.status == 'ACTIVE'):
form.save_m2m()
route.commit_edit()
requesters_address = request.META['HTTP_X_FORWARDED_FOR']
fqdn = Site.objects.get_current().domain
admin_url = "https://%s%s" % (fqdn, "/fod/edit/%s"%route.name)
mail_body = render_to_string("rule_action.txt",
{"route": route, "address": requesters_address, "action": "edit", "url": admin_url})
user_mail = "%s" %route.applier.email
user_mail = user_mail.split(';')
send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s edit request submitted by %s" %(route.name, route.applier.username),
mail_body, settings.SERVER_EMAIL, user_mail,
get_peer_techc_mails(route.applier))
d = { 'clientip' : requesters_address, 'user' : route.applier.username }
logger.info(mail_body, extra=d)
d = { 'clientip' : requesters_address, 'user' : route.applier.username }
logger.info(mail_body, extra=d)
return HttpResponseRedirect(reverse("group-routes"))
else:
if not request.user.is_superuser:
form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True)
form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False)
return render_to_response('apply.html', {'form': form, 'edit':True, 'applier': applier},
context_instance=RequestContext(request))
else:
if (not route_original.status == 'ACTIVE'):
route_edit.expires = datetime.date.today() + datetime.timedelta(days = settings.EXPIRATION_DAYS_OFFSET)
dictionary = model_to_dict(route_edit, fields=[], exclude=[])
#form = RouteForm(instance=route_edit)
if request.user.is_superuser:
dictionary['issuperuser'] = request.user.username
else:
try:
del dictionary['issuperuser']
except:
pass
form = RouteForm(dictionary)
if not request.user.is_superuser:
form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True)
......@@ -183,22 +235,26 @@ def delete_route(request, route_slug):
route = get_object_or_404(Route, name=route_slug)
applier_peer = route.applier.get_profile().peer
requester_peer = request.user.get_profile().peer
if applier_peer == requester_peer:
if applier_peer == requester_peer or request.user.is_superuser:
route.status = "PENDING"
route.expires = datetime.date.today()
route.applier = request.user
if not request.user.is_superuser:
route.applier = request.user
route.response = "Suspending"
route.save()
route.commit_delete()
requesters_address = request.META['HTTP_X_FORWARDED_FOR']
mail_body = render_to_string("rule_delete_mail.txt",
{"route": route, "address": requesters_address})
fqdn = Site.objects.get_current().domain
admin_url = "https://%s%s" % (fqdn, "/fod/edit/%s"%route.name)
mail_body = render_to_string("rule_action.txt",
{"route": route, "address": requesters_address, "action": "removal", "url": admin_url})
user_mail = "%s" %route.applier.email
user_mail = user_mail.split(';')
send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s removal request submitted by %s" %(route.name, route.applier.username),
mail_body, settings.SERVER_EMAIL, user_mail,
get_peer_techc_mails(route.applier))
d = { 'clientip' : requesters_address, 'user' : route.applier.username }
logger.info(mail_body, extra=d)
logger.info(mail_body, extra=d)
html = "<html><body>Done</body></html>"
return HttpResponse(html)
else:
......@@ -208,9 +264,15 @@ def delete_route(request, route_slug):
@never_cache
def user_profile(request):
user = request.user
peer = request.user.get_profile().peer
return render_to_response('profile.html', {'user': user, 'peer':peer},
try:
peer = request.user.get_profile().peer
peers = Peer.objects.filter(pk=peer.pk)
if user.is_superuser:
peers = Peer.objects.all()
except UserProfile.DoesNotExist:
error = "User <strong>%s</strong> does not belong to any peer or organization. It is not possible to create new firewall rules.<br>Please contact Helpdesk to resolve this issue" % user.username
return render_to_response('error.html', {'error': error})
return render_to_response('profile.html', {'user': user, 'peers':peers},
context_instance=RequestContext(request))
@never_cache
......@@ -251,10 +313,14 @@ def user_login(request):
context_instance=RequestContext(request))
try:
user = User.objects.get(username__exact=username)
user.email = mail
user.first_name = firstname
user.last_name = lastname
user.save()
user_exists = True
except:
user_exists = False
user = authenticate(username=username, firstname=firstname, lastname=lastname, mail=mail)
user = authenticate(username=username, firstname=firstname, lastname=lastname, mail=mail, authsource='shibboleth')
if user is not None:
try:
peer = Peer.objects.get(domain_name=organization)
......
This diff is collapsed.
......@@ -45,7 +45,7 @@ a:hover {
}
#main {
background: url("/static/background_grnet.png") repeat-x scroll 0 0 #FFFFFF;
background: url("/static/background.png") repeat-x scroll 0 0 #FFFFFF;
padding: 0;
margin: 0;
}
......
This diff is collapsed.
{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Application submitted" %}{% endblock %}
{% block content %}
<div align="center">
{% if pending %}
<h2>{% trans "Pending applications" %}</h2>
<table>
<tr><th>{% trans "Hostname" %}</th><th>{% trans "User" %}</th><th>{% trans "Memory" %}</th><th>{% trans "vCPUs" %}</th><th>{% trans "Network" %}</th><th>{% trans "Filed" %}</th></tr>
{% for app in pending %}
<tr><td><a href="{% url application-review app.pk %}">{{ app.hostname }}</a></td><td>{{ app.applicant }}</td><td>{{ app.memory }}</td><td>{{ app.vcpus }}</td><td>{{ app.network|default_if_none:"&mdash;" }}</td><td>{{ app.filed|date }}</td></tr>
{% endfor %}
</table>
{% endif %}
<h2>{% trans "Completed applications" %}</h2>
<table>
<tr><th>{% trans "Hostname" %}</th><th>{% trans "User" %}</th><th>{% trans "Memory" %}</th><th>{% trans "vCPUs" %}</th><th>{% trans "Network" %}</th><th>{% trans "Filed" %}</th></tr>
{% for app in completed %}
<tr><td><a href="{% url application-review app.pk %}">{{ app.hostname }}</a></td><td>{{ app.applicant }}</td><td>{{ app.memory }}</td><td>{{ app.vcpus }}</td><td>{{ app.network|default_if_none:"&mdash;" }}</td><td>{{ app.filed|date }}</td></tr>
{% endfor %}
</table>
</div>
{% endblock %}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment