Compare commits
	
		
			No commits in common. "e44bdd7be2270915ee8bef993c8ffc6276f1527b" and "472e27230594df92b152e94d24ca447600e5f992" have entirely different histories.
		
	
	
		
			e44bdd7be2
			...
			472e272305
		
	
		
					 11 changed files with 387 additions and 212 deletions
				
			
		|  | @ -5,7 +5,24 @@ with the django admin site. | |||
| """ | ||||
| from django.contrib import admin | ||||
| 
 | ||||
| from domains.models import HostingDomain, MailDomain | ||||
| from .models import ( | ||||
|     DNSComment, | ||||
|     DNSCryptoKey, | ||||
|     DNSDomain, | ||||
|     DNSDomainMetadata, | ||||
|     DNSRecord, | ||||
|     DNSSupermaster, | ||||
|     DNSTSIGKey, | ||||
|     HostingDomain, | ||||
|     MailDomain, | ||||
| ) | ||||
| 
 | ||||
| admin.site.register(MailDomain) | ||||
| admin.site.register(HostingDomain) | ||||
| admin.site.register(DNSComment) | ||||
| admin.site.register(DNSCryptoKey) | ||||
| admin.site.register(DNSDomain) | ||||
| admin.site.register(DNSDomainMetadata) | ||||
| admin.site.register(DNSRecord) | ||||
| admin.site.register(DNSSupermaster) | ||||
| admin.site.register(DNSTSIGKey) | ||||
|  |  | |||
|  | @ -1,74 +0,0 @@ | |||
| # Generated by Django 3.2.18 on 2023-04-15 09:53 | ||||
| 
 | ||||
| from django.db import migrations | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('domains', '0004_auto_20151107_1708'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AlterIndexTogether( | ||||
|             name='dnscomment', | ||||
|             index_together=None, | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='dnscomment', | ||||
|             name='customer', | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='dnscomment', | ||||
|             name='domain', | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='dnscryptokey', | ||||
|             name='domain', | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='dnsdomain', | ||||
|             name='customer', | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='dnsdomainmetadata', | ||||
|             name='domain', | ||||
|         ), | ||||
|         migrations.AlterIndexTogether( | ||||
|             name='dnsrecord', | ||||
|             index_together=None, | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='dnsrecord', | ||||
|             name='domain', | ||||
|         ), | ||||
|         migrations.AlterUniqueTogether( | ||||
|             name='dnssupermaster', | ||||
|             unique_together=None, | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='dnssupermaster', | ||||
|             name='customer', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='DNSTSIGKey', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='DNSComment', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='DNSCryptoKey', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='DNSDomain', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='DNSDomainMetadata', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='DNSRecord', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='DNSSupermaster', | ||||
|         ), | ||||
|     ] | ||||
|  | @ -7,8 +7,45 @@ from __future__ import absolute_import | |||
| from django.conf import settings | ||||
| from django.db import models, transaction | ||||
| from django.utils.translation import gettext as _ | ||||
| from model_utils import Choices | ||||
| from model_utils.models import TimeStampedModel | ||||
| 
 | ||||
| DNS_DOMAIN_TYPES = Choices( | ||||
|     ("MASTER", _("Master")), | ||||
|     ("SLAVE", _("Slave")), | ||||
|     ("NATIVE", _("Native")), | ||||
| ) | ||||
| 
 | ||||
| # see https://doc.powerdns.com/md/authoritative/domainmetadata/ | ||||
| DNS_DOMAIN_METADATA_KINDS = Choices( | ||||
|     "ALLOW-DNSUPDATE-FROM", | ||||
|     "ALSO-NOTIFY", | ||||
|     "AXFR-MASTER-TSIG", | ||||
|     "AXFR-SOURCE", | ||||
|     "FORWARD-DNSUPDATE", | ||||
|     "GSS-ACCEPTOR-PRINCIPAL", | ||||
|     "GSS-ALLOW-AXFR-PRINCIPAL", | ||||
|     "LUA-AXFR-SCRIPT", | ||||
|     "NSEC3NARROW", | ||||
|     "NSEC3PARAM", | ||||
|     "PRESIGNED", | ||||
|     "PUBLISH_CDNSKEY", | ||||
|     "PUBLISH_CDS", | ||||
|     "SOA-EDIT", | ||||
|     "SOA-EDIT-DNSUPDATE", | ||||
|     "TSIG-ALLOW-AXFR", | ||||
|     "TSIG-ALLOW-DNSUPDATE", | ||||
| ) | ||||
| 
 | ||||
| DNS_TSIG_KEY_ALGORITHMS = Choices( | ||||
|     ("hmac-md5", _("HMAC MD5")), | ||||
|     ("hmac-sha1", _("HMAC SHA1")), | ||||
|     ("hmac-sha224", _("HMAC SHA224")), | ||||
|     ("hmac-sha256", _("HMAC SHA256")), | ||||
|     ("hmac-sha384", _("HMAC SHA384")), | ||||
|     ("hmac-sha512", _("HMAC SHA512")), | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| class DomainBase(TimeStampedModel): | ||||
|     """ | ||||
|  | @ -103,3 +140,296 @@ class HostingDomain(DomainBase): | |||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.domain | ||||
| 
 | ||||
