diff --git a/django_messages/conf.py b/django_messages/conf.py new file mode 100644 index 0000000..0a3d133 --- /dev/null +++ b/django_messages/conf.py @@ -0,0 +1,8 @@ +from django.conf import settings +from appconf import AppConf + +class MessagesAppConf(AppConf): + DELETED_MAX_AGE = 30 + + class Meta: + prefix = 'MESSAGES' diff --git a/django_messages/management.py b/django_messages/management.py index 366296b..114be28 100644 --- a/django_messages/management.py +++ b/django_messages/management.py @@ -11,7 +11,9 @@ def create_notice_types(app, created_models, verbosity, **kwargs): notification.create_notice_type("messages_replied", _("Message Replied"), _("you have replied to a message"), default=1) notification.create_notice_type("messages_reply_received", _("Reply Received"), _("you have received a reply to a message"), default=2) notification.create_notice_type("messages_deleted", _("Message Deleted"), _("you have deleted a message"), default=1) + notification.create_notice_type("messages_permanently_deleted", _("Message Permanently Deleted"), _("you have permanently deleted a message"), default=0) notification.create_notice_type("messages_recovered", _("Message Recovered"), _("you have undeleted a message"), default=1) + notification.create_notice_type("empty_trash", _("Emptied Trash"), _("you have permanently deleted all messages in your trash bin"), default=0) signals.post_syncdb.connect(create_notice_types, sender=notification) else: diff --git a/django_messages/management/commands/delete_deleted_messages.py b/django_messages/management/commands/delete_deleted_messages.py index e79483d..9d1c758 100644 --- a/django_messages/management/commands/delete_deleted_messages.py +++ b/django_messages/management/commands/delete_deleted_messages.py @@ -2,18 +2,19 @@ from django.core.management.base import BaseCommand, CommandError from django.utils import timezone from ...models import Message +from django_messages.conf import settings class Command(BaseCommand): args = '' help = ( 'Deletes messages that have been marked as deleted by both the sender ' - 'and recipient. You must provide the minimum age in days.' + 'and recipient. Minimum age in days is pulled from settings or given as an argument.' ) def handle(self, *args, **options): if len(args) == 0: - raise CommandError('You must provide the minimum age in days.') + args = [settings.MESSAGES_DELETED_MAX_AGE] elif len(args) > 1: raise CommandError( 'This management command accepts only one argument.' diff --git a/django_messages/models.py b/django_messages/models.py index 5dd07f4..e3b5566 100644 --- a/django_messages/models.py +++ b/django_messages/models.py @@ -1,9 +1,11 @@ +import datetime from django.conf import settings from django.db import models from django.db.models import signals from django.utils import timezone from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ +from django_messages.conf import settings AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') @@ -33,14 +35,15 @@ def outbox_for(self, user): def trash_for(self, user): """ Returns all messages that were either received or sent by the given - user and are marked as deleted. + user and are marked as deleted since less than MESSAGES_DELETED_MAX_AGE days. """ + the_date = timezone.now() - datetime.timedelta(days=settings.MESSAGES_DELETED_MAX_AGE) return self.filter( recipient=user, - recipient_deleted_at__isnull=False, + recipient_deleted_at__gt=the_date, ) | self.filter( sender=user, - sender_deleted_at__isnull=False, + sender_deleted_at__gt=the_date, ) diff --git a/django_messages/templates/django_messages/trash.html b/django_messages/templates/django_messages/trash.html index 02fb11e..b769829 100644 --- a/django_messages/templates/django_messages/trash.html +++ b/django_messages/templates/django_messages/trash.html @@ -5,6 +5,7 @@ {% block content %}

{% trans "Deleted Messages" %}

{% if message_list %} +{% trans "Empty trash" %} @@ -17,7 +18,7 @@

{% trans "Deleted Messages" %}

{{ message.subject }} - + {% endfor %} @@ -26,5 +27,5 @@

{% trans "Deleted Messages" %}

{% trans "No messages." %}

{% endif %}
-

{% trans "Deleted Messages are removed from the trash at unregular intervals, don't rely on this feature for long-time storage." %}

+

{% blocktrans with deleted_max_age=max_age %} Deleted Messages are removed from the trash after {{deleted_max_age}} days, don't rely on this feature for long-time storage.{% endblocktrans %}

{% endblock %} \ No newline at end of file diff --git a/django_messages/urls.py b/django_messages/urls.py index 1effc02..23e6cd4 100644 --- a/django_messages/urls.py +++ b/django_messages/urls.py @@ -12,6 +12,8 @@ url(r'^reply/(?P[\d]+)/$', reply, name='messages_reply'), url(r'^view/(?P[\d]+)/$', view, name='messages_detail'), url(r'^delete/(?P[\d]+)/$', delete, name='messages_delete'), + url(r'^permanently_delete/(?P[\d]+)/$', permanently_delete, name='messages_permanently_delete'), url(r'^undelete/(?P[\d]+)/$', undelete, name='messages_undelete'), url(r'^trash/$', trash, name='messages_trash'), + url(r'^empty_trash/$', empty_trash, name='messages_empty_trash'), ) diff --git a/django_messages/views.py b/django_messages/views.py index 3341c32..9d458f0 100644 --- a/django_messages/views.py +++ b/django_messages/views.py @@ -1,3 +1,4 @@ +import datetime from django.http import Http404, HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext @@ -11,6 +12,7 @@ from django_messages.models import Message from django_messages.forms import ComposeForm from django_messages.utils import format_quote, get_user_model, get_username_field +from django_messages.conf import settings User = get_user_model() @@ -46,7 +48,7 @@ def outbox(request, template_name='django_messages/outbox.html'): @login_required def trash(request, template_name='django_messages/trash.html'): """ - Displays a list of deleted messages. + Displays a list of deleted messages which are less than MESSAGES_DELETED_MAX_AGE days old. Optional arguments: ``template_name``: name of the template to use Hint: A Cron-Job could periodicly clean up old messages, which are deleted @@ -54,7 +56,7 @@ def trash(request, template_name='django_messages/trash.html'): """ message_list = Message.objects.trash_for(request.user) return render_to_response(template_name, { - 'message_list': message_list, + 'message_list': message_list, 'max_age': settings.MESSAGES_DELETED_MAX_AGE }, context_instance=RequestContext(request)) @login_required @@ -189,6 +191,64 @@ def undelete(request, message_id, success_url=None): return HttpResponseRedirect(success_url) raise Http404 +def permanently_delete_message(user, message): + """ + Function called to permanently delete a message + """ + permanently_deleted_date = timezone.now() - datetime.timedelta(days=settings.MESSAGES_DELETED_MAX_AGE) + deleted = False + + if message.sender == user: + message.sender_deleted_at = permanently_deleted_date + deleted = True + if message.recipient == user: + message.recipient_deleted_at = permanently_deleted_date + deleted = True + if deleted: + message.save() + if message.sender_deleted_at and message.recipient_deleted_at: + if message.sender_deleted_at <= permanently_deleted_date and message.recipient_deleted_at <= permanently_deleted_date: + message.delete() + return deleted + +@login_required +def permanently_delete(request, message_id, success_url=None): + """ + Marks a message as permanently deleted by sender or recipient. + This is done by marking deleted_at to more than MESSAGES_DELETED_MAX_AGE + days ago. + The message is permanently deleted if both users permanently deleted it or + if it was deleted more than MESSAGES_DELETED_MAX_AGE days ago. + """ + message = get_object_or_404(Message, id=message_id) + if success_url is None: + success_url = reverse('messages_inbox') + if 'next' in request.GET: + success_url = request.GET['next'] + if permanently_delete_message(request.user, message): + messages.info(request, _(u"Message permanently deleted.")) + if notification: + notification.send([user], "messages_permanently_deleted") + return HttpResponseRedirect(success_url) + raise Http404 + +@login_required +def empty_trash(request, success_url=None): + """ + Empties a user's trash. + """ + if success_url is None: + success_url = reverse('messages_inbox') + if 'next' in request.GET: + success_url = request.GET['next'] + message_list = Message.objects.trash_for(request.user) + for message in message_list.all(): + permanently_delete_message(request.user, message) + messages.info(request, _(u"Trash is now empty.")) + if notification: + notification.send([user], "trash_empty") + return HttpResponseRedirect(success_url) + @login_required def view(request, message_id, form_class=ComposeForm, quote_helper=format_quote, subject_template=_(u"Re: %(subject)s"), diff --git a/setup.py b/setup.py index 5530c06..ba20cf8 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,9 @@ 'locale/*/LC_MESSAGES/*', ] }, + install_requires=[ + "django-appconf>=0.6", + ], classifiers=( 'Development Status :: 4 - Beta', 'Environment :: Web Environment',
{% trans "Sender" %}{% trans "Subject" %}{% trans "Date" %}{% trans "Action" %}
{{ message.sent_at|date:_("DATETIME_FORMAT") }}{% trans "undelete" %}{% trans "undelete" %}, {% trans "permanently delete" %}