Log/archive deleted data #84
@ -1,9 +1,7 @@
|
|||||||
from urllib.parse import urljoin, urlparse
|
from urllib.parse import urlparse
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.contrib.sites.shortcuts import get_current_site
|
|
||||||
from django.template import Library, loader
|
from django.template import Library, loader
|
||||||
from django.template.defaultfilters import stringfilter
|
from django.template.defaultfilters import stringfilter
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
@ -22,22 +20,11 @@ register = Library()
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
|
||||||
def absolutify(url: str, request=None) -> str:
|
|
||||||
"""Return an absolute URL."""
|
|
||||||
if url and url.startswith(('http://', 'https://')):
|
|
||||||
return url
|
|
||||||
|
|
||||||
proto = 'http' if settings.DEBUG else 'https'
|
|
||||||
domain = get_current_site(request).domain
|
|
||||||
return urljoin(f'{proto}://{domain}', url)
|
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def absolute_url(context, path: str) -> str:
|
def absolute_url(context, path: str) -> str:
|
||||||
"""Return an absolute URL of a given path."""
|
"""Return an absolute URL of a given path."""
|
||||||
request = context.get('request')
|
request = context.get('request')
|
||||||
return absolutify(path, request=request)
|
return utils.absolutify(path, request=request)
|
||||||
|
|
||||||
|
|
||||||
class PaginationRenderer:
|
class PaginationRenderer:
|
||||||
|
20
notifications/admin.py
Normal file
20
notifications/admin.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from notifications.models import Notification
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationAdmin(admin.ModelAdmin):
|
||||||
|
readonly_fields = (
|
||||||
|
'recipient',
|
||||||
|
'action',
|
||||||
|
'email_sent',
|
||||||
|
'processed_by_mailer_at',
|
||||||
|
'read_at',
|
||||||
|
)
|
||||||
|
fields = readonly_fields
|
||||||
|
|
||||||
|
def get_queryset(self, request):
|
||||||
|
return Notification.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Notification, NotificationAdmin)
|
@ -3,7 +3,7 @@ from django.contrib.auth import get_user_model
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from constants.activity import Verb
|
from constants.activity import Verb
|
||||||
from common.templatetags.common import absolutify
|
from utils import absolutify
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ class RatingAdmin(admin.ModelAdmin):
|
|||||||
fields = ('status',) + readonly_fields
|
fields = ('status',) + readonly_fields
|
||||||
list_display = (
|
list_display = (
|
||||||
'date_created',
|
'date_created',
|
||||||
|
'extension',
|
||||||
'user',
|
'user',
|
||||||
'ip_address',
|
'ip_address',
|
||||||
'score',
|
'score',
|
||||||
|
@ -7,9 +7,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from common.model_mixins import CreatedModifiedMixin, TrackChangesMixin
|
from common.model_mixins import CreatedModifiedMixin, TrackChangesMixin
|
||||||
from common.templatetags import common
|
|
||||||
from constants.base import RATING_STATUS_CHOICES, RATING_SCORE_CHOICES
|
from constants.base import RATING_STATUS_CHOICES, RATING_SCORE_CHOICES
|
||||||
from utils import send_mail
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -139,46 +137,6 @@ class Rating(CreatedModifiedMixin, TrackChangesMixin, models.Model):
|
|||||||
qs = Rating.objects.filter(reply_to__in=ratings)
|
qs = Rating.objects.filter(reply_to__in=ratings)
|
||||||
return {r.reply_to_id: r for r in qs}
|
return {r.reply_to_id: r for r in qs}
|
||||||
|
|
||||||
def send_notification_email(self):
|
|
||||||
if self.reply_to:
|
|
||||||
# It's a reply.
|
|
||||||
reply_url = common.url(
|
|
||||||
'extensions.ratings.detail',
|
|
||||||
self.extension.slug,
|
|
||||||
self.reply_to.pk,
|
|
||||||
add_prefix=False,
|
|
||||||
)
|
|
||||||
data = {
|
|
||||||
'name': self.extension.name,
|
|
||||||
'reply': self.text,
|
|
||||||
'rating_url': common.absolutify(reply_url),
|
|
||||||
}
|
|
||||||
recipients = [self.reply_to.user.email]
|
|
||||||
subject = 'Blender Extensions: Developer Reply: %s' % self.extension.name
|
|
||||||
template = 'ratings/emails/reply_review.ltxt'
|
|
||||||
perm_setting = 'reply'
|
|
||||||
else:
|
|
||||||
# It's a new rating.
|
|
||||||
rating_url = common.url(
|
|
||||||
'extensions.ratings.detail', self.extension.slug, self.pk, add_prefix=False
|
|
||||||
)
|
|
||||||
data = {
|
|
||||||
'name': self.extension.name,
|
|
||||||
'rating': self,
|
|
||||||
'rating_url': common.absolutify(rating_url),
|
|
||||||
}
|
|
||||||
recipients = [author.email for author in self.extension.authors.all()]
|
|
||||||
subject = 'Blender Extensions: New User Rating: %s' % self.extension.name
|
|
||||||
template = 'ratings/emails/new_rating.txt'
|
|
||||||
perm_setting = 'new_review'
|
|
||||||
send_mail(
|
|
||||||
subject,
|
|
||||||
template,
|
|
||||||
data,
|
|
||||||
recipient_list=recipients,
|
|
||||||
perm_setting=perm_setting,
|
|
||||||
)
|
|
||||||
|
|
||||||
def post_save(sender, instance, created, **kwargs):
|
def post_save(sender, instance, created, **kwargs):
|
||||||
if kwargs.get('raw'):
|
if kwargs.get('raw'):
|
||||||
return
|
return
|
||||||
@ -194,10 +152,6 @@ class Rating(CreatedModifiedMixin, TrackChangesMixin, models.Model):
|
|||||||
else:
|
else:
|
||||||
log.info(f'{action} rating: {instance.pk}')
|
log.info(f'{action} rating: {instance.pk}')
|
||||||
|
|
||||||
# For new ratings and new replies we want to send an email.
|
|
||||||
if created:
|
|
||||||
instance.send_notification_email()
|
|
||||||
|
|
||||||
def get_report_url(self):
|
def get_report_url(self):
|
||||||
return reverse(
|
return reverse(
|
||||||
'abuse:report-ratings',
|
'abuse:report-ratings',
|
||||||
|
@ -10,8 +10,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
import common.help_texts
|
import common.help_texts
|
||||||
from extensions.models import Extension
|
from extensions.models import Extension
|
||||||
from common.model_mixins import CreatedModifiedMixin, RecordDeletionMixin
|
from common.model_mixins import CreatedModifiedMixin, RecordDeletionMixin
|
||||||
from common.templatetags.common import absolutify
|
from utils import absolutify, send_mail
|
||||||
from utils import send_mail
|
|
||||||
|
|
||||||
from constants.base import EXTENSION_TYPE_CHOICES
|
from constants.base import EXTENSION_TYPE_CHOICES
|
||||||
from constants.reviewers import CANNED_RESPONSE_CATEGORY_CHOICES
|
from constants.reviewers import CANNED_RESPONSE_CATEGORY_CHOICES
|
||||||
|
22
utils.py
22
utils.py
@ -1,4 +1,5 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from urllib.parse import urljoin
|
||||||
import datetime
|
import datetime
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
@ -12,7 +13,9 @@ from urllib.parse import (
|
|||||||
urlencode as urllib_urlencode,
|
urlencode as urllib_urlencode,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.sites.shortcuts import get_current_site
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import validate_ipv46_address
|
from django.core.validators import validate_ipv46_address
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
@ -45,8 +48,7 @@ def urlencode(items):
|
|||||||
|
|
||||||
|
|
||||||
def utc_millesecs_from_epoch(for_datetime=None):
|
def utc_millesecs_from_epoch(for_datetime=None):
|
||||||
"""
|
"""Returns millesconds from the Unix epoch in UTC.
|
||||||
Returns millesconds from the Unix epoch in UTC.
|
|
||||||
|
|
||||||
If `for_datetime` is None, the current datetime will be used.
|
If `for_datetime` is None, the current datetime will be used.
|
||||||
"""
|
"""
|
||||||
@ -70,8 +72,7 @@ def slugify(s: str):
|
|||||||
|
|
||||||
|
|
||||||
def urlparams(url_, hash=None, **query):
|
def urlparams(url_, hash=None, **query):
|
||||||
"""
|
"""Add a fragment and/or query parameters to a URL.
|
||||||
Add a fragment and/or query parameters to a URL.
|
|
||||||
|
|
||||||
New query params will be appended to existing parameters, except duplicate
|
New query params will be appended to existing parameters, except duplicate
|
||||||
names, which will be replaced.
|
names, which will be replaced.
|
||||||
@ -96,8 +97,7 @@ def send_mail(*args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def chunked(seq, n):
|
def chunked(seq, n):
|
||||||
"""
|
"""Yield successive n-sized chunks from seq.
|
||||||
Yield successive n-sized chunks from seq.
|
|
||||||
|
|
||||||
>>> for group in chunked(range(8), 3):
|
>>> for group in chunked(range(8), 3):
|
||||||
... print group
|
... print group
|
||||||
@ -179,3 +179,13 @@ def _remove_port_nr(remote_addr: str) -> str:
|
|||||||
return ipv6_with_port_match.group(1)
|
return ipv6_with_port_match.group(1)
|
||||||
|
|
||||||
return remote_addr
|
return remote_addr
|
||||||
|
|
||||||
|
|
||||||
|
def absolutify(url: str, request=None) -> str:
|
||||||
|
"""Return an absolute URL."""
|
||||||
|
if url and url.startswith(('http://', 'https://')):
|
||||||
|
return url
|
||||||
|
|
||||||
|
proto = 'http' if settings.DEBUG else 'https'
|
||||||
|
domain = get_current_site(request).domain
|
||||||
|
return urljoin(f'{proto}://{domain}', url)
|
||||||
|
Loading…
Reference in New Issue
Block a user