Files
zulip/zerver/views/thumbnail.py
Aditya Bansal 98a4e87e1d thumbor: Complete implementation of thumbnailing.
Various pieces of our thumbor-based thumbnailing system were already
merged; this adds the remaining pieces required for it to work:

* a THUMBOR_URL Django setting that controls whether thumbor is
  enabled on the Zulip server (and if so, where thumbor is hosted).

* Replaces the overly complicated prototype cryptography logic

* Adds a /thumbnail endpoint (supported both on web and mobile) for
  accessing thumbnails in messages, designed to support hosting both
  external URLs as well as uploaded files (and applying Zulip's
  security model for access to thumbnails of uploaded files).

* Modifies bugdown to, when THUMBOR_URL is set, render images with the
  `src` attribute pointing /thumbnail (to provide a small thumbnail
  for the image), along with adding a "data-original" attribute that
  can be used to access the "original/full" size version of the image.

There are a few things that don't work quite yet:
* The S3 backend support is incomplete and doesn't work yet.
* The error pages for unauthorized access are ugly.
* We might want to rename data-original and /thumbnail?size=original
  to use some other name, like "full", that better reflects the fact
  that we're potentially not serving the original image URL.
2018-07-15 00:39:41 +05:30

39 lines
1.5 KiB
Python

# -*- coding: utf-8 -*-
from django.shortcuts import redirect
from django.utils.translation import ugettext as _
from django.http import HttpRequest, HttpResponse, HttpResponseForbidden
from django.conf import settings
from typing import Optional
from zerver.models import UserProfile, validate_attachment_request
from zerver.lib.request import has_request_variables, REQ
from zerver.lib.thumbnail import generate_thumbnail_url
import urllib
def validate_thumbnail_request(user_profile: UserProfile, path: str) -> Optional[bool]:
# path here does not have a leading / as it is parsed from request hitting the
# thumbnail endpoint (defined in urls.py) that way.
if path.startswith('user_uploads/'):
path_id = path[len('user_uploads/'):]
return validate_attachment_request(user_profile, path_id)
# This is an external link and we don't enforce restricted view policy here.
return True
@has_request_variables
def backend_serve_thumbnail(request: HttpRequest, user_profile: UserProfile,
url: str=REQ(), size_requested: str=REQ("size")) -> HttpResponse:
if not validate_thumbnail_request(user_profile, url):
return HttpResponseForbidden(_("<p>You are not authorized to view this file.</p>"))
size = None
if size_requested == 'thumbnail':
size = '0x100'
elif size_requested == 'original':
size = '0x0'
if size is None:
return HttpResponseForbidden(_("<p>Invalid size.</p>"))
thumbnail_url = generate_thumbnail_url(url, size)
return redirect(thumbnail_url)