only allow owner to handle domains, mailboxes and aliases
This commit is contained in:
		
							parent
							
								
									66eb84bb8e
								
							
						
					
					
						commit
						252ac918cc
					
				
					 14 changed files with 382 additions and 149 deletions
				
			
		
							
								
								
									
										155
									
								
								backend/backend/settings.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								backend/backend/settings.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,155 @@ | |||
| """ | ||||
| Django settings for backend project. | ||||
| 
 | ||||
| Generated by 'django-admin startproject' using Django 3.1.3. | ||||
| 
 | ||||
| For more information on this file, see | ||||
| https://docs.djangoproject.com/en/3.1/topics/settings/ | ||||
| 
 | ||||
| For the full list of settings and their values, see | ||||
| https://docs.djangoproject.com/en/3.1/ref/settings/ | ||||
| """ | ||||
| 
 | ||||
| from pathlib import Path | ||||
| 
 | ||||
| # Build paths inside the project like this: BASE_DIR / 'subdir'. | ||||
| import config.secret | ||||
| import config.sql | ||||
| import config.ldap | ||||
| 
 | ||||
| BASE_DIR = Path(__file__).resolve().parent.parent | ||||
| 
 | ||||
| # Quick-start development settings - unsuitable for production | ||||
| # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ | ||||
| 
 | ||||
| # SECURITY WARNING: keep the secret key used in production secret! | ||||
| SECRET_KEY = config.secret.key | ||||
| 
 | ||||
| # SECURITY WARNING: don't run with debug turned on in production! | ||||
| DEBUG = True | ||||
| 
 | ||||
| ALLOWED_HOSTS = [] | ||||
| 
 | ||||
| import ldap | ||||
| from django_auth_ldap.config import LDAPSearch | ||||
| 
 | ||||
| AUTH_LDAP_SERVER_URI = config.ldap.uri | ||||
| AUTH_LDAP_BIND_DN = config.ldap.bind_dn | ||||
| AUTH_LDAP_BIND_PASSWORD = config.ldap.bind_pass | ||||
| AUTH_LDAP_USER_SEARCH = LDAPSearch( | ||||
|     config.ldap.search_dn, ldap.SCOPE_SUBTREE, config.ldap.search_filter | ||||
| ) | ||||
| 
 | ||||
| AUTHENTICATION_BACKENDS = [ | ||||
|     "django_auth_ldap.backend.LDAPBackend", | ||||
|     "django.contrib.auth.backends.ModelBackend", | ||||
| ] | ||||
| 
 | ||||
| LOGIN_REDIRECT_URL = '/' | ||||
| 
 | ||||
| # Application definition | ||||
| 
 | ||||
| INSTALLED_APPS = [ | ||||
|     'multimail.apps.MultimailConfig', | ||||
|     'bootstrap4', | ||||
|     'django_static_fontawesome', | ||||
|     'django.contrib.admin', | ||||
|     'django.contrib.auth', | ||||
|     'django.contrib.contenttypes', | ||||
|     'django.contrib.sessions', | ||||
|     'django.contrib.messages', | ||||
|     'django.contrib.staticfiles', | ||||
| ] | ||||
| 
 | ||||
| MIDDLEWARE = [ | ||||
|     'django.middleware.security.SecurityMiddleware', | ||||
|     'django.contrib.sessions.middleware.SessionMiddleware', | ||||
|     'django.middleware.common.CommonMiddleware', | ||||
|     'django.middleware.csrf.CsrfViewMiddleware', | ||||
|     'django.contrib.auth.middleware.AuthenticationMiddleware', | ||||
|     'django.contrib.messages.middleware.MessageMiddleware', | ||||
|     'django.middleware.clickjacking.XFrameOptionsMiddleware', | ||||
| ] | ||||
| 
 | ||||
| ROOT_URLCONF = 'backend.urls' | ||||
| 
 | ||||
| TEMPLATES = [ | ||||
|     { | ||||
|         'BACKEND': 'django.template.backends.django.DjangoTemplates', | ||||
|         'DIRS': [BASE_DIR / 'multimail/templates'] | ||||
|         , | ||||
|         'APP_DIRS': True, | ||||
|         'OPTIONS': { | ||||
|             'context_processors': [ | ||||
|                 'django.template.context_processors.debug', | ||||
|                 'django.template.context_processors.request', | ||||
|                 'django.contrib.auth.context_processors.auth', | ||||
|                 'django.contrib.messages.context_processors.messages', | ||||
|             ], | ||||
|         }, | ||||
|     }, | ||||
| ] | ||||
| 
 | ||||
| WSGI_APPLICATION = 'backend.wsgi.application' | ||||
| 
 | ||||
| # Database | ||||
| # https://docs.djangoproject.com/en/3.1/ref/settings/#databases | ||||
| 
 | ||||
| DATABASES = { | ||||
|     'default': { | ||||
|         'ENGINE': 'django.db.backends.sqlite3', | ||||
|         'NAME': BASE_DIR / 'db.sqlite3', | ||||
|     }, | ||||
|     'mail': { | ||||
|         'ENGINE': 'django.db.backends.sqlite3', | ||||
|         'NAME': BASE_DIR / 'mail.sqlite3', | ||||
|     }, | ||||
|     'ldap': { | ||||
|         'ENGINE': 'ldapdb.backends.ldap', | ||||
|         'NAME': config.ldap.uri, | ||||
|         'USER': config.ldap.bind_dn, | ||||
|         'PASSWORD': config.ldap.bind_pass, | ||||
|     }, | ||||
|     #'mysql': { | ||||
|     #    'NAME': 'user_data', | ||||
|     #    'ENGINE': 'django.db.backends.mysql', | ||||
|     #    'USER': 'mysql_user', | ||||
|     #    'PASSWORD': 'priv4te' | ||||
|     #} | ||||
| } | ||||
| 
 | ||||
| # Password validation | ||||
| # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators | ||||
| 
 | ||||
| AUTH_PASSWORD_VALIDATORS = [ | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', | ||||
|     }, | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', | ||||
|     }, | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', | ||||
|     }, | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', | ||||
|     }, | ||||
| ] | ||||
| 
 | ||||
| # Internationalization | ||||
| # https://docs.djangoproject.com/en/3.1/topics/i18n/ | ||||
| 
 | ||||
| LANGUAGE_CODE = 'en-us' | ||||
| 
 | ||||
| TIME_ZONE = 'UTC' | ||||
| 
 | ||||
| USE_I18N = True | ||||
| 
 | ||||
| USE_L10N = True | ||||
| 
 | ||||
| USE_TZ = True | ||||
| 
 | ||||
| # Static files (CSS, JavaScript, Images) | ||||
| # https://docs.djangoproject.com/en/3.1/howto/static-files/ | ||||
| 
 | ||||
| STATIC_URL = '/static/' | ||||
|  | @ -1,28 +1,44 @@ | |||
| from django.http import HttpResponseRedirect | ||||
| from django.shortcuts import get_object_or_404 | ||||
| from django.http import HttpResponseRedirect, Http404 | ||||
| from django.urls import reverse | ||||
| from django.contrib.auth.decorators import login_required | ||||
| from django.contrib.auth import logout as auth_logout | ||||
| 
 | ||||
| from .models import Domain, Mailbox, Alias | ||||
| from .owner import user_from_request | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def delete_domain(request, domain_id): | ||||
|     domain = get_object_or_404(Domain, pk=domain_id) | ||||
|     try: | ||||
|         user = user_from_request(request) | ||||
|         domain = Domain.objects.filter(admin__admin=user['name'], admin__source=user['source']).get(pk=domain_id) | ||||
|     except: | ||||
|         raise Http404 | ||||
|     # TODO this might fail due to foreign key constraint | ||||
|     domain.delete() | ||||
|     return HttpResponseRedirect(reverse('multimail:domains')) | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def delete_mailbox(request, mailbox_id): | ||||
|     mailbox = get_object_or_404(Mailbox, pk=mailbox_id) | ||||
|     try: | ||||
|         user = user_from_request(request) | ||||
|         domains = [o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         mailbox = Mailbox.objects.filter(domain__in=domains).get(pk=mailbox_id) | ||||
|     except: | ||||
|         raise Http404 | ||||
|     mailbox.delete() | ||||
|     return HttpResponseRedirect(reverse('multimail:mailboxes')) | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def delete_alias(request, alias_id): | ||||
|     alias = get_object_or_404(Alias, pk=alias_id) | ||||
|     try: | ||||
|         user = user_from_request(request) | ||||
|         domains = [o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         alias = Alias.objects.filter(source_domain__in=domains).get(pk=alias_id) | ||||
|     except: | ||||
|         raise Http404 | ||||
|     alias.delete() | ||||
|     return HttpResponseRedirect(reverse('multimail:aliases')) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,32 +1,26 @@ | |||
| from django.contrib import admin | ||||
| 
 | ||||
| from .models import Choice, Question | ||||
| from .models import Alias, Domain, Mailbox, TLSPolicy | ||||
| from .models import TLSPolicy, Domain, DomainOwner | ||||
| 
 | ||||
| 
 | ||||
| class ChoiceInline(admin.TabularInline): | ||||
|     model = Choice | ||||
| class AdminInline(admin.TabularInline): | ||||
|     model = DomainOwner | ||||
|     extra = 1 | ||||
| 
 | ||||
| 
 | ||||
| class QuestionAdmin(admin.ModelAdmin): | ||||
|     fieldsets = [ | ||||
|         (None, {'fields': ['question_text']}), | ||||
|         ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), | ||||
|     ] | ||||
|     list_display = ('question_text', 'pub_date', 'was_published_recently') | ||||
|     inlines = [ChoiceInline] | ||||
| class DomainAdmin(admin.ModelAdmin): | ||||
|     list_display = [('domain'), ('admins')] | ||||
|     inlines = [AdminInline] | ||||
| 
 | ||||
|     def admins(self, obj): | ||||
|         return "[" + ", ".join([x.source + ":" + x.admin for x in obj.admin.all()]) + "]" | ||||
| 
 | ||||
| 
 | ||||
| admin.site.register(Question, QuestionAdmin) | ||||
| admin.site.register(Domain, DomainAdmin) | ||||
| 
 | ||||
| 
 | ||||
| class TLSPolicyAdmin(admin.ModelAdmin): | ||||
|     list_display = ('domain', 'policy', 'params') | ||||
|     list_display = [('domain'), ('policy'), ('params')] | ||||
| 
 | ||||
| 
 | ||||
| admin.site.register(TLSPolicy, TLSPolicyAdmin) | ||||
| 
 | ||||
| admin.site.register(Alias) | ||||
| admin.site.register(Domain) | ||||
| admin.site.register(Mailbox) | ||||
|  |  | |||
|  | @ -1,29 +1,38 @@ | |||
| from django.contrib.auth.decorators import login_required | ||||
| from django.forms import ModelForm | ||||
| from django.http import HttpResponseRedirect | ||||
| from django.http import HttpResponseRedirect, Http404 | ||||
| from django.shortcuts import render | ||||
| 
 | ||||
| from multimail.models import Domain, Mailbox, Alias | ||||
| from multimail.owner import user_from_request | ||||
| 
 | ||||
| 
 | ||||
| class DomainForm(ModelForm): | ||||
|    class Meta: | ||||
|     class Meta: | ||||
|         model = Domain | ||||
|         fields = ['domain'] | ||||
|         fields = '__all__' | ||||
|         #fields = ['domain'] | ||||
| 
 | ||||
| 
 | ||||
| class MailboxForm(ModelForm): | ||||
|    class Meta: | ||||
|     class Meta: | ||||
|         model = Mailbox | ||||
|         fields = '__all__' | ||||
| 
 | ||||
| 
 | ||||
| class AliasForm(ModelForm): | ||||
|    class Meta: | ||||
|     class Meta: | ||||
|         model = Alias | ||||
|         fields = '__all__' | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def edit_domain(request, domain_id): | ||||
|     domain = Domain.objects.get(id=domain_id) | ||||
|     try: | ||||
|         user = user_from_request(request) | ||||
|         domain = Domain.objects.filter(admin__admin=user['name'], admin__source=user['source']).get(pk=domain_id) | ||||
|     except: | ||||
|         raise Http404 | ||||
|     if request.method == 'POST': | ||||
|         form = DomainForm(request.POST, instance=domain) | ||||
|         if form.is_valid(): | ||||
|  | @ -35,9 +44,31 @@ def edit_domain(request, domain_id): | |||
| 
 | ||||
|     return render(request, 'multimail/edit_domain.html', {'form': form}) | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def new_domain(request): | ||||
|     user = user_from_request(request) | ||||
|     if request.method == 'POST': | ||||
|         form = DomainForm(request.POST) | ||||
|         if form.is_valid(): | ||||
|             domain = form.save() | ||||
|             domain.admin.create(admin=user['name'], source=user['source']) | ||||
|             return HttpResponseRedirect('/domains/') | ||||
| 
 | ||||
|     else: | ||||
|         form = DomainForm() | ||||
| 
 | ||||
|     return render(request, 'multimail/edit_domain.html', {'form': form}) | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def edit_mailbox(request, mailbox_id): | ||||
|     mailbox = Mailbox.objects.get(id=mailbox_id) | ||||
|     try: | ||||
|         user = user_from_request(request) | ||||
|         domains = [o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         mailbox = Mailbox.objects.filter(domain__in=domains).get(pk=mailbox_id) | ||||
|     except: | ||||
|         raise Http404 | ||||
|     if request.method == 'POST': | ||||
|         form = MailboxForm(request.POST, instance=mailbox) | ||||
|         if form.is_valid(): | ||||
|  | @ -49,9 +80,31 @@ def edit_mailbox(request, mailbox_id): | |||
| 
 | ||||
|     return render(request, 'multimail/edit_mailbox.html', {'form': form}) | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def new_mailbox(request): | ||||
|     if request.method == 'POST': | ||||
|         user = user_from_request(request) | ||||
|         domains = [o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         form = MailboxForm(request.POST) | ||||
|         if form.is_valid() and form.domain in domains: | ||||
|             form.save() | ||||
|             return HttpResponseRedirect('/mailboxes/') | ||||
| 
 | ||||
|     else: | ||||
|         form = MailboxForm() | ||||
| 
 | ||||
|     return render(request, 'multimail/edit_mailbox.html', {'form': form}) | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def edit_alias(request, alias_id): | ||||
|     alias = Alias.objects.get(id=alias_id) | ||||
|     try: | ||||
|         user = user_from_request(request) | ||||
|         domains = [o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         alias = Alias.objects.filter(source_domain__in=domains).get(pk=alias_id) | ||||
|     except: | ||||
|         raise Http404 | ||||
|     if request.method == 'POST': | ||||
|         form = AliasForm(request.POST, instance=alias) | ||||
|         if form.is_valid(): | ||||
|  | @ -61,4 +114,20 @@ def edit_alias(request, alias_id): | |||
|     else: | ||||
|         form = AliasForm(instance=alias) | ||||
| 
 | ||||
|     return render(request, 'multimail/edit_alias.html', {'form': form}) | ||||
|     return render(request, 'multimail/edit_alias.html', {'form': form}) | ||||
| 
 | ||||
| 
 | ||||
| @login_required(login_url='/login/') | ||||
| def new_alias(request): | ||||
|     if request.method == 'POST': | ||||
|         user = user_from_request(request) | ||||
|         domains = [o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         form = AliasForm(request.POST) | ||||
|         if form.is_valid() and form.source_domain in domains: | ||||
|             form.save() | ||||
|             return HttpResponseRedirect('/aliases/') | ||||
| 
 | ||||
|     else: | ||||
|         form = AliasForm() | ||||
| 
 | ||||
|     return render(request, 'multimail/edit_alias.html', {'form': form}) | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| # Generated by Django 3.1.3 on 2020-11-02 18:55 | ||||
| # Generated by Django 3.1.3 on 2020-11-07 16:49 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
|  | @ -13,20 +13,67 @@ class Migration(migrations.Migration): | |||
| 
 | ||||
|     operations = [ | ||||
|         migrations.CreateModel( | ||||
|             name='Question', | ||||
|             name='Alias', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('question_text', models.CharField(max_length=200)), | ||||
|                 ('pub_date', models.DateTimeField(verbose_name='date published')), | ||||
|                 ('id', models.AutoField(primary_key=True, serialize=False)), | ||||
|                 ('source_username', models.CharField(max_length=64)), | ||||
|                 ('source_domain', models.CharField(max_length=255)), | ||||
|                 ('destination_username', models.CharField(max_length=64)), | ||||
|                 ('destination_domain', models.CharField(max_length=255)), | ||||
|                 ('enabled', models.IntegerField(blank=True, null=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'aliases', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='Choice', | ||||
|             name='Domain', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('choice_text', models.CharField(max_length=200)), | ||||
|                 ('votes', models.IntegerField(default=0)), | ||||
|                 ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='multimail.question')), | ||||
|                 ('domain', models.CharField(max_length=255)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'domains', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='Mailbox', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(primary_key=True, serialize=False)), | ||||
|                 ('username', models.CharField(max_length=64)), | ||||
|                 ('domain', models.CharField(max_length=255)), | ||||
|                 ('password', models.CharField(max_length=255)), | ||||
|                 ('quota', models.IntegerField(blank=True, null=True)), | ||||
|                 ('enabled', models.IntegerField(blank=True, null=True)), | ||||
|                 ('sendonly', models.IntegerField(blank=True, null=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'mailboxes', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='TLSPolicy', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('domain', models.CharField(max_length=255)), | ||||
|                 ('policy', models.TextField()), | ||||
|                 ('params', models.CharField(blank=True, max_length=255, null=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'tlspolicies', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='DomainOwner', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('admin', models.CharField(max_length=200)), | ||||
|                 ('source', models.CharField(choices=[('system', 'system'), ('ldap', 'ldap'), ('mail', 'mail')], default=0, max_length=8)), | ||||
|                 ('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='admin', to='multimail.domain')), | ||||
|             ], | ||||
|         ), | ||||
|     ] | ||||
|  |  | |||
|  | @ -1,68 +0,0 @@ | |||
| # Generated by Django 3.1.3 on 2020-11-02 21:11 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('multimail', '0001_initial'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.CreateModel( | ||||
|             name='Aliases', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(primary_key=True, serialize=False)), | ||||
|                 ('source_username', models.CharField(max_length=64)), | ||||
|                 ('source_domain', models.CharField(max_length=255)), | ||||
|                 ('destination_username', models.CharField(max_length=64)), | ||||
|                 ('destination_domain', models.CharField(max_length=255)), | ||||
|                 ('enabled', models.IntegerField(blank=True, null=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'aliases', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='Domains', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('domain', models.CharField(max_length=255)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'domains', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='Mailboxes', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(primary_key=True, serialize=False)), | ||||
|                 ('username', models.CharField(max_length=64)), | ||||
|                 ('domain', models.CharField(max_length=255)), | ||||
|                 ('password', models.CharField(max_length=255)), | ||||
|                 ('quota', models.IntegerField(blank=True, null=True)), | ||||
|                 ('enabled', models.IntegerField(blank=True, null=True)), | ||||
|                 ('sendonly', models.IntegerField(blank=True, null=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'mailboxes', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='Tlspolicies', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('domain', models.CharField(max_length=255)), | ||||
|                 ('policy', models.TextField()), | ||||
|                 ('params', models.CharField(blank=True, max_length=255, null=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'db_table': 'tlspolicies', | ||||
|                 'managed': False, | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | @ -3,27 +3,6 @@ from django.db import models | |||
| from django.utils import timezone | ||||
| 
 | ||||
| 
 | ||||
| class Question(models.Model): | ||||
|     question_text = models.CharField(max_length=200) | ||||
|     pub_date = models.DateTimeField('date published') | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.question_text | ||||
| 
 | ||||
|     def was_published_recently(self): | ||||
|         now = timezone.now() | ||||
|         return now - datetime.timedelta(days=1) <= self.pub_date <= now | ||||
| 
 | ||||
| 
 | ||||
| class Choice(models.Model): | ||||
|     question = models.ForeignKey(Question, on_delete=models.CASCADE) | ||||
|     choice_text = models.CharField(max_length=200) | ||||
|     votes = models.IntegerField(default=0) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.choice_text | ||||
| 
 | ||||
| 
 | ||||
| class Alias(models.Model): | ||||
|     id = models.AutoField(primary_key=True) | ||||
|     source_username = models.CharField(max_length=64) | ||||
|  | @ -67,3 +46,12 @@ class TLSPolicy(models.Model): | |||
|     class Meta: | ||||
|         managed = False | ||||
|         db_table = 'tlspolicies' | ||||
| 
 | ||||
| 
 | ||||
| class DomainOwner(models.Model): | ||||
|     domain = models.ForeignKey(Domain, on_delete=models.CASCADE, related_name='admin') | ||||
|     admin = models.CharField(max_length=200) | ||||
|     source = models.CharField(max_length=8, choices=[('system','system'), ('ldap', 'ldap'), ('mail', 'mail')], default=0) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.admin | ||||
|  |  | |||
							
								
								
									
										7
									
								
								backend/multimail/owner.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								backend/multimail/owner.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| 
 | ||||
| def user_from_request(request): | ||||
|     if hasattr(request.user, 'ldap_user'): | ||||
|         # print(request.user.ldap_user.attrs.data) | ||||
|         return {'name': request.user.username, 'source': 'ldap'} | ||||
|     else: | ||||
|         return {'name': request.user.username, 'source': 'system'} | ||||
|  | @ -16,13 +16,25 @@ | |||
| 
 | ||||
|             {% for alias in alias_list %} | ||||
|                 <tr> | ||||
|                     <th scope="row"><a href="{% url 'multimail:edit_alias' alias.id %}">{{ alias.source_username }}@{{ alias.source_domain }}</a></th> | ||||
|                     <th scope="row"><a | ||||
|                             href="{% url 'multimail:edit_alias' alias.id %}">{{ alias.source_username }}@{{ alias.source_domain }}</a> | ||||
|                     </th> | ||||
|                     <th scope="row">{{ alias.destination_username }}@{{ alias.destination_domain }}</th> | ||||
|                     <td><a href="{% url 'multimail:delete_alias' alias.id %}" class="btn btn-danger btn-sm m-0">Delete</a></td> | ||||
|                     <td><a href="{% url 'multimail:delete_alias' alias.id %}" | ||||
|                            class="btn btn-danger btn-sm m-0">Delete</a></td> | ||||
|                 </tr> | ||||
|             {% endfor %} | ||||
| 
 | ||||
|             </tbody> | ||||
|             <tfoot> | ||||
|             <tr> | ||||
|                 <th scope="row"> | ||||
|                 </th> | ||||
|                 <th scope="row"></th> | ||||
|                 <td><a href="{% url 'multimail:new_alias' %}" class="btn btn-primary btn-sm m-0">Add</a> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             </tfoot> | ||||
|         </table> | ||||
|     {% else %} | ||||
|         <p>You haven't set up any aliases yet.</p> | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ | |||
|     <div id="page-content-wrapper"> | ||||
| 
 | ||||
|         <nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom"> | ||||
|             <button class="btn btn-primary" id="menu-toggle">Toggle Menu</button> | ||||
|             <button class="btn btn-link btn-lg" id="menu-toggle"><i class="fas fa-bars"></i></button> | ||||
| 
 | ||||
|             <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" | ||||
|                     aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> | ||||
|  | @ -48,12 +48,12 @@ | |||
| 
 | ||||
|             <div class="collapse navbar-collapse" id="navbarSupportedContent"> | ||||
|                 <ul class="navbar-nav ml-auto mt-2 mt-lg-0"> | ||||
|                     <li class="nav-item active"> | ||||
|                     <!--li class="nav-item active"> | ||||
|                         <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> | ||||
|                     </li> | ||||
|                     <li class="nav-item"> | ||||
|                         <a class="nav-link" href="#">Link</a> | ||||
|                     </li> | ||||
|                     </li--> | ||||
|                     <li class="nav-item dropdown"> | ||||
|                         <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" | ||||
|                            data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | ||||
|  |  | |||
|  | @ -21,6 +21,14 @@ | |||
|             {% endfor %} | ||||
| 
 | ||||
|             </tbody> | ||||
|             <tfoot> | ||||
|             <tr> | ||||
|                 <th scope="row"> | ||||
|                 </th> | ||||
|                 <td><a href="{% url 'multimail:new_domain' %}" class="btn btn-primary btn-sm m-0">Add</a> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             </tfoot> | ||||
|         </table> | ||||
|     {% else %} | ||||
|         <p>You haven't set up any domains yet.</p> | ||||
|  |  | |||
|  | @ -21,6 +21,14 @@ | |||
|             {% endfor %} | ||||
| 
 | ||||
|             </tbody> | ||||
|             <tfoot> | ||||
|             <tr> | ||||
|                 <th scope="row"> | ||||
|                 </th> | ||||
|                 <td><a href="{% url 'multimail:new_mailbox' %}" class="btn btn-primary btn-sm m-0">Add</a> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             </tfoot> | ||||
|         </table> | ||||
|     {% else %} | ||||
|         <p>You haven't set up any mailboxes yet.</p> | ||||
|  |  | |||
|  | @ -9,14 +9,17 @@ urlpatterns = [ | |||
|     path('', views.DomainListView.as_view(), name='index'), | ||||
| 
 | ||||
|     path('domains/', views.DomainListView.as_view(), name='domains'), | ||||
|     path('domain/new/', forms.new_domain, name='new_domain'), | ||||
|     path('domain/<int:domain_id>/', forms.edit_domain, name='edit_domain'), | ||||
|     path('domain/<int:domain_id>/delete', actions.delete_domain, name='delete_domain'), | ||||
| 
 | ||||
|     path('mailboxes/', views.MailboxListView.as_view(), name='mailboxes'), | ||||
|     path('mailbox/new/', forms.new_mailbox, name='new_mailbox'), | ||||
|     path('mailbox/<int:mailbox_id>/', forms.edit_mailbox, name='edit_mailbox'), | ||||
|     path('mailbox/<int:mailbox_id>/delete', actions.delete_mailbox, name='delete_mailbox'), | ||||
| 
 | ||||
|     path('aliases/', views.AliasListView.as_view(), name='aliases'), | ||||
|     path('alias/new/', forms.new_alias, name='new_alias'), | ||||
|     path('alias/<int:alias_id>/', forms.edit_alias, name='edit_alias'), | ||||
|     path('alias/<int:alias_id>/delete', actions.delete_alias, name='delete_alias'), | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin | |||
| from django.contrib.auth.views import LoginView | ||||
| 
 | ||||
| from .models import Domain, Mailbox, Alias | ||||
| from .owner import user_from_request | ||||
| 
 | ||||
| 
 | ||||
| class UserLoginView(LoginView): | ||||
|  | @ -15,12 +16,9 @@ class DomainListView(LoginRequiredMixin, generic.ListView): | |||
|     context_object_name = 'domain_list' | ||||
| 
 | ||||
|     def get_queryset(self): | ||||
|         print(self.request.user) | ||||
|         """Return the last five published questions.""" | ||||
|         # return Domain.objects.filter( | ||||
|         #    pub_date__lte=timezone.now() | ||||
|         # ).order_by('-pub_date')[:5] | ||||
|         return Domain.objects.all() | ||||
|         user = user_from_request(self.request) | ||||
|         return Domain.objects.filter(admin__admin=user['name'], admin__source=user['source']) | ||||
| 
 | ||||
| 
 | ||||
| class MailboxListView(LoginRequiredMixin, generic.ListView): | ||||
|  | @ -29,12 +27,10 @@ class MailboxListView(LoginRequiredMixin, generic.ListView): | |||
|     context_object_name = 'mailbox_list' | ||||
| 
 | ||||
|     def get_queryset(self): | ||||
|         print(self.request.user) | ||||
|         """Return the last five published questions.""" | ||||
|         # return Domain.objects.filter( | ||||
|         #    pub_date__lte=timezone.now() | ||||
|         # ).order_by('-pub_date')[:5] | ||||
|         return Mailbox.objects.all() | ||||
|         user = user_from_request(self.request) | ||||
|         domains = [ o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         return Mailbox.objects.filter(domain__in=domains) | ||||
| 
 | ||||
| 
 | ||||
| class AliasListView(LoginRequiredMixin, generic.ListView): | ||||
|  | @ -43,9 +39,7 @@ class AliasListView(LoginRequiredMixin, generic.ListView): | |||
|     context_object_name = 'alias_list' | ||||
| 
 | ||||
|     def get_queryset(self): | ||||
|         print(self.request.user) | ||||
|         """Return the last five published questions.""" | ||||
|         # return Domain.objects.filter( | ||||
|         #    pub_date__lte=timezone.now() | ||||
|         # ).order_by('-pub_date')[:5] | ||||
|         return Alias.objects.all() | ||||
|         user = user_from_request(self.request) | ||||
|         domains = [ o.domain for o in Domain.objects.filter(admin__admin=user['name'], admin__source=user['source'])] | ||||
|         return Alias.objects.filter(source_domain__in=domains) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue