2024-05-30 09:26:04 +02:00
|
|
|
import logging
|
|
|
|
|
2024-11-18 23:01:27 +01:00
|
|
|
from django.http import HttpResponseRedirect, JsonResponse, HttpResponse
|
2024-03-19 18:18:55 +01:00
|
|
|
from django.shortcuts import render, redirect
|
|
|
|
from django.urls import reverse
|
2024-04-12 23:37:03 +02:00
|
|
|
from django.contrib.auth.decorators import login_required
|
2024-04-14 15:45:57 +02:00
|
|
|
from django.utils import translation
|
2024-05-30 14:37:15 +02:00
|
|
|
from django.core.exceptions import PermissionDenied
|
2024-09-28 23:45:59 +02:00
|
|
|
from django.contrib.auth.decorators import user_passes_test
|
2024-11-18 23:01:27 +01:00
|
|
|
from django.core.serializers import serialize
|
|
|
|
import json
|
2024-05-30 14:37:15 +02:00
|
|
|
|
2024-03-25 10:49:56 +01:00
|
|
|
from .mail import mail_admins_new_report
|
2024-04-12 23:37:03 +02:00
|
|
|
from notfellchen import settings
|
2024-03-17 11:26:32 +01:00
|
|
|
|
2024-05-30 09:26:04 +02:00
|
|
|
from fellchensammlung import logger
|
2024-06-08 12:31:22 +02:00
|
|
|
from .models import AdoptionNotice, Text, Animal, Rule, Image, Report, ModerationAction, \
|
2024-10-05 11:22:10 +02:00
|
|
|
User, Location, AdoptionNoticeStatus, Subscriptions, CommentNotification, BaseNotification, RescueOrganization, \
|
2024-12-26 20:24:10 +01:00
|
|
|
Species, Log, Timestamp, TrustLevel, SexChoicesWithAll, SearchSubscription
|
2024-06-08 12:31:22 +02:00
|
|
|
from .forms import AdoptionNoticeForm, AdoptionNoticeFormWithDateWidget, ImageForm, ReportAdoptionNoticeForm, \
|
|
|
|
CommentForm, ReportCommentForm, AnimalForm, \
|
2024-09-29 13:38:56 +02:00
|
|
|
AdoptionNoticeSearchForm, AnimalFormWithDateWidget, AdoptionNoticeFormWithDateWidgetAutoAnimal
|
2024-05-31 09:58:03 +02:00
|
|
|
from .models import Language, Announcement
|
2025-01-01 20:26:59 +01:00
|
|
|
from .tools.geo import GeoAPI, zoom_level_for_radius
|
2024-06-06 23:16:57 +02:00
|
|
|
from .tools.metrics import gather_metrics_data
|
2024-12-14 09:32:37 +01:00
|
|
|
from .tools.admin import clean_locations, get_unchecked_adoption_notices, deactivate_unchecked_adoption_notices, \
|
|
|
|
deactivate_404_adoption_notices
|
2025-01-01 14:35:40 +01:00
|
|
|
from .tasks import post_adoption_notice_save
|
2024-11-18 22:40:59 +01:00
|
|
|
from rest_framework.authtoken.models import Token
|
2024-08-06 17:38:17 +02:00
|
|
|
|
2024-12-26 16:55:37 +01:00
|
|
|
from .tools.search import Search
|
|
|
|
|
2024-08-06 17:38:17 +02:00
|
|
|
|
2024-11-20 19:55:16 +01:00
|
|
|
def user_is_trust_level_or_above(user, trust_level=TrustLevel.MODERATOR):
|
|
|
|
return user.is_authenticated and user.trust_level >= trust_level
|
2024-08-06 19:28:03 +02:00
|
|
|
|
|
|
|
|
2024-11-20 19:55:16 +01:00
|
|
|
def user_is_owner_or_trust_level(user, django_object, trust_level=TrustLevel.MODERATOR):
|
2024-08-06 19:28:03 +02:00
|
|
|
return user.is_authenticated and (
|
2024-11-20 19:55:16 +01:00
|
|
|
user.trust_level == trust_level or django_object.owner == user)
|
2024-08-06 19:28:03 +02:00
|
|
|
|
|
|
|
|
2024-11-20 19:55:16 +01:00
|
|
|
def fail_if_user_not_owner_or_trust_level(user, django_object, trust_level=TrustLevel.MODERATOR):
|
2024-08-06 19:28:03 +02:00
|
|
|
if not user_is_owner_or_trust_level(user, django_object, trust_level):
|
|
|
|
raise PermissionDenied
|
2024-03-17 11:26:32 +01:00
|
|
|
|
|
|
|
|
|
|
|
def index(request):
|
2024-03-18 14:53:31 +01:00
|
|
|
"""View function for home page of site."""
|
2024-08-24 08:36:10 +02:00
|
|
|
latest_adoption_list = AdoptionNotice.objects.filter(
|
2024-09-28 13:56:10 +02:00
|
|
|
adoptionnoticestatus__major_status=AdoptionNoticeStatus.ACTIVE).order_by("-created_at")
|
2024-05-31 16:00:52 +02:00
|
|
|
active_adoptions = [adoption for adoption in latest_adoption_list if adoption.is_active]
|
2024-05-31 09:58:03 +02:00
|
|
|
language_code = translation.get_language()
|
|
|
|
lang = Language.objects.get(languagecode=language_code)
|
|
|
|
active_announcements = Announcement.get_active_announcements(lang)
|
2024-08-08 10:50:11 +02:00
|
|
|
|
2024-10-05 11:02:26 +02:00
|
|
|
context = {"adoption_notices": active_adoptions[:5], "adoption_notices_map": active_adoptions,
|
|
|
|
"announcements": active_announcements}
|
|
|
|
Text.get_texts(["how_to", "introduction"], lang, context)
|
2024-03-18 14:53:31 +01:00
|
|
|
|
|
|
|
return render(request, 'fellchensammlung/index.html', context=context)
|
2024-03-18 08:26:21 +01:00
|
|
|
|
|
|
|
|
2024-04-12 23:37:03 +02:00
|
|
|
def change_language(request):
|
|
|
|
if request.method == 'POST':
|
|
|
|
language_code = request.POST.get('language')
|
|
|
|
if language_code:
|
|
|
|
if language_code != settings.LANGUAGE_CODE and language_code in list(zip(*settings.LANGUAGES))[0]:
|
|
|
|
redirect_path = f'/{language_code}/'
|
|
|
|
elif language_code == settings.LANGUAGE_CODE:
|
|
|
|
redirect_path = '/'
|
|
|
|
else:
|
|
|
|
response = HttpResponseRedirect('/')
|
|
|
|
return response
|
|
|
|
translation.activate(language_code)
|
|
|
|
response = HttpResponseRedirect(redirect_path)
|
|
|
|
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language_code)
|
2024-11-18 22:40:59 +01:00
|
|
|
return response
|
|
|
|
else:
|
|
|
|
return render(request, 'fellchensammlung/index.html')
|
2024-04-12 23:37:03 +02:00
|
|
|
|
|
|
|
|
2024-03-18 08:26:21 +01:00
|
|
|
def adoption_notice_detail(request, adoption_notice_id):
|
2024-03-20 10:35:40 +01:00
|
|
|
adoption_notice = AdoptionNotice.objects.get(id=adoption_notice_id)
|
2024-09-29 23:35:54 +02:00
|
|
|
if request.user.is_authenticated:
|
2024-10-05 11:22:10 +02:00
|
|
|
try:
|
2024-09-29 23:35:54 +02:00
|
|
|
subscription = Subscriptions.objects.get(owner=request.user, adoption_notice=adoption_notice)
|
|
|
|
is_subscribed = True
|
|
|
|
except Subscriptions.DoesNotExist:
|
|
|
|
is_subscribed = False
|
2024-10-19 17:45:26 +02:00
|
|
|
else:
|
|
|
|
is_subscribed = False
|
2024-08-06 19:37:08 +02:00
|
|
|
has_edit_permission = user_is_owner_or_trust_level(request.user, adoption_notice)
|
2024-05-30 14:37:15 +02:00
|
|
|
if request.method == 'POST':
|
2024-09-29 23:35:54 +02:00
|
|
|
action = request.POST.get("action")
|
2024-05-30 14:37:15 +02:00
|
|
|
if request.user.is_authenticated:
|
2024-09-29 23:35:54 +02:00
|
|
|
if action == "comment":
|
|
|
|
comment_form = CommentForm(request.POST)
|
|
|
|
|
|
|
|
if comment_form.is_valid():
|
|
|
|
comment_instance = comment_form.save(commit=False)
|
|
|
|
comment_instance.adoption_notice_id = adoption_notice_id
|
|
|
|
comment_instance.user = request.user
|
|
|
|
comment_instance.save()
|
|
|
|
|
2024-10-10 23:21:07 +02:00
|
|
|
"""Log"""
|
|
|
|
Log.objects.create(user=request.user, action="comment",
|
|
|
|
text=f"{request.user} hat Kommentar {comment_instance.pk} zur Vermittlung {adoption_notice_id} hinzugefügt")
|
|
|
|
|
2024-09-29 23:35:54 +02:00
|
|
|
# Auto-subscribe user to adoption notice
|
|
|
|
subscription, created = Subscriptions.objects.get_or_create(adoption_notice=adoption_notice,
|
|
|
|
owner=request.user)
|
|
|
|
subscription.save()
|
|
|
|
|
|
|
|
# Notify users that a comment was added
|
|
|
|
for subscription in adoption_notice.get_subscriptions():
|
|
|
|
# Create a notification but only if the user is not the one that posted the comment
|
|
|
|
if subscription.owner != request.user:
|
|
|
|
notification = CommentNotification(user=subscription.owner,
|
2024-10-05 11:22:10 +02:00
|
|
|
title=f"{adoption_notice.name} - Neuer Kommentar",
|
|
|
|
text=f"{request.user}: {comment_instance.text}",
|
|
|
|
comment=comment_instance)
|
2024-09-29 23:35:54 +02:00
|
|
|
notification.save()
|
|
|
|
else:
|
|
|
|
comment_form = CommentForm(instance=adoption_notice)
|
|
|
|
if action == "subscribe":
|
|
|
|
Subscriptions.objects.create(owner=request.user, adoption_notice=adoption_notice)
|
|
|
|
is_subscribed = True
|
|
|
|
if action == "unsubscribe":
|
2024-10-05 11:22:10 +02:00
|
|
|
subscription.delete()
|
|
|
|
is_subscribed = False
|
2024-05-30 14:37:15 +02:00
|
|
|
else:
|
|
|
|
raise PermissionDenied
|
|
|
|
else:
|
|
|
|
comment_form = CommentForm(instance=adoption_notice)
|
2024-10-05 11:22:10 +02:00
|
|
|
context = {"adoption_notice": adoption_notice, "comment_form": comment_form, "user": request.user,
|
2024-09-29 23:35:54 +02:00
|
|
|
"has_edit_permission": has_edit_permission, "is_subscribed": is_subscribed}
|
2024-03-25 11:04:01 +01:00
|
|
|
return render(request, 'fellchensammlung/details/detail_adoption_notice.html', context=context)
|
2024-03-18 08:26:21 +01:00
|
|
|
|
2024-05-30 11:47:18 +02:00
|
|
|
|
2024-05-31 16:42:32 +02:00
|
|
|
@login_required()
|
2024-05-30 09:54:54 +02:00
|
|
|
def adoption_notice_edit(request, adoption_notice_id):
|
2024-05-30 09:57:20 +02:00
|
|
|
"""
|
|
|
|
Form to update adoption notices
|
|
|
|
"""
|
|
|
|
adoption_notice = AdoptionNotice.objects.get(pk=adoption_notice_id)
|
2024-08-06 19:28:03 +02:00
|
|
|
fail_if_user_not_owner_or_trust_level(request.user, adoption_notice)
|
2024-05-30 09:57:20 +02:00
|
|
|
if request.method == 'POST':
|
2024-05-30 16:38:55 +02:00
|
|
|
form = AdoptionNoticeForm(request.POST, instance=adoption_notice)
|
2024-05-30 09:57:20 +02:00
|
|
|
|
|
|
|
if form.is_valid():
|
|
|
|
adoption_notice_instance = form.save()
|
2024-08-08 13:27:08 +02:00
|
|
|
"""Search the location given in the location string and add it to the adoption notice"""
|
|
|
|
location = Location.get_location_from_string(adoption_notice_instance.location_string)
|
|
|
|
adoption_notice_instance.location = location
|
|
|
|
adoption_notice_instance.save()
|
2024-10-10 23:21:07 +02:00
|
|
|
|
|
|
|
"""Log"""
|
2024-11-14 19:16:47 +01:00
|
|
|
Log.objects.create(user=request.user, action="adoption_notice_edit",
|
|
|
|
text=f"{request.user} hat Vermittlung {adoption_notice.pk} geändert")
|
2024-05-30 09:57:20 +02:00
|
|
|
return redirect(reverse("adoption-notice-detail", args=[adoption_notice_instance.pk], ))
|
|
|
|
else:
|
|
|
|
form = AdoptionNoticeForm(instance=adoption_notice)
|
2024-05-30 09:54:54 +02:00
|
|
|
return render(request, 'fellchensammlung/forms/form-adoption-notice.html', context={"form": form})
|
2024-03-18 08:26:21 +01:00
|
|
|
|
2024-05-30 11:47:18 +02:00
|
|
|
|
2024-03-18 08:26:21 +01:00
|
|
|
def animal_detail(request, animal_id):
|
2024-03-19 06:15:38 +01:00
|
|
|
animal = Animal.objects.get(id=animal_id)
|
|
|
|
context = {"animal": animal}
|
2024-03-25 11:04:01 +01:00
|
|
|
return render(request, 'fellchensammlung/details/detail_animal.html', context=context)
|
2024-03-18 16:36:45 +01:00
|
|
|
|
2024-03-19 18:18:55 +01:00
|
|
|
|
2024-03-18 16:36:45 +01:00
|
|
|
def search(request):
|
2024-12-31 13:37:31 +01:00
|
|
|
# A user just visiting the search site did not search, only upon completing the search form a user has really
|
|
|
|
# searched. This will toggle the "subscribe" button
|
|
|
|
searched = False
|
2024-12-26 16:55:37 +01:00
|
|
|
search = Search()
|
|
|
|
search.search_from_request(request)
|
2024-05-31 13:40:06 +02:00
|
|
|
if request.method == 'POST':
|
2024-12-31 13:37:31 +01:00
|
|
|
searched = True
|
2024-12-26 16:55:37 +01:00
|
|
|
if "subscribe_to_search" in request.POST:
|
|
|
|
# Make sure user is logged in
|
|
|
|
if not request.user.is_authenticated:
|
|
|
|
return redirect(f"{settings.LOGIN_URL}?next={request.path}")
|
|
|
|
search.subscribe(request.user)
|
2024-12-31 16:25:18 +01:00
|
|
|
if "unsubscribe_to_search" in request.POST:
|
|
|
|
if not request.user.is_authenticated:
|
|
|
|
return redirect(f"{settings.LOGIN_URL}?next={request.path}")
|
|
|
|
search_subscription = SearchSubscription.objects.get(pk=request.POST["unsubscribe_to_search"])
|
|
|
|
if search_subscription.owner == request.user:
|
|
|
|
search_subscription.delete()
|
|
|
|
else:
|
|
|
|
raise PermissionDenied
|
2025-01-01 09:47:07 +01:00
|
|
|
if request.user.is_authenticated:
|
|
|
|
subscribed_search = search.get_subscription_or_none(request.user)
|
|
|
|
else:
|
|
|
|
subscribed_search = None
|
2025-01-01 20:14:07 +01:00
|
|
|
|
2024-12-31 13:37:31 +01:00
|
|
|
context = {"adoption_notices": search.get_adoption_notices(),
|
|
|
|
"search_form": search.search_form,
|
|
|
|
"place_not_found": search.place_not_found,
|
2025-01-01 09:47:07 +01:00
|
|
|
"subscribed_search": subscribed_search,
|
2025-01-01 19:48:33 +01:00
|
|
|
"searched": searched,
|
2025-01-01 20:14:07 +01:00
|
|
|
"adoption_notices_map": AdoptionNotice.get_active_ANs(),
|
|
|
|
"map_center": search.position,
|
2025-01-01 20:26:59 +01:00
|
|
|
"search_radius": search.max_distance,
|
|
|
|
"zoom_level": zoom_level_for_radius(search.max_distance)}
|
2024-05-31 13:48:24 +02:00
|
|
|
return render(request, 'fellchensammlung/search.html', context=context)
|
2024-03-19 18:18:55 +01:00
|
|
|
|
|
|
|
|
2024-04-12 23:37:03 +02:00
|
|
|
@login_required
|
2024-05-31 10:58:57 +02:00
|
|
|
def add_adoption_notice(request):
|
2024-03-19 18:18:55 +01:00
|
|
|
if request.method == 'POST':
|
2024-10-05 11:22:10 +02:00
|
|
|
form = AdoptionNoticeFormWithDateWidgetAutoAnimal(request.POST, request.FILES,
|
|
|
|
in_adoption_notice_creation_flow=True)
|
2024-03-19 18:18:55 +01:00
|
|
|
|
|
|
|
if form.is_valid():
|
2024-12-14 13:24:51 +01:00
|
|
|
an_instance = form.save(commit=False)
|
|
|
|
an_instance.owner = request.user
|
2024-05-31 10:58:57 +02:00
|
|
|
|
2024-11-20 23:08:02 +01:00
|
|
|
if request.user.trust_level >= TrustLevel.MODERATOR:
|
2024-12-14 13:24:51 +01:00
|
|
|
an_instance.set_active()
|
2024-06-08 12:32:57 +02:00
|
|
|
else:
|
2024-12-14 13:24:51 +01:00
|
|
|
an_instance.set_unchecked()
|
2024-09-29 13:38:56 +02:00
|
|
|
|
2024-10-05 11:22:10 +02:00
|
|
|
# Get the species and number of animals from the form
|
2024-09-29 13:38:56 +02:00
|
|
|
species = form.cleaned_data["species"]
|
|
|
|
sex = form.cleaned_data["sex"]
|
|
|
|
num_animals = form.cleaned_data["num_animals"]
|
|
|
|
date_of_birth = form.cleaned_data["date_of_birth"]
|
|
|
|
for i in range(0, num_animals):
|
|
|
|
Animal.objects.create(owner=request.user,
|
2024-12-14 13:24:51 +01:00
|
|
|
name=f"{species} {i + 1}", adoption_notice=an_instance, species=species, sex=sex,
|
2024-10-05 11:22:10 +02:00
|
|
|
date_of_birth=date_of_birth)
|
2024-10-10 23:21:07 +02:00
|
|
|
|
|
|
|
"""Log"""
|
|
|
|
Log.objects.create(user=request.user, action="add_adoption_notice",
|
2024-12-14 13:24:51 +01:00
|
|
|
text=f"{request.user} hat Vermittlung {an_instance.pk} hinzugefügt")
|
|
|
|
|
2025-01-01 14:35:40 +01:00
|
|
|
"""Spin up a task that adds the location"""
|
|
|
|
post_adoption_notice_save.delay(an_instance.id)
|
|
|
|
|
2024-12-14 13:24:51 +01:00
|
|
|
"""Subscriptions"""
|
|
|
|
# Automatically subscribe user that created AN to AN
|
|
|
|
Subscriptions.objects.create(owner=request.user, adoption_notice=an_instance)
|
|
|
|
|
|
|
|
return redirect(reverse("adoption-notice-detail", args=[an_instance.pk]))
|
2024-03-19 18:18:55 +01:00
|
|
|
else:
|
2024-09-29 13:38:56 +02:00
|
|
|
form = AdoptionNoticeFormWithDateWidgetAutoAnimal(in_adoption_notice_creation_flow=True)
|
2024-03-25 11:04:01 +01:00
|
|
|
return render(request, 'fellchensammlung/forms/form_add_adoption.html', {'form': form})
|
2024-03-19 18:18:55 +01:00
|
|
|
|
2024-05-31 10:56:41 +02:00
|
|
|
|
2024-05-30 15:49:32 +02:00
|
|
|
@login_required
|
|
|
|
def adoption_notice_add_animal(request, adoption_notice_id):
|
2024-08-06 19:28:03 +02:00
|
|
|
# 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)
|
2024-05-30 15:49:32 +02:00
|
|
|
if request.method == 'POST':
|
2024-06-08 12:31:22 +02:00
|
|
|
form = AnimalFormWithDateWidget(request.POST, request.FILES)
|
2024-05-30 15:49:32 +02:00
|
|
|
|
|
|
|
if form.is_valid():
|
|
|
|
instance = form.save(commit=False)
|
|
|
|
instance.adoption_notice_id = adoption_notice_id
|
2024-08-08 13:29:20 +02:00
|
|
|
instance.owner = request.user
|
2024-05-30 15:49:32 +02:00
|
|
|
instance.save()
|
|
|
|
form.save_m2m()
|
2024-05-31 10:56:41 +02:00
|
|
|
if "save-and-add-another-animal" in request.POST:
|
2024-06-08 12:31:22 +02:00
|
|
|
form = AnimalFormWithDateWidget(in_adoption_notice_creation_flow=True)
|
2024-05-31 10:56:41 +02:00
|
|
|
return render(request, 'fellchensammlung/forms/form_add_animal_to_adoption.html', {'form': form})
|
2024-05-30 15:49:32 +02:00
|
|
|
else:
|
2024-05-31 10:56:41 +02:00
|
|
|
return redirect(reverse("adoption-notice-detail", args=[adoption_notice_id]))
|
2024-05-30 15:49:32 +02:00
|
|
|
else:
|
2024-06-08 12:31:22 +02:00
|
|
|
form = AnimalFormWithDateWidget(in_adoption_notice_creation_flow=True)
|
2024-05-30 15:49:32 +02:00
|
|
|
return render(request, 'fellchensammlung/forms/form_add_animal_to_adoption.html', {'form': form})
|
2024-03-19 18:18:55 +01:00
|
|
|
|
2024-05-31 10:56:41 +02:00
|
|
|
|
2024-05-31 10:56:43 +02:00
|
|
|
@login_required
|
|
|
|
def add_photo_to_animal(request, animal_id):
|
|
|
|
animal = Animal.objects.get(id=animal_id)
|
2024-08-06 19:28:03 +02:00
|
|
|
# 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)
|
2024-05-31 10:56:43 +02:00
|
|
|
if request.method == 'POST':
|
|
|
|
form = ImageForm(request.POST, request.FILES)
|
|
|
|
|
|
|
|
if form.is_valid():
|
2024-08-08 16:48:51 +02:00
|
|
|
instance = form.save(commit=False)
|
|
|
|
instance.owner = request.user
|
|
|
|
instance.save()
|
|
|
|
|
2024-05-31 10:56:43 +02:00
|
|
|
animal.photos.add(instance)
|
2024-10-10 23:21:07 +02:00
|
|
|
|
|
|
|
"""Log"""
|
|
|
|
Log.objects.create(user=request.user, action="add_photo_to_animal",
|
|
|
|
text=f"{request.user} hat Foto {instance.pk} zum Tier {animal.pk} hinzugefügt")
|
|
|
|
|
2024-05-31 10:56:43 +02:00
|
|
|
if "save-and-add-another" in request.POST:
|
|
|
|
form = ImageForm(in_flow=True)
|
|
|
|
return render(request, 'fellchensammlung/forms/form-image.html', {'form': form})
|
|
|
|
else:
|
2024-12-18 10:17:27 +01:00
|
|
|
return redirect(reverse("adoption-notice-detail", args=[animal.adoption_notice.pk], ))
|
2024-05-31 10:56:43 +02:00
|
|
|
else:
|
|
|
|
form = ImageForm(in_flow=True)
|
|
|
|
return render(request, 'fellchensammlung/forms/form-image.html', {'form': form})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
def add_photo_to_adoption_notice(request, adoption_notice_id):
|
|
|
|
adoption_notice = AdoptionNotice.objects.get(id=adoption_notice_id)
|
2024-08-06 19:28:03 +02:00
|
|
|
# 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)
|
2024-05-31 10:56:43 +02:00
|
|
|
if request.method == 'POST':
|
|
|
|
form = ImageForm(request.POST, request.FILES)
|
|
|
|
|
|
|
|
if form.is_valid():
|
2024-08-08 16:48:51 +02:00
|
|
|
instance = form.save(commit=False)
|
|
|
|
instance.owner = request.user
|
|
|
|
instance.save()
|
2024-05-31 10:56:43 +02:00
|
|
|
adoption_notice.photos.add(instance)
|
2024-10-10 23:21:07 +02:00
|
|
|
"""Log"""
|
|
|
|
Log.objects.create(user=request.user, action="add_photo_to_animal",
|
|
|
|
text=f"{request.user} hat Foto {instance.pk} zur Vermittlung {adoption_notice.pk} hinzugefügt")
|
2024-05-31 10:56:43 +02:00
|
|
|
if "save-and-add-another" in request.POST:
|
|
|
|
form = ImageForm(in_flow=True)
|
|
|
|
return render(request, 'fellchensammlung/forms/form-image.html', {'form': form})
|
|
|
|
else:
|
|
|
|
return redirect(reverse("adoption-notice-detail", args=[adoption_notice_id]))
|
2024-08-08 16:48:51 +02:00
|
|
|
else:
|
|
|
|
return render(request, 'fellchensammlung/forms/form-image.html', {'form': form})
|
2024-05-31 10:56:43 +02:00
|
|
|
else:
|
|
|
|
form = ImageForm(in_flow=True)
|
|
|
|
return render(request, 'fellchensammlung/forms/form-image.html', {'form': form})
|
|
|
|
|
|
|
|
|
2024-05-10 13:54:16 +02:00
|
|
|
@login_required
|
2024-05-30 09:54:54 +02:00
|
|
|
def animal_edit(request, animal_id):
|
2024-05-10 13:54:16 +02:00
|
|
|
"""
|
|
|
|
View implements the following methods
|
|
|
|
* Updating an Animal
|
|
|
|
"""
|
2024-05-30 16:57:47 +02:00
|
|
|
animal = Animal.objects.get(pk=animal_id)
|
2024-08-06 19:28:03 +02:00
|
|
|
# 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)
|
2024-05-10 13:54:16 +02:00
|
|
|
if request.method == 'POST':
|
2024-05-30 16:57:47 +02:00
|
|
|
form = AnimalForm(request.POST, instance=animal)
|
2024-05-10 13:54:16 +02:00
|
|
|
|
2024-05-30 16:57:47 +02:00
|
|
|
if form.is_valid():
|
|
|
|
animal = form.save()
|
2024-10-10 23:21:07 +02:00
|
|
|
|
|
|
|
"""Log"""
|
|
|
|
Log.objects.create(user=request.user, action="add_photo_to_animal",
|
|
|
|
text=f"{request.user} hat Tier {animal.pk} zum Tier geändert")
|
2024-12-18 10:15:00 +01:00
|
|
|
return redirect(reverse("adoption-notice-detail", args=[animal.adoption_notice.pk], ))
|
2024-03-19 18:18:55 +01:00
|
|
|
else:
|
2024-05-30 16:57:47 +02:00
|
|
|
form = AnimalForm(instance=animal)
|
|
|
|
return render(request, 'fellchensammlung/forms/form-adoption-notice.html', context={"form": form})
|
2024-03-19 18:18:55 +01:00
|
|
|
|
2024-03-18 16:36:45 +01:00
|
|
|
|
2024-03-18 16:41:22 +01:00
|
|
|
def about(request):
|
2024-03-20 11:02:24 +01:00
|
|
|
rules = Rule.objects.all()
|
2024-04-14 14:39:49 +02:00
|
|
|
|
2024-04-14 15:45:57 +02:00
|
|
|
language_code = translation.get_language()
|
2024-04-14 15:39:54 +02:00
|
|
|
lang = Language.objects.get(languagecode=language_code)
|
2024-04-14 14:39:49 +02:00
|
|
|
|
|
|
|
legal = {}
|
2024-12-24 09:05:11 +01:00
|
|
|
for text_code in ["terms_of_service", "privacy_statement", "imprint", "about_us", "faq"]:
|
2024-04-14 14:39:49 +02:00
|
|
|
try:
|
2024-05-01 10:09:36 +02:00
|
|
|
legal[text_code] = Text.objects.get(text_code=text_code, language=lang, )
|
2024-04-14 14:39:49 +02:00
|
|
|
except Text.DoesNotExist:
|
|
|
|
legal[text_code] = None
|
|
|
|
|
2024-05-01 10:09:36 +02:00
|
|
|
context = {"rules": rules, }
|
2024-04-14 14:39:49 +02:00
|
|
|
context.update(legal)
|
2024-03-18 16:41:22 +01:00
|
|
|
return render(
|
|
|
|
request,
|
|
|
|
"fellchensammlung/about.html",
|
|
|
|
context=context
|
|
|
|
)
|
2024-03-22 12:45:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
def report_adoption(request, adoption_notice_id):
|
|
|
|
"""
|
|
|
|
Form to report adoption notices
|
|
|
|
"""
|
|
|
|
if request.method == 'POST':
|
2024-05-30 15:46:51 +02:00
|
|
|
form = ReportAdoptionNoticeForm(request.POST)
|
2024-03-22 12:45:50 +01:00
|
|
|
|
|
|
|
if form.is_valid():
|
|
|
|
report_instance = form.save(commit=False)
|
|
|
|
report_instance.adoption_notice_id = adoption_notice_id
|
|
|
|
report_instance.status = Report.WAITING
|
|
|
|
report_instance.save()
|
2024-05-30 15:46:51 +02:00
|
|
|
form.save_m2m()
|
2024-03-25 10:49:56 +01:00
|
|
|
mail_admins_new_report(report_instance)
|
2024-03-22 12:45:50 +01:00
|
|
|
return redirect(reverse("report-detail-success", args=[report_instance.pk], ))
|
|
|
|
else:
|
2024-05-30 15:46:51 +02:00
|
|
|
form = ReportAdoptionNoticeForm()
|
|
|
|
return render(request, 'fellchensammlung/forms/form-report.html', {'form': form})
|
|
|
|
|
|
|
|
|
|
|
|
def report_comment(request, comment_id):
|
|
|
|
"""
|
|
|
|
Form to report comments
|
|
|
|
"""
|
|
|
|
if request.method == 'POST':
|
|
|
|
form = ReportCommentForm(request.POST)
|
|
|
|
|
|
|
|
if form.is_valid():
|
|
|
|
report_instance = form.save(commit=False)
|
|
|
|
report_instance.reported_comment_id = comment_id
|
|
|
|
report_instance.status = Report.WAITING
|
|
|
|
report_instance.save()
|
|
|
|
form.save_m2m()
|
|
|
|
mail_admins_new_report(report_instance)
|
|
|
|
return redirect(reverse("report-detail-success", args=[report_instance.pk], ))
|
|
|
|
else:
|
|
|
|
form = ReportCommentForm()
|
2024-03-25 11:04:01 +01:00
|
|
|
return render(request, 'fellchensammlung/forms/form-report.html', {'form': form})
|
2024-03-22 12:45:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
def report_detail(request, report_id, form_complete=False):
|
|
|
|
"""
|
|
|
|
Detailed view of a report, including moderation actions
|
|
|
|
"""
|
|
|
|
report = Report.objects.get(pk=report_id)
|
|
|
|
moderation_actions = ModerationAction.objects.filter(report_id=report_id)
|
|
|
|
|
|
|
|
context = {"report": report, "moderation_actions": moderation_actions, "form_complete": form_complete}
|
|
|
|
|
2024-03-25 11:04:01 +01:00
|
|
|
return render(request, 'fellchensammlung/details/detail-report.html', context)
|
2024-03-22 12:45:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
def report_detail_success(request, report_id):
|
|
|
|
"""
|
|
|
|
Calls the report detail view with form_complete set to true, so success message shows
|
|
|
|
"""
|
|
|
|
return report_detail(request, report_id, form_complete=True)
|
2024-03-23 22:20:31 +01:00
|
|
|
|
|
|
|
|
2024-11-18 22:40:59 +01:00
|
|
|
def user_detail(request, user, token=None):
|
|
|
|
context = {"user": user,
|
|
|
|
"adoption_notices": AdoptionNotice.objects.filter(owner=user),
|
2024-11-20 23:03:02 +01:00
|
|
|
"notifications": BaseNotification.objects.filter(user=user, read=False)}
|
2024-11-18 22:40:59 +01:00
|
|
|
if token is not None:
|
|
|
|
context["token"] = token
|
|
|
|
return render(request, 'fellchensammlung/details/detail-user.html', context=context)
|
|
|
|
|
|
|
|
|
2024-08-06 17:38:17 +02:00
|
|
|
@login_required
|
2024-11-18 22:40:59 +01:00
|
|
|
def user_by_id(request, user_id):
|
2024-08-06 19:28:03 +02:00
|
|
|
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)
|
2024-11-20 20:00:27 +01:00
|
|
|
if user == request.user:
|
|
|
|
return my_profile(request)
|
|
|
|
else:
|
|
|
|
return user_detail(request, user)
|
2024-11-18 22:40:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
@login_required()
|
|
|
|
def my_profile(request):
|
|
|
|
if request.method == 'POST':
|
|
|
|
if "create_token" in request.POST:
|
|
|
|
Token.objects.create(user=request.user)
|
|
|
|
elif "delete_token" in request.POST:
|
|
|
|
Token.objects.get(user=request.user).delete()
|
2024-12-17 21:42:10 +01:00
|
|
|
elif "toggle_email_notifications" in request.POST:
|
|
|
|
user = request.user
|
|
|
|
user.email_notifications = not user.email_notifications
|
|
|
|
user.save()
|
2024-11-18 22:40:59 +01:00
|
|
|
|
2024-08-02 21:04:44 +02:00
|
|
|
action = request.POST.get("action")
|
|
|
|
if action == "notification_mark_read":
|
|
|
|
notification_id = request.POST.get("notification_id")
|
2024-11-20 23:37:55 +01:00
|
|
|
try:
|
|
|
|
notification = CommentNotification.objects.get(pk=notification_id)
|
|
|
|
except CommentNotification.DoesNotExist:
|
|
|
|
notification = BaseNotification.objects.get(pk=notification_id)
|
2024-08-02 21:04:44 +02:00
|
|
|
notification.read = True
|
|
|
|
notification.save()
|
|
|
|
elif action == "notification_mark_all_read":
|
2024-08-03 09:02:09 +02:00
|
|
|
notifications = CommentNotification.objects.filter(user=request.user, mark_read=False)
|
2024-08-02 21:04:44 +02:00
|
|
|
for notification in notifications:
|
|
|
|
notification.read = True
|
|
|
|
notification.save()
|
2024-12-17 21:42:10 +01:00
|
|
|
|
2024-11-18 22:40:59 +01:00
|
|
|
try:
|
|
|
|
token = Token.objects.get(user=request.user)
|
|
|
|
except Token.DoesNotExist:
|
|
|
|
token = None
|
|
|
|
return user_detail(request, request.user, token)
|
2024-04-07 09:03:20 +02:00
|
|
|
|
|
|
|
|
2024-08-06 19:28:03 +02:00
|
|
|
@user_passes_test(user_is_trust_level_or_above)
|
2024-04-07 09:03:20 +02:00
|
|
|
def modqueue(request):
|
|
|
|
open_reports = Report.objects.filter(status=Report.WAITING)
|
|
|
|
context = {"reports": open_reports}
|
|
|
|
return render(request, 'fellchensammlung/modqueue.html', context=context)
|
2024-06-06 23:16:57 +02:00
|
|
|
|
2024-10-05 11:22:10 +02:00
|
|
|
|
2024-09-30 15:22:19 +02:00
|
|
|
@login_required
|
|
|
|
def updatequeue(request):
|
|
|
|
if request.method == "POST":
|
|
|
|
adoption_notice = AdoptionNotice.objects.get(id=request.POST.get("adoption_notice_id"))
|
2024-11-20 23:22:56 +01:00
|
|
|
edit_permission = request.user == adoption_notice.owner or user_is_trust_level_or_above(request.user,
|
|
|
|
TrustLevel.MODERATOR)
|
|
|
|
if not edit_permission:
|
|
|
|
return render(request, "fellchensammlung/errors/403.html", status=403)
|
2024-09-30 15:22:19 +02:00
|
|
|
action = request.POST.get("action")
|
|
|
|
if action == "checked_inactive":
|
|
|
|
adoption_notice.set_closed()
|
2024-10-30 11:17:57 +01:00
|
|
|
if action == "checked_active":
|
|
|
|
adoption_notice.set_active()
|
2024-09-30 15:22:19 +02:00
|
|
|
|
2024-11-20 23:08:02 +01:00
|
|
|
if user_is_trust_level_or_above(request.user, TrustLevel.MODERATOR):
|
2024-09-30 15:22:19 +02:00
|
|
|
last_checked_adoption_list = AdoptionNotice.objects.order_by("last_checked")
|
|
|
|
else:
|
|
|
|
last_checked_adoption_list = AdoptionNotice.objects.filter(owner=request.user).order_by("last_checked")
|
2024-11-02 09:42:39 +01:00
|
|
|
adoption_notices_active = [adoption for adoption in last_checked_adoption_list if adoption.is_active]
|
|
|
|
adoption_notices_disabled = [adoption for adoption in last_checked_adoption_list if adoption.is_disabled_unchecked]
|
|
|
|
context = {"adoption_notices_disabled": adoption_notices_disabled,
|
|
|
|
"adoption_notices_active": adoption_notices_active}
|
2024-09-30 15:22:19 +02:00
|
|
|
return render(request, 'fellchensammlung/updatequeue.html', context=context)
|
|
|
|
|
2024-06-06 23:16:57 +02:00
|
|
|
|
2024-08-24 08:36:10 +02:00
|
|
|
def map(request):
|
2025-01-01 19:48:33 +01:00
|
|
|
adoption_notices = AdoptionNotice.get_active_ANs()
|
2024-09-28 13:56:10 +02:00
|
|
|
context = {"adoption_notices_map": adoption_notices}
|
2024-09-27 14:29:12 +02:00
|
|
|
return render(request, 'fellchensammlung/map.html', context=context)
|
2024-08-24 08:36:10 +02:00
|
|
|
|
|
|
|
|
2024-06-06 23:16:57 +02:00
|
|
|
def metrics(request):
|
|
|
|
data = gather_metrics_data()
|
|
|
|
return JsonResponse(data)
|
2024-09-28 23:45:59 +02:00
|
|
|
|
2024-10-05 11:22:10 +02:00
|
|
|
|
2024-09-28 23:45:59 +02:00
|
|
|
@login_required
|
|
|
|
def instance_health_check(request):
|
|
|
|
"""
|
|
|
|
Allows an administrator to check common problems of an instance
|
|
|
|
"""
|
|
|
|
if request.method == "POST":
|
|
|
|
action = request.POST.get("action")
|
|
|
|
if action == "clean_locations":
|
|
|
|
clean_locations(quiet=False)
|
2024-10-10 17:06:50 +02:00
|
|
|
elif action == "deactivate_unchecked_adoption_notices":
|
|
|
|
deactivate_unchecked_adoption_notices()
|
2024-12-14 09:32:37 +01:00
|
|
|
elif action == "deactivate_404":
|
|
|
|
deactivate_404_adoption_notices()
|
2024-09-28 23:45:59 +02:00
|
|
|
|
|
|
|
number_of_adoption_notices = AdoptionNotice.objects.all().count()
|
2024-09-29 17:03:46 +02:00
|
|
|
none_geocoded_adoption_notices = AdoptionNotice.objects.filter(location__isnull=True)
|
|
|
|
number_not_geocoded_adoption_notices = len(none_geocoded_adoption_notices)
|
|
|
|
|
2024-09-28 23:45:59 +02:00
|
|
|
number_of_rescue_orgs = RescueOrganization.objects.all().count()
|
2024-09-29 17:03:46 +02:00
|
|
|
none_geocoded_rescue_orgs = RescueOrganization.objects.filter(location__isnull=True)
|
|
|
|
number_not_geocoded_rescue_orgs = len(none_geocoded_rescue_orgs)
|
2024-09-29 00:20:08 +02:00
|
|
|
|
2024-10-10 17:06:50 +02:00
|
|
|
unchecked_ans = get_unchecked_adoption_notices()
|
|
|
|
number_unchecked_ans = len(unchecked_ans)
|
|
|
|
|
2024-09-29 00:20:08 +02:00
|
|
|
# CHECK FOR MISSING TEXTS
|
|
|
|
languages = Language.objects.all()
|
|
|
|
texts = Text.objects.all()
|
|
|
|
text_codes = set([text.text_code for text in texts])
|
|
|
|
missing_texts = []
|
|
|
|
for language in languages:
|
|
|
|
for text_code in text_codes:
|
|
|
|
try:
|
|
|
|
Text.objects.get(text_code=text_code, language=language)
|
|
|
|
except Text.DoesNotExist:
|
|
|
|
missing_texts.append((text_code, language))
|
|
|
|
|
2024-10-19 19:46:11 +02:00
|
|
|
# Timestamps
|
|
|
|
timestamps = Timestamp.objects.all()
|
|
|
|
|
2024-09-28 23:45:59 +02:00
|
|
|
context = {
|
|
|
|
"number_of_adoption_notices": number_of_adoption_notices,
|
|
|
|
"number_not_geocoded_adoption_notices": number_not_geocoded_adoption_notices,
|
2024-09-29 17:03:46 +02:00
|
|
|
"none_geocoded_adoption_notices": none_geocoded_adoption_notices,
|
2024-09-28 23:45:59 +02:00
|
|
|
"number_of_rescue_orgs": number_of_rescue_orgs,
|
2024-09-29 00:20:08 +02:00
|
|
|
"number_not_geocoded_rescue_orgs": number_not_geocoded_rescue_orgs,
|
2024-09-29 17:03:46 +02:00
|
|
|
"none_geocoded_rescue_orgs": none_geocoded_rescue_orgs,
|
2024-10-10 17:06:50 +02:00
|
|
|
"missing_texts": missing_texts,
|
|
|
|
"number_unchecked_ans": number_unchecked_ans,
|
2024-10-19 19:46:11 +02:00
|
|
|
"unchecked_ans": unchecked_ans,
|
|
|
|
"timestamps": timestamps
|
2024-09-28 23:45:59 +02:00
|
|
|
}
|
2024-09-29 00:20:08 +02:00
|
|
|
|
2024-09-28 23:45:59 +02:00
|
|
|
return render(request, 'fellchensammlung/instance-health-check.html', context=context)
|
|
|
|
|
|
|
|
|
2024-10-05 11:22:10 +02:00
|
|
|
def external_site_warning(request):
|
|
|
|
url = request.GET.get("url")
|
|
|
|
context = {"url": url}
|
|
|
|
language_code = translation.get_language()
|
|
|
|
lang = Language.objects.get(languagecode=language_code)
|
2024-11-12 17:18:20 +01:00
|
|
|
texts = Text.get_texts(["external_site_warning", "good_adoption_practices"], language=lang)
|
|
|
|
context.update(texts)
|
2024-10-05 11:22:10 +02:00
|
|
|
|
|
|
|
return render(request, 'fellchensammlung/external_site_warning.html', context=context)
|
2024-11-14 19:16:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
def detail_view_rescue_organization(request, rescue_organization_id):
|
|
|
|
org = RescueOrganization.objects.get(pk=rescue_organization_id)
|
|
|
|
return render(request, 'fellchensammlung/details/detail-rescue-organization.html', context={"org": org})
|
2024-11-18 23:01:27 +01:00
|
|
|
|
|
|
|
|
|
|
|
def export_own_profile(request):
|
|
|
|
user = request.user
|
|
|
|
ANs = AdoptionNotice.objects.filter(owner=user)
|
|
|
|
user_as_json = serialize('json', [user])
|
|
|
|
user_editable = json.loads(user_as_json)
|
|
|
|
user_editable[0]["fields"]["password"] = "Password hash redacted for security reasons"
|
|
|
|
user_as_json = json.dumps(user_editable)
|
|
|
|
ANs_as_json = serialize('json', ANs)
|
|
|
|
full_json = f"{user_as_json}, {ANs_as_json}"
|
|
|
|
return HttpResponse(full_json, content_type="application/json")
|