diff --git a/djnro/static/css/style.css b/djnro/static/css/style.css index 2ddd45ac..93dc3b3f 100644 --- a/djnro/static/css/style.css +++ b/djnro/static/css/style.css @@ -139,3 +139,7 @@ footer.auth { input[readonly].input { color: rgba(51, 51, 51, 0.5); } + +dd.preproduction { + color: rgb(230, 93, 0); +} \ No newline at end of file diff --git a/djnro/static/img/edupin-preprod.png b/djnro/static/img/edupin-preprod.png new file mode 100644 index 00000000..ee84cc26 Binary files /dev/null and b/djnro/static/img/edupin-preprod.png differ diff --git a/djnro/static/img/edupin.png b/djnro/static/img/edupin.png index 3c9c9384..6ef0ff6a 100644 Binary files a/djnro/static/img/edupin.png and b/djnro/static/img/edupin.png differ diff --git a/djnro/static/img/edupin.svg b/djnro/static/img/edupin.svg new file mode 100644 index 00000000..4e566544 --- /dev/null +++ b/djnro/static/img/edupin.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/djnro/static/js/geolocate.js b/djnro/static/js/geolocate.js index 89b3eec5..b91a1345 100644 --- a/djnro/static/js/geolocate.js +++ b/djnro/static/js/geolocate.js @@ -20,9 +20,11 @@ function initialize() { image = new google.maps.MarkerImage(pinImg, - new google.maps.Size(29, 40), + new google.maps.Size(50, 80), new google.maps.Point(0, 0), - new google.maps.Point(14, 40) + // The anchor for this image is the base of the flagpole at 18,42. + new google.maps.Point(12, 40), + new google.maps.Size(25, 40) ); var styleArray = [{ featureType : "all", diff --git a/djnro/static/js/home-page-map.js b/djnro/static/js/home-page-map.js index ada80df6..309c95bf 100644 --- a/djnro/static/js/home-page-map.js +++ b/djnro/static/js/home-page-map.js @@ -5,21 +5,29 @@ var map; var bounds; var image; + var imagePreProd; var infoWindow; var cityImg; var countryImg; var styles; var markersUrl; var pinImg; + var pinImgPreProd; function initialize() { image = new google.maps.MarkerImage(pinImg, - // This marker is 29 pixels wide by 40 pixels tall. - new google.maps.Size(29, 40), - // The origin for this image is 0,0. - new google.maps.Point(0, 0), - // The anchor for this image is the base of the flagpole at 18,42. - new google.maps.Point(14, 40)); + new google.maps.Size(50, 80), + new google.maps.Point(0, 0), + // The anchor for this image is the base of the flagpole at 18,42. + new google.maps.Point(12, 40), + new google.maps.Size(25, 40) + ); + imagePreProd = new google.maps.MarkerImage(pinImgPreProd, + new google.maps.Size(50, 80), + new google.maps.Point(0, 0), + new google.maps.Point(12, 40), + new google.maps.Size(25, 40) + ); var styleArray = [ { featureType : "all", @@ -126,12 +134,10 @@ marker, 'click', function() { - infoWindow.setContent ( "

" + infoWindow.setContent ( "

" + jsonMarker.inst + "

" - + - - "
" + + "
" + "
" + "
" + "
" @@ -169,6 +178,9 @@ + "
NAT
" + jsonMarker.NAT + " 
" + + '
Location tested
❌' : 'nro_has_tested_yes">' + jsonMarker.nro_has_tested) + + " 
" + "
Wired Number
" + jsonMarker.wired_no + " 
" @@ -203,7 +215,7 @@ 'map' : map, 'title' : title, 'address' : address, - 'icon' : pinImg, + 'icon' : markerObj.stage == 1 ? image : imagePreProd, }); return marker } @@ -350,6 +362,7 @@ image = ''; infoWindow; pinImg = mapDiv.data("pin"); + pinImgPreProd = mapDiv.data("pin-preprod"); pinGrpImg = mapDiv.data("group-pin"); addr = {}; styles = [{ diff --git a/djnro/static/js/management-map.js b/djnro/static/js/management-map.js index 4dda154b..c4081331 100644 --- a/djnro/static/js/management-map.js +++ b/djnro/static/js/management-map.js @@ -13,13 +13,12 @@ var servicesEditUrl; function initialize() { image = new google.maps.MarkerImage(pinImg, - // This marker is 29 pixels wide by 40 pixels tall. - new google.maps.Size(29, 40), - // The origin for this image is 0,0. - new google.maps.Point(0,0), - // The anchor for this image is the base of the flagpole at 18,42. - new google.maps.Point(14, 40) -); + new google.maps.Size(50, 80), + new google.maps.Point(0, 0), + // The anchor for this image is the base of the flagpole at 18,42. + new google.maps.Point(12, 40), + new google.maps.Size(25, 40) + ); var styleArray = [ { featureType: "all", diff --git a/djnro/static/js/world-map.js b/djnro/static/js/world-map.js index a24b1036..a7e781af 100644 --- a/djnro/static/js/world-map.js +++ b/djnro/static/js/world-map.js @@ -15,12 +15,12 @@ function initialize() { image = new google.maps.MarkerImage(pinImg, - // This marker is 29 pixels wide by 40 pixels tall. - new google.maps.Size(29, 40), - // The origin for this image is 0,0. - new google.maps.Point(0, 0), - // The anchor for this image is the base of the flagpole at 18,42. - new google.maps.Point(14, 40)); + new google.maps.Size(50, 80), + new google.maps.Point(0, 0), + // The anchor for this image is the base of the flagpole at 18,42. + new google.maps.Point(12, 40), + new google.maps.Size(25, 40) + ); var styleArray = [ { featureType : "all", diff --git a/djnro/templates/edumanage/monlocauthpar_edit.html b/djnro/templates/edumanage/monlocauthpar_edit.html index 47d2ab6a..df9ad8ff 100644 --- a/djnro/templates/edumanage/monlocauthpar_edit.html +++ b/djnro/templates/edumanage/monlocauthpar_edit.html @@ -6,6 +6,12 @@ {% block management_content %}

{% if edit %}{{realm.realm}} {% trans 'parameters' %} ({% trans "edit" %}){% else %}{% trans "Add Monitored Realm Parameters" %} ({{realm.realm}}){% endif %}


+ +
{% csrf_token %} {% if form.non_field_errors %} @@ -44,7 +50,7 @@

{% if edit %}{{realm.realm}} {% trans 'parameters' %} ({% trans "edit" %}){% {% endif %} {{ form.username.help_text }}

-
+
@@ -64,9 +70,14 @@

{% if edit %}{{realm.realm}} {% trans 'parameters' %} ({% trans "edit" %}){% {% block extrajs %} + + {% endblock %} diff --git a/djnro/templates/edumanage/realms_edit.html b/djnro/templates/edumanage/realms_edit.html index e6f65534..61a26610 100644 --- a/djnro/templates/edumanage/realms_edit.html +++ b/djnro/templates/edumanage/realms_edit.html @@ -7,6 +7,9 @@ {% block management_content %}

{% if edit %}{{form.instance.realm}} ({% trans "edit" %}){% else %}{% trans "Add Realm" %}{% endif %}


+ {% if messages %} {% for message in messages %} diff --git a/djnro/templates/edumanage/servers_edit.html b/djnro/templates/edumanage/servers_edit.html index 777912a5..b503fd22 100644 --- a/djnro/templates/edumanage/servers_edit.html +++ b/djnro/templates/edumanage/servers_edit.html @@ -7,6 +7,9 @@ {% block management_content %}

{% if edit %}{{form.instance.get_name}} ({% trans "edit" %}){% else %}{% trans "Add Server" %}{% endif %}


+ {% if form.non_field_errors %}
    @@ -41,11 +44,11 @@

    {% if edit %}{{form.instance.get_name}} ({% trans "edit" %}){% else %}{% tra
    - +
    {{ form.host }} {% if form.host.errors %}
    {{ form.host.errors|join_with_linebreaks }}
    - {% endif %} {{ form.host.help_text }} + {% endif %} IP address of RADIUS server
    @@ -55,7 +58,7 @@

    {% if edit %}{{form.instance.get_name}} ({% trans "edit" %}){% else %}{% tra
    {{ form.name }} {% if form.name.errors %}
    {{ form.name.errors|join_with_linebreaks }}
    - {% endif %} {{ form.name.help_text }} + {% endif %} FQDN hostname | {{ form.name.help_text }}
    @@ -97,13 +100,13 @@

    {% if edit %}{{form.instance.get_name}} ({% trans "edit" %}){% else %}{% tra
    {{ form.status_server }} {% if form.status_server.errors %}
    {{ form.status_server.errors|join_with_linebreaks }}
    - {% endif %} {{ form.status_server.help_text }} + {% endif %} {{ form.status_server.help_text }}}
    (Do not tick this if you use Windows NPS)
    - +
    {% if form.secret.errors %}
    {{ form.secret.errors|join_with_linebreaks }}
    @@ -117,7 +120,7 @@

    {% if edit %}{{form.instance.get_name}} ({% trans "edit" %}){% else %}{% tra
    {{ form.proto }} {% if form.proto.errors %}
    {{ form.proto.errors|join_with_linebreaks }}
    - {% endif %} {{ form.proto.help_text }} + {% endif %}

    @@ -136,10 +139,80 @@

    {% if edit %}{{form.instance.get_name}} ({% trans "edit" %}){% else %}{% tra {% block extrajs %} + + {% endblock %} diff --git a/djnro/templates/edumanage/service_details.html b/djnro/templates/edumanage/service_details.html index f591cd61..3c5434a3 100644 --- a/djnro/templates/edumanage/service_details.html +++ b/djnro/templates/edumanage/service_details.html @@ -190,6 +190,16 @@

    {% tolocale service LANGUAGE_CODE %}

    {{service.get_tag_display}}
    +
    + +
    + {% if service.nro_has_tested %} + ✔ {{ service.nro_has_tested }} + {% else %} + + {% endif %} +
    +
    diff --git a/djnro/templates/edumanage/services.html b/djnro/templates/edumanage/services.html index abb2bd16..ac8f27e2 100644 --- a/djnro/templates/edumanage/services.html +++ b/djnro/templates/edumanage/services.html @@ -33,7 +33,9 @@

    {% trans "Locations" %}

{% for service in services %} - + {% tolocale service LANGUAGE_CODE get="address" as service_address %} diff --git a/djnro/templates/edumanage/welcome_manage.html b/djnro/templates/edumanage/welcome_manage.html index 87b665d2..79957134 100644 --- a/djnro/templates/edumanage/welcome_manage.html +++ b/djnro/templates/edumanage/welcome_manage.html @@ -6,6 +6,12 @@

Login


+
diff --git a/djnro/templates/front/index.html b/djnro/templates/front/index.html index 18e63a07..c3890036 100644 --- a/djnro/templates/front/index.html +++ b/djnro/templates/front/index.html @@ -8,7 +8,7 @@ {% block bodyclass %}home{% endblock %} {% block content %}
-
+
diff --git a/edumanage/management/commands/clearcache.py b/edumanage/management/commands/clearcache.py new file mode 100644 index 00000000..c6739fbe --- /dev/null +++ b/edumanage/management/commands/clearcache.py @@ -0,0 +1,9 @@ +# "edumanage/management/commands/clearcache.py" + +from django.core.management.base import BaseCommand +from django.core.cache import cache + +class Command(BaseCommand): + def handle(self, *args, **kwargs): + cache.clear() + self.stdout.write('Cache is cleared\n') \ No newline at end of file diff --git a/edumanage/management/commands/servdata.py b/edumanage/management/commands/servdata.py index 3d642791..e5413901 100644 --- a/edumanage/management/commands/servdata.py +++ b/edumanage/management/commands/servdata.py @@ -74,6 +74,8 @@ def servdata(): if srv.name: srv_dict['label'] = srv.name srv_dict['secret'] = srv.secret + srv_dict['addr_type'] = srv.addr_type + srv_dict['proto'] = srv.proto root['clients'].update({srv_id: srv_dict}) servers = hosts.filter(ertype__in=ERTYPE_ROLES.IDP) @@ -92,6 +94,8 @@ def servdata(): srv_dict['label'] = srv.name srv_dict['secret'] = srv.secret srv_dict['status_server'] = bool(srv.status_server) + srv_dict['addr_type'] = srv.addr_type + srv_dict['proto'] = srv.proto root['servers'].update({srv_id: srv_dict}) if insts: diff --git a/edumanage/migrations/0100_stats_only.py b/edumanage/migrations/0100_stats_only.py new file mode 100644 index 00000000..1db76460 --- /dev/null +++ b/edumanage/migrations/0100_stats_only.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2024-12-12 07:32 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('edumanage', '0011_edb21_server_schema'), + ] + + operations = [ + migrations.AlterField( + model_name='institution', + name='ertype', + field=models.PositiveIntegerField(choices=[(0, 'None (Stats Only)'), (1, 'IdP only'), (2, 'SP only'), (3, 'IdP and SP')], db_column='type'), + ), + migrations.AlterField( + model_name='instserver', + name='ertype', + field=models.PositiveIntegerField(choices=[(0, 'None (Stats Only)'), (1, 'IdP only'), (2, 'SP only'), (3, 'IdP and SP')], db_column='type'), + ), + ] diff --git a/edumanage/migrations/0101_display_ordering.py b/edumanage/migrations/0101_display_ordering.py new file mode 100644 index 00000000..7c113085 --- /dev/null +++ b/edumanage/migrations/0101_display_ordering.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2024-12-12 07:32 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('edumanage', '0100_stats_only'), + ] + + operations = [ + migrations.AlterModelOptions( + name='contact', + options={'ordering': ['name'], 'verbose_name': 'Contact', 'verbose_name_plural': 'Contacts'}, + ), + migrations.AlterModelOptions( + name='institutioncontactpool', + options={'ordering': ['contact__name'], 'verbose_name': 'Instutution Contact (Pool)', 'verbose_name_plural': 'Instutution Contacts (Pool)'}, + ), + migrations.AlterModelOptions( + name='instrealm', + options={'ordering': ['realm'], 'verbose_name': 'Institution Realm', 'verbose_name_plural': "Institutions' Realms"}, + ), + ] diff --git a/edumanage/migrations/0102_eap_versions.py b/edumanage/migrations/0102_eap_versions.py new file mode 100644 index 00000000..fb68b52a --- /dev/null +++ b/edumanage/migrations/0102_eap_versions.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2024-12-12 07:32 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('edumanage', '0101_display_ordering'), + ] + + operations = [ + migrations.AlterField( + model_name='monlocalauthnparam', + name='eap_method', + field=models.CharField(choices=[('PEAP', 'EAP-PEAP'), ('TTLS', 'EAP-TTLS'), ('TLS', 'EAP-TLS'), ('PWD', 'EAP-PWD')], max_length=16), + ), + migrations.AlterField( + model_name='monlocalauthnparam', + name='phase2', + field=models.CharField(choices=[('PAP', 'PAP'), ('CHAP', 'CHAP'), ('MS-CHAPv2', 'MS-CHAPv2'), ('EAP-GTC', 'GTC')], max_length=16), + ), + ] diff --git a/edumanage/migrations/0103_nro_has_tested.py b/edumanage/migrations/0103_nro_has_tested.py new file mode 100644 index 00000000..4d6c12e0 --- /dev/null +++ b/edumanage/migrations/0103_nro_has_tested.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import edumanage.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('edumanage', '0102_eap_versions'), + ] + + operations = [ + migrations.AddField( + model_name='serviceloc', + name='nro_has_tested', + field=models.DateField(blank=True, null=True), + ), + ] diff --git a/edumanage/models.py b/edumanage/models.py index fab947c9..2fa87df4 100644 --- a/edumanage/models.py +++ b/edumanage/models.py @@ -3,7 +3,7 @@ from collections import namedtuple from functools import partial import uuid -from django.utils.inspect import getargspec +from inspect import signature from django.db import models from django.utils.translation import ugettext_lazy as _ from django.contrib.contenttypes.models import ContentType @@ -47,9 +47,9 @@ class MultiSelectFormField(forms.MultipleChoiceField): def __init__(self, *args, **kwargs): supercls = super(MultiSelectFormField, self) # remove TypedChoiceField extra args - supercls_init_args = getargspec(supercls.__init__)[0] - if supercls_init_args[0:0] == ['self']: - del supercls_init_args[0] + supercls_init_args = signature(supercls.__init__).parameters + if 'self' in supercls_init_args: + supercls_init_args.pop('self', None) supercls.__init__( *args, **{key: val for (key, val) in kwargs.items() @@ -262,6 +262,7 @@ def __contains__(self, item): # Last member in choices tuples maps numeric to string (EDB2) ERTYPE _ERTYPES = ( + ('NONE', 0, 'None (Stats Only)', 'None'), ('IDP', 1, 'IdP only', 'IdP'), ('SP', 2, 'SP only', 'SP'), ('IDPSP', 3, 'IdP and SP', 'IdP+SP'), @@ -269,7 +270,7 @@ def __contains__(self, item): ERTYPES = get_namedtuple_choices(*_ERTYPES) ERTYPE_ROLES = get_namedtuple_choices(*( (cat.upper(), [val for val, descr in ERTYPES if cat in descr]) - for cat in ('IdP', 'SP') + for cat in ('IdP', 'SP', 'None') )) def get_ertype_string(ertype, reverse=False): """ @@ -349,7 +350,7 @@ def all_names(**kwargs): manager.all() return ', '.join([n.name for n in names_qs]) if not lang: - return all_names() + lang = getattr(settings, 'LANGUAGE_CODE', 'en') try: return manager.get(lang=lang).name except Name_i18n.DoesNotExist: @@ -385,6 +386,7 @@ def __str__(self): class Meta: verbose_name = "Contact" verbose_name_plural = "Contacts" + ordering = ['name'] @python_2_unicode_compatible @@ -424,6 +426,7 @@ def __str__(self): class Meta: verbose_name = "Instutution Contact (Pool)" verbose_name_plural = "Instutution Contacts (Pool)" + ordering = ['contact__name'] @python_2_unicode_compatible @@ -506,6 +509,7 @@ class InstRealm(models.Model): class Meta: verbose_name = "Institution Realm" verbose_name_plural = "Institutions' Realms" + ordering = ['realm'] def __str__(self): return '%s' % self.realm @@ -655,12 +659,14 @@ class MonLocalAuthnParam(models.Model): EAPTYPES = ( ('PEAP', 'EAP-PEAP'), ('TTLS', 'EAP-TTLS'), - # ('TLS', 'EAP-TLS'), + ('TLS', 'EAP-TLS'), + ('PWD', 'EAP-PWD'), ) EAP2TYPES = ( ('PAP', 'PAP'), ('CHAP', 'CHAP'), ('MS-CHAPv2', 'MS-CHAPv2'), + ('EAP-GTC', 'GTC'), ) # MONRESPTYPES = ( # ('accept', 'Access-Accept expected' ), @@ -769,6 +775,7 @@ class ServiceLoc(models.Model): )) # only urltype = 'info' should be accepted here url = fields.GenericRelation(URL_i18n, blank=True, null=True) + nro_has_tested = models.DateField(null=True, blank=True) ts = models.DateTimeField(auto_now=True) class Meta: @@ -839,7 +846,7 @@ class Institution(models.Model): ) def __str__(self): - return "%s" % ', '.join([i.name for i in self.org_name.all()]) + return "%s" % ', '.join([i.name for i in self.org_name.filter(lang=getattr(settings, 'LANGUAGE_CODE', 'en'))]) get_name = Name_i18n.get_name_factory('org_name') @@ -904,12 +911,12 @@ class Meta: def __str__(self): return _('Institution: %(inst)s, Type: %(ertype)s') % { # but name is many-to-many from institution - 'inst': ', '.join([i.name for i in self.institution.org_name.all()]), + 'inst': ', '.join([i.name for i in self.institution.org_name.filter(lang=getattr(settings, 'LANGUAGE_CODE', 'en'))]), 'ertype': self.institution.get_ertype_display(), } def get_inst_name(self): - return ", ".join([i.name for i in self.institution.org_name.all()]) + return ", ".join([i.name for i in self.institution.org_name.filter(lang=getattr(settings, 'LANGUAGE_CODE', 'en'))]) get_inst_name.short_description = "Institution Name" diff --git a/edumanage/views.py b/edumanage/views.py index 7fcbbd47..5a52b024 100644 --- a/edumanage/views.py +++ b/edumanage/views.py @@ -35,6 +35,8 @@ from accounts.models import User from django.core.cache import cache from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.admin.models import LogEntry, CHANGE, ADDITION, DELETION +from django.contrib.contenttypes.models import ContentType from edumanage.models import ( ServiceLoc, @@ -611,7 +613,11 @@ def add_server(request, server_pk): return HttpResponseRedirect(reverse("servers")) if form.is_valid(): - form.save() + if server_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(server).id, object_id=server_pk, object_repr=str(server), action_flag=CHANGE, change_message='Changed ' + server.name) + r = form.save() + if r and not server_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(r).id, object_id=r.id, object_repr=str(r), action_flag=ADDITION, change_message='Added') if not inst in form.instance.instid.all(): form.instance.instid.add(inst) return HttpResponseRedirect(reverse("servers")) @@ -784,6 +790,7 @@ def del_server(request): resp['error'] = "Could not get server or you have no rights to delete" return HttpResponse(json.dumps(resp), content_type='application/json') try: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(server).id, object_id=server_pk, object_repr=str(server), action_flag=DELETION, change_message='Deleted ' + server.name) server.delete() except: resp['error'] = "Could not delete server" @@ -886,7 +893,11 @@ def add_realm(request, realm_pk): ) return HttpResponseRedirect(reverse("realms")) if form.is_valid(): - form.save() + if realm_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(realm).id, object_id=realm_pk, object_repr=str(realm), action_flag=CHANGE, change_message='Changed ' + realm.realm) + r = form.save() + if r and not realm_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(r).id, object_id=r.id, object_repr=str(r), action_flag=ADDITION, change_message='Added') return HttpResponseRedirect(reverse("realms")) else: form.fields['instid'] = forms.ModelChoiceField( @@ -928,6 +939,7 @@ def del_realm(request): resp['error'] = "Could not get realm or you have no rights to delete" return HttpResponse(json.dumps(resp), content_type='application/json') try: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(realm).id, object_id=realm_pk, object_repr=str(realm), action_flag=DELETION, change_message='Deleted ' + realm.realm) realm.delete() except: resp['error'] = "Could not delete realm" @@ -1189,7 +1201,11 @@ def add_instrealmmon(request, instrealmmon_pk): ) return HttpResponseRedirect(reverse("instrealmmon")) if form.is_valid(): - form.save() + if instrealmmon_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(instrealmmon).id, object_id=instrealmmon_pk, object_repr=str(instrealmmon), action_flag=CHANGE, change_message='Changed') + r = form.save() + if r and not instrealmmon_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(r).id, object_id=r.id, object_repr=str(r), action_flag=ADDITION, change_message='Added') return HttpResponseRedirect(reverse("instrealmmon")) if instrealmmon: edit = True @@ -1226,6 +1242,7 @@ def del_instrealmmon(request): pk=instrealmmon_pk, realm__instid=institution ) + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(instrealmmon).id, object_id=instrealmmon_pk, object_repr=str(instrealmmon), action_flag=DELETION, change_message='Deleted') instrealmmon.delete() except InstRealmMon.DoesNotExist: resp['error'] = "Could not get monitored realm or you have no rights to delete" @@ -1320,7 +1337,11 @@ def add_monlocauthpar(request, instrealmmon_pk, monlocauthpar_pk): ) return HttpResponseRedirect(reverse("instrealmmon")) if form.is_valid(): - form.save() + if monlocauthpar_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(monlocauthpar).id, object_id=monlocauthpar_pk, object_repr=str(monlocauthpar), action_flag=CHANGE, change_message='Changed ' + monlocauthpar.username) + r = form.save() + if r and not monlocauthpar_pk: + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(r).id, object_id=r.id, object_repr=str(r), action_flag=ADDITION, change_message='Added') return HttpResponseRedirect(reverse("instrealmmon")) if monlocauthpar: edit = True @@ -1355,6 +1376,7 @@ def del_monlocauthpar(request): pk=monlocauthpar_pk, instrealmmonid__realm__instid=institution ) + LogEntry.objects.log_action(user_id=user.id, content_type_id=ContentType.objects.get_for_model(monlocauthpar).id, object_id=monlocauthpar_pk, object_repr=str(monlocauthpar), action_flag=DELETION, change_message='Deleted ' + monlocauthpar.username) monlocauthpar.delete() except MonLocalAuthnParam.DoesNotExist: resp['error'] = "Could not get realm monitoring parameters or you have no rights to delete" @@ -1674,6 +1696,7 @@ def api(request): def participants(request): institutions = Institution.objects.filter(stage=PRODUCTION_STATES.ACTIVE, institutiondetails__isnull=False).\ + exclude(ertype__in=ERTYPE_ROLES.NONE).\ select_related('institutiondetails') cat_instance = 'production' dets = [] @@ -2054,6 +2077,8 @@ def cache_key(inst_key): point['wired_no'] = u"%s" % (sl.wired_no) point['SSID'] = u"%s" % (sl.SSID) point['key'] = u"%s" % sl.pk + point['stage'] = u"%s" % (sl.stage) + point['nro_has_tested'] = u"%s" % (sl.nro_has_tested) points[cache_key].append(point) points_ret.extend(points[cache_key]) @@ -2131,7 +2156,7 @@ def instxml(request, version): root = ElementTree.Element("institutions") ns_xsi = "{http://www.w3.org/2001/XMLSchema-instance}" root.set(ns_xsi + "noNamespaceSchemaLocation", "institution.xsd") - institutions = Institution.objects.all().select_related( + institutions = Institution.objects.exclude(ertype__in=ERTYPE_ROLES.NONE).select_related( 'institutiondetails', 'realmid' ).prefetch_related( 'org_name', 'institutiondetails__contact', @@ -2763,6 +2788,9 @@ def to_xml(ele, encoding="UTF-8"): with specified *encoding*.''' # on python3, we need to get a string, not bytestring - so if requesting unicode, request it as "unicode" xml = ElementTree.tostring(ele, "unicode" if six.PY3 and encoding.lower()=="utf-8" else encoding) + # pretty print the XML to make reporting from the OT more meaningful + from xml.dom import minidom + xml = minidom.parseString(xml).toprettyxml(indent = " ") return xml if xml.startswith('%s' % (encoding, xml) @@ -2814,7 +2842,11 @@ def lookupShibAttr(attrmap, requestMeta): for attr in attrmap: if (attr in requestMeta.keys()): if len(requestMeta[attr]) > 0: - return requestMeta[attr] + # HTTP headers are encoded in latin1 (RFC2616). However, by default + # Shibboleth SP ignores this and puts UTF-8 encoded values into its + # request headers with ShibUseHeaders. So we need to fix up the + # resulting misencoding of accented characters + return bytearray(requestMeta[attr], "iso-8859-1").decode("utf-8") return '' # def get_i18n_name(i18n_name, lang, default_lang='en', default_name='unknown'): diff --git a/requirements-optional.txt b/requirements-optional.txt index 5ff9bdc9..3852da05 100644 --- a/requirements-optional.txt +++ b/requirements-optional.txt @@ -1,2 +1,2 @@ -Mako==1.2.2 +Mako==1.2.4 raven>=5.10.1,<=5.32.0 diff --git a/requirements.txt b/requirements.txt index a3e2cac4..1381a55f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django>=1.11,<2.0 +Django==1.11.29 argparse>=1.2.1 django-registration==2.0.4 django-tinymce>=2.3.0,<3.0a diff --git a/utils/functional.py b/utils/functional.py index 6c41c297..d356cd5b 100644 --- a/utils/functional.py +++ b/utils/functional.py @@ -1,5 +1,5 @@ from functools import partial -from django.utils.inspect import getargspec +from inspect import signature try: from functools import partialmethod except ImportError: @@ -81,7 +81,7 @@ def __delete__(self, obj): else: if self.fdel is not None: fdel_args = [obj] - if len(getargspec(self.fdel)[0]) == 2: + if len(signature(self.fdel).parameters) == 2: fdel_args.append(value) self.fdel(*fdel_args)
{% tolocale service LANGUAGE_CODE %}{% tolocale service LANGUAGE_CODE %} + {% if service.nro_has_tested %} {% endif %} + {{service_address.street}}
{{service_address.city}}
{{service.SSID}}