feat(newsletter): Add permission to send newsletter campaigns and update model options
This commit is contained in:
parent
c8bcdb0ee6
commit
4303c1f5db
@ -0,0 +1,20 @@
|
|||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("base", "0008_alter_contactformsubmission_options_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="newslettercampaign",
|
||||||
|
options={
|
||||||
|
"ordering": ["-created_at"],
|
||||||
|
"permissions": [("send_newslettercampaign", "Can send newsletter campaign")],
|
||||||
|
"verbose_name": "Newsletter Campaign",
|
||||||
|
"verbose_name_plural": "Newsletter Campaigns",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -459,6 +459,9 @@ class NewsletterCampaign(models.Model):
|
|||||||
ordering = ["-created_at"]
|
ordering = ["-created_at"]
|
||||||
verbose_name = _("Newsletter Campaign")
|
verbose_name = _("Newsletter Campaign")
|
||||||
verbose_name_plural = _("Newsletter Campaigns")
|
verbose_name_plural = _("Newsletter Campaigns")
|
||||||
|
permissions = [
|
||||||
|
("send_newslettercampaign", "Can send newsletter campaign"),
|
||||||
|
]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import json
|
|||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.admin.views.decorators import staff_member_required
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
from django.core.exceptions import ValidationError
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.core.exceptions import PermissionDenied, ValidationError
|
||||||
from django.core.validators import validate_email
|
from django.core.validators import validate_email
|
||||||
from django.http import HttpResponseNotAllowed, JsonResponse
|
from django.http import HttpResponseNotAllowed, JsonResponse
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
@ -35,6 +36,8 @@ from .newsletter_scheduler import dispatch_campaign
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SEND_NEWSLETTER_PERMISSION = "base.send_newslettercampaign"
|
||||||
|
|
||||||
|
|
||||||
@require_GET
|
@require_GET
|
||||||
def health_check(request):
|
def health_check(request):
|
||||||
@ -464,9 +467,12 @@ def one_click_unsubscribe(request):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@staff_member_required
|
@login_required
|
||||||
@require_GET
|
@require_GET
|
||||||
def newsletter_campaign_send_now(request, campaign_id: int):
|
def newsletter_campaign_send_now(request, campaign_id: int):
|
||||||
|
if not request.user.has_perm(SEND_NEWSLETTER_PERMISSION):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
campaign = get_object_or_404(NewsletterCampaign, pk=campaign_id)
|
campaign = get_object_or_404(NewsletterCampaign, pk=campaign_id)
|
||||||
if campaign.status == NewsletterCampaign.STATUS_SENDING:
|
if campaign.status == NewsletterCampaign.STATUS_SENDING:
|
||||||
messages.error(request, "Campaign is currently sending.")
|
messages.error(request, "Campaign is currently sending.")
|
||||||
|
|||||||
@ -10,6 +10,8 @@ from wagtail.snippets.views.snippets import CreateView, SnippetViewSet
|
|||||||
|
|
||||||
from .models import NewsletterCampaign, NewsletterDispatchRecord, NewsletterSystemSettings
|
from .models import NewsletterCampaign, NewsletterDispatchRecord, NewsletterSystemSettings
|
||||||
|
|
||||||
|
SEND_NEWSLETTER_PERMISSION = "base.send_newslettercampaign"
|
||||||
|
|
||||||
|
|
||||||
class NewsletterCampaignCreateView(CreateView):
|
class NewsletterCampaignCreateView(CreateView):
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
@ -89,7 +91,7 @@ register_snippet(NewsletterDispatchRecordViewSet)
|
|||||||
def newsletter_campaign_listing_buttons(snippet, user, next_url=None):
|
def newsletter_campaign_listing_buttons(snippet, user, next_url=None):
|
||||||
if not isinstance(snippet, NewsletterCampaign):
|
if not isinstance(snippet, NewsletterCampaign):
|
||||||
return
|
return
|
||||||
if not user.is_staff:
|
if not user.has_perm(SEND_NEWSLETTER_PERMISSION):
|
||||||
return
|
return
|
||||||
if snippet.status == NewsletterCampaign.STATUS_SENDING:
|
if snippet.status == NewsletterCampaign.STATUS_SENDING:
|
||||||
return
|
return
|
||||||
|
|||||||
@ -55,6 +55,28 @@ def env_optional(name, default=None):
|
|||||||
return normalized
|
return normalized
|
||||||
|
|
||||||
|
|
||||||
|
def build_media_storage_options():
|
||||||
|
options = {
|
||||||
|
"access_key": os.environ.get("AWS_ACCESS_KEY_ID"),
|
||||||
|
"secret_key": os.environ.get("AWS_SECRET_ACCESS_KEY"),
|
||||||
|
"bucket_name": os.environ.get("AWS_STORAGE_BUCKET_NAME"),
|
||||||
|
"region_name": os.environ.get("AWS_S3_REGION_NAME", default="us-east-1"),
|
||||||
|
"default_acl": env_optional("AWS_S3_DEFAULT_ACL"),
|
||||||
|
"querystring_auth": env_bool("AWS_S3_QUERYSTRING_AUTH", default=True),
|
||||||
|
"custom_domain": env_optional("AWS_S3_CUSTOM_DOMAIN"),
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint_url = env_optional("AWS_S3_ENDPOINT_URL")
|
||||||
|
if endpoint_url:
|
||||||
|
options["endpoint_url"] = endpoint_url
|
||||||
|
|
||||||
|
addressing_style = env_optional("AWS_S3_ADDRESSING_STYLE")
|
||||||
|
if addressing_style:
|
||||||
|
options["addressing_style"] = addressing_style
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
|
||||||
def detect_private_ip():
|
def detect_private_ip():
|
||||||
"""
|
"""
|
||||||
Return the primary private IPv4 address for this container when available.
|
Return the primary private IPv4 address for this container when available.
|
||||||
@ -258,15 +280,7 @@ MEDIA_URL = (
|
|||||||
STORAGES = {
|
STORAGES = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
|
"BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
|
||||||
"OPTIONS": {
|
"OPTIONS": build_media_storage_options(),
|
||||||
"access_key": os.environ.get("AWS_ACCESS_KEY_ID"),
|
|
||||||
"secret_key": os.environ.get("AWS_SECRET_ACCESS_KEY"),
|
|
||||||
"bucket_name": os.environ.get("AWS_STORAGE_BUCKET_NAME"),
|
|
||||||
"region_name": os.environ.get("AWS_S3_REGION_NAME", default="us-east-1"),
|
|
||||||
"default_acl": env_optional("AWS_S3_DEFAULT_ACL"),
|
|
||||||
"querystring_auth": env_bool("AWS_S3_QUERYSTRING_AUTH", default=True),
|
|
||||||
"custom_domain": env_optional("AWS_S3_CUSTOM_DOMAIN"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"staticfiles": {
|
"staticfiles": {
|
||||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user