| 
 | ||||
| class DNSDomain(DomainBase): | ||||
|     """ | ||||
|     This model represents a DNS zone. The model is similar to the domain table | ||||
|     in the PowerDNS schema specified in | ||||
|     https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. | ||||
| 
 | ||||
|     .. code-block:: sql | ||||
| 
 | ||||
|        CREATE TABLE domains ( | ||||
|          id                    SERIAL PRIMARY KEY, | ||||
|          name                  VARCHAR(255) NOT NULL, | ||||
|          master                VARCHAR(128) DEFAULT NULL, | ||||
|          last_check            INT DEFAULT NULL, | ||||
|          type                  VARCHAR(6) NOT NULL, | ||||
|          notified_serial       INT DEFAULT NULL, | ||||
|          account               VARCHAR(40) DEFAULT NULL, | ||||
|          CONSTRAINT c_lowercase_name CHECK ( | ||||
|              ((name)::TEXT = LOWER((name)::TEXT))) | ||||
|        ); | ||||
| 
 | ||||
|        CREATE UNIQUE INDEX name_index ON domains(name); | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     # name is represented by domain | ||||
|     master = models.CharField(max_length=128, blank=True, null=True) | ||||
|     last_check = models.IntegerField(null=True) | ||||
|     domaintype = models.CharField( | ||||
|         max_length=6, choices=DNS_DOMAIN_TYPES, db_column="type" | ||||
|     ) | ||||
|     notified_serial = models.IntegerField(null=True) | ||||
|     # account is represented by customer_id | ||||
|     # check constraint is added via RunSQL in migration | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _("DNS domain") | ||||
|         verbose_name_plural = _("DNS domains") | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.domain | ||||
| 
 | ||||
| 
 | ||||
| class DNSRecord(models.Model): | ||||
|     """ | ||||
|     This model represents a DNS record. The model is similar to the record | ||||
|     table in the PowerDNS schema specified in | ||||
|     https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. | ||||
| 
 | ||||
|     .. code-block:: sql | ||||
| 
 | ||||
|        CREATE TABLE records ( | ||||
|          id                    SERIAL PRIMARY KEY, | ||||
|          domain_id             INT DEFAULT NULL, | ||||
|          name                  VARCHAR(255) DEFAULT NULL, | ||||
|          type                  VARCHAR(10) DEFAULT NULL, | ||||
|          content               VARCHAR(65535) DEFAULT NULL, | ||||
|          ttl                   INT DEFAULT NULL, | ||||
|          prio                  INT DEFAULT NULL, | ||||
|          change_date           INT DEFAULT NULL, | ||||
|          disabled              BOOL DEFAULT 'f', | ||||
|          ordername             VARCHAR(255), | ||||
|          auth                  BOOL DEFAULT 't', | ||||
|          CONSTRAINT domain_exists | ||||
|          FOREIGN KEY(domain_id) REFERENCES domains(id) | ||||
|          ON DELETE CASCADE, | ||||
|          CONSTRAINT c_lowercase_name CHECK ( | ||||
|              ((name)::TEXT = LOWER((name)::TEXT))) | ||||
|        ); | ||||
| 
 | ||||
|        CREATE INDEX rec_name_index ON records(name); | ||||
|        CREATE INDEX nametype_index ON records(name,type); | ||||
|        CREATE INDEX domain_id ON records(domain_id); | ||||
|        CREATE INDEX recordorder ON records ( | ||||
|            domain_id, ordername text_pattern_ops); | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     domain = models.ForeignKey("DNSDomain", on_delete=models.CASCADE) | ||||
|     name = models.CharField(max_length=255, blank=True, null=True, db_index=True) | ||||
|     recordtype = models.CharField( | ||||
|         max_length=10, blank=True, null=True, db_column="type" | ||||
|     ) | ||||
|     content = models.CharField(max_length=65535, blank=True, null=True) | ||||
|     ttl = models.IntegerField(null=True) | ||||
|     prio = models.IntegerField(null=True) | ||||
|     change_date = models.IntegerField(null=True) | ||||
|     disabled = models.BooleanField(default=False) | ||||
|     ordername = models.CharField(max_length=255) | ||||
|     auth = models.BooleanField(default=True) | ||||
|     # check constraint and index recordorder are added via RunSQL in migration | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _("DNS record") | ||||
|         verbose_name_plural = _("DNS records") | ||||
|         index_together = [["name", "recordtype"]] | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "{name} IN {type} {content}".format( | ||||
|             name=self.name, type=self.recordtype, content=self.content | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class DNSSupermaster(models.Model): | ||||
|     """ | ||||
|     This model represents the supermasters table in the PowerDNS schema | ||||
|     specified in | ||||
|     https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. | ||||
| 
 | ||||
|     .. code-block:: sql | ||||
| 
 | ||||
|        CREATE TABLE supermasters ( | ||||
|          ip                    INET NOT NULL, | ||||
|          nameserver            VARCHAR(255) NOT NULL, | ||||
|          account               VARCHAR(40) NOT NULL, | ||||
|          PRIMARY KEY(ip, nameserver) | ||||
|        ); | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     ip = models.GenericIPAddressField() | ||||
|     nameserver = models.CharField(max_length=255) | ||||
|     # account is replaced by customer | ||||
|     customer = models.ForeignKey( | ||||
|         settings.AUTH_USER_MODEL, verbose_name=_("customer"), on_delete=models.CASCADE | ||||
|     ) | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _("DNS supermaster") | ||||
|         verbose_name_plural = _("DNS supermasters") | ||||
|         unique_together = ("ip", "nameserver") | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "{ip} {nameserver}".format(ip=self.ip, nameserver=self.nameserver) | ||||
| 
 | ||||
| 
 | ||||
| class DNSComment(models.Model): | ||||
|     """ | ||||
|     This model represents the comments table in the PowerDNS schema specified | ||||
|     in https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. The | ||||
|     comments table is used to store user comments related to individual DNS | ||||
|     records. | ||||
| 
 | ||||
|     .. code-block:: sql | ||||
| 
 | ||||
|        CREATE TABLE comments ( | ||||
|          id                    SERIAL PRIMARY KEY, | ||||
|          domain_id             INT NOT NULL, | ||||
|          name                  VARCHAR(255) NOT NULL, | ||||
|          type                  VARCHAR(10) NOT NULL, | ||||
|          modified_at           INT NOT NULL, | ||||
|          account               VARCHAR(40) DEFAULT NULL, | ||||
|          comment               VARCHAR(65535) NOT NULL, | ||||
|          CONSTRAINT domain_exists | ||||
|          FOREIGN KEY(domain_id) REFERENCES domains(id) | ||||
|          ON DELETE CASCADE, | ||||
|          CONSTRAINT c_lowercase_name CHECK ( | ||||
|              ((name)::TEXT = LOWER((name)::TEXT))) | ||||
|        ); | ||||
| 
 | ||||
|        CREATE INDEX comments_domain_id_idx ON comments (domain_id); | ||||
|        CREATE INDEX comments_name_type_idx ON comments (name, type); | ||||
|        CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     domain = models.ForeignKey("DNSDomain", on_delete=models.CASCADE) | ||||
|     name = models.CharField(max_length=255) | ||||
|     commenttype = models.CharField(max_length=10, db_column="type") | ||||
|     modified_at = models.IntegerField() | ||||
|     # account is replaced by customer | ||||
|     customer = models.ForeignKey( | ||||
|         settings.AUTH_USER_MODEL, verbose_name=_("customer"), on_delete=models.CASCADE | ||||
|     ) | ||||
|     comment = models.CharField(max_length=65535) | ||||
|     # check constraint is added via RunSQL in migration | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _("DNS comment") | ||||
|         verbose_name_plural = _("DNS comments") | ||||
|         index_together = [["name", "commenttype"], ["domain", "modified_at"]] | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "{name} IN {type}: {comment}".format( | ||||
|             name=self.name, type=self.commenttype, comment=self.comment | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class DNSDomainMetadata(models.Model): | ||||
|     """ | ||||
|     This model represents the domainmetadata table in the PowerDNS schema | ||||
|     specified in | ||||
|     https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. | ||||
|     The domainmetadata table is used to store domain meta data as described in | ||||
|     https://doc.powerdns.com/md/authoritative/domainmetadata/. | ||||
| 
 | ||||
|     .. code-block:: sql | ||||
| 
 | ||||
|        CREATE TABLE domainmetadata ( | ||||
|          id                    SERIAL PRIMARY KEY, | ||||
|          domain_id             INT REFERENCES domains(id) ON DELETE CASCADE, | ||||
|          kind                  VARCHAR(32), | ||||
|          content               TEXT | ||||
|        ); | ||||
| 
 | ||||
|        CREATE INDEX domainidmetaindex ON domainmetadata(domain_id); | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     domain = models.ForeignKey("DNSDomain", on_delete=models.CASCADE) | ||||
|     kind = models.CharField(max_length=32, choices=DNS_DOMAIN_METADATA_KINDS) | ||||
|     content = models.TextField() | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _("DNS domain metadata item") | ||||
|         verbose_name_plural = _("DNS domain metadata items") | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "{domain} {kind} {content}".format( | ||||
|             domain=self.domain.domain, kind=self.kind, content=self.content | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class DNSCryptoKey(models.Model): | ||||
|     """ | ||||
|     This model represents the cryptokeys table in the PowerDNS schema | ||||
|     specified in | ||||
|     https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. | ||||
| 
 | ||||
|     .. code-block:: sql | ||||
| 
 | ||||
|        CREATE TABLE cryptokeys ( | ||||
|          id                    SERIAL PRIMARY KEY, | ||||
|          domain_id             INT REFERENCES domains(id) ON DELETE CASCADE, | ||||
|          flags                 INT NOT NULL, | ||||
|          active                BOOL, | ||||
|          content               TEXT | ||||
|        ); | ||||
| 
 | ||||
|        CREATE INDEX domainidindex ON cryptokeys(domain_id); | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     domain = models.ForeignKey("DNSDomain", on_delete=models.CASCADE) | ||||
|     flags = models.IntegerField() | ||||
|     active = models.BooleanField(default=True) | ||||
|     content = models.TextField() | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _("DNS crypto key") | ||||
|         verbose_name_plural = _("DNS crypto keys") | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "{domain} {content}".format( | ||||
|             domain=self.domain.domain, content=self.content | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class DNSTSIGKey(models.Model): | ||||
|     """ | ||||
|     This model represents the tsigkeys table in the PowerDNS schema specified | ||||
|     in https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. | ||||
| 
 | ||||
|     .. code-block:: sql | ||||
| 
 | ||||
|        CREATE TABLE tsigkeys ( | ||||
|          id                    SERIAL PRIMARY KEY, | ||||
|          name                  VARCHAR(255), | ||||
|          algorithm             VARCHAR(50), | ||||
|          secret                VARCHAR(255), | ||||
|          CONSTRAINT c_lowercase_name CHECK ( | ||||
|              ((name)::TEXT = LOWER((name)::TEXT))) | ||||
|        ); | ||||
| 
 | ||||
|        CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     name = models.CharField(max_length=255) | ||||
|     algorithm = models.CharField(max_length=50, choices=DNS_TSIG_KEY_ALGORITHMS) | ||||
|     secret = models.CharField(max_length=255) | ||||
|     # check constraint is added via RunSQL in migration | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _("DNS TSIG key") | ||||
|         verbose_name_plural = _("DNS TSIG keys") | ||||
|         unique_together = [["name", "algorithm"]] | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "{name} {algorithm} XXXX".format( | ||||
|             name=self.name, algorithm=self.algorithm | ||||
|         ) | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| # import celery_app to initialize it | ||||
| from gnuviechadmin.celery import app as celery_app  # NOQA | ||||
| 
 | ||||
| __version__ = "0.13.0" | ||||
| __version__ = '0.12.1' | ||||
|  |  | |||
|  | @ -86,6 +86,7 @@ USE_TZ = True | |||
| 
 | ||||
| LOCALE_PATHS = (normpath(join(SITE_ROOT, "gnuviechadmin", "locale")),) | ||||
| 
 | ||||
| 
 | ||||
| # ######### MEDIA CONFIGURATION | ||||
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root | ||||
| MEDIA_ROOT = normpath(join(SITE_ROOT, "media")) | ||||
|  | @ -179,6 +180,7 @@ AUTHENTICATION_BACKENDS = ( | |||
|     "allauth.account.auth_backends.AuthenticationBackend", | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| # ######### URL CONFIGURATION | ||||
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf | ||||
| ROOT_URLCONF = "%s.urls" % SITE_NAME | ||||
|  | @ -206,7 +208,6 @@ DJANGO_APPS = ( | |||
|     # Flatpages for about page | ||||
|     "django.contrib.flatpages", | ||||
|     "crispy_forms", | ||||
|     "impersonate", | ||||
| ) | ||||
| 
 | ||||
| ALLAUTH_APPS = ( | ||||
|  | @ -276,7 +277,7 @@ LOGGING = { | |||
|     "formatters": { | ||||
|         "verbose": { | ||||
|             "format": "%(levelname)s %(asctime)s %(name)s " | ||||
|                       "%(module)s:%(lineno)d %(process)d %(thread)d %(message)s" | ||||
|             "%(module)s:%(lineno)d %(process)d %(thread)d %(message)s" | ||||
|         }, | ||||
|         "simple": {"format": "%(levelname)s %(name)s:%(lineno)d %(message)s"}, | ||||
|     }, | ||||
|  | @ -365,10 +366,7 @@ def show_debug_toolbar(request): | |||
| # See: http://django-debug-toolbar.readthedocs.org/en/latest/installation.html#explicit-setup # noqa | ||||
| INSTALLED_APPS += ("debug_toolbar",) | ||||
| 
 | ||||
| MIDDLEWARE += [ | ||||
|     "impersonate.middleware.ImpersonateMiddleware", | ||||
|     "debug_toolbar.middleware.DebugToolbarMiddleware", | ||||
| ] | ||||
| MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] | ||||
| 
 | ||||
| DEBUG_TOOLBAR_CONFIG = { | ||||
|     "SHOW_TOOLBAR_CALLBACK": "gnuviechadmin.settings.show_debug_toolbar" | ||||
|  | @ -405,21 +403,21 @@ if GVA_ENVIRONMENT == "local": | |||
|             [ | ||||
|                 (key, {"handlers": ["console"], "level": "DEBUG", "propagate": True}) | ||||
|                 for key in [ | ||||
|                 "dashboard", | ||||
|                 "domains", | ||||
|                 "fileservertasks", | ||||
|                 "gvacommon", | ||||
|                 "gvawebcore", | ||||
|                 "hostingpackages", | ||||
|                 "ldaptasks", | ||||
|                 "managemails", | ||||
|                 "mysqltasks", | ||||
|                 "osusers", | ||||
|                 "pgsqltasks", | ||||
|                 "taskresults", | ||||
|                 "userdbs", | ||||
|                 "websites", | ||||
|             ] | ||||
|                     "dashboard", | ||||
|                     "domains", | ||||
|                     "fileservertasks", | ||||
|                     "gvacommon", | ||||
|                     "gvawebcore", | ||||
|                     "hostingpackages", | ||||
|                     "ldaptasks", | ||||
|                     "managemails", | ||||
|                     "mysqltasks", | ||||
|                     "osusers", | ||||
|                     "pgsqltasks", | ||||
|                     "taskresults", | ||||
|                     "userdbs", | ||||
|                     "websites", | ||||
|                 ] | ||||
|             ] | ||||
|         ) | ||||
|     ) | ||||
|  | @ -440,21 +438,21 @@ elif GVA_ENVIRONMENT == "test": | |||
|             [ | ||||
|                 (key, {"handlers": ["console"], "level": "ERROR", "propagate": True}) | ||||
|                 for key in [ | ||||
|                 "dashboard", | ||||
|                 "domains", | ||||
|                 "fileservertasks", | ||||
|                 "gvacommon", | ||||
|                 "gvawebcore", | ||||
|                 "hostingpackages", | ||||
|                 "ldaptasks", | ||||
|                 "managemails", | ||||
|                 "mysqltasks", | ||||
|                 "osusers", | ||||
|                 "pgsqltasks", | ||||
|                 "taskresults", | ||||
|                 "userdbs", | ||||
|                 "websites", | ||||
|             ] | ||||
|                     "dashboard", | ||||
|                     "domains", | ||||
|                     "fileservertasks", | ||||
|                     "gvacommon", | ||||
|                     "gvawebcore", | ||||
|                     "hostingpackages", | ||||
|                     "ldaptasks", | ||||
|                     "managemails", | ||||
|                     "mysqltasks", | ||||
|                     "osusers", | ||||
|                     "pgsqltasks", | ||||
|                     "taskresults", | ||||
|                     "userdbs", | ||||
|                     "websites", | ||||
|                 ] | ||||
|             ] | ||||
|         ) | ||||
|     ) | ||||
|  |  | |||
|  | @ -11,8 +11,6 @@ admin.autodiscover() | |||
| 
 | ||||
| urlpatterns = [ | ||||
|     re_path(r"", include("dashboard.urls")), | ||||
|     re_path(r"^admin/", admin.site.urls), | ||||
|     re_path(r"^impersonate/", include("impersonate.urls")), | ||||
|     re_path(r"^accounts/", include("allauth.urls")), | ||||
|     re_path(r"^database/", include("userdbs.urls")), | ||||
|     re_path(r"^domains/", include("domains.urls")), | ||||
|  | @ -20,6 +18,7 @@ urlpatterns = [ | |||
|     re_path(r"^website/", include("websites.urls")), | ||||
|     re_path(r"^mail/", include("managemails.urls")), | ||||
|     re_path(r"^osuser/", include("osusers.urls")), | ||||
|     re_path(r"^admin/", admin.site.urls), | ||||
|     re_path(r"^contact/", include("contact_form.urls")), | ||||
|     re_path(r"^impressum/$", views.flatpage, {"url": "/impressum/"}, name="imprint"), | ||||
| ] | ||||
|  |  | |||
|  | @ -71,7 +71,6 @@ | |||
|             <li class="dropdown{% if active_item == 'account' %} active{% endif %}"> | ||||
|               <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-user"></i> {% trans "My Account" %} <span class="caret"></span></a> | ||||
|               <ul class="dropdown-menu" role="menu"> | ||||
|                 {% if user.is_superuser %}<li><a href="{% url 'impersonate-search' %}"><i class="fa fa-angellist"></i> {% trans "Impersonate user" %}</a></li>{% endif %} | ||||
|                 {% if user.is_staff %}<li><a href="{% url 'admin:index' %}"><i class="fa fa-wrench"></i> {% trans "Admin site" %}</a></li>{% endif %} | ||||
|                 <li><a href="{% url 'account_email' %}"><i class="fa fa-at"></i> {% trans "Change Email" %}</a></li> | ||||
|                 <li><a href="{% url 'socialaccount_connections' %}"><i class="fa fa-users"></i> {% trans "Social Accounts" %}</a></li> | ||||
|  | @ -86,13 +85,7 @@ | |||
|           {% if user.is_authenticated %} | ||||
|           {% user_display user as user_display %} | ||||
|           {% url 'user_profile' slug=user.username as profile_url %} | ||||
|               {% if user.is_impersonate %} | ||||
|                   {% user_display user.impersonator as impersonator_display %} | ||||
|                   {% url 'impersonate-stop' as stop_impersonation_url %} | ||||
|                   <p class="navbar-text navbar-right">{% blocktrans %}Signed in as <a href="{{ profile_url }}" class="navbar-link" title="My Profile">{{ user_display }}</a> (impersonated by {{ impersonator_display }}, <a href="{{ stop_impersonation_url }}" class="navbar-link">stop impersonation</a>){% endblocktrans %}</p> | ||||
|               {% else %} | ||||
|                   <p class="navbar-text navbar-right">{% blocktrans %}Signed in as <a href="{{ profile_url }}" class="navbar-link" title="My Profile">{{ user_display }}</a>{% endblocktrans %}</p> | ||||
|               {% endif %} | ||||
|           <p class="navbar-text navbar-right">{% blocktrans %}Signed in as <a href="{{ profile_url }}" class="navbar-link" title="My Profile">{{ user_display }}</a>{% endblocktrans %}</p> | ||||
|           {% endif %} | ||||
|         </div><!--/.nav-collapse --> | ||||
|       </div> | ||||
|  |  | |||
|  | @ -1,31 +0,0 @@ | |||
| {% extends "base.html" %} | ||||
| {% load i18n %} | ||||
| 
 | ||||
| {% block title %}{{ block.super }} - {% trans "Django Impersonate - User List" %}{% endblock title %} | ||||
| {% block page_title %}{% blocktrans %}User List - Page {{ page_number }}{% endblocktrans %}{% endblock page_title %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     {% if page.object_list %} | ||||
|         <ul class="list-group"> | ||||
|             {% for user in page.object_list %} | ||||
|                 <li class="list-group-item"><a href="{% url 'impersonate-start' user.pk %}{{ redirect }}">{{ user }}</a> | ||||
|                     - Impersonate | ||||
|                 </li> | ||||
|             {% endfor %} | ||||
|         </ul> | ||||
|     {% endif %} | ||||
| 
 | ||||
|     <p> | ||||
|         <a href="{% url 'impersonate-search' %}">{% trans "Search users" %}</a> | ||||
|     </p> | ||||
| 
 | ||||
|     <p> | ||||
|         {% if page.has_previous %} | ||||
|             <a href="{% url 'impersonate-list' %}?page={{ page.previous_page_number }}">Previous Page</a>   | ||||
|         {% endif %} | ||||
| 
 | ||||
|         {% if page.has_next %} | ||||
|             <a href="{% url 'impersonate-list' %}?page={{ page.next_page_number }}">Next Page</a>   | ||||
|         {% endif %} | ||||
|     </p> | ||||
| {% endblock %} | ||||
|  | @ -1,45 +0,0 @@ | |||
| {% extends "base.html" %} | ||||
| {% load i18n %} | ||||
| 
 | ||||
| {% block title %}{{ block.super }} - {% trans "Django Impersonate - Search Users" %}{% endblock title %} | ||||
| {% block page_title %}Search Users {% if query %}- Page {{ page_number }}{% endif %}{% endblock page_title %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <form action="{% url 'impersonate-search' %}" method="GET"> | ||||
|         {{ redirect_field }} | ||||
|         <div class="form-group"> | ||||
|             <label for="user-query">{% trans "Enter Search Query:" %}</label> | ||||
|             <input type="text" name="q" id="user-query" class="form-control" | ||||
|                    value="{% if query %}{{ query }}{% endif %}"> | ||||
|         </div> | ||||
|         <button type="submit" class="btn btn-primary">{% trans "Search" %}</button> | ||||
|     </form> | ||||
| 
 | ||||
|     <p> | ||||
|         <a href="{% url 'impersonate-list' %}">{% trans "List all users" %}</a> | ||||
|     </p> | ||||
| 
 | ||||
|     <p> | ||||
|         {% if query and page.object_list %} | ||||
|             <ul class="list-group"> | ||||
|                 {% for user in page.object_list %} | ||||
|                     <li class="list-group-item"><a | ||||
|                             href="{% url 'impersonate-start' user.pk %}{{ redirect }}">{{ user }}</a> - Impersonate | ||||
|                     </li> | ||||
|                 {% endfor %} | ||||
|             </ul> | ||||
|         {% endif %} | ||||
|     </p> | ||||
| 
 | ||||
|     <p> | ||||
|         {% if query and page.has_previous %} | ||||
|             <a href="{% url 'impersonate-search' %}?page={{ page.previous_page_number }}&q={{ query|urlencode }}">Previous | ||||
|                 Page</a>   | ||||
|         {% endif %} | ||||
| 
 | ||||
|         {% if query and page.has_next %} | ||||
|             <a href="{% url 'impersonate-search' %}?page={{ page.next_page_number }}&q={{ query|urlencode }}">Next | ||||
|                 Page</a> | ||||
|         {% endif %} | ||||
|     </p> | ||||
| {% endblock %} | ||||
							
								
								
									
										13
									
								
								poetry.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										13
									
								
								poetry.lock
									
										
									
										generated
									
									
									
								
							|  | @ -666,17 +666,6 @@ files = [ | |||
| django = ">=3.2.4" | ||||
| sqlparse = ">=0.2" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "django-impersonate" | ||||
| version = "1.9.1" | ||||
| description = "Django app to allow superusers to impersonate other users." | ||||
| category = "main" | ||||
| optional = false | ||||
| python-versions = "*" | ||||
| files = [ | ||||
|     {file = "django-impersonate-1.9.1.tar.gz", hash = "sha256:0befdb096198b458507239a6f21574c9e0f608ab01fad352d71eb9284e5bb9c9"}, | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "django-model-utils" | ||||
| version = "4.3.1" | ||||
|  | @ -1753,4 +1742,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more | |||
| [metadata] | ||||
| lock-version = "2.0" | ||||
| python-versions = "^3.7" | ||||
| content-hash = "dd56e0233689448f08dfcae943871bf9d72c05ad7bfd326c69f9ecb33ea8a461" | ||||
| content-hash = "6041c8bb49cd1df098f1948f8ad2cbd48fd8f42ff44e410f3fecb61be7e80a18" | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| [tool.poetry] | ||||
| name = "gva" | ||||
| version = "0.13.0" | ||||
| version = "0.12.1" | ||||
| description = "gnuviechadmin web interface" | ||||
| authors = ["Jan Dittberner <jan@dittberner.info>"] | ||||
| license = "AGPL-3+" | ||||
|  | @ -19,7 +19,6 @@ gvacommon = {version = "^0.6.0", source = "gnuviech"} | |||
| passlib = "^1.7.4" | ||||
| redis = "^4.5.1" | ||||
| requests-oauthlib = "^1.3.1" | ||||
| django-impersonate = "^1.9.1" | ||||
| 
 | ||||
| 
 | ||||
| [tool.poetry.group.dev.dependencies] | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue