feat: Add permission control to edit and add-to actions
This commit is contained in:
parent
97b19a3b6e
commit
8c51597c29
@ -1,4 +1,3 @@
|
|||||||
from django.contrib.auth.models import User
|
|
||||||
from model_bakery.recipe import Recipe, seq
|
from model_bakery.recipe import Recipe, seq
|
||||||
from fellchensammlung.models import *
|
from fellchensammlung.models import *
|
||||||
|
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-08-06 17:23
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("fellchensammlung", "0003_subscriptions"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="adoptionnotice",
|
||||||
|
old_name="created_by",
|
||||||
|
new_name="owner",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="subscriptions",
|
||||||
|
old_name="user",
|
||||||
|
new_name="owner",
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="animal",
|
||||||
|
name="owner",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
default=1,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="image",
|
||||||
|
name="owner",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
default=1,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
@ -74,10 +74,15 @@ class User(AbstractUser):
|
|||||||
def get_num_unread_notifications(self):
|
def get_num_unread_notifications(self):
|
||||||
return BaseNotification.objects.filter(user=self,read=False).count()
|
return BaseNotification.objects.filter(user=self,read=False).count()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def owner(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
class Image(models.Model):
|
class Image(models.Model):
|
||||||
image = models.ImageField(upload_to='images')
|
image = models.ImageField(upload_to='images')
|
||||||
alt_text = models.TextField(max_length=2000)
|
alt_text = models.TextField(max_length=2000)
|
||||||
|
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.alt_text
|
return self.alt_text
|
||||||
@ -164,7 +169,7 @@ class AdoptionNotice(models.Model):
|
|||||||
photos = models.ManyToManyField(Image, blank=True)
|
photos = models.ManyToManyField(Image, blank=True)
|
||||||
location_string = models.CharField(max_length=200, verbose_name=_("Ortsangabe"))
|
location_string = models.CharField(max_length=200, verbose_name=_("Ortsangabe"))
|
||||||
location = models.ForeignKey(Location, blank=True, null=True, on_delete=models.SET_NULL, )
|
location = models.ForeignKey(Location, blank=True, null=True, on_delete=models.SET_NULL, )
|
||||||
created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('Creator'))
|
owner = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('Creator'))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def animals(self):
|
def animals(self):
|
||||||
@ -328,6 +333,7 @@ class Animal(models.Model):
|
|||||||
photos = models.ManyToManyField(Image, blank=True)
|
photos = models.ManyToManyField(Image, blank=True)
|
||||||
sex = models.CharField(max_length=20, choices=SEX_CHOICES, )
|
sex = models.CharField(max_length=20, choices=SEX_CHOICES, )
|
||||||
adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE)
|
adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE)
|
||||||
|
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name}"
|
return f"{self.name}"
|
||||||
@ -566,6 +572,6 @@ class CommentNotification(BaseNotification):
|
|||||||
|
|
||||||
|
|
||||||
class Subscriptions(models.Model):
|
class Subscriptions(models.Model):
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('Nutzer*in'))
|
owner = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('Nutzer*in'))
|
||||||
adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE, verbose_name=_('AdoptionNotice'))
|
adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE, verbose_name=_('AdoptionNotice'))
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
@ -22,8 +22,18 @@ from .tools.metrics import gather_metrics_data
|
|||||||
from django.contrib.auth.decorators import user_passes_test
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
|
|
||||||
|
|
||||||
def user_is_mod_or_above(user):
|
def user_is_trust_level_or_above(user, trust_level=User.MODERATOR):
|
||||||
return user.is_authenticated and user.trust_level > User.TRUST_LEVEL[User.MODERATOR]
|
return user.is_authenticated and user.trust_level >= User.TRUST_LEVEL[trust_level]
|
||||||
|
|
||||||
|
|
||||||
|
def user_is_owner_or_trust_level(user, django_object, trust_level=User.MODERATOR):
|
||||||
|
return user.is_authenticated and (
|
||||||
|
user.trust_level == User.TRUST_LEVEL[trust_level] or django_object.owner == user)
|
||||||
|
|
||||||
|
|
||||||
|
def fail_if_user_not_owner_or_trust_level(user, django_object, trust_level=User.MODERATOR):
|
||||||
|
if not user_is_owner_or_trust_level(user, django_object, trust_level):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
@ -68,7 +78,8 @@ def adoption_notice_detail(request, adoption_notice_id):
|
|||||||
comment_instance.save()
|
comment_instance.save()
|
||||||
|
|
||||||
# Auto-subscribe user to adoption notice
|
# Auto-subscribe user to adoption notice
|
||||||
subscription, created = Subscriptions.objects.get_or_create(adoption_notice=adoption_notice, user=request.user)
|
subscription, created = Subscriptions.objects.get_or_create(adoption_notice=adoption_notice,
|
||||||
|
user=request.user)
|
||||||
subscription.save()
|
subscription.save()
|
||||||
|
|
||||||
# Notify users that a comment was added
|
# Notify users that a comment was added
|
||||||
@ -94,6 +105,7 @@ def adoption_notice_edit(request, adoption_notice_id):
|
|||||||
Form to update adoption notices
|
Form to update adoption notices
|
||||||
"""
|
"""
|
||||||
adoption_notice = AdoptionNotice.objects.get(pk=adoption_notice_id)
|
adoption_notice = AdoptionNotice.objects.get(pk=adoption_notice_id)
|
||||||
|
fail_if_user_not_owner_or_trust_level(request.user, adoption_notice)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = AdoptionNoticeForm(request.POST, instance=adoption_notice)
|
form = AdoptionNoticeForm(request.POST, instance=adoption_notice)
|
||||||
|
|
||||||
@ -148,12 +160,14 @@ def add_adoption_notice(request):
|
|||||||
# Set correct status
|
# Set correct status
|
||||||
if request.user.trust_level >= User.TRUST_LEVEL[User.COORDINATOR]:
|
if request.user.trust_level >= User.TRUST_LEVEL[User.COORDINATOR]:
|
||||||
status = AdoptionNoticeStatus.objects.create(major_status=AdoptionNoticeStatus.ACTIVE,
|
status = AdoptionNoticeStatus.objects.create(major_status=AdoptionNoticeStatus.ACTIVE,
|
||||||
minor_status=AdoptionNoticeStatus.MINOR_STATUS_CHOICES[AdoptionNoticeStatus.ACTIVE]["searching"],
|
minor_status=AdoptionNoticeStatus.MINOR_STATUS_CHOICES[
|
||||||
|
AdoptionNoticeStatus.ACTIVE]["searching"],
|
||||||
adoption_notice=instance)
|
adoption_notice=instance)
|
||||||
status.save()
|
status.save()
|
||||||
else:
|
else:
|
||||||
status = AdoptionNoticeStatus.objects.create(major_status=AdoptionNoticeStatus.AWAITING_ACTION,
|
status = AdoptionNoticeStatus.objects.create(major_status=AdoptionNoticeStatus.AWAITING_ACTION,
|
||||||
minor_status=AdoptionNoticeStatus.MINOR_STATUS_CHOICES[AdoptionNoticeStatus.AWAITING_ACTION][
|
minor_status=AdoptionNoticeStatus.MINOR_STATUS_CHOICES[
|
||||||
|
AdoptionNoticeStatus.AWAITING_ACTION][
|
||||||
"waiting_for_review"],
|
"waiting_for_review"],
|
||||||
adoption_notice=instance)
|
adoption_notice=instance)
|
||||||
status.save()
|
status.save()
|
||||||
@ -166,6 +180,9 @@ def add_adoption_notice(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def adoption_notice_add_animal(request, adoption_notice_id):
|
def adoption_notice_add_animal(request, adoption_notice_id):
|
||||||
|
# Only users that are mods or owners of the adoption notice are allowed to add to it
|
||||||
|
adoption_notice = AdoptionNotice.objects.get(pk=adoption_notice_id)
|
||||||
|
fail_if_user_not_owner_or_trust_level(request.user, adoption_notice)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = AnimalFormWithDateWidget(request.POST, request.FILES)
|
form = AnimalFormWithDateWidget(request.POST, request.FILES)
|
||||||
|
|
||||||
@ -187,6 +204,8 @@ def adoption_notice_add_animal(request, adoption_notice_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def add_photo_to_animal(request, animal_id):
|
def add_photo_to_animal(request, animal_id):
|
||||||
animal = Animal.objects.get(id=animal_id)
|
animal = Animal.objects.get(id=animal_id)
|
||||||
|
# Only users that are mods or owners of the animal are allowed to add to it
|
||||||
|
fail_if_user_not_owner_or_trust_level(request.user, animal)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = ImageForm(request.POST, request.FILES)
|
form = ImageForm(request.POST, request.FILES)
|
||||||
|
|
||||||
@ -206,6 +225,8 @@ def add_photo_to_animal(request, animal_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def add_photo_to_adoption_notice(request, adoption_notice_id):
|
def add_photo_to_adoption_notice(request, adoption_notice_id):
|
||||||
adoption_notice = AdoptionNotice.objects.get(id=adoption_notice_id)
|
adoption_notice = AdoptionNotice.objects.get(id=adoption_notice_id)
|
||||||
|
# Only users that are mods or owners of the adoption notice are allowed to add to it
|
||||||
|
fail_if_user_not_owner_or_trust_level(request.user, adoption_notice)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = ImageForm(request.POST, request.FILES)
|
form = ImageForm(request.POST, request.FILES)
|
||||||
|
|
||||||
@ -229,6 +250,8 @@ def animal_edit(request, animal_id):
|
|||||||
* Updating an Animal
|
* Updating an Animal
|
||||||
"""
|
"""
|
||||||
animal = Animal.objects.get(pk=animal_id)
|
animal = Animal.objects.get(pk=animal_id)
|
||||||
|
# Only users that are mods or owners of the animal are allowed to edit it
|
||||||
|
fail_if_user_not_owner_or_trust_level(request.user, animal)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = AnimalForm(request.POST, instance=animal)
|
form = AnimalForm(request.POST, instance=animal)
|
||||||
|
|
||||||
@ -323,11 +346,13 @@ def report_detail_success(request, report_id):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def user_detail(request, user_id):
|
def user_detail(request, user_id):
|
||||||
|
user = User.objects.get(id=user_id)
|
||||||
|
# Only users that are mods or owners of the user are allowed to view
|
||||||
|
fail_if_user_not_owner_or_trust_level(request.user, user)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
action = request.POST.get("action")
|
action = request.POST.get("action")
|
||||||
if action == "notification_mark_read":
|
if action == "notification_mark_read":
|
||||||
notification_id = request.POST.get("notification_id")
|
notification_id = request.POST.get("notification_id")
|
||||||
print(notification_id)
|
|
||||||
notification = CommentNotification.objects.get(pk=notification_id)
|
notification = CommentNotification.objects.get(pk=notification_id)
|
||||||
notification.read = True
|
notification.read = True
|
||||||
notification.save()
|
notification.save()
|
||||||
@ -337,14 +362,13 @@ def user_detail(request, user_id):
|
|||||||
notification.read = True
|
notification.read = True
|
||||||
notification.save()
|
notification.save()
|
||||||
|
|
||||||
user = User.objects.get(id=user_id)
|
|
||||||
context = {"user": user,
|
context = {"user": user,
|
||||||
"adoption_notices": AdoptionNotice.objects.filter(created_by=user),
|
"adoption_notices": AdoptionNotice.objects.filter(owner=user),
|
||||||
"notifications": CommentNotification.objects.filter(user=user, read=False)}
|
"notifications": CommentNotification.objects.filter(user=user, read=False)}
|
||||||
return render(request, 'fellchensammlung/details/detail-user.html', context=context)
|
return render(request, 'fellchensammlung/details/detail-user.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
@user_passes_test(user_is_mod_or_above)
|
@user_passes_test(user_is_trust_level_or_above)
|
||||||
def modqueue(request):
|
def modqueue(request):
|
||||||
open_reports = Report.objects.filter(status=Report.WAITING)
|
open_reports = Report.objects.filter(status=Report.WAITING)
|
||||||
context = {"reports": open_reports}
|
context = {"reports": open_reports}
|
||||||
|
Loading…
Reference in New Issue
Block a user