From 816d26d09438fae35927547bbdbf9549884d816b Mon Sep 17 00:00:00 2001
From: Will Gearty
Date: Thu, 28 Apr 2022 19:35:12 -0500
Subject: [PATCH] Add user interface for URL and email redirects (#3523)
* Add user interface for URL and email redirects
* Move help text to fix failing test
* Fix less than/greater than
* Fix lint error
* Fix test?
---
esp/esp/dbmail/models.py | 4 +-
esp/esp/program/forms.py | 16 ++
esp/esp/program/urls.py | 1 +
esp/esp/program/views.py | 82 +++++++++-
esp/templates/program/manage_programs.html | 2 +
esp/templates/program/redirects.html | 173 +++++++++++++++++++++
6 files changed, 274 insertions(+), 4 deletions(-)
create mode 100644 esp/templates/program/redirects.html
diff --git a/esp/esp/dbmail/models.py b/esp/esp/dbmail/models.py
index 82d92c6a52..3279fcae88 100644
--- a/esp/esp/dbmail/models.py
+++ b/esp/esp/dbmail/models.py
@@ -601,9 +601,9 @@ class PlainRedirect(models.Model):
A simple catch-all for mail redirection.
"""
- original = models.CharField(max_length=512)
+ original = models.CharField(max_length=512, help_text='A real or custom email address name (e.g., "directors" or "splash"). Any emails to <original>@<yourdomain> will be redirected to the destination email address(es).')
- destination = models.CharField(max_length=512)
+ destination = models.CharField(max_length=512, help_text='A comma-seperated list of one or more real email address(es) that will receive the redirected email(s)')
def __unicode__(self):
return '%s --> %s' % (self.original, self.destination)
diff --git a/esp/esp/program/forms.py b/esp/esp/program/forms.py
index a3631ce045..36674a8cd9 100644
--- a/esp/esp/program/forms.py
+++ b/esp/esp/program/forms.py
@@ -38,9 +38,12 @@
from esp.users.models import StudentInfo, K12School
from esp.program.models import Program, ProgramModule, ClassFlag, ClassFlagType, ClassCategories
+from esp.dbmail.models import PlainRedirect
from esp.utils.widgets import DateTimeWidget
from django import forms
from django.core import validators
+from django.contrib.redirects.models import Redirect
+from django.contrib.sites.models import Site
from form_utils.forms import BetterModelForm, BetterForm
from django.utils.safestring import mark_safe
from esp.tagdict import all_global_tags, tag_categories
@@ -423,6 +426,19 @@ class Meta:
model = ClassCategories
fields = ['category','symbol','seq']
+class RedirectForm(forms.ModelForm):
+ class Meta:
+ model = Redirect
+ fields = ['old_path', 'new_path']
+
+class PlainRedirectForm(forms.ModelForm):
+ def __init__(self, *args, **kwargs):
+ super(PlainRedirectForm, self).__init__(*args, **kwargs)
+ self.fields['original'].help_text = 'A real or custom email address name (e.g., "directors" or "splash"). Any emails to <original>@%s will be redirected to the destination email address(es).' % Site.objects.get_current().domain
+ class Meta:
+ model = PlainRedirect
+ fields = ['original', 'destination']
+
class TagSettingsForm(BetterForm):
""" Form for changing global tags. """
def __init__(self, *args, **kwargs):
diff --git a/esp/esp/program/urls.py b/esp/esp/program/urls.py
index a561ae404f..3c72208d13 100644
--- a/esp/esp/program/urls.py
+++ b/esp/esp/program/urls.py
@@ -18,6 +18,7 @@
url(r'^manage/emails/?$', views.emails),
url(r'^manage/categoriesandflags/?(?P[^/]*)/?$', views.categoriesandflags),
url(r'^manage/tags/?(?P[^/]*)/?$', views.tags),
+ url(r'^manage/redirects/?(?P[^/]*)/?$', views.redirects),
url(r'^manage/statistics/?$', views.statistics),
url(r'^manage/preview/?$', views.template_preview),
url(r'^manage/mergeaccounts/?$', esp.users.views.merge.merge_accounts),
diff --git a/esp/esp/program/views.py b/esp/esp/program/views.py
index 8e564d3606..6df5aaa0de 100644
--- a/esp/esp/program/views.py
+++ b/esp/esp/program/views.py
@@ -50,6 +50,8 @@
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
+from django.contrib.redirects.models import Redirect
+from django.contrib.sites.models import Site
from django.db.models.query import Q
from django.db.models import Min
from django.db import transaction
@@ -64,7 +66,7 @@
from esp.program.modules.module_ext import ClassRegModuleInfo, StudentClassRegModuleInfo
from esp.program.models import Program, TeacherBio, RegistrationType, ClassSection, StudentRegistration, VolunteerOffer, RegistrationProfile, ClassCategories, ClassFlagType
-from esp.program.forms import ProgramCreationForm, StatisticsQueryForm, TagSettingsForm, CategoryForm, FlagTypeForm
+from esp.program.forms import ProgramCreationForm, StatisticsQueryForm, TagSettingsForm, CategoryForm, FlagTypeForm, RedirectForm, PlainRedirectForm
from esp.program.setup import prepare_program, commit_program
from esp.program.controllers.confirmation import ConfirmationEmailController
from esp.program.controllers.studentclassregmodule import RegistrationTypeController as RTC
@@ -74,7 +76,7 @@
from esp.middleware import ESPError
from esp.accounting.controllers import ProgramAccountingController, IndividualAccountingController
from esp.accounting.models import CybersourcePostback
-from esp.dbmail.models import MessageRequest, TextOfEmail
+from esp.dbmail.models import MessageRequest, TextOfEmail, PlainRedirect
from esp.mailman import create_list, load_list_settings, apply_list_settings, add_list_members
from esp.resources.models import ResourceType
from esp.tagdict.models import Tag
@@ -839,6 +841,82 @@ def tags(request, section=""):
return render_to_response('program/modules/admincore/tags.html', request, context)
+@admin_required
+def redirects(request, section=""):
+ """
+ View that lets admins create/edit URL and email redirects
+ """
+ context = {}
+ redirect_form = RedirectForm()
+ email_redirect_form = PlainRedirectForm()
+
+ if request.method == 'POST':
+ if request.POST.get('object') == 'redirect':
+ section = 'redirects'
+ if request.POST.get('command') == 'add': # New redirect
+ redirect_form = RedirectForm(request.POST)
+ if redirect_form.is_valid():
+ redirect = redirect_form.save(commit=False)
+ redirect.site = Site.objects.get_current()
+ redirect.save()
+ redirect_form = RedirectForm()
+ elif request.POST.get('command') == 'load': # Load existing redirect into form
+ redirect_id = request.POST.get('id')
+ redirects = Redirect.objects.filter(id = redirect_id)
+ if redirects.count() == 1:
+ redirect = redirects[0]
+ redirect_form = RedirectForm(instance = redirect)
+ elif request.POST.get('command') == 'edit': # Edit existing redirect
+ redirect_id = request.POST.get('id')
+ redirects = Redirect.objects.filter(id = redirect_id)
+ if redirects.count() == 1:
+ redirect = redirects[0]
+ redirect_form = RedirectForm(request.POST, instance = redirect)
+ if redirect_form.is_valid():
+ redirect_form.save()
+ redirect_form = RedirectForm()
+ elif request.POST.get('command') == 'delete': # Delete redirect
+ redirect_id = request.POST.get('id')
+ redirects = Redirect.objects.filter(id = redirect_id)
+ if redirects.count() == 1:
+ redirect = redirects[0]
+ redirect.delete()
+ elif request.POST.get('object') == 'email_redirect':
+ section = 'email_redirects'
+ if request.POST.get('command') == 'add': # New email redirect
+ email_redirect_form = PlainRedirectForm(request.POST)
+ if email_redirect_form.is_valid():
+ email_redirect_form.save()
+ email_redirect_form = PlainRedirectForm()
+ elif request.POST.get('command') == 'load': # Load existing email redirect into form
+ redirect_id = request.POST.get('id')
+ redirects = PlainRedirect.objects.filter(id = redirect_id)
+ if redirects.count() == 1:
+ redirect = redirects[0]
+ email_redirect_form = PlainRedirectForm(instance = redirect)
+ elif request.POST.get('command') == 'edit': # Edit existing email redirect
+ redirect_id = request.POST.get('id')
+ redirects = PlainRedirect.objects.filter(id = redirect_id)
+ if redirects.count() == 1:
+ redirect = redirects[0]
+ email_redirect_form = PlainRedirectForm(request.POST, instance = redirect)
+ if email_redirect_form.is_valid():
+ email_redirect_form.save()
+ email_redirect_form = PlainRedirectForm()
+ elif request.POST.get('command') == 'delete': # Delete email redirect
+ redirect_id = request.POST.get('id')
+ redirects = PlainRedirect.objects.filter(id = redirect_id)
+ if redirects.count() == 1:
+ redirect = redirects[0]
+ redirect.delete()
+ context['open_section'] = section
+ context['redirect_form'] = redirect_form
+ context['email_redirect_form'] = email_redirect_form
+ context['redirects'] = Redirect.objects.all()
+ context['email_redirects'] = PlainRedirect.objects.all()
+
+ return render_to_response('program/redirects.html', request, context)
+
@admin_required
def categoriesandflags(request, section=""):
"""
diff --git a/esp/templates/program/manage_programs.html b/esp/templates/program/manage_programs.html
index 75b6292a53..0fed247d58 100644
--- a/esp/templates/program/manage_programs.html
+++ b/esp/templates/program/manage_programs.html
@@ -30,6 +30,8 @@ Hello Admins!
Manage class categories and flag types
+ Manage URL and email redirects
+
Modify tag settings (generic miscellaneous settings, for experts only)
diff --git a/esp/templates/program/redirects.html b/esp/templates/program/redirects.html
new file mode 100644
index 0000000000..f78858e28d
--- /dev/null
+++ b/esp/templates/program/redirects.html
@@ -0,0 +1,173 @@
+{% extends "main.html" %}
+
+{% block title %}
+ URL and Email Redirect Management
+{% endblock %}
+
+{% block stylesheets %}
+ {{ block.super }}
+
+
+{% endblock %}
+
+{% block xtrajs %}
+
+{% endblock %}
+
+{% block content %}
+
+
+ URL and Email Redirect Management
+
+
+Welcome to the redirect management page. Here you can create, edit, and delete URL redirects which redirect users from one URL to another and
+email redirects which redirect emails sent to a custom or real email address on your domain to one or more real email addresses on any domain.
+
+