views.py 14.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# -*- coding:utf-8 -*
#
# Copyright 2016,2017
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#

Krophil's avatar
Krophil committed
25
from django.shortcuts import redirect
Sli's avatar
Sli committed
26
from django.http import HttpResponse, Http404
27
from django.urls import reverse_lazy, reverse
Krophil's avatar
Krophil committed
28
from core.views.forms import SelectDate
Krophil's avatar
Krophil committed
29 30
from django.views.generic import DetailView, TemplateView
from django.views.generic.edit import UpdateView, FormMixin, FormView
Skia's avatar
Skia committed
31
from django.utils.translation import ugettext_lazy as _
Skia's avatar
Skia committed
32 33
from django.conf import settings
from django import forms
Skia's avatar
Skia committed
34
from django.core.exceptions import PermissionDenied
Sli's avatar
Sli committed
35
from django.core.paginator import Paginator, InvalidPage
Skia's avatar
Skia committed
36

Krophil's avatar
Krophil committed
37 38
from ajax_select import make_ajax_field
from ajax_select.fields import AutoCompleteSelectMultipleField
Skia's avatar
Skia committed
39

Krophil's avatar
Krophil committed
40
from core.views import CanViewMixin, CanEditMixin
Skia's avatar
Skia committed
41
from core.views.files import send_file, FileView
Skia's avatar
Skia committed
42
from core.models import SithFile, User, Notification, RealGroup
Skia's avatar
Skia committed
43

44
from sas.models import Picture, Album, PeoplePictureRelation
Skia's avatar
Skia committed
45

Krophil's avatar
Krophil committed
46

Skia's avatar
Skia committed
47
class SASForm(forms.Form):
Sli's avatar
Sli committed
48 49 50 51 52 53 54 55
    album_name = forms.CharField(
        label=_("Add a new album"), max_length=30, required=False
    )
    images = forms.ImageField(
        widget=forms.ClearableFileInput(attrs={"multiple": True}),
        label=_("Upload images"),
        required=False,
    )
Skia's avatar
Skia committed
56

Skia's avatar
Skia committed
57
    def process(self, parent, owner, files, automodere=False):
Skia's avatar
Skia committed
58
        try:
Sli's avatar
Sli committed
59 60 61 62 63 64 65
            if self.cleaned_data["album_name"] != "":
                album = Album(
                    parent=parent,
                    name=self.cleaned_data["album_name"],
                    owner=owner,
                    is_moderated=automodere,
                )
Skia's avatar
Skia committed
66 67 68
                album.clean()
                album.save()
        except Exception as e:
Sli's avatar
Sli committed
69 70 71 72 73
            self.add_error(
                None,
                _("Error creating album %(album)s: %(msg)s")
                % {"album": self.cleaned_data["album_name"], "msg": repr(e)},
            )
Skia's avatar
Skia committed
74
        for f in files:
Sli's avatar
Sli committed
75 76 77 78 79 80
            new_file = Picture(
                parent=parent,
                name=f.name,
                file=f,
                owner=owner,
                mime_type=f.content_type,
81
                size=f.size,
Sli's avatar
Sli committed
82 83 84
                is_folder=False,
                is_moderated=automodere,
            )
Skia's avatar
Skia committed
85 86
            if automodere:
                new_file.moderator = owner
Skia's avatar
Skia committed
87 88
            try:
                new_file.clean()
Skia's avatar
Skia committed
89
                new_file.generate_thumbnails()
Skia's avatar
Skia committed
90 91
                new_file.save()
            except Exception as e:
Sli's avatar
Sli committed
92 93 94 95 96
                self.add_error(
                    None,
                    _("Error uploading file %(file_name)s: %(msg)s")
                    % {"file_name": f, "msg": repr(e)},
                )
Skia's avatar
Skia committed
97

Krophil's avatar
Krophil committed
98

99 100 101
class RelationForm(forms.ModelForm):
    class Meta:
        model = PeoplePictureRelation
Sli's avatar
Sli committed
102 103 104 105 106 107
        fields = ["picture"]
        widgets = {"picture": forms.HiddenInput}

    users = AutoCompleteSelectMultipleField(
        "users", show_help_text=False, help_text="", label=_("Add user"), required=False
    )
108

Krophil's avatar
Krophil committed
109

Skia's avatar
Skia committed
110 111
class SASMainView(FormView):
    form_class = SASForm
Skia's avatar
Skia committed
112
    template_name = "sas/main.jinja"
Sli's avatar
Sli committed
113
    success_url = reverse_lazy("sas:main")
Skia's avatar
Skia committed
114 115 116 117

    def post(self, request, *args, **kwargs):
        self.form = self.get_form()
        parent = SithFile.objects.filter(id=settings.SITH_SAS_ROOT_DIR_ID).first()
Sli's avatar
Sli committed
118
        files = request.FILES.getlist("images")
Skia's avatar
Skia committed
119
        root = User.objects.filter(username="root").first()
120
        if request.user.is_authenticated and request.user.is_in_group(
Sli's avatar
Sli committed
121 122
            settings.SITH_GROUP_SAS_ADMIN_ID
        ):
Skia's avatar
Skia committed
123
            if self.form.is_valid():
Sli's avatar
Sli committed
124 125 126
                self.form.process(
                    parent=parent, owner=root, files=files, automodere=True
                )
Skia's avatar
Skia committed
127 128 129 130
                if self.form.is_valid():
                    return super(SASMainView, self).form_valid(self.form)
        else:
            self.form.add_error(None, _("You do not have the permission to do that"))
Skia's avatar
Skia committed
131
        return self.form_invalid(self.form)
Skia's avatar
Skia committed
132 133 134

    def get_context_data(self, **kwargs):
        kwargs = super(SASMainView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
135 136 137 138
        kwargs["categories"] = Album.objects.filter(
            parent__id=settings.SITH_SAS_ROOT_DIR_ID
        ).order_by("id")
        kwargs["latest"] = Album.objects.filter(is_moderated=True).order_by("-id")[:5]
Skia's avatar
Skia committed
139 140
        return kwargs

Krophil's avatar
Krophil committed
141

142
class PictureView(CanViewMixin, DetailView, FormMixin):
Skia's avatar
Skia committed
143
    model = Picture
144
    form_class = RelationForm
Skia's avatar
Skia committed
145 146 147
    pk_url_kwarg = "picture_id"
    template_name = "sas/picture.jinja"

148
    def get_initial(self):
Sli's avatar
Sli committed
149
        return {"picture": self.object}
150 151 152 153

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.form = self.get_form()
Sli's avatar
Sli committed
154
        if "rotate_right" in request.GET.keys():
Skia's avatar
Skia committed
155
            self.object.rotate(270)
Sli's avatar
Sli committed
156
        if "rotate_left" in request.GET.keys():
Skia's avatar
Skia committed
157
            self.object.rotate(90)
Sli's avatar
Sli committed
158
        if "remove_user" in request.GET.keys():
159
            try:
Sli's avatar
Sli committed
160 161 162 163 164 165 166
                user = User.objects.filter(id=int(request.GET["remove_user"])).first()
                if user.id == request.user.id or request.user.is_in_group(
                    settings.SITH_GROUP_SAS_ADMIN_ID
                ):
                    PeoplePictureRelation.objects.filter(
                        user=user, picture=self.object
                    ).delete()
Krophil's avatar
Krophil committed
167 168
            except:
                pass
Sli's avatar
Sli committed
169
        if "ask_removal" in request.GET.keys():
170 171 172 173 174 175 176 177 178
            self.object.is_moderated = False
            self.object.asked_for_removal = True
            self.object.save()
            return redirect("sas:album", album_id=self.object.parent.id)
        return super(PictureView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.form = self.get_form()
179
        if request.user.is_authenticated and request.user.was_subscribed:
180
            if self.form.is_valid():
Sli's avatar
Sli committed
181
                for uid in self.form.cleaned_data["users"]:
Skia's avatar
Skia committed
182
                    u = User.objects.filter(id=uid).first()
183 184 185 186 187 188
                    if not u:  # Don't use a non existing user
                        continue
                    if PeoplePictureRelation.objects.filter(
                        user=u, picture=self.form.cleaned_data["picture"]
                    ).exists():  # Avoid existing relation
                        continue
Sli's avatar
Sli committed
189 190 191 192 193 194 195 196 197 198 199
                    PeoplePictureRelation(
                        user=u, picture=self.form.cleaned_data["picture"]
                    ).save()
                    if not u.notifications.filter(
                        type="NEW_PICTURES", viewed=False
                    ).exists():
                        Notification(
                            user=u,
                            url=reverse("core:user_pictures", kwargs={"user_id": u.id}),
                            type="NEW_PICTURES",
                        ).save()
200 201 202 203 204 205 206
                return super(PictureView, self).form_valid(self.form)
        else:
            self.form.add_error(None, _("You do not have the permission to do that"))
        return self.form_invalid(self.form)

    def get_context_data(self, **kwargs):
        kwargs = super(PictureView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
207
        kwargs["form"] = self.form
208 209 210
        return kwargs

    def get_success_url(self):
Sli's avatar
Sli committed
211
        return reverse("sas:picture", kwargs={"picture_id": self.object.id})
212

Krophil's avatar
Krophil committed
213

Skia's avatar
Skia committed
214 215 216
def send_album(request, album_id):
    return send_file(request, album_id, Album)

Sli's avatar
Sli committed
217

Skia's avatar
Skia committed
218 219 220
def send_pict(request, picture_id):
    return send_file(request, picture_id, Picture)

Krophil's avatar
Krophil committed
221

Skia's avatar
Skia committed
222 223 224
def send_compressed(request, picture_id):
    return send_file(request, picture_id, Picture, "compressed")

Krophil's avatar
Krophil committed
225

Skia's avatar
Skia committed
226 227 228
def send_thumb(request, picture_id):
    return send_file(request, picture_id, Picture, "thumbnail")

Krophil's avatar
Krophil committed
229

Skia's avatar
Skia committed
230 231 232 233 234 235 236
class AlbumUploadView(CanViewMixin, DetailView, FormMixin):
    model = Album
    form_class = SASForm
    pk_url_kwarg = "album_id"

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
237 238
        if not self.object.file:
            self.object.generate_thumbnail()
Skia's avatar
Skia committed
239 240
        self.form = self.get_form()
        parent = SithFile.objects.filter(id=self.object.id).first()
Sli's avatar
Sli committed
241
        files = request.FILES.getlist("images")
242
        if request.user.is_authenticated and request.user.is_subscribed:
Skia's avatar
Skia committed
243
            if self.form.is_valid():
Sli's avatar
Sli committed
244 245 246 247 248 249 250 251
                self.form.process(
                    parent=parent,
                    owner=request.user,
                    files=files,
                    automodere=request.user.is_in_group(
                        settings.SITH_GROUP_SAS_ADMIN_ID
                    ),
                )
Skia's avatar
Skia committed
252 253 254 255 256
                if self.form.is_valid():
                    return HttpResponse(str(self.form.errors), status=200)
        return HttpResponse(str(self.form.errors), status=500)


Skia's avatar
Skia committed
257
class AlbumView(CanViewMixin, DetailView, FormMixin):
Skia's avatar
Skia committed
258
    model = Album
Skia's avatar
Skia committed
259
    form_class = SASForm
Skia's avatar
Skia committed
260 261
    pk_url_kwarg = "album_id"
    template_name = "sas/album.jinja"
Sli's avatar
Sli committed
262 263 264 265 266 267 268 269
    paginate_by = settings.SITH_SAS_IMAGES_PER_PAGE

    def dispatch(self, request, *args, **kwargs):
        try:
            self.asked_page = int(request.GET.get("page", 1))
        except ValueError:
            raise Http404
        return super(AlbumView, self).dispatch(request, *args, **kwargs)
Skia's avatar
Skia committed
270 271 272

    def get(self, request, *args, **kwargs):
        self.form = self.get_form()
Sli's avatar
Sli committed
273 274
        if "clipboard" not in request.session.keys():
            request.session["clipboard"] = []
Skia's avatar
Skia committed
275 276 277 278
        return super(AlbumView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
279 280
        if not self.object.file:
            self.object.generate_thumbnail()
Skia's avatar
Skia committed
281
        self.form = self.get_form()
Sli's avatar
Sli committed
282 283
        if "clipboard" not in request.session.keys():
            request.session["clipboard"] = []
Krophil's avatar
Krophil committed
284
        if request.user.can_edit(self.object):  # Handle the copy-paste functions
Skia's avatar
Skia committed
285
            FileView.handle_clipboard(request, self.object)
Skia's avatar
Skia committed
286
        parent = SithFile.objects.filter(id=self.object.id).first()
Sli's avatar
Sli committed
287
        files = request.FILES.getlist("images")
288
        if request.user.is_authenticated and request.user.is_subscribed:
Skia's avatar
Skia committed
289
            if self.form.is_valid():
Sli's avatar
Sli committed
290 291 292 293 294 295 296 297
                self.form.process(
                    parent=parent,
                    owner=request.user,
                    files=files,
                    automodere=request.user.is_in_group(
                        settings.SITH_GROUP_SAS_ADMIN_ID
                    ),
                )
Skia's avatar
Skia committed
298 299 300
                if self.form.is_valid():
                    return super(AlbumView, self).form_valid(self.form)
        else:
Skia's avatar
Skia committed
301
            self.form.add_error(None, _("You do not have the permission to do that"))
Skia's avatar
Skia committed
302 303
        return self.form_invalid(self.form)

Skia's avatar
Skia committed
304
    def get_success_url(self):
Sli's avatar
Sli committed
305
        return reverse("sas:album", kwargs={"album_id": self.object.id})
Skia's avatar
Skia committed
306 307 308

    def get_context_data(self, **kwargs):
        kwargs = super(AlbumView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
309 310 311 312 313 314 315
        kwargs["paginator"] = Paginator(
            self.object.children_pictures.order_by("id"), self.paginate_by
        )
        try:
            kwargs["pictures"] = kwargs["paginator"].page(self.asked_page)
        except InvalidPage:
            raise Http404
Sli's avatar
Sli committed
316 317 318 319
        kwargs["form"] = self.form
        kwargs["clipboard"] = SithFile.objects.filter(
            id__in=self.request.session["clipboard"]
        )
Skia's avatar
Skia committed
320
        return kwargs
Skia's avatar
Skia committed
321

Sli's avatar
Sli committed
322

Skia's avatar
Skia committed
323 324
# Admin views

Krophil's avatar
Krophil committed
325

Skia's avatar
Skia committed
326 327 328
class ModerationView(TemplateView):
    template_name = "sas/moderation.jinja"

Skia's avatar
Skia committed
329
    def get(self, request, *args, **kwargs):
Skia's avatar
Skia committed
330
        if request.user.is_in_group(settings.SITH_GROUP_SAS_ADMIN_ID):
Skia's avatar
Skia committed
331 332 333
            return super(ModerationView, self).get(request, *args, **kwargs)
        raise PermissionDenied

Skia's avatar
Skia committed
334
    def post(self, request, *args, **kwargs):
Skia's avatar
Skia committed
335 336
        if request.user.is_in_group(settings.SITH_GROUP_SAS_ADMIN_ID):
            try:
Sli's avatar
Sli committed
337 338
                a = Album.objects.filter(id=request.POST["album_id"]).first()
                if "moderate" in request.POST.keys():
Skia's avatar
Skia committed
339 340 341
                    a.moderator = request.user
                    a.is_moderated = True
                    a.save()
Sli's avatar
Sli committed
342
                elif "delete" in request.POST.keys():
Skia's avatar
Skia committed
343
                    a.delete()
Krophil's avatar
Krophil committed
344 345
            except:
                pass
Skia's avatar
Skia committed
346
        return super(ModerationView, self).get(request, *args, **kwargs)
Skia's avatar
Skia committed
347

Skia's avatar
Skia committed
348 349
    def get_context_data(self, **kwargs):
        kwargs = super(ModerationView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
350 351 352 353 354 355 356 357 358
        kwargs["albums_to_moderate"] = Album.objects.filter(
            is_moderated=False, is_in_sas=True, is_folder=True
        ).order_by("id")
        kwargs["pictures"] = Picture.objects.filter(
            is_moderated=False, is_in_sas=True, is_folder=False
        )
        kwargs["albums"] = Album.objects.filter(
            id__in=kwargs["pictures"].values("parent").distinct("parent")
        )
Skia's avatar
Skia committed
359 360
        return kwargs

Krophil's avatar
Krophil committed
361

Skia's avatar
Skia committed
362 363 364
class PictureEditForm(forms.ModelForm):
    class Meta:
        model = Picture
Sli's avatar
Sli committed
365 366 367
        fields = ["name", "parent"]

    parent = make_ajax_field(Picture, "parent", "files", help_text="")
Skia's avatar
Skia committed
368

Krophil's avatar
Krophil committed
369

Skia's avatar
Skia committed
370 371 372
class AlbumEditForm(forms.ModelForm):
    class Meta:
        model = Album
Sli's avatar
Sli committed
373 374
        fields = ["name", "date", "file", "parent", "edit_groups"]

Skia's avatar
Skia committed
375
    date = forms.DateField(label=_("Date"), widget=SelectDate, required=True)
Sli's avatar
Sli committed
376 377
    parent = make_ajax_field(Album, "parent", "files", help_text="")
    edit_groups = make_ajax_field(Album, "edit_groups", "groups", help_text="")
378
    recursive = forms.BooleanField(label=_("Apply rights recursively"), required=False)
Skia's avatar
Skia committed
379

Krophil's avatar
Krophil committed
380

Skia's avatar
Skia committed
381
class PictureEditView(CanEditMixin, UpdateView):
Krophil's avatar
Krophil committed
382 383
    model = Picture
    form_class = PictureEditForm
Sli's avatar
Sli committed
384
    template_name = "core/edit.jinja"
Skia's avatar
Skia committed
385 386
    pk_url_kwarg = "picture_id"

Krophil's avatar
Krophil committed
387

Skia's avatar
Skia committed
388
class AlbumEditView(CanEditMixin, UpdateView):
Krophil's avatar
Krophil committed
389 390
    model = Album
    form_class = AlbumEditForm
Sli's avatar
Sli committed
391
    template_name = "core/edit.jinja"
Skia's avatar
Skia committed
392
    pk_url_kwarg = "album_id"
Skia's avatar
Skia committed
393

394 395
    def form_valid(self, form):
        ret = super(AlbumEditView, self).form_valid(form)
Sli's avatar
Sli committed
396
        if form.cleaned_data["recursive"]:
397 398
            self.object.apply_rights_recursively(True)
        return ret