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)
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-24 11:23+0200\n"
"POT-Creation-Date: 2012-05-03 11:07+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Leonidas Poulopoulos <leopoul@grnet.gr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -31,28 +31,28 @@ msgstr "Αγγλικά"
msgid "%sUser account activated"
msgstr "%s Ενεργοποιήθηκε ο λογαριασμός του χρήστη"
#: flowspec/forms.py:52 flowspec/forms.py:81
#: flowspec/forms.py:60 flowspec/forms.py:89
msgid "Invalid network address format"
msgstr "Λανθασμένη μορφή διεύθυνσης δικυου στο πεδίο Πηγή"
#: flowspec/forms.py:54
#: flowspec/forms.py:62
msgid "Private addresses not allowed"
msgstr "Δεν επιτρέπονται οι private διευθύνσεις"
#: flowspec/forms.py:56 flowspec/forms.py:85
#: flowspec/forms.py:64 flowspec/forms.py:93
msgid "You have no authority on this subnet"
msgstr "Δεν έχετε δικαιώματα σε αυτό το υποδίκτυο"
#: flowspec/forms.py:77
#: flowspec/forms.py:85
#, python-format
msgid "Currently no prefix lengths < %s are allowed"
msgstr "Προς το παρόν δεν επιτρέπονται υποδίκτυα <%s"
#: flowspec/forms.py:99
#: flowspec/forms.py:107
msgid "Errors in form. Please review and fix them"
msgstr "Σφάλματα στη φόρμα. Παρακαλώ διορθώστε τα"
#: flowspec/forms.py:119
#: flowspec/forms.py:134
msgid ""
"Destination address/network should belong to your administrative address "
"space. Check My Profile to review your networks"
......@@ -60,145 +60,155 @@ msgstr ""
"Η διεύθυνση προορισμού πρέπει να ανήκει στα διαχειριστικά σας δίκτυα. "
"Επισκεφθείτε 'Το Προφίλ μου' για την προβολή των διαχειριστικών σας δικτύων"
#: flowspec/forms.py:121
#: flowspec/forms.py:136
msgid ""
"Cannot create rule for source ports and ports at the same time. Select "
"either ports or source ports"
msgstr "Δεν μπορεί να δημιουργηθεί φίλτρο για source ports και ports ταυτόχρονα. Επιλέξτε είτε ports είτε source ports"
msgstr ""
"Δεν μπορεί να δημιουργηθεί φίλτρο για source ports και ports ταυτόχρονα. "
"Επιλέξτε είτε ports είτε source ports"
#: flowspec/forms.py:123
#: flowspec/forms.py:138
msgid ""
"Cannot create rule for destination ports and ports at the same time. Select "
"either ports or destination ports"
msgstr "Δεν μπορεί να δημιουργηθεί φίλτρο για destination ports και ports ταυτόχρονα. Επιλέξτε είτε ports είτε destination ports"
msgstr ""
"Δεν μπορεί να δημιουργηθεί φίλτρο για destination ports και ports "
"ταυτόχρονα. Επιλέξτε είτε ports είτε destination ports"
#: flowspec/forms.py:125
#: flowspec/forms.py:140
msgid ""
"Once source port is matched, source has to be filled as well. Either "
"deselect source port or fill source address"
msgstr "Εφόσον έχετε επιλέξει source port, το πεδίο source πρέπει να συμπληρωθεί. Είτε απο-επιλέξτε το πεδίο source port είτε συμπληρώστε μια διεύθυνση στο source"
msgstr ""
"Εφόσον έχετε επιλέξει source port, το πεδίο source πρέπει να συμπληρωθεί. "
"Είτε απο-επιλέξτε το πεδίο source port είτε συμπληρώστε μια διεύθυνση στο "
"source"
#: flowspec/forms.py:127
#: flowspec/forms.py:142
msgid ""
"Once destination port is matched, destination has to be filled as well. "
"Either deselect destination port or fill destination address"
msgstr "Εφόσον έχετε επιλέξει destination port, το πεδίο destination πρέπει να συμπληρωθεί. Είτε απο-επιλέξτε το πεδίο destination port είτε συμπληρώστε μια διεύθυνση στο destination"
msgstr ""
"Εφόσον έχετε επιλέξει destination port, το πεδίο destination πρέπει να "
"συμπληρωθεί. Είτε απο-επιλέξτε το πεδίο destination port είτε συμπληρώστε "
"μια διεύθυνση στο destination"
#: flowspec/forms.py:129
#: flowspec/forms.py:144
msgid "Fill at least a Rule Match Condition"
msgstr "Συμπληρώστε τουλάχιστον έναν όρο ταύτισης"
#: flowspec/forms.py:131
#: flowspec/forms.py:146
#, python-format
msgid "This action \"%s\" is not permitted"
msgstr "Η ενέργεια %s δεν επιτρέπεται"
#: flowspec/forms.py:183
#: flowspec/forms.py:198
msgid "Rate-limiting cannot be < 50kbps"
msgstr ""
#: flowspec/forms.py:186
#: flowspec/forms.py:201
msgid "Rate-limiting should be an integer < 50"
msgstr ""
#: flowspec/forms.py:188 flowspec/forms.py:212
#: flowspec/forms.py:203 flowspec/forms.py:227
msgid "Cannot be empty"
msgstr "Το πεδίο δεν μπορεί να είναι κενό"
#: flowspec/forms.py:193
#: flowspec/forms.py:208
msgid "Cannot select something other than rate-limit"
msgstr ""
#: flowspec/forms.py:210
#: flowspec/forms.py:225
msgid "Port should be an integer"
msgstr "Η port θα πρέπει να είναι ένας ακέραιος αριθμός"
#: flowspec/models.py:103 templates/user_routes.html:273
msgid "Then"
msgstr "Ενέργειες"
#: flowspec/models.py:108 templates/review.html:49
#: templates/review.html.py:107 templates/user_routes.html:271
#: flowspec/models.py:107 templates/user_routes.html:265
msgid "Name"
msgstr "Όνομα"
#: flowspec/models.py:110 flowspec/models.py:112
#: flowspec/models.py:109 flowspec/models.py:111
msgid "Network address. Use address/CIDR notation"
msgstr "Διεύθυνση δικτύου/υποδικτύου. Χρησιμοποιήστε σύνταξη διεύθυνσης/CIDR"
#: flowspec/models.py:110
#: flowspec/models.py:109
msgid "Source Address"
msgstr ""
msgstr "Διεύθυνση Πηγής"
#: flowspec/models.py:111
#: flowspec/models.py:110
msgid "Source Port"
msgstr ""
msgstr "Port Πηγής"
#: flowspec/models.py:112
#: flowspec/models.py:111
msgid "Destination Address"
msgstr ""
msgstr "Διεύθυνση Προορισμού"
#: flowspec/models.py:113
#: flowspec/models.py:112
msgid "Destination Port"
msgstr ""
msgstr "Port Προορισμού"
#: flowspec/models.py:114 templates/add_port.html:14 templates/apply.html:308
#: templates/apply.html.py:327 templates/apply.html:346
#: flowspec/models.py:113 templates/add_port.html:14 templates/apply.html:326
#: templates/apply.html.py:345 templates/apply.html:364
msgid "Port"
msgstr ""
#: flowspec/models.py:120
#: flowspec/models.py:119
msgid "Protocol"
msgstr "Πρωτόκολλο"
#: flowspec/models.py:125 templates/user_routes.html:274
#: flowspec/models.py:121 templates/user_routes.html:267
msgid "Then"
msgstr "Ενέργειες"
#: flowspec/models.py:124 templates/user_routes.html:268
msgid "Status"
msgstr "Κατάσταση"
#: flowspec/models.py:128 templates/user_routes.html:277
#: flowspec/models.py:127 templates/user_routes.html:271
msgid "Expires"
msgstr "Λήγει"
#: flowspec/models.py:129 templates/user_routes.html:278
#: flowspec/models.py:128 templates/user_routes.html:272
msgid "Response"
msgstr "Απόκριση Δικτύου"
#: flowspec/models.py:130 templates/review.html:57
#: templates/review.html.py:115
#: flowspec/models.py:129
msgid "Comments"
msgstr "Σχόλια"
#: flowspec/models.py:155
#: flowspec/models.py:154
msgid "Invalid network address format at Destination Field"
msgstr "Λανθασμένη μορφή διεύθυνσης δικυου στο πεδίο Προορισμός"
#: flowspec/models.py:161
#: flowspec/models.py:160
msgid "Invalid network address format at Source Field"
msgstr "Λανθασμένη μορφή διεύθυνσης δικυου στο πεδίο Πηγή"
#: flowspec/views.py:83
#: flowspec/views.py:89
msgid ""
"Insufficient rights on administrative networks. Cannot add rule. Contact "
"your administrator"
msgstr "Μη επαρκή δικαιώματα στα διαχειριστικά δίκτυα. Η προσθήκη φίλτρων δεν είναι εφικτή. Επικοινωνήστε με το διαχειριστή σας"
msgstr ""
"Μη επαρκή δικαιώματα στα διαχειριστικά δίκτυα. Η προσθήκη φίλτρων δεν είναι "