Sybren A. Stüvel
375cab6e6e
Notes can now be added to *any* model in the admin. Deletion is immediate and irreversible. The following permissions can be granted to users/groups: - blender_notes.add_note - blender_notes.change_note - blender_notes.delete_note - blender_notes.view_note WARNING: a user with view_note permissions can view *ALL* notes. There is no model-level access. In other words, even when someone cannot see Memberships, they can read ALL notes on ALL Memberships.
92 lines
3.6 KiB
Python
92 lines
3.6 KiB
Python
import logging
|
|
|
|
from django.contrib.auth.decorators import permission_required
|
|
from django.http import HttpResponseBadRequest
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.utils.decorators import method_decorator
|
|
from django.views import View
|
|
from django.views.generic.edit import FormView
|
|
from django.shortcuts import redirect
|
|
|
|
from . import forms, models
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class NotesView(FormView):
|
|
"""Fetching and creating notes."""
|
|
template_name = 'blender_notes/notes_in_admin.html'
|
|
form_class = forms.NoteForm
|
|
|
|
@method_decorator(permission_required('blender_notes.view_note', raise_exception=True))
|
|
def get(self, request, *args, **kwargs):
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
@method_decorator(permission_required('blender_notes.add_note', raise_exception=True))
|
|
def post(self, request, *args, **kwargs):
|
|
return super().post(request, *args, **kwargs)
|
|
|
|
def form_valid(self, form):
|
|
ctype = ContentType.objects.get_by_natural_key(
|
|
self.kwargs['app_label'], self.kwargs['model_name'])
|
|
|
|
log.info('Attaching note to %s %s %s for user %s',
|
|
self.kwargs['app_label'], self.kwargs['model_name'], self.kwargs['object_id'],
|
|
self.request.user)
|
|
|
|
note: models.Note = form.instance
|
|
note.creator = self.request.user
|
|
note.object_id = self.kwargs['object_id']
|
|
note.content_type = ctype
|
|
note.save()
|
|
|
|
context = self.get_context_data(**self.kwargs)
|
|
|
|
# Note was succesfully added, start with a fresh form instead of from POSTed data.
|
|
form_class = self.get_form_class()
|
|
context['form'] = form_class()
|
|
|
|
return self.render_to_response(context)
|
|
|
|
def get_context_data(self, **kwargs) -> dict:
|
|
context = super().get_context_data(**kwargs)
|
|
context.update(self.kwargs)
|
|
query = models.Note.objects.get_by_natural_key(
|
|
self.kwargs['app_label'],
|
|
self.kwargs['model_name'],
|
|
self.kwargs['object_id'])
|
|
context['notes'] = query
|
|
return context
|
|
|
|
def get_success_url(self):
|
|
return self.request.get_raw_uri()
|
|
|
|
|
|
class DeleteNoteView(View):
|
|
|
|
@method_decorator(permission_required('blender_notes.delete_note', raise_exception=True))
|
|
def post(self, request, **kwargs):
|
|
app_label = self.kwargs['app_label']
|
|
model_name = self.kwargs['model_name']
|
|
object_id = self.kwargs['object_id']
|
|
note_id = self.kwargs['note_id']
|
|
|
|
note = models.Note.objects.get(pk=note_id)
|
|
if note.object_id != object_id:
|
|
log.warning('Not deleting note %d, it was called for object_id=%d but '
|
|
'belongs to object_id=%d', note.pk, object_id)
|
|
return HttpResponseBadRequest('Mismatched Object ID')
|
|
if note.content_type.model != model_name or note.content_type.app_label != app_label:
|
|
log.warning('Not deleting note %d, it was called for content_type=%r/%r but '
|
|
'belongs to content_type=%r/%r', note.pk, app_label, model_name,
|
|
note.content_type.app_label, note.content_type.model)
|
|
return HttpResponseBadRequest('Mismatched Content Type')
|
|
|
|
log.info('Deleting note %d of %s %s %s on behalf of user %s',
|
|
note_id, app_label, model_name, object_id, self.request.user)
|
|
note.delete()
|
|
return redirect('notes:for-object',
|
|
app_label=app_label,
|
|
model_name=model_name,
|
|
object_id=object_id)
|