Many changes, including a switch to a MariaDB database

This commit is contained in:
Kumi 2019-08-31 08:51:00 +00:00
parent 00464d2311
commit 619de983f2
39 changed files with 3810 additions and 53 deletions

View file

@ -1,8 +1,11 @@
from django.forms import Form from django.forms import Form, ImageField
from multiupload.fields import MultiImageField
class UploadForm(Form): class UploadForm(Form):
images = MultiImageField() image1 = ImageField(label="Bilddatei", required=False)
image2 = ImageField(label="Bilddatei", required=False)
image3 = ImageField(label="Bilddatei", required=False)
image4 = ImageField(label="Bilddatei", required=False)
image5 = ImageField(label="Bilddatei", required=False)
class ItemFoundForm(Form): class ItemFoundForm(Form):
pass pass

View file

@ -0,0 +1,23 @@
# Generated by Django 2.2.4 on 2019-08-30 15:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0003_auto_20190829_1414'),
]
operations = [
migrations.AddField(
model_name='report',
name='anonymised',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='report',
name='status',
field=models.IntegerField(choices=[(-1, 'Invalid'), (0, 'Unprocessed'), (1, 'Processing'), (2, 'Processed')], default=-1),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 2.2.4 on 2019-08-30 15:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0004_auto_20190830_1521'),
]
operations = [
migrations.AlterField(
model_name='report',
name='status',
field=models.IntegerField(choices=[(-1, 'Invalid'), (0, 'Unprocessed'), (1, 'Processing'), (2, 'Processed')], default=0),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 2.2.4 on 2019-08-30 16:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0005_auto_20190830_1521'),
]
operations = [
migrations.AddField(
model_name='reportimage',
name='anonymised',
field=models.BooleanField(default=False),
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 2.2.4 on 2019-08-30 16:57
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('app', '0006_reportimage_anonymised'),
]
operations = [
migrations.RemoveField(
model_name='userprofile',
name='id',
),
migrations.AddField(
model_name='userprofile',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False),
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-08-31 08:48
import app.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0007_auto_20190830_1657'),
]
operations = [
migrations.AlterField(
model_name='item',
name='iid',
field=models.CharField(default=app.models.generateIID, max_length=10, unique=True),
),
]

View file

@ -20,6 +20,13 @@ ITEM_STATUS_CHOICES = [
(2, "Legal change of ownership") (2, "Legal change of ownership")
] ]
REPORT_STATUS_CHOICES = [
(-1, "Invalid"),
(0, "Unprocessed"),
(1, "Processing"),
(2, "Processed")
]
class UserPrivacyMeta: class UserPrivacyMeta:
fields = [ "first_name", "last_name", "email" ] fields = [ "first_name", "last_name", "email" ]
@ -47,7 +54,7 @@ class Category(models.Model):
class Item(models.Model): class Item(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4) uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
iid = models.IntegerField(unique=True, default=generateIID) iid = models.CharField(max_length=10, unique=True, default=generateIID)
name = models.CharField(max_length=128) name = models.CharField(max_length=128)
description = models.TextField("Beschreibung", max_length=2048) description = models.TextField("Beschreibung", max_length=2048)
owner = models.ForeignKey(User, on_delete=models.CASCADE) owner = models.ForeignKey(User, on_delete=models.CASCADE)
@ -77,10 +84,10 @@ class Item(models.Model):
if self.status == -1: if self.status == -1:
return '<span style="color: orange;">Noch nicht freigeschaltet!</span>' return '<span style="color: orange;">Noch nicht freigeschaltet!</span>'
if self.status == 0: if self.status == 0:
return '<span style="color: green;">Nicht als gestohlen gemeldet.</p>' return '<span style="color: green;">Nicht als gestohlen gemeldet.</span>'
if self.status == 1: if self.status == 1:
return '<span style="color: red;">Als gestohlen gemeldet!</span>' return '<span style="color: red;">Als gestohlen gemeldet!</span>'
if object.status == 2: if self.status == 2:
return '<span style="color: blue;">Gegenstand verkauft</span>' return '<span style="color: blue;">Gegenstand verkauft</span>'
class Image(models.Model): class Image(models.Model):
@ -104,6 +111,7 @@ class Image(models.Model):
return reverse_lazy("edititem", kwargs={'uuid': self.item.uuid}) return reverse_lazy("edititem", kwargs={'uuid': self.item.uuid})
class UserProfile(models.Model): class UserProfile(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
user = models.OneToOneField(User, on_delete=models.CASCADE) user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(null=True, blank=True) avatar = models.ImageField(null=True, blank=True)
company = models.CharField(max_length=64, null=True, blank=True) company = models.CharField(max_length=64, null=True, blank=True)
@ -126,6 +134,23 @@ class Report(models.Model):
message = models.TextField("Details") message = models.TextField("Details")
item = models.ForeignKey(Item, on_delete=models.CASCADE) item = models.ForeignKey(Item, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=REPORT_STATUS_CHOICES, default=0)
def get_status_html(self):
if self.status == 0:
return '<span style="color: blue;">Unbeantwortet</p>'
if self.status == 1:
return '<span style="color: orange;">In Beantwortung</span>'
if self.status == 2:
return '<span style="color: green;">Bearbeitet</span>'
if self.status == -1:
return '<span style="color: red;">Abgelehnt</span>'
def get_absolute_url(self):
return reverse_lazy("report", kwargs={'uuid': self.uuid})
class PrivacyMeta:
fields = [ "name", "mail", "phone", "found_on", "found_at", "message" ]
class ReportImage(models.Model): class ReportImage(models.Model):
image = models.ImageField() image = models.ImageField()
@ -134,6 +159,9 @@ class ReportImage(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy("reportimages", kwargs={'report': self.report.id}) return reverse_lazy("reportimages", kwargs={'report': self.report.id})
class PrivacyMeta:
fields = [ "image" ]
@receiver(post_save, sender=User) @receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs): def create_user_profile(sender, instance, created, **kwargs):
if kwargs.get('created', True) and not kwargs.get('raw', False): if kwargs.get('created', True) and not kwargs.get('raw', False):

File diff suppressed because one or more lines are too long

View file

@ -2,6 +2,7 @@ from django.urls import path, include, reverse
from django.conf.urls import url from django.conf.urls import url
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.views import LogoutView
from two_factor.urls import urlpatterns as tf_urls from two_factor.urls import urlpatterns as tf_urls
from two_factor.gateways.twilio.urls import urlpatterns as tf_twilio_urls from two_factor.gateways.twilio.urls import urlpatterns as tf_twilio_urls
@ -12,17 +13,33 @@ urlpatterns = [
path('', views.index, name="index"), path('', views.index, name="index"),
path('clientarea/', views.clientarea, name="clientarea"), path('clientarea/', views.clientarea, name="clientarea"),
path('clientarea/profile/', views.userprofile, name="userprofile"), path('clientarea/profile/', views.userprofile, name="userprofile"),
path('clientarea/profile/<userid>/', views.userprofile, name="userprofilebyid"),
path('clientarea/profile/password/', views.changepassword, name="changepassword"), path('clientarea/profile/password/', views.changepassword, name="changepassword"),
path('clientarea/profile/<userid>/promote/', views.UserPromoteView.as_view(), name="promoteuser"),
path('clientarea/profile/<userid>/demote/', views.UserDemoteView.as_view(), name="demoteuser"),
path('clientarea/items/', views.items, name="items"), path('clientarea/items/', views.items, name="items"),
path('clientarea/items/add/', views.ItemCreateView.as_view(), name="additem"), path('clientarea/items/add/', views.ItemCreateView.as_view(), name="additem"),
path('clientarea/items/<slug:uuid>/', views.ItemDetailView.as_view(), name="edititem"), path('clientarea/items/<slug:uuid>/', views.ItemDetailView.as_view(), name="edititem"),
path('clientarea/items/<slug:uuid>/upload/', views.ImageCreateView.as_view(), name="imageupload"), path('clientarea/items/<slug:uuid>/upload/', views.ImageCreateView.as_view(), name="imageupload"),
path('clientarea/items/<slug:uuid>/report/', views.ItemStolenView.as_view(), name="itemstolen"), path('clientarea/items/<slug:uuid>/report/', views.ItemStolenView.as_view(), name="itemstolen"),
path('clientarea/items/<slug:uuid>/found/', views.ItemFoundView.as_view(), name="founditem"), path('clientarea/items/<slug:uuid>/found/', views.ItemFoundView.as_view(), name="founditem"),
path('clientarea/items/<slug:uuid>/sold/', views.ItemSoldView.as_view(), name="solditem"),
path('clientarea/items/<slug:uuid>/transfer/', views.ItemTransferView.as_view(), name="transferitem"),
path('clientarea/items/<slug:uuid>/activate/', views.ItemActivateView.as_view(), name="activateitem"),
path('clientarea/categories/', views.CategoryListView.as_view(), name="categories"), path('clientarea/categories/', views.CategoryListView.as_view(), name="categories"),
path('clientarea/categories/add/', views.CategoryCreateView.as_view(), name="addcategory"), path('clientarea/categories/add/', views.CategoryCreateView.as_view(), name="addcategory"),
path('clientarea/categories/<slug:slug>/delete', views.CategoryDeleteView.as_view(), name="deletecategory"), path('clientarea/categories/<slug:slug>/delete/', views.CategoryDeleteView.as_view(), name="deletecategory"),
path('clientarea/reports/', views.ReportListView.as_view(), name="reports"),
path('clientarea/reports/<slug:uuid>/', views.ReportDetailView.as_view(), name="report"),
path('clientarea/reports/<slug:uuid>/delete/', views.ReportDeleteView.as_view(), name="deletereport"),
path('clientarea/reports/<slug:uuid>/refuse/', views.ReportRefuseView.as_view(), name="refusereport"),
path('clientarea/reports/<slug:uuid>/process/', views.ReportProcessingView.as_view(), name="processreport"),
path('clientarea/reports/<slug:uuid>/finalize/', views.ReportFinalizeView.as_view(), name="finalizereport"),
path('clientarea/users/', views.UserListView.as_view(), name="users"), path('clientarea/users/', views.UserListView.as_view(), name="users"),
path('clientarea/users/<id>/delete/', views.UserDeleteView.as_view(), name="deleteuser"),
path('clientarea/users/add/', views.UserCreateView.as_view(), name="adduser"),
path('account/register/', views.UserRegisterView.as_view(), name="register"),
path('accounts/logout/', LogoutView.as_view(), name="logout"),
path('protect/', views.protect, name="protect"), path('protect/', views.protect, name="protect"),
path('check/', views.check, name="check"), path('check/', views.check, name="check"),
path('check/<slug:slug>/', views.StolenItemListView.as_view(), name="checkcategory"), path('check/<slug:slug>/', views.StolenItemListView.as_view(), name="checkcategory"),

View file

@ -2,8 +2,8 @@ import datetime
from django.contrib import messages from django.contrib import messages
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import update_session_auth_hash from django.contrib.auth import update_session_auth_hash, login, authenticate
from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.forms import PasswordChangeForm, UserCreationForm
from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.decorators import login_required, user_passes_test
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
@ -35,27 +35,34 @@ def clientarea(request):
return render(request, "app/backend/base.html", context) return render(request, "app/backend/base.html", context)
@login_required @login_required
def userprofile(request): def userprofile(request, userid=None):
userprofile = UserProfile.objects.get(user=request.user) if not userid:
user = request.user
elif request.user.is_superuser:
user = User.objects.get(id=userid)
else:
raise PermissionDenied()
userprofile = UserProfile.objects.get(user=user)
if request.POST: if request.POST:
try: try:
userprofile.company = request.POST.get("company", userprofile.company) userprofile.company = request.POST.get("company", userprofile.company)
request.user.email = request.POST.get("email", request.user.email) user.email = request.POST.get("email", user.email)
request.user.first_name = request.POST.get("firstname", request.user.first_name) first_name = request.POST.get("firstname", user.first_name)
request.user.last_name = request.POST.get("lastname", request.user.last_name) last_name = request.POST.get("lastname", user.last_name)
userprofile.address = request.POST.get("address", userprofile.address) userprofile.address = request.POST.get("address", userprofile.address)
userprofile.zipcode = request.POST.get("zip", userprofile.zipcode) userprofile.zipcode = request.POST.get("zip", userprofile.zipcode)
userprofile.city = request.POST.get("city", userprofile.city) userprofile.city = request.POST.get("city", userprofile.city)
userprofile.country = request.POST.get("country", userprofile.country) userprofile.country = request.POST.get("country", userprofile.country)
userprofile.mobile = request.POST.get("mobile", userprofile.mobile) userprofile.mobile = request.POST.get("mobile", userprofile.mobile)
request.user.save() user.save()
userprofile.save() userprofile.save()
messages.success(request, "Dein Profil wurde erfolgreich bearbeitet!") messages.success(request, "Das Profil wurde erfolgreich bearbeitet!")
return redirect(reverse_lazy("userprofile")) return redirect(reverse_lazy("userprofilebyid", kwargs={"userid": user.id}))
except: except:
messages.error(request, "Dein Profil konnte nicht bearbeitet werden!") messages.error(request, "Das Profil konnte nicht bearbeitet werden!")
return redirect(reverse_lazy("userprofile")) return redirect(reverse_lazy("userprofilebyid", kwargs={"userid": user.id}))
context = { "title": "Benutzerprofil", } context = { "title": "Benutzerprofil", "user": user }
return render(request, "app/backend/user.html", context) return render(request, "app/backend/user.html", context)
def protect(request): def protect(request):
@ -128,7 +135,7 @@ class ItemCreateView(CreateView):
return super(ItemCreateView, self).form_valid(form) return super(ItemCreateView, self).form_valid(form)
def form_invalid(self, form): def form_invalid(self, form):
messages.error("Der Gegenstand konnte nicht hinzugefügt werden!") messages.error(self.request, "Der Gegenstand konnte nicht hinzugefügt werden!")
return redirect("items") return redirect("items")
@class_view_decorator(user_passes_test(is_superuser)) @class_view_decorator(user_passes_test(is_superuser))
@ -164,12 +171,15 @@ class CategoryCreateView(CreateView):
return ctx return ctx
def form_invalid(self, form): def form_invalid(self, form):
messages.error("Die Kategorie konnte nicht hinzugefügt werden!") messages.error(self.request, "Die Kategorie konnte nicht hinzugefügt werden!")
return redirect("categories") return redirect("categories")
@class_view_decorator(user_passes_test(is_superuser)) @class_view_decorator(user_passes_test(is_superuser))
class CategoryDeleteView(DeleteView): class CategoryDeleteView(DeleteView):
model = Category model = Category
pk_url_kwarg = "slug"
template_name = "app/backend/deletecategory.html"
success_url = reverse_lazy("categories")
@class_view_decorator(login_required) @class_view_decorator(login_required)
class ItemDetailView(DetailView): class ItemDetailView(DetailView):
@ -211,7 +221,7 @@ class StolenItemListView(ListView):
template_name = "app/frontend/items.html" template_name = "app/frontend/items.html"
def get_queryset(self): def get_queryset(self):
return Item.objects.filter(cats__slug=self.kwargs["slug"]) return Item.objects.filter(cats__slug=self.kwargs["slug"], status=1)
class StolenItemView(DetailView): class StolenItemView(DetailView):
model = Item model = Item
@ -228,19 +238,114 @@ class StolenItemView(DetailView):
self.title = obj.name self.title = obj.name
return obj return obj
@class_view_decorator(user_passes_test(is_superuser))
class ReportDetailView(DetailView):
model = Report
pk_url_kwarg = "uuid"
template_name = "app/backend/report.html"
class ReportDeleteView(DeleteView):
model = Report
pk_url_kwarg = "uuid"
template_name = "app/backend/deletereport.html"
@class_view_decorator(user_passes_test(is_superuser))
class ReportListView(ListView):
model = Report
template_name = "app/backend/reports.html"
def get_context_data(self, **kwargs):
ctx = super(ReportListView, self).get_context_data(**kwargs)
ctx['title'] = "Berichte"
return ctx
class ReportCreateView(CreateView): class ReportCreateView(CreateView):
model = Report model = Report
template_name = "app/frontend/report.html" template_name = "app/frontend/report.html"
fields = ["name", "mail", "phone", "found_on", "found_at", "message"] fields = ["name", "mail", "phone", "found_on", "found_at", "message"]
def post(self, request, **kwargs):
request.POST = request.POST.copy()
request.POST["found_on"] = datetime.datetime.strptime(request.POST["found_on"], "%d.%m.%Y %H:%M").strftime('%Y-%m-%d %H:%M:%S')
return super(ReportCreateView, self).post(request, **kwargs)
def get_initial(self, *args, **kwargs):
initial = super(ReportCreateView, self).get_initial(**kwargs)
if self.request.user.is_authenticated:
initial["name"] = self.request.user.get_full_name()
initial["phone"] = self.request.user.userprofile.mobile
initial["mail"] = self.request.user.email
return initial
def form_valid(self, form): def form_valid(self, form):
form.instance.item = Item.objects.get(uuid=self.kwargs['uuid']) form.instance.item = Item.objects.get(uuid=self.kwargs['uuid'])
return super(ReportCreateView, self).form_valid(form) form.instance.save()
imageform = UploadForm(self.request.POST, self.request.FILES)
if imageform.is_valid():
for image in [imageform.cleaned_data["image%i" % i] for i in range(1, 5)]:
if image:
ReportImage.objects.create(image=image, report=form.instance)
messages.success(self.request, "Vielen Dank für deine Meldung - wir werden sie prüfen und uns bald bei dir melden!")
return redirect(reverse_lazy("checkitem", kwargs={"uuid": self.kwargs['uuid']}))
def form_invalid(self, form):
messages.error(self.request, "Leider konnte deine Eingabe nicht verarbeitet werden. Bitte stelle sicher, dass die angegebenen Daten korrekt sind und versuche es nochmals!")
return redirect(reverse_lazy("checkitem", kwargs={"uuid": self.kwargs['uuid']}))
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super(ReportCreateView, self).get_context_data(**kwargs) ctx = super(ReportCreateView, self).get_context_data(**kwargs)
ctx['imageform'] = UploadForm(self.request.POST, self.request.FILES) ctx['imageform'] = UploadForm(self.request.POST, self.request.FILES)
return ctx
@class_view_decorator(user_passes_test(is_superuser))
class ReportRefuseView(UpdateView):
model = Report
pk_url_kwarg = "uuid"
template_name = "app/backend/refuse.html"
fields = []
def form_valid(self, form):
form.instance.status = -1
return super(ReportRefuseView, self).form_valid(form)
@class_view_decorator(user_passes_test(is_superuser))
class ReportProcessingView(UpdateView):
model = Report
pk_url_kwarg = "uuid"
template_name = "app/backend/processing.html"
fields = []
def form_valid(self, form):
form.instance.status = 1
return super(ReportProcessingView, self).form_valid(form)
@class_view_decorator(user_passes_test(is_superuser))
class ReportFinalizeView(UpdateView):
model = Report
pk_url_kwarg = "uuid"
template_name = "app/backend/finalize.html"
fields = []
def form_valid(self, form):
form.instance.status = 2
return super(ReportFinalizeView, self).form_valid(form)
@class_view_decorator(user_passes_test(is_superuser))
class ReportDeleteView(DeleteView):
model = Report
pk_url_kwarg = "uuid"
template_name = "app/backend/deletereport.html"
success_url = reverse_lazy("reports")
@class_view_decorator(user_passes_test(is_superuser))
class UserDeleteView(DeleteView):
model = User
pk_url_kwarg = "id"
template_name = "app/backend/deleteuser.html"
success_url = reverse_lazy("users")
@class_view_decorator(login_required)
class ItemStolenView(UpdateView): class ItemStolenView(UpdateView):
model = Item model = Item
pk_url_kwarg = "uuid" pk_url_kwarg = "uuid"
@ -260,6 +365,13 @@ class ItemStolenView(UpdateView):
def form_invalid(self, form): def form_invalid(self, form):
return redirect(reverse_lazy("item", uuid=self.form.instance.uuid)) return redirect(reverse_lazy("item", uuid=self.form.instance.uuid))
def get_object(self, queryset = None):
obj = super(ItemStolenView, self).get_object(queryset)
if self.request.user != obj.owner and not self.request.user.is_superuser:
raise PermissionDenied()
return obj
@class_view_decorator(login_required)
class ItemFoundView(UpdateView): class ItemFoundView(UpdateView):
model = Item model = Item
pk_url_kwarg = "uuid" pk_url_kwarg = "uuid"
@ -271,3 +383,121 @@ class ItemFoundView(UpdateView):
form.instance.stolen_at = None form.instance.stolen_at = None
form.instance.status = 0 form.instance.status = 0
return super(ItemFoundView, self).form_valid(form) return super(ItemFoundView, self).form_valid(form)
def get_object(self, queryset = None):
obj = super(ItemFoundView, self).get_object(queryset)
if self.request.user != obj.owner and not self.request.user.is_superuser:
raise PermissionDenied()
return obj
@class_view_decorator(user_passes_test(is_superuser))
class ItemActivateView(UpdateView):
model = Item
pk_url_kwarg = "uuid"
template_name = "app/backend/activate.html"
fields = []
def form_valid(self, form):
form.instance.status = 0
return super(ItemActivateView, self).form_valid(form)
@class_view_decorator(user_passes_test(is_superuser))
class ItemDeleteView(DeleteView):
model = Item
pk_url_kwarg = "uuid"
template_name = "app/backend/deleteitem.html"
def get_object(self, queryset = None):
obj = super(ItemDeleteView, self).get_object(queryset)
if not self.request.user.is_superuser:
raise PermissionDenied()
return obj
@class_view_decorator(login_required)
class ItemSoldView(UpdateView):
model = Item
pk_url_kwarg = "uuid"
template_name = "app/backend/sold.html"
fields = []
def get_object(self, queryset = None):
obj = super(ItemSoldView, self).get_object(queryset)
if self.request.user != obj.owner and not self.request.user.is_superuser:
raise PermissionDenied()
return obj
def form_valid(self, form):
form.instance.status = 2
return super(ItemSoldView, self).form_valid(form)
@class_view_decorator(login_required)
class ItemTransferView(UpdateView):
model = Item
pk_url_kwarg = "uuid"
template_name = "app/backend/transfer.html"
fields = []
def get(self, request, *args, **kwargs):
return redirect(reverse_lazy("item", uuid=self.get_object().uuid))
def form_valid(self, form):
try:
new = User.objects.get(email=form.data["id_email"])
if new != form.instance.owner:
form.instance.owner = new
form.instance.save()
messages.success(self.request, "Der Gegenstand wurde erfolgreich übertragen und ist ab sofort im Empfängeraccount verfügbar!")
else:
messages.info(self.request, "Wieso willst du dir diesen Gegenstand selbst übertragen?")
return redirect(reverse_lazy("items"))
except:
messages.error(self.request, "Diese E-Mail-Adresse wurde in unserem System nicht gefunden! Wenn die Person, an die du den Gegenstand übergeben hast, bereits einen Account besitzt, überprüfe bitte nochmals die E-Mail-Adresse. Ansonsten bitte sie darum, einen Account zu erstellen.")
return super(ItemTransferView, self).form_valid(form)
def get_object(self, queryset = None):
obj = super(ItemTransferView, self).get_object(queryset)
if self.request.user != obj.owner and not self.request.user.is_superuser:
raise PermissionDenied()
return obj
class UserRegisterView(CreateView):
model = User
form_class = UserCreationForm
template_name = "app/backend/register.html"
success_url = reverse_lazy("userprofile")
def form_valid(self, form):
res = super(UserRegisterView, self).form_valid(form)
login(self.request, form.instance)
return res
@class_view_decorator(user_passes_test(is_superuser))
class UserCreateView(CreateView):
model = User
form_class = UserCreationForm
template_name = "app/backend/adduser.html"
def form_valid(self, form):
return redirect(reverse_lazy("userprofilebyid", kwargs={"userid": form.instance.id}))
@class_view_decorator(user_passes_test(is_superuser))
class UserPromoteView(UpdateView):
model = User
pk_url_kwarg = "userid"
template_name = "app/backend/promote.html"
fields = []
def form_valid(self, form):
form.instance.is_superuser = True
return super(UserPromoteView, self).form_valid(form)
@class_view_decorator(user_passes_test(is_superuser))
class UserDemoteView(UpdateView):
model = User
pk_url_kwarg = "userid"
template_name = "app/backend/demote.html"
fields = []
def form_valid(self, form):
form.instance.is_superuser = False
return super(UserDemoteView, self).form_valid(form)

5
database_update.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash
./manage.py makemigrations
./manage.py migrate
./manage.py migrate --database=gdpr_log

View file

@ -75,12 +75,21 @@ WSGI_APPLICATION = 'stolen.wsgi.application'
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.mysql',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'NAME': 'stolen',
'USER': 'stolen',
'PASSWORD': 'eiph8aXoo7Phee5ahwaeziegu',
'HOST': 'localhost',
'PORT': '',
}, },
'gdpr_log': { 'gdpr_log': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.mysql',
'NAME': os.path.join(BASE_DIR, 'gdpr-log.sqlite3'), 'NAME': 'stolen_gdpr',
'USER': 'stolen',
'PASSWORD': 'eiph8aXoo7Phee5ahwaeziegu',
'HOST': 'localhost',
'PORT': '',
} }
} }
@ -117,7 +126,7 @@ USE_I18N = True
USE_L10N = True USE_L10N = True
USE_TZ = True USE_TZ = True
TIME_ZONE = "Europe/Vienna"
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/ # https://docs.djangoproject.com/en/2.2/howto/static-files/
@ -152,3 +161,8 @@ TWILIO_ACCOUNT_SID = "ACe7c611d487010543fd2d7f16ef3fbacb"
TWILIO_AUTH_TOKEN = "74e7804cee2f7220bcf43c94ae222b57" TWILIO_AUTH_TOKEN = "74e7804cee2f7220bcf43c94ae222b57"
TWILIO_CALLER_ID = "+12132665722" TWILIO_CALLER_ID = "+12132665722"
ABSOLUTE_URL_OVERRIDES = {
'auth.user': lambda u: "/clientarea/profile/%s/" % str(u.id),
}
LOGOUT_REDIRECT_URL = "/"

View file

@ -0,0 +1,10 @@
{% load bootstrap4 %}
{% block content %}
<p>Möchtest du diesen Gegenstand freischalten?</p>
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
{% buttons %}<button type="submit" class="btn btn-success">Freischalten</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,14 @@
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<div class="form-group"><label for="id_username">Benutzername</label><input type="text" name="username" maxlength="150" autofocus="" class="form-control" placeholder="Username" title="" required="" id="id_username">
</div>
<div class="form-group"><label for="id_password1">Passwort</label><input type="password" name="password1" class="form-control" placeholder="Passwort" title="" required="" id="id_password1">
</div>
<div class="form-group"><label for="id_password2">Passwort bestätigen</label><input type="password" name="password2" class="form-control" placeholder="Passwort bestätigen" title="Gib dasselbe Passwort nochmal zur Bestätigung ein." required="" id="id_password2">
</div>
<button type="submit" class="btn btn-primary">Registrieren</button>
</form>
{% endblock %}

View file

@ -54,6 +54,12 @@
<p>Benutzerverwaltung</p> <p>Benutzerverwaltung</p>
</a> </a>
</li> </li>
<li class="nav-item {% if title == "Berichte" %}active{% endif %}">
<a class="nav-link" href="{% url "reports" %}">
<i class="nc-icon nc-notification-70"></i>
<p>Berichte</p>
</a>
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url "admin:index" %}"> <a class="nav-link" href="{% url "admin:index" %}">
<i class="nc-icon nc-cctv"></i> <i class="nc-icon nc-cctv"></i>

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1 @@
{% extends "app/backend/form.html" %}

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -15,7 +15,7 @@
{% if object.status == -1 %} {% if object.status == -1 %}
<p class="card-text" style="color: orange;">Noch nicht freigeschaltet!</p> <p class="card-text" style="color: orange;">Noch nicht freigeschaltet!</p>
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<button id="publish" class="btn btn-success">Freischalten</p> <button id="publish" class="btn btn-success">Freischalten</button>
{% endif %} {% endif %}
{% elif object.status == 0 %} {% elif object.status == 0 %}
<p class="card-text" style="color: green;">Nicht als gestohlen gemeldet.</p> <p class="card-text" style="color: green;">Nicht als gestohlen gemeldet.</p>
@ -25,12 +25,24 @@
<p class="card-text" style="color: red;">Als gestohlen gemeldet!</p> <p class="card-text" style="color: red;">Als gestohlen gemeldet!</p>
<button id="found" class="btn btn-success">Wieder erhalten</button> <button id="found" class="btn btn-success">Wieder erhalten</button>
{% elif object.status == 2 %} {% elif object.status == 2 %}
<p class="card text" style="color: blue;">Gegenstand verkauft</p> <p class="card-text" style="color: blue;">Gegenstand verkauft</p>
<button id="transfer" class="color: blue;">An anderen Benutzer übertragen</p> {% if request.user.is_superuser %}
<button id="transfer" class="btn btn-info">An anderen Benutzer übertragen</button>
{% endif %} {% endif %}
{% endif %}
{% if request.user.is_superuser %}
<a href="{% url "userprofilebyid" userid=object.owner.id %}" class="btn btn-primary" role="button">Benutzerprofil ansehen</a>
<button id="delete" class="btn btn-info">Löschen</button> <button id="delete" class="btn btn-info">Löschen</button>
{% endif %}
</div> </div>
</div> </div>
{% if object.status == 1 %}
<br/>
<h3>Aktueller Status</h3>
<p>Als gestohlen gemeldet</p>
<p>Zeitpunkt: {{ object.stolen_on | date:'d.m.Y H:i' }}</p>
<p>Ort: {{ object.stolen_at }}</p>
{% endif %}
<br/> <br/>
<h3>Bilder</h3> <h3>Bilder</h3>
<button id="addImage" class="addImage btn btn-info btn-fill float-right">Bild hochladen</button> <button id="addImage" class="addImage btn btn-info btn-fill float-right">Bild hochladen</button>
@ -86,6 +98,35 @@ $('#addImage').on('click',function(){
$('#myModal').modal({show:true}); $('#myModal').modal({show:true});
}); });
}); });
$('#publish').on('click',function(){
$('#modaltitle').text("Gegenstand freischalten");
$('.modal-body').load('activate/',function(){
$('#modalform').attr('action', "activate/");
$('#myModal').modal({show:true});
});
});
$('#sold').on('click',function(){
$('#modaltitle').text("Gegenstand übergeben");
$('.modal-body').load('sold/',function(){
$('#modalform').attr('action', "sold/");
$('#modalform2').attr('action', 'transfer/');
$('#myModal').modal({show:true});
});
});
$('#delete').on('click',function(){
$('#modaltitle').text("Gegenstand löschen");
$('.modal-body').load('delete/',function(){
$('#modalform').attr('action', "delete/");
$('#myModal').modal({show:true});
});
});
$('#transfer').on('click',function(){
$('#modaltitle').text("Gegenstand übergeben");
$('.modal-body').load('transfer/',function(){
$('#modalform').attr('action', "transfer/");
$('#myModal').modal({show:true});
});
});
</script> </script>
<script src="{% static "app/backend/js/jquery.datetimepicker.js" %}" /> <script src="{% static "app/frontend/js/jquery.datetimepicker.full.js" %}" />
{% endblock %} {% endblock %}

View file

@ -14,6 +14,7 @@
</thead> </thead>
<tbody> <tbody>
{% for item in request.user.item_set.all %} {% for item in request.user.item_set.all %}
{% if item.status != 2 %}
<tr> <tr>
<td><img style="max-width: 50px; max-height: 100px;" src="{{ item.get_primary_image.image.url }}" /></td> <td><img style="max-width: 50px; max-height: 100px;" src="{{ item.get_primary_image.image.url }}" /></td>
<td>{{ item.name }}</td> <td>{{ item.name }}</td>
@ -21,6 +22,7 @@
<td>{% autoescape off %}{{ item.get_status_html }}{% endautoescape %}</td> <td>{% autoescape off %}{{ item.get_status_html }}{% endautoescape %}</td>
<td><a href="{{ item.uuid }}/"><span title="Gegenstand bearbeiten"><i class="fas fa-edit"></i></span></a></td> <td><a href="{{ item.uuid }}/"><span title="Gegenstand bearbeiten"><i class="fas fa-edit"></i></span></a></td>
</tr> </tr>
{% endif %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>

View file

@ -23,7 +23,7 @@
<nav class="navbar navbar-expand-lg navbar-transparent navbar-absolute"> <nav class="navbar navbar-expand-lg navbar-transparent navbar-absolute">
<div class="container"> <div class="container">
<div class="navbar-wrapper"> <div class="navbar-wrapper">
<a class="navbar-brand" href="#pablo">Stolen</a> <a class="navbar-brand" href="{% url "index" %}">Stolen</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" aria-controls="navigation-index" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" aria-controls="navigation-index" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-bar burger-lines"></span> <span class="navbar-toggler-bar burger-lines"></span>
<span class="navbar-toggler-bar burger-lines"></span> <span class="navbar-toggler-bar burger-lines"></span>
@ -40,7 +40,7 @@
<div class="col-md-4 col-sm-6 ml-auto mr-auto"> <div class="col-md-4 col-sm-6 ml-auto mr-auto">
<!--<form class="form" method="" action="">--> <!--<form class="form" method="" action="">-->
<div class="card card-login card-hidden"> <div class="card card-login card-hidden">
<div class="card-header "> <div class="card-header">
<h3 class="header text-center">Login</h3> <h3 class="header text-center">Login</h3>
</div> </div>
<div class="card-body" align="center"> <div class="card-body" align="center">

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,11 @@
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,18 @@
{% extends "app/backend/login.html" %}
{% load bootstrap4 %}
{% block content %}
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<div class="form-group"><label for="id_username">Benutzername</label><input type="text" name="username" maxlength="150" autofocus="" class="form-control" placeholder="Username" title="" required="" id="id_username">
</div>
<div class="form-group"><label for="id_password1">Passwort</label><input type="password" name="password1" class="form-control" placeholder="Passwort" title="" required="" id="id_password1">
</div>
<div class="form-group"><label for="id_password2">Passwort bestätigen</label><input type="password" name="password2" class="form-control" placeholder="Passwort bestätigen" title="Gib dasselbe Passwort nochmal zur Bestätigung ein." required="" id="id_password2">
</div>
{% buttons %}<button type="submit" class="btn btn-primary">Registrieren</button>{% endbuttons %}
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -0,0 +1,93 @@
{% extends "app/backend/base.html" %}
{% load static %}
{% block content %}
<div class="card" class="mx-auto" style="margin: 0 auto; float: none; margin-bottom: 10px; width: 18rem;">
<div class="card-body" style="text-align: center;">
{% if object.reportimage_set.all %}
<img style="max-width: 100%;" class="card-img-top" src="{{ object.reportimage_set.all.0.url }}">
{% endif %}
<h5 class="card-title">{{ object.item.name }}</h5>
<h6 class="card-subtitle mb-2 text-muted">{{ object.item.iid }}</h6>
<p class="card-text">Finder: <a href="mailto:{{ object.mail }}">{{ object.name }}</a></p>
<p class="card-text">Telefon: {{ object.phone }}</p>
<p class="card-text">{{ object.description }}</p>
<p class="card-text">{% autoescape off %}{{ object.get_status_html }}{% endautoescape %}</p>
{% if object.status == 0 %}
<button id="processingreport" class="btn btn-success">Bericht in Bearbeitung</button>
{% elif object.status == 1 %}
<button id="finalizereport" class="btn btn-success">Bericht abgeschlossen</button>
{% endif %}
{% if object.status == -1 or object.status == 2 %}
<button id="deletereport" class="btn btn-danger">Bericht löschen</button>
{% else %}
<button id="refusereport" class="btn btn-danger">Bericht unrichtig</button>
{% endif %}
<a href="{{ object.item.get_absolute_url }}" class="btn btn-primary" role="button">Gegenstand ansehen</a>
</div>
</div>
<br/>
<h3>Funddaten</h3>
<p>Fundzeitpunkt: {{ object.found_on | date:'d.m.Y H:i' }}</p>
<p>Fundort: {{ object.found_at }}</p>
<p>Nachricht: {{ object.message }}</p>
<br/>
<h3>Bilder</h3>
{% if not object.reportimage_set.all %}Es wurden keine Bilder hinzugefügt!{% endif %}
<div class="card-columns">
{% for image in object.reportimage_set.all %}
<div class="card">
<img class="card-img" src="{{ image.image.url }}" />
</div>
{% endfor %}
</div>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 id="modaltitle" class="modal-title">Modal with Dynamic Content</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
$('#deletereport').on('click',function(){
$('#modaltitle').text("Bericht löschen");
$('.modal-body').load('delete/',function(){
$('#modalform').attr('action', "delete/");
$('#myModal').modal({show:true});
});
});
$('#refusereport').on('click',function(){
$('#modaltitle').text("Bericht ablehnen");
$('.modal-body').load('refuse/',function(){
$('#modalform').attr('action', "refuse/");
$('#myModal').modal({show:true});
});
});
$('#processingreport').on('click',function(){
$('#modaltitle').text("Bericht in Bearbeitung");
$('.modal-body').load('process/',function(){
$('#modalform').attr('action', "process/");
$('#myModal').modal({show:true});
});
});
$('#finalizereport').on('click',function(){
$('#modaltitle').text("Bericht erledigt");
$('.modal-body').load('finalize/',function(){
$('#modalform').attr('action', "finalize/");
$('#myModal').modal({show:true});
});
});
</script>
{% endblock %}

View file

@ -0,0 +1,61 @@
{% extends "app/backend/base.html" %}
{% block content %}
<table id="reports" name="reports" class="table">
<thead>
<tr>
<th>Gegenstand</th>
<th>Absender</th>
<th>Status</th>
<th>Erstellungsdatum</th>
<th>Optionen</th>
</tr>
</thead>
<tbody>
{% for report in object_list %}
<tr>
<td>{{ report.item.name }} ({{ report.item.owner.get_full_name }})</td>
<td>{{ report.name }}</td>
<td>{% autoescape off %}{{ report.get_status_html }}{% endautoescape %}</td>
<td>{{ report.created | date:'d.m.Y H:i' }}</td>
<td><a href="{{ report.uuid }}/"><span title="Bericht bearbeiten"><i class="fas fa-edit" aria-hidden="true"></i></span></a> <span onclick='deleteReport("{{ report.uuid }}");' title="Bericht löschen"><i class="fas fa-trash"></i></span></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 id="modaltitle" class="modal-title">Modal with Dynamic Content</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function deleteReport(rid) {
$('#modaltitle').text("Bericht löschen");
$('.modal-body').load(rid + '/delete/',function(){
$('#modalform').attr('action', rid + "/delete/");
$('#myModal').modal({show:true});
})};
$(document).ready( function () {
$('#reports').DataTable(
{
"language": {
"url": "/static/app/backend/js/plugins/dataTables.german.lang"
}
}
);
} );
</script>
{% endblock %}

View file

@ -0,0 +1,21 @@
{% load bootstrap4 %}
{% block content %}
<h6>Als verkauft markieren</h6>
<p>Wenn du den Gegenstand an eine Person übergeben hast, die hier noch keinen Account besitzt, kannst du ihn hier als verkauft markieren. Der Gegenstand wird dann nicht mehr in deinem Profil angezeigt.<p>
<p>Die neue Besitzerin kann sich dann, sobald sie einen Account erstellt hat, mit einem Kaufnachweis an uns wenden und wir fügen den Gegenstand zu ihrem Profil hinzu.</p>
<form id="modalform" action="" method="post" class="form">
{% csrf_token %}
<button type="submit" class="btn btn-primary" id="btnSold">Als verkauft markieren</button>
</form>
<hr/>
<h6>Gegenstand übertragen</h6>
<p>Wenn die Person, an die du den Gegenstand übergeben hast, bereits einen Account besitzt, gib hier die dazugehörige E-Mail-Adresse ein, und wir kümmern uns um den Rest.</p>
<p>Der Gegenstand wird danach sofort im Empfängerprofil angezeigt.</p>
<form id="modalform2" action="" method="post" class="form">
{% csrf_token %}
<input type="email" class="form-control" name="id_email" placeholder="E-Mail" required="required" />
<button type="submit" class="btn btn-primary" id="btnTransfer">Gegenstand übertragen</button>
</form>
{% endblock %}
{% block scripts %}
{% endblock %}

View file

@ -3,7 +3,7 @@
<script> <script>
$(function () { $(function () {
$("#id_stolen_on").datetimepicker({ $("#id_stolen_on").datetimepicker({
format:'D.M.Y H:m' format:'D.M.Y H:m',
}); });
}); });
</script> </script>

View file

@ -20,13 +20,13 @@
<div class="col-md-6 pr-1"> <div class="col-md-6 pr-1">
<div class="form-group"> <div class="form-group">
<label>Firma</label> <label>Firma</label>
<input type="text" name="company" class="form-control" placeholder="Firma" value="{% if request.user.userprofile.company %}{{ request.user.userprofile.company }}{% endif %}"> <input type="text" name="company" class="form-control" placeholder="Firma" value="{% if user.userprofile.company %}{{ user.userprofile.company }}{% endif %}">
</div> </div>
</div> </div>
<div class="col-md-6 pl-1"> <div class="col-md-6 pl-1">
<div class="form-group"> <div class="form-group">
<label>E-Mail-Adresse</label> <label>E-Mail-Adresse</label>
<input type="email" name="email" class="form-control" placeholder="E-Mail" value="{% if request.user.email %}{{ request.user.email }}{% endif %}"> <input type="email" name="email" class="form-control" placeholder="E-Mail" value="{% if user.email %}{{ user.email }}{% endif %}">
</div> </div>
</div> </div>
</div> </div>
@ -34,13 +34,13 @@
<div class="col-md-6 pr-1"> <div class="col-md-6 pr-1">
<div class="form-group"> <div class="form-group">
<label>Vorname</label> <label>Vorname</label>
<input type="text" name="firstname" class="form-control" placeholder="Vorname" value="{% if request.user.first_name %}{{ request.user.first_name }}{% endif %}"> <input type="text" name="firstname" class="form-control" placeholder="Vorname" value="{% if user.first_name %}{{ user.first_name }}{% endif %}">
</div> </div>
</div> </div>
<div class="col-md-6 pl-1"> <div class="col-md-6 pl-1">
<div class="form-group"> <div class="form-group">
<label>Nachname</label> <label>Nachname</label>
<input type="text" name="lastname" class="form-control" placeholder="Nachname" value="{% if request.user.last_name %}{{ request.user.last_name }}{% endif %}"> <input type="text" name="lastname" class="form-control" placeholder="Nachname" value="{% if user.last_name %}{{ user.last_name }}{% endif %}">
</div> </div>
</div> </div>
</div> </div>
@ -48,7 +48,7 @@
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label>Adresse</label> <label>Adresse</label>
<input type="text" name="address" class="form-control" placeholder="Adresse" value="{% if request.user.userprofile.address %}{{ request.user.userprofile.address }}{% endif %}"> <input type="text" name="address" class="form-control" placeholder="Adresse" value="{% if user.userprofile.address %}{{ user.userprofile.address }}{% endif %}">
</div> </div>
</div> </div>
</div> </div>
@ -56,19 +56,19 @@
<div class="col-md-4 pr-1"> <div class="col-md-4 pr-1">
<div class="form-group"> <div class="form-group">
<label>Postleitzahl</label> <label>Postleitzahl</label>
<input type="text" name="zip" class="form-control" placeholder="Postleitzahl" value="{% if request.user.userprofile.zipcode %}{{ request.user.userprofile.zipcode }}{% endif %}"> <input type="text" name="zip" class="form-control" placeholder="Postleitzahl" value="{% if user.userprofile.zipcode %}{{ user.userprofile.zipcode }}{% endif %}">
</div> </div>
</div> </div>
<div class="col-md-4 px-1"> <div class="col-md-4 px-1">
<div class="form-group"> <div class="form-group">
<label>Stadt</label> <label>Stadt</label>
<input type="text" name="city" class="form-control" placeholder="Stadt" value="{% if request.user.userprofile.city %}{{ request.user.userprofile.city }}{% endif %}"> <input type="text" name="city" class="form-control" placeholder="Stadt" value="{% if user.userprofile.city %}{{ user.userprofile.city }}{% endif %}">
</div> </div>
</div> </div>
<div class="col-md-4 pl-1"> <div class="col-md-4 pl-1">
<div class="form-group"> <div class="form-group">
<label>Staat</label> <label>Staat</label>
<input type="text" name="country" class="form-control" placeholder="Land" value="{% if request.user.userprofile.country %}{{ request.user.userprofile.country }}{% endif %}"> <input type="text" name="country" class="form-control" placeholder="Land" value="{% if user.userprofile.country %}{{ user.userprofile.country }}{% endif %}">
</div> </div>
</div> </div>
</div> </div>
@ -76,7 +76,7 @@
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label>Mobiltelefon</label> <label>Mobiltelefon</label>
<input type="tel" name="mobile" class="form-control" placeholder="Mobiltelefon" value="{% if request.user.userprofile.mobile %}{{ request.user.userprofile.mobile }}{% endif %}"> <input type="tel" name="mobile" class="form-control" placeholder="Mobiltelefon" value="{% if user.userprofile.mobile %}{{ user.userprofile.mobile }}{% endif %}">
</div> </div>
</div> </div>
</div> </div>
@ -101,8 +101,17 @@
</p> </p>
</div> </div>
<p class="card-description text-center"> <p class="card-description text-center">
{% if request.user == user %}
<button id="changePass" class="btn btn-info btn-fill pull-center">Passwort ändern</button> <button id="changePass" class="btn btn-info btn-fill pull-center">Passwort ändern</button>
<button id="tfa" class="btn btn-info btn-fill pull-center">Two-Factor-Authentication</button> <button id="tfa" class="btn btn-info btn-fill pull-center">Two-Factor-Authentication</button>
{% endif %}
{% if request.user.is_superuser %}
{% if user.is_superuser %}
<button id="demote" class="btn btn-danger btn-fill pull-center">Administratorrechte entziehen</button>
{% else %}
<button id="promote" class="btn btn-danger btn-fill pull-center">Administratorrechte erteilen</button>
{% endif %}
{% endif %}
</p> </p>
</div> </div>
<div class="card-footer "> <div class="card-footer ">
@ -113,6 +122,37 @@
</div> </div>
</div> </div>
</div> </div>
{% if request.user.is_superuser and not request.user == user %}
<div class="card">
<div class="card-header">Gegenstände</div>
<div class="card-body">
<table id="useritems" name="useritems" class="table">
<thead>
<tr>
<th></th>
<th>Bezeichnung</th>
<th>ID</th>
<th>Status</th>
<th>Optionen</th>
</tr>
</thead>
<tbody>
{% for item in user.item_set.all %}
<tr>
<td><img style="max-width: 50px; max-height: 100px;" src="{{ item.get_primary_image.image.url }}" /></td>
<td>{{ item.name }}</td>
<td>{{ item.iid }}</td>
<td>{% autoescape off %}{{ item.get_status_html }}{% endautoescape %}</td>
<td><a href="{% url "item" uuid=item.uuid %}"><span title="Gegenstand bearbeiten"><i class="fas fa-edit"></i></span></a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<div class="modal fade" id="myModal" role="dialog"> <div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog"> <div class="modal-dialog">
<!-- Modal content--> <!-- Modal content-->
@ -135,12 +175,39 @@
$('#changePass').on('click',function(){ $('#changePass').on('click',function(){
$('#modaltitle').text("Passwort ändern"); $('#modaltitle').text("Passwort ändern");
$('.modal-body').load('password/',function(){ $('.modal-body').load('password/',function(){
$('#modalform').attr('action', "password/");
$('#myModal').modal({show:true}); $('#myModal').modal({show:true});
}); });
}); });
$('#promote').on('click',function(){
$('#modaltitle').text("Administratorrechte erteilen");
$('.modal-body').load('promote/',function(){
$('#modalform').attr('action', "promote/");
$('#myModal').modal({show:true});
});
});
$('#demote').on('click',function(){
$('#modaltitle').text("Administratorrechte entfernen");
$('.modal-body').load('demote/',function(){
$('#modalform').attr('action', "demote/");
$('#myModal').modal({show:true});
});
});
$('#tfa').on('click', function() { $('#tfa').on('click', function() {
window.location.href = "{% url "two_factor:profile" %}" window.location.href = "{% url "two_factor:profile" %}"
}); });
$(document).ready( function () {
$('#useritems').DataTable(
{
"language": {
"url": "{% static "app/backend/js/plugins/dataTables.german.lang" %}"
}
}
);
} );
</script> </script>
{% endblock %} {% endblock %}

View file

@ -14,7 +14,7 @@
<tr> <tr>
<td>{{ user.username }}</td> <td>{{ user.username }}</td>
<td>{{ user.first_name }} {{ user.last_name }}</td> <td>{{ user.first_name }} {{ user.last_name }}</td>
<td><span onclick='deleteUser("{{ user.id }}");' title="Benutzer löschen"><i class="fas fa-trash"></i></span></a></td> <td><a href="{% url "userprofilebyid" userid=user.id %}"><i class="fas fa-search"></i></a> <span onclick='deleteUser("{{ user.id }}");' title="Benutzer löschen"><i class="fas fa-trash"></i></span></a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -43,6 +43,7 @@
$('.addUser').on('click',function(){ $('.addUser').on('click',function(){
$('#modaltitle').text("Benutzer hinzufügen"); $('#modaltitle').text("Benutzer hinzufügen");
$('.modal-body').load('add/',function(){ $('.modal-body').load('add/',function(){
$('#modalform').attr('action', "add/");
$('#myModal').modal({show:true}); $('#myModal').modal({show:true});
}); });
}); });
@ -50,6 +51,7 @@ $('.addUser').on('click',function(){
function deleteUser(uid) { function deleteUser(uid) {
$('#modaltitle').text("Benutzer löschen"); $('#modaltitle').text("Benutzer löschen");
$('.modal-body').load(uid + '/delete/',function(){ $('.modal-body').load(uid + '/delete/',function(){
$('#modalform').attr('action', uid + "/delete/");
$('#myModal').modal({show:true}); $('#myModal').modal({show:true});
})}; })};
</script> </script>

View file

@ -7,6 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="{% static "app/frontend/css/main.css" %}" /> <link rel="stylesheet" href="{% static "app/frontend/css/main.css" %}" />
<link rel="stylesheet" href="{% static "app/backend/css/bootstrap.min.css" %}" /> <link rel="stylesheet" href="{% static "app/backend/css/bootstrap.min.css" %}" />
{% block css %}{% endblock %}
</head> </head>
<body class="is-preload"> <body class="is-preload">

View file

@ -18,8 +18,7 @@
<div id="content"></div> <div id="content"></div>
{% endblock %} {% endblock %}
{% block script %} {% block scripts %}
<script src="{% static "app/frontend/js/check.js" %}"></script>
<script> <script>
function showItems() { function showItems() {
var slug = $("#category").val(); var slug = $("#category").val();

View file

@ -0,0 +1,4 @@
{% extends "app/frontend/base.html" %}
{% block content %}
Hier ist Platz für die Beantwortung häufig gestellter Fragen.
{% endblock %}

View file

@ -12,6 +12,13 @@
<button id="foundItem" class="btn btn-success">Als gefunden melden</button> <button id="foundItem" class="btn btn-success">Als gefunden melden</button>
</div> </div>
</div> </div>
{% if object.status == 1 %}
<br/>
<h3>Aktueller Status</h3>
<p>Als gestohlen gemeldet</p>
<p>Zeitpunkt: {{ object.stolen_on | date:'d.m.Y H:i' }}</p>
<p>Ort: {{ object.stolen_at }}</p>
{% endif %}
<br/> <br/>
<h3>Bilder</h3> <h3>Bilder</h3>
{% if not object.image_set.all %}Es wurden noch keine Bilder hinzugefügt!{% endif %} {% if not object.image_set.all %}Es wurden noch keine Bilder hinzugefügt!{% endif %}
@ -50,7 +57,7 @@
$('#foundItem').on('click',function(){ $('#foundItem').on('click',function(){
$('#modaltitle').text("Gegenstand gefunden"); $('#modaltitle').text("Gegenstand gefunden");
$('.modal-body').load('report/',function(){ $('.modal-body').load('report/',function(){
$('#modalform').attr("action", "{% url "additem" %}"); $('#modalform').attr("action", "report/");
$('#myModal').modal({show:true}); $('#myModal').modal({show:true});
}); });
}); });

View file

@ -1,12 +1,25 @@
{% load bootstrap4 %} {% load bootstrap4 %}
{% load static %}
{% block content %} {% block content %}
<form id="modalform" action="" method="post" class="form"> <p>Bitte fülle dieses Formular sorgfältig aus, damit wir deine Meldung bearbeiten können.</p>
<form id="modalform" action="" method="post" class="form" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{% form %}
{% imageform %}
{% bootstrap_form form %} {% bootstrap_form form %}
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %} <p>Lade bis zu fünf Bilddateien hoch, um deinen Fund besser zu dokumentieren.</p>
{% bootstrap_form imageform %}
{% buttons %}<button type="submit" class="btn btn-success">Absenden</button>{% endbuttons %}
</form> </form>
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script src="{% static "app/frontend/js/jquery.datetimepicker.full.js" %}" />
<script>
$(function () {
$("#id_found_on").datetimepicker({
format:'d.m.Y H:i',
});
});
</script>
{% endblock %}
{% block css %}
<link rel="stylesheet" href="{% static "app/backend/css/jquery.datetimepicker.css" %}" />
{% endblock %} {% endblock %}