requirements: Remove Thumbor.

Thumbor and tc-aws have been dragging their feet on Python 3 support
for years, and even the alphas and unofficial forks we’ve been running
don’t seem to be maintained anymore.  Depending on these projects is
no longer viable for us.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2021-05-06 15:38:24 -07:00 committed by Tim Abbott
parent 779353b44e
commit 405bc8dabf
51 changed files with 26 additions and 2336 deletions

View File

@ -12,4 +12,3 @@
!/var/puppeteer/test_credentials.d.ts
/zulip-current-venv
/zulip-py3-venv
/zulip-thumbor-venv

View File

@ -73,7 +73,7 @@ jobs:
uses: actions/cache@v2
with:
path: /srv/zulip-venv-cache
key: v1-venv-${{ github.job }}-${{ hashFiles('requirements/thumbor-dev.txt') }}-${{ hashFiles('requirements/dev.txt') }}
key: v1-venv-${{ github.job }}-${{ hashFiles('requirements/dev.txt') }}
restore-keys: v1-venv-${{ github.job }}
- name: Restore emoji cache

View File

@ -91,7 +91,7 @@ jobs:
uses: actions/cache@v2
with:
path: /srv/zulip-venv-cache
key: v1-venv-${{ matrix.os }}-${{ hashFiles('requirements/thumbor-dev.txt') }}-${{ hashFiles('requirements/dev.txt') }}
key: v1-venv-${{ matrix.os }}-${{ hashFiles('requirements/dev.txt') }}
restore-keys: v1-venv-${{ matrix.os }}
- name: Restore emoji cache

2
.gitignore vendored
View File

@ -60,7 +60,6 @@ zulip-git-version
/zproject/prod_settings.py
/zulip-current-venv
/zulip-py3-venv
/zulip-thumbor-venv
## Files left by various editors and local environments
# (Ideally these should be in everyone's respective personal gitignore files.)
@ -85,5 +84,4 @@ core
## Miscellaneous
# (Ideally this section is empty.)
zthumbor/thumbor_local_settings.py
.transifexrc

View File

@ -242,7 +242,6 @@ expected.
9992: Django
9993: Tornado
9994: webpack
9995: Thumbor
```
Visit the indicated URL in your web browser.

View File

@ -247,13 +247,6 @@ development PostgreSQL user.
`tools/provision` also invokes `tools/rebuild-dev-database`
to create the actual database with its schema.
### Thumbor and thumbnailing
We use Thumbor, a popular open source thumbnailing server, to serve
images (both for inline URL previews and serving uploaded image
files). See [our thumbnailing docs](../subsystems/thumbnailing.md)
for more details on how this works.
### Nagios
Nagios is an optional component used for notifications to the system

View File

@ -32,7 +32,6 @@ Subsystems documentation
release-checklist
api-release-checklist
input-pills
thumbnailing
presence
unread_messages
billing

View File

@ -1,95 +0,0 @@
# Thumbnailing
Note: Thumbnailing is an experimental feature. While it is
implemented in Zulip, due to issues with the upstream Thumbor project
being almost unmaintained, it is not recommended for production use.
This is the design document for how thumbnailing will work in Zulip,
assuming Thumbor recovers as a project or we replace it with a similar
alternative.
There are two key places one would naturally want to thumbnail images
in a team chat application like Zulip:
* On the server-side, when serving inline image and URL previews in
the bodies of messages. This is very important for Zulip's network
performance of low-bandwidth networks.
* In mobile apps, to avoid uploading full-size images on a mobile
network (which Zulip does not yet implement),
Our server-side thumbnailing system is powered by [thumbor][], a
popular open source server for serving images and thumbnailing them.
Thumbor is responsible for a few things in Zulip:
* Serving all image content over HTTPS, even if the original/upstream
image was hosted on HTTP (this was previously done by `camo` in
older versions of Zulip; the `THUMBOR_SERVES_CAMO` setting controls
whether Thumbor will serve the old-style Camo URLs that might be
present in old messages). This is important to avoid mixed-content
warnings from browsers (which look very bad), and does have some
real security benefit in protecting our users from malicious
content.
* Minimizing potentially unnecessary bandwidth that might be used in
communication between the Zulip server and clients. Before we
introduced this feature, uploading large photos could result in a
bad experience for users with a slow network connection.
Thumbor handles a lot of details for us, varying from signing of
thumbnailing URLs, to caching for DoS prevention.
It is configured via the `THUMBOR_URL` and `THUMBNAIL_IMAGES` settings in
`/etc/zulip/settings.py`; you can host Thumbor on the same machine as
the Zulip server, or a remote server (which is better for isolation,
since security bugs in image-processing libraries have in the past
been a common attack vector).
The thumbnailing system is used for any images that appear in the
bodies of Zulip messages (i.e. both images linked to by users, as well
as uploaded image files.). We exclude a few special image sources
(e.g. youtube stills) only because they are already thumbnailed.
For uploaded image files, we enforce the same security policy on
thumbnail URLs that we do for the uploaded files themselves.
A correct client implementation interacting with the thumbnailing
system should do the following:
* For serving the thumbnailed to 100px height version of images,
nothing special is required; the client just needs to display the
`src=` value in the `<img>` tag in the rendered message HTML.
* For displaying a "full-size" version of an image (e.g. to use in a
lightbox), the client can access the `data-fullsize-src` attribute
on the `<img>` tag; this will contain the URL for a full-size
version.
* Ideally, when clicking on an image to switch from the thumbnail to
the full-size / lightbox size, the client should immediately display
the thumbnailed (low resolution) version and in parallel fetch the
full-size version in the background, transparently swapping it into
place once the full size version is available. This provides a
slick user experience where the user doesn't see a loading state,
and instead just sees the image focus a few hundred milliseconds
after clicking the image.
## URL design
The raw Thumbor URLs are ugly, and regardless, have the property that
we might want to change them over time (a classic case is if one moves
the thumbor installation to be hosted by a different server). In
order to avoid encoding these into Zulip messages, we encode in the
[HTML rendered message content](../subsystems/markdown.md) URLs of
the form
`/thumbnail/?url=https://example.com/image.png&size=thumbnail` as the
`src` in our image tags, and that URL serves a
(configuration-dependent) redirect to the actual image hosted on
thumbor.
## Avatars, realm icons, and custom emoji
Currently, these user-uploaded content are thumbnailed by Zulip's
internal file-upload code, in part because they change rarely and
don't have the same throughput/performance requirements as
user-uploaded files. We may later convert them to use thumbor as
well.
[thumbor]: https://github.com/thumbor/thumbor

View File

@ -1,7 +0,0 @@
# This configuration proxies requests to /thumbor to a copy of the
# thumbor service installed locally on the Zulip server.
location /thumbor {
rewrite /thumbor/(.*) /$1 break;
proxy_pass http://thumbor;
include /etc/nginx/zulip-include/proxy;
}

View File

@ -11,7 +11,3 @@ upstream localhost_sso {
upstream camo {
server 127.0.0.1:9292;
}
upstream thumbor {
server localhost:9995;
}

View File

@ -1,12 +0,0 @@
[program:zulip-thumbor]
command=/home/zulip/deployments/current/zulip-thumbor-venv/bin/thumbor --port=9995 --conf=/home/zulip/deployments/current/zthumbor/thumbor_settings.py
user=zulip
directory=/home/zulip/deployments/current/
autostart=true
autorestart=true
startretries=3
stopsignal=TERM
redirect_stderr=true
stdout_logfile=/var/log/zulip/thumbor.log
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=3

View File

@ -1,25 +0,0 @@
class zulip::profile::thumbor {
include zulip::profile::base
include zulip::nginx
include zulip::supervisor
file { "${zulip::common::supervisor_conf_dir}/thumbor.conf":
ensure => file,
require => Package[supervisor],
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/zulip/supervisor/conf.d/thumbor.conf',
notify => Service[$zulip::common::supervisor_service],
}
file { '/etc/nginx/zulip-include/app.d/thumbor.conf':
ensure => file,
require => Package[$zulip::common::nginx],
owner => 'root',
group => 'root',
mode => '0644',
notify => Service['nginx'],
source => 'puppet:///modules/zulip/nginx/zulip-include-app.d/thumbor.conf',
}
}

View File

@ -156,10 +156,6 @@ disposable-email-domains
# Needed for parsing YAML with JSON references from the REST API spec files
jsonref
# Needed for signing thumbnail requests so that they can be authenticated on the
# other end.
libthumbor
# Needed for string matching in AlertWordProcessor
pyahocorasick

View File

@ -627,10 +627,6 @@ libcst==0.3.18 \
--hash=sha256:30154cd0aaede8f3adfc4bdead23fe022a57e88898b9993cc3fea3bfbaf780d2 \
--hash=sha256:da89cc1a37702caa6fe7207b1257fad58f0d4643597279733106ca902b4fdbad
# via pyre-check
libthumbor==2.0.1 \
--hash=sha256:3c4e1a59c019d22f868d225315c06f97fad30fb5e78112d6a230b978e7d24e38 \
--hash=sha256:ed4fe5f27f8f90e7285b7e6dce99c1b67d43a140bf370e989080b43d80ce25f0
# via -r requirements/common.in
line-profiler==3.1.0 \
--hash=sha256:23b074497f196d7dd7bc74386cbba47766162f187ebd78bfbc96238f1ce1202d \
--hash=sha256:2b937d8b207cee753d175cc65907901bd9ccadfe20ff2038df9aeae2eafcba6b \
@ -1352,7 +1348,6 @@ six==1.15.0 \
# html5lib
# isodate
# jsonschema
# libthumbor
# moto
# openapi-core
# openapi-schema-validator

View File

@ -431,10 +431,6 @@ lazy-object-proxy==1.6.0 \
--hash=sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93 \
--hash=sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b
# via openapi-core
libthumbor==2.0.1 \
--hash=sha256:3c4e1a59c019d22f868d225315c06f97fad30fb5e78112d6a230b978e7d24e38 \
--hash=sha256:ed4fe5f27f8f90e7285b7e6dce99c1b67d43a140bf370e989080b43d80ce25f0
# via -r requirements/common.in
lxml==4.6.3 \
--hash=sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d \
--hash=sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3 \
@ -900,7 +896,6 @@ six==1.15.0 \
# html5lib
# isodate
# jsonschema
# libthumbor
# openapi-core
# openapi-schema-validator
# openapi-spec-validator

View File

@ -1,2 +0,0 @@
-r pip.in
-r thumbor.in

View File

@ -1,414 +0,0 @@
#
# This file is GENERATED. Don't edit directly.
#
# To update, edit the non-"lock" files in requirements/*.in, then:
#
# tools/update-locked-requirements
#
# For details, see requirements/README.md .
#
aiobotocore==1.3.0 \
--hash=sha256:81890d270b1f948ffd218e8bab11e235bea272840ea8b1b9e0aef1954c6cec9e
# via tc-aws
aiohttp==3.7.4.post0 \
--hash=sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe \
--hash=sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe \
--hash=sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5 \
--hash=sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8 \
--hash=sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd \
--hash=sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb \
--hash=sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c \
--hash=sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87 \
--hash=sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0 \
--hash=sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290 \
--hash=sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5 \
--hash=sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287 \
--hash=sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde \
--hash=sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf \
--hash=sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8 \
--hash=sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16 \
--hash=sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf \
--hash=sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809 \
--hash=sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213 \
--hash=sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f \
--hash=sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013 \
--hash=sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b \
--hash=sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9 \
--hash=sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5 \
--hash=sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb \
--hash=sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df \
--hash=sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4 \
--hash=sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439 \
--hash=sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f \
--hash=sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22 \
--hash=sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f \
--hash=sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5 \
--hash=sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970 \
--hash=sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009 \
--hash=sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc \
--hash=sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a \
--hash=sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95
# via aiobotocore
aioitertools==0.7.1 \
--hash=sha256:54a56c7cf3b5290d1cb5e8974353c9f52c677612b5d69a859369a020c53414a3 \
--hash=sha256:8972308474c41ed5e0636819f948ebff32f2318e70f7e7d23cd208c4357cc773
# via aiobotocore
asgiref==3.3.4 \
--hash=sha256:92906c611ce6c967347bbfea733f13d6313901d54dcca88195eaeb52b2a8e8ee \
--hash=sha256:d1216dfbdfb63826470995d31caed36225dcaf34f182e0fa257a4dd9e86f1b78
# via django
async-timeout==3.0.1 \
--hash=sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f \
--hash=sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3
# via aiohttp
attrs==20.3.0 \
--hash=sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6 \
--hash=sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700
# via aiohttp
botocore==1.20.49 \
--hash=sha256:6a672ba41dd00e5c1c1824ca8143d180d88de8736d78c0b1f96b8d3cb0466561 \
--hash=sha256:f7f103fa0651c69dd360c7d0ecd874854303de5cc0869e0cbc2818a52baacc69
# via aiobotocore
chardet==4.0.0 \
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
# via aiohttp
colorful==0.5.4 \
--hash=sha256:86848ad4e2eda60cd2519d8698945d22f6f6551e23e95f3f14dfbb60997807ea \
--hash=sha256:8d264b52a39aae4c0ba3e2a46afbaec81b0559a99be0d2cfe2aba4cf94531348
# via thumbor
derpconf==0.8.3 \
--hash=sha256:1bb152d8a1cf5c2a6d629bf29acd4af0c00811339642fc0a56172b0a83b31a15
# via thumbor
django-auth-ldap==2.4.0 \
--hash=sha256:2d869955da8a0c9a4448671bd9826b9f87458f6a9fc20278e84de8a81200a2be \
--hash=sha256:60fcbfc3141c99c3c49d3ccd7311a3992a231c319d94b6d2c143968f63676676
# via -r requirements/thumbor.in
django==3.1.8 \
--hash=sha256:c348b3ddc452bf4b62361f0752f71a339140c777ebea3cdaaaa8fdb7f417a862 \
--hash=sha256:f8393103e15ec2d2d313ccbb95a3f1da092f9f58d74ac1c61ca2ac0436ae1eac
# via
# -r requirements/thumbor.in
# django-auth-ldap
idna-ssl==1.1.0 \
--hash=sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c
# via aiohttp
idna==3.1 \
--hash=sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16 \
--hash=sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1
# via
# idna-ssl
# yarl
jmespath==0.10.0 \
--hash=sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9 \
--hash=sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f
# via botocore
libthumbor==2.0.1 \
--hash=sha256:3c4e1a59c019d22f868d225315c06f97fad30fb5e78112d6a230b978e7d24e38 \
--hash=sha256:ed4fe5f27f8f90e7285b7e6dce99c1b67d43a140bf370e989080b43d80ce25f0
# via thumbor
multidict==5.1.0 \
--hash=sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a \
--hash=sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93 \
--hash=sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632 \
--hash=sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656 \
--hash=sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79 \
--hash=sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7 \
--hash=sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d \
--hash=sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5 \
--hash=sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224 \
--hash=sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26 \
--hash=sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea \
--hash=sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348 \
--hash=sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6 \
--hash=sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76 \
--hash=sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1 \
--hash=sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f \
--hash=sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952 \
--hash=sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a \
--hash=sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37 \
--hash=sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9 \
--hash=sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359 \
--hash=sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8 \
--hash=sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da \
--hash=sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3 \
--hash=sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d \
--hash=sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf \
--hash=sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841 \
--hash=sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d \
--hash=sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93 \
--hash=sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f \
--hash=sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647 \
--hash=sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635 \
--hash=sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456 \
--hash=sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda \
--hash=sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5 \
--hash=sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281 \
--hash=sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80
# via
# aiohttp
# yarl
numpy==1.19.5 \
--hash=sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94 \
--hash=sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080 \
--hash=sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e \
--hash=sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c \
--hash=sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76 \
--hash=sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371 \
--hash=sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c \
--hash=sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2 \
--hash=sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a \
--hash=sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb \
--hash=sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140 \
--hash=sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28 \
--hash=sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f \
--hash=sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d \
--hash=sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff \
--hash=sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8 \
--hash=sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa \
--hash=sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea \
--hash=sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc \
--hash=sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73 \
--hash=sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d \
--hash=sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d \
--hash=sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4 \
--hash=sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c \
--hash=sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e \
--hash=sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea \
--hash=sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd \
--hash=sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f \
--hash=sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff \
--hash=sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e \
--hash=sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7 \
--hash=sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa \
--hash=sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827 \
--hash=sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60
# via opencv-python-headless
opencv-python-headless==4.5.1.48 \
--hash=sha256:0e02809db2968e54f3c23340be6ff9a1428b3f03f5dca7cd5aceda66e319ce86 \
--hash=sha256:1f7c14f5d4e5af4dc4669fc6b4a983b36072a934c439ac11266b930496da8255 \
--hash=sha256:243aea91cc1e36a47c46da4cc408071af39444a48df1fe1539ea8d7990500fd2 \
--hash=sha256:2560dcf3c1158226b066302f777bfe0f65282410b8d90871dd872306c967d1f1 \
--hash=sha256:2e6a9a88617a0ef7219cff24ba78a58416670a77e6ac63975f9009af3319ab63 \
--hash=sha256:372149d007e20bf556b7687591d22b58b56b3c225f492da051d81587e5dc7411 \
--hash=sha256:522f12dd994e064a30562adfd63b9439099bd7c80819f5261c37ebe593283c9e \
--hash=sha256:526b9e19cf6300f0891d8f427eac1048091912332bb781eb4957a4994bfbe608 \
--hash=sha256:5f0c7d34fa9953706c2a1a6d2760a91dc5a68cab3df16af61609894c6c8586f1 \
--hash=sha256:657cdd9fbbbbb7e898ae3d9b0649b367d0e440d429c714104d069c5612d578bb \
--hash=sha256:65c9ea57be5ebcaed009b3fee14fe59f3b6aa1e573fe08c5039ff057ad593c53 \
--hash=sha256:777fb596e04331f73ef5b0c1faa4d33348f29ca58216d9286355c16f5489c939 \
--hash=sha256:7c75680ffdf32d7044415a215d1fc60dbec14a7f2f0b59a85f0f74ef5efcb6ad \
--hash=sha256:924aa4c34ead0b817309f42291dc526b2a7755476afe3009d1e275fc3090d92d \
--hash=sha256:96d1da6ad061d8f3509668d398d14dd8265e529d6407f87eb26e7f4ddf043cc0 \
--hash=sha256:9aa04a491c534531029fbac61da961fae0bf4abb1786eed9c91befde4ca7bd81 \
--hash=sha256:a322d4df14c3a5f19701a023b3da91e9b8af8653b0d2ee0c50b0b341212f7343 \
--hash=sha256:aa562c520f46283423ba8fac29099458e42deab697a9abd0491622e421c5c454 \
--hash=sha256:ba2f0bd46e9534f29969e39f7895cbea9764173102b0c04b7818b8a9910d66e4 \
--hash=sha256:d16825755e7b5a6d8737f93e116670229e1510199e0af9213004e187ae0dbcc5 \
--hash=sha256:e3027e0d1b71b68b5cfe1ea9c627e323dff71112c854ba19805258d8fc6c630e \
--hash=sha256:f2011ecb3980bbed283d17d43e0f1221bac88c0cac1a6fb59a056544de2df2f7 \
--hash=sha256:f5e40a06116460ef2fd2d1c24be3b65f8bfb5fcdfe433f3fc01bcb4c2eb485bf \
--hash=sha256:f7f8e4f7c63c8e95eb210f4cba88d0069a0a964d6335d7a35b07f0d0baa13558 \
--hash=sha256:fe02a943b1a28b505e954fbce24e867119a3eb4351f93adad55c6cfe81a70484
# via thumbor
pillow==7.2.0 \
--hash=sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f \
--hash=sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8 \
--hash=sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad \
--hash=sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f \
--hash=sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae \
--hash=sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d \
--hash=sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5 \
--hash=sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b \
--hash=sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8 \
--hash=sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233 \
--hash=sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6 \
--hash=sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727 \
--hash=sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f \
--hash=sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38 \
--hash=sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4 \
--hash=sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626 \
--hash=sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d \
--hash=sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6 \
--hash=sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6 \
--hash=sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63 \
--hash=sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f \
--hash=sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41 \
--hash=sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1 \
--hash=sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117 \
--hash=sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d \
--hash=sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9 \
--hash=sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a \
--hash=sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce
# via thumbor
pyasn1-modules==0.2.8 \
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74
# via python-ldap
pyasn1==0.4.8 \
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
# via
# pyasn1-modules
# python-ldap
pycurl==7.43.0.6 \
--hash=sha256:8301518689daefa53726b59ded6b48f33751c383cf987b0ccfbbc4ed40281325
# via -r requirements/thumbor.in
python-dateutil==2.8.1 \
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a
# via
# botocore
# tc-aws
python-ldap==3.3.1 \
--hash=sha256:4711cacf013e298754abd70058ccc995758177fb425f1c2d30e71adfc1d00aa5
# via django-auth-ldap
pytz==2019.3 \
--hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \
--hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be
# via
# django
# thumbor
six==1.15.0 \
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced
# via
# derpconf
# libthumbor
# python-dateutil
sqlparse==0.4.1 \
--hash=sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0 \
--hash=sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8
# via django
statsd==3.3.0 \
--hash=sha256:c610fb80347fca0ef62666d241bce64184bd7cc1efe582f9690e045c25535eaa \
--hash=sha256:e3e6db4c246f7c59003e51c9720a51a7f39a396541cb9b147ff4b14d15b5dd1f
# via thumbor
https://github.com/kkopachev/aws/archive/b5058e6b9fec7354629acc6d5df423e0310bb0cd.zip#egg=tc_aws==6.3 \
--hash=sha256:8a28437b0dfab88c89f280a2d6ec55a6abfa3e26d495dc15e1b3f38744e27f0c
# via -r requirements/thumbor.in
thumbor==7.0.0a5 \
--hash=sha256:5042c9c8facf0da028a22f1aee717f856d213ec037835ca0edaa0282217654bb
# via
# -r requirements/thumbor.in
# tc-aws
tornado==6.1 \
--hash=sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb \
--hash=sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c \
--hash=sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288 \
--hash=sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95 \
--hash=sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558 \
--hash=sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe \
--hash=sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791 \
--hash=sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d \
--hash=sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326 \
--hash=sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b \
--hash=sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4 \
--hash=sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c \
--hash=sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910 \
--hash=sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5 \
--hash=sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c \
--hash=sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0 \
--hash=sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675 \
--hash=sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd \
--hash=sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f \
--hash=sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c \
--hash=sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea \
--hash=sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6 \
--hash=sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05 \
--hash=sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd \
--hash=sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575 \
--hash=sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a \
--hash=sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37 \
--hash=sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795 \
--hash=sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f \
--hash=sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32 \
--hash=sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c \
--hash=sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01 \
--hash=sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4 \
--hash=sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2 \
--hash=sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921 \
--hash=sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085 \
--hash=sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df \
--hash=sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102 \
--hash=sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5 \
--hash=sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68 \
--hash=sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5
# via thumbor
typing-extensions==3.7.4.3 \
--hash=sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918 \
--hash=sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c \
--hash=sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f
# via
# aiohttp
# aioitertools
# asgiref
# yarl
urllib3==1.26.4 \
--hash=sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df \
--hash=sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937
# via botocore
virtualenv-clone==0.5.4 \
--hash=sha256:07e74418b7cc64f4fda987bf5bc71ebd59af27a7bc9e8a8ee9fd54b1f2390a27 \
--hash=sha256:665e48dd54c84b98b71a657acb49104c54e7652bce9c1c4f6c6976ed4c827a29
# via -r requirements/thumbor.in
webcolors==1.11.1 \
--hash=sha256:76f360636957d1c976db7466bc71dcb713bb95ac8911944dffc55c01cb516de6 \
--hash=sha256:b8cd5d865a25c51ff1218f0c90d0c0781fc64312a49b746b320cf50de1648f6e
# via thumbor
wheel==0.36.2 \
--hash=sha256:78b5b185f0e5763c26ca1e324373aadd49182ca90e825f7853f4b2509215dc0e \
--hash=sha256:e11eefd162658ea59a60a0f6c7d493a7190ea4b9a85e335b33489d9f17e0245e
# via -r requirements/pip.in
wrapt==1.12.1 \
--hash=sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7
# via aiobotocore
yarl==1.6.3 \
--hash=sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e \
--hash=sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434 \
--hash=sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366 \
--hash=sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3 \
--hash=sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec \
--hash=sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959 \
--hash=sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e \
--hash=sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c \
--hash=sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6 \
--hash=sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a \
--hash=sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6 \
--hash=sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424 \
--hash=sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e \
--hash=sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f \
--hash=sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50 \
--hash=sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2 \
--hash=sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc \
--hash=sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4 \
--hash=sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970 \
--hash=sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10 \
--hash=sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0 \
--hash=sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406 \
--hash=sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896 \
--hash=sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643 \
--hash=sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721 \
--hash=sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478 \
--hash=sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724 \
--hash=sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e \
--hash=sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8 \
--hash=sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96 \
--hash=sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25 \
--hash=sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76 \
--hash=sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2 \
--hash=sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2 \
--hash=sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c \
--hash=sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a \
--hash=sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71
# via aiohttp
# The following packages are considered to be unsafe in a requirements file:
pip==20.2.4 \
--hash=sha256:51f1c7514530bd5c145d8f13ed936ad6b8bfcb8cf74e10403d0890bc986f0033 \
--hash=sha256:85c99a857ea0fb0aedf23833d9be5c40cf253fe24443f0829c7b472e23c364a1
# via -r requirements/pip.in
setuptools==56.0.0 \
--hash=sha256:08a1c0f99455307c48690f00d5c2ac2c1ccfab04df00454fef854ec145b81302 \
--hash=sha256:7430499900e443375ba9449a9cc5d78506b801e929fef4a186496012f93683b5
# via -r requirements/pip.in

View File

@ -1,12 +0,0 @@
https://github.com/kkopachev/aws/archive/b5058e6b9fec7354629acc6d5df423e0310bb0cd.zip#egg=tc_aws==6.3
thumbor>=7.dev
# Not required by Thumbor, but recommended
pycurl
# Required for just importing settings from our main django app.
django-auth-ldap
Django==3.1.*
# Needed for cloning virtual environments
virtualenv-clone

View File

@ -1,400 +0,0 @@
#
# This file is GENERATED. Don't edit directly.
#
# To update, edit the non-"lock" files in requirements/*.in, then:
#
# tools/update-locked-requirements
#
# For details, see requirements/README.md .
#
aiobotocore==1.3.0 \
--hash=sha256:81890d270b1f948ffd218e8bab11e235bea272840ea8b1b9e0aef1954c6cec9e
# via tc-aws
aiohttp==3.7.4.post0 \
--hash=sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe \
--hash=sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe \
--hash=sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5 \
--hash=sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8 \
--hash=sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd \
--hash=sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb \
--hash=sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c \
--hash=sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87 \
--hash=sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0 \
--hash=sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290 \
--hash=sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5 \
--hash=sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287 \
--hash=sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde \
--hash=sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf \
--hash=sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8 \
--hash=sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16 \
--hash=sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf \
--hash=sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809 \
--hash=sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213 \
--hash=sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f \
--hash=sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013 \
--hash=sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b \
--hash=sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9 \
--hash=sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5 \
--hash=sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb \
--hash=sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df \
--hash=sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4 \
--hash=sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439 \
--hash=sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f \
--hash=sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22 \
--hash=sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f \
--hash=sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5 \
--hash=sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970 \
--hash=sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009 \
--hash=sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc \
--hash=sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a \
--hash=sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95
# via aiobotocore
aioitertools==0.7.1 \
--hash=sha256:54a56c7cf3b5290d1cb5e8974353c9f52c677612b5d69a859369a020c53414a3 \
--hash=sha256:8972308474c41ed5e0636819f948ebff32f2318e70f7e7d23cd208c4357cc773
# via aiobotocore
asgiref==3.3.4 \
--hash=sha256:92906c611ce6c967347bbfea733f13d6313901d54dcca88195eaeb52b2a8e8ee \
--hash=sha256:d1216dfbdfb63826470995d31caed36225dcaf34f182e0fa257a4dd9e86f1b78
# via django
async-timeout==3.0.1 \
--hash=sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f \
--hash=sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3
# via aiohttp
attrs==20.3.0 \
--hash=sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6 \
--hash=sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700
# via aiohttp
botocore==1.20.49 \
--hash=sha256:6a672ba41dd00e5c1c1824ca8143d180d88de8736d78c0b1f96b8d3cb0466561 \
--hash=sha256:f7f103fa0651c69dd360c7d0ecd874854303de5cc0869e0cbc2818a52baacc69
# via aiobotocore
chardet==4.0.0 \
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
# via aiohttp
colorful==0.5.4 \
--hash=sha256:86848ad4e2eda60cd2519d8698945d22f6f6551e23e95f3f14dfbb60997807ea \
--hash=sha256:8d264b52a39aae4c0ba3e2a46afbaec81b0559a99be0d2cfe2aba4cf94531348
# via thumbor
derpconf==0.8.3 \
--hash=sha256:1bb152d8a1cf5c2a6d629bf29acd4af0c00811339642fc0a56172b0a83b31a15
# via thumbor
django-auth-ldap==2.4.0 \
--hash=sha256:2d869955da8a0c9a4448671bd9826b9f87458f6a9fc20278e84de8a81200a2be \
--hash=sha256:60fcbfc3141c99c3c49d3ccd7311a3992a231c319d94b6d2c143968f63676676
# via -r requirements/thumbor.in
django==3.1.8 \
--hash=sha256:c348b3ddc452bf4b62361f0752f71a339140c777ebea3cdaaaa8fdb7f417a862 \
--hash=sha256:f8393103e15ec2d2d313ccbb95a3f1da092f9f58d74ac1c61ca2ac0436ae1eac
# via
# -r requirements/thumbor.in
# django-auth-ldap
idna-ssl==1.1.0 \
--hash=sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c
# via aiohttp
idna==3.1 \
--hash=sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16 \
--hash=sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1
# via
# idna-ssl
# yarl
jmespath==0.10.0 \
--hash=sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9 \
--hash=sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f
# via botocore
libthumbor==2.0.1 \
--hash=sha256:3c4e1a59c019d22f868d225315c06f97fad30fb5e78112d6a230b978e7d24e38 \
--hash=sha256:ed4fe5f27f8f90e7285b7e6dce99c1b67d43a140bf370e989080b43d80ce25f0
# via thumbor
multidict==5.1.0 \
--hash=sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a \
--hash=sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93 \
--hash=sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632 \
--hash=sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656 \
--hash=sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79 \
--hash=sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7 \
--hash=sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d \
--hash=sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5 \
--hash=sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224 \
--hash=sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26 \
--hash=sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea \
--hash=sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348 \
--hash=sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6 \
--hash=sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76 \
--hash=sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1 \
--hash=sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f \
--hash=sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952 \
--hash=sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a \
--hash=sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37 \
--hash=sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9 \
--hash=sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359 \
--hash=sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8 \
--hash=sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da \
--hash=sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3 \
--hash=sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d \
--hash=sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf \
--hash=sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841 \
--hash=sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d \
--hash=sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93 \
--hash=sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f \
--hash=sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647 \
--hash=sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635 \
--hash=sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456 \
--hash=sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda \
--hash=sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5 \
--hash=sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281 \
--hash=sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80
# via
# aiohttp
# yarl
numpy==1.19.5 \
--hash=sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94 \
--hash=sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080 \
--hash=sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e \
--hash=sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c \
--hash=sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76 \
--hash=sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371 \
--hash=sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c \
--hash=sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2 \
--hash=sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a \
--hash=sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb \
--hash=sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140 \
--hash=sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28 \
--hash=sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f \
--hash=sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d \
--hash=sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff \
--hash=sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8 \
--hash=sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa \
--hash=sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea \
--hash=sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc \
--hash=sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73 \
--hash=sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d \
--hash=sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d \
--hash=sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4 \
--hash=sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c \
--hash=sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e \
--hash=sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea \
--hash=sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd \
--hash=sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f \
--hash=sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff \
--hash=sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e \
--hash=sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7 \
--hash=sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa \
--hash=sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827 \
--hash=sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60
# via opencv-python-headless
opencv-python-headless==4.5.1.48 \
--hash=sha256:0e02809db2968e54f3c23340be6ff9a1428b3f03f5dca7cd5aceda66e319ce86 \
--hash=sha256:1f7c14f5d4e5af4dc4669fc6b4a983b36072a934c439ac11266b930496da8255 \
--hash=sha256:243aea91cc1e36a47c46da4cc408071af39444a48df1fe1539ea8d7990500fd2 \
--hash=sha256:2560dcf3c1158226b066302f777bfe0f65282410b8d90871dd872306c967d1f1 \
--hash=sha256:2e6a9a88617a0ef7219cff24ba78a58416670a77e6ac63975f9009af3319ab63 \
--hash=sha256:372149d007e20bf556b7687591d22b58b56b3c225f492da051d81587e5dc7411 \
--hash=sha256:522f12dd994e064a30562adfd63b9439099bd7c80819f5261c37ebe593283c9e \
--hash=sha256:526b9e19cf6300f0891d8f427eac1048091912332bb781eb4957a4994bfbe608 \
--hash=sha256:5f0c7d34fa9953706c2a1a6d2760a91dc5a68cab3df16af61609894c6c8586f1 \
--hash=sha256:657cdd9fbbbbb7e898ae3d9b0649b367d0e440d429c714104d069c5612d578bb \
--hash=sha256:65c9ea57be5ebcaed009b3fee14fe59f3b6aa1e573fe08c5039ff057ad593c53 \
--hash=sha256:777fb596e04331f73ef5b0c1faa4d33348f29ca58216d9286355c16f5489c939 \
--hash=sha256:7c75680ffdf32d7044415a215d1fc60dbec14a7f2f0b59a85f0f74ef5efcb6ad \
--hash=sha256:924aa4c34ead0b817309f42291dc526b2a7755476afe3009d1e275fc3090d92d \
--hash=sha256:96d1da6ad061d8f3509668d398d14dd8265e529d6407f87eb26e7f4ddf043cc0 \
--hash=sha256:9aa04a491c534531029fbac61da961fae0bf4abb1786eed9c91befde4ca7bd81 \
--hash=sha256:a322d4df14c3a5f19701a023b3da91e9b8af8653b0d2ee0c50b0b341212f7343 \
--hash=sha256:aa562c520f46283423ba8fac29099458e42deab697a9abd0491622e421c5c454 \
--hash=sha256:ba2f0bd46e9534f29969e39f7895cbea9764173102b0c04b7818b8a9910d66e4 \
--hash=sha256:d16825755e7b5a6d8737f93e116670229e1510199e0af9213004e187ae0dbcc5 \
--hash=sha256:e3027e0d1b71b68b5cfe1ea9c627e323dff71112c854ba19805258d8fc6c630e \
--hash=sha256:f2011ecb3980bbed283d17d43e0f1221bac88c0cac1a6fb59a056544de2df2f7 \
--hash=sha256:f5e40a06116460ef2fd2d1c24be3b65f8bfb5fcdfe433f3fc01bcb4c2eb485bf \
--hash=sha256:f7f8e4f7c63c8e95eb210f4cba88d0069a0a964d6335d7a35b07f0d0baa13558 \
--hash=sha256:fe02a943b1a28b505e954fbce24e867119a3eb4351f93adad55c6cfe81a70484
# via thumbor
pillow==7.2.0 \
--hash=sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f \
--hash=sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8 \
--hash=sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad \
--hash=sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f \
--hash=sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae \
--hash=sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d \
--hash=sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5 \
--hash=sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b \
--hash=sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8 \
--hash=sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233 \
--hash=sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6 \
--hash=sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727 \
--hash=sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f \
--hash=sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38 \
--hash=sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4 \
--hash=sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626 \
--hash=sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d \
--hash=sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6 \
--hash=sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6 \
--hash=sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63 \
--hash=sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f \
--hash=sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41 \
--hash=sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1 \
--hash=sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117 \
--hash=sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d \
--hash=sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9 \
--hash=sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a \
--hash=sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce
# via thumbor
pyasn1-modules==0.2.8 \
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74
# via python-ldap
pyasn1==0.4.8 \
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
# via
# pyasn1-modules
# python-ldap
pycurl==7.43.0.6 \
--hash=sha256:8301518689daefa53726b59ded6b48f33751c383cf987b0ccfbbc4ed40281325
# via -r requirements/thumbor.in
python-dateutil==2.8.1 \
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a
# via
# botocore
# tc-aws
python-ldap==3.3.1 \
--hash=sha256:4711cacf013e298754abd70058ccc995758177fb425f1c2d30e71adfc1d00aa5
# via django-auth-ldap
pytz==2019.3 \
--hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \
--hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be
# via
# django
# thumbor
six==1.15.0 \
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced
# via
# derpconf
# libthumbor
# python-dateutil
sqlparse==0.4.1 \
--hash=sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0 \
--hash=sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8
# via django
statsd==3.3.0 \
--hash=sha256:c610fb80347fca0ef62666d241bce64184bd7cc1efe582f9690e045c25535eaa \
--hash=sha256:e3e6db4c246f7c59003e51c9720a51a7f39a396541cb9b147ff4b14d15b5dd1f
# via thumbor
https://github.com/kkopachev/aws/archive/b5058e6b9fec7354629acc6d5df423e0310bb0cd.zip#egg=tc_aws==6.3 \
--hash=sha256:8a28437b0dfab88c89f280a2d6ec55a6abfa3e26d495dc15e1b3f38744e27f0c
# via -r requirements/thumbor.in
thumbor==7.0.0a5 \
--hash=sha256:5042c9c8facf0da028a22f1aee717f856d213ec037835ca0edaa0282217654bb
# via
# -r requirements/thumbor.in
# tc-aws
tornado==6.1 \
--hash=sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb \
--hash=sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c \
--hash=sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288 \
--hash=sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95 \
--hash=sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558 \
--hash=sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe \
--hash=sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791 \
--hash=sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d \
--hash=sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326 \
--hash=sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b \
--hash=sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4 \
--hash=sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c \
--hash=sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910 \
--hash=sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5 \
--hash=sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c \
--hash=sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0 \
--hash=sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675 \
--hash=sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd \
--hash=sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f \
--hash=sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c \
--hash=sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea \
--hash=sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6 \
--hash=sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05 \
--hash=sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd \
--hash=sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575 \
--hash=sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a \
--hash=sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37 \
--hash=sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795 \
--hash=sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f \
--hash=sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32 \
--hash=sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c \
--hash=sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01 \
--hash=sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4 \
--hash=sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2 \
--hash=sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921 \
--hash=sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085 \
--hash=sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df \
--hash=sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102 \
--hash=sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5 \
--hash=sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68 \
--hash=sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5
# via thumbor
typing-extensions==3.7.4.3 \
--hash=sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918 \
--hash=sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c \
--hash=sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f
# via
# aiohttp
# aioitertools
# asgiref
# yarl
urllib3==1.26.4 \
--hash=sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df \
--hash=sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937
# via botocore
virtualenv-clone==0.5.4 \
--hash=sha256:07e74418b7cc64f4fda987bf5bc71ebd59af27a7bc9e8a8ee9fd54b1f2390a27 \
--hash=sha256:665e48dd54c84b98b71a657acb49104c54e7652bce9c1c4f6c6976ed4c827a29
# via -r requirements/thumbor.in
webcolors==1.11.1 \
--hash=sha256:76f360636957d1c976db7466bc71dcb713bb95ac8911944dffc55c01cb516de6 \
--hash=sha256:b8cd5d865a25c51ff1218f0c90d0c0781fc64312a49b746b320cf50de1648f6e
# via thumbor
wrapt==1.12.1 \
--hash=sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7
# via aiobotocore
yarl==1.6.3 \
--hash=sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e \
--hash=sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434 \
--hash=sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366 \
--hash=sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3 \
--hash=sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec \
--hash=sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959 \
--hash=sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e \
--hash=sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c \
--hash=sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6 \
--hash=sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a \
--hash=sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6 \
--hash=sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424 \
--hash=sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e \
--hash=sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f \
--hash=sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50 \
--hash=sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2 \
--hash=sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc \
--hash=sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4 \
--hash=sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970 \
--hash=sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10 \
--hash=sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0 \
--hash=sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406 \
--hash=sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896 \
--hash=sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643 \
--hash=sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721 \
--hash=sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478 \
--hash=sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724 \
--hash=sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e \
--hash=sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8 \
--hash=sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96 \
--hash=sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25 \
--hash=sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76 \
--hash=sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2 \
--hash=sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2 \
--hash=sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c \
--hash=sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a \
--hash=sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71
# via aiohttp

View File

@ -32,7 +32,6 @@ def get_caches_in_use(threshold_days: int) -> Set[str]:
setups_to_check |= get_recent_deployments(threshold_days)
if ENV == "dev":
add_current_venv_cache("zulip-py3-venv")
add_current_venv_cache("zulip-thumbor-venv")
for path in setups_to_check:
reqs_dir = os.path.join(path, "requirements")

View File

@ -1,35 +0,0 @@
#!/usr/bin/env python3
import argparse
import os
import sys
ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if ZULIP_PATH not in sys.path:
sys.path.append(ZULIP_PATH)
from scripts.lib.setup_venv import (
THUMBOR_VENV_DEPENDENCIES,
YUM_THUMBOR_VENV_DEPENDENCIES,
setup_virtualenv,
)
from scripts.lib.zulip_tools import os_families, parse_os_release, run
parser = argparse.ArgumentParser(description="Create a thumbor virtualenv with caching")
parser.add_argument("deploy_path")
args = parser.parse_args()
# install dependencies for setting up the virtualenv
distro_info = parse_os_release()
if "debian" in os_families():
run(["apt-get", "-y", "install", *THUMBOR_VENV_DEPENDENCIES])
elif "fedora" in os_families():
run(["yum", "-y", "install", *YUM_THUMBOR_VENV_DEPENDENCIES])
else:
print("Unsupported platform: {}".format(distro_info["ID"]))
sys.exit(1)
venv_name = "zulip-thumbor-venv"
cached_venv_path = setup_virtualenv(
os.path.join(args.deploy_path, venv_name),
os.path.join(ZULIP_PATH, "requirements", "thumbor.txt"),
)

View File

@ -365,7 +365,6 @@ fi
# Create and activate a virtualenv
if [ "$VIRTUALENV_NEEDED" = "yes" ]; then
"$ZULIP_PATH"/scripts/lib/create-production-venv "$ZULIP_PATH"
"$ZULIP_PATH"/scripts/lib/create-thumbor-venv "$ZULIP_PATH"
fi
"$ZULIP_PATH"/scripts/lib/install-node

View File

@ -69,24 +69,6 @@ FEDORA_VENV_DEPENDENCIES = [
"virtualenv", # see https://unix.stackexchange.com/questions/27877/install-virtualenv-on-fedora-16
]
THUMBOR_VENV_DEPENDENCIES = [
"libcurl4-openssl-dev",
"libjpeg-dev",
"zlib1g-dev",
"libfreetype6-dev",
"libpng-dev",
"gifsicle",
]
YUM_THUMBOR_VENV_DEPENDENCIES = [
"libcurl-devel",
"libjpeg-turbo-devel",
"zlib-devel",
"freetype-devel",
"libpng-devel",
"gifsicle",
]
def get_venv_dependencies(vendor: str, os_version: str) -> List[str]:
if "debian" in os_families():

View File

@ -169,11 +169,6 @@ subprocess.check_call(
[os.path.join(deploy_path, "scripts", "lib", "create-production-venv"), deploy_path]
)
# Set up the thumbor venv
subprocess.check_call(
[os.path.join(deploy_path, "scripts", "lib", "create-thumbor-venv"), deploy_path]
)
# Make sure the right version of node is installed
subprocess.check_call([os.path.join(deploy_path, "scripts", "lib", "install-node"), deploy_path])
@ -279,7 +274,6 @@ class_renames = {
"zulip::postgres_appdb_tuned": "zulip::profile::postgresql",
"zulip::postgres_backups": "zulip::postgresql_backups",
"zulip::rabbit": "zulip::profile::rabbitmq",
"zulip::thumbor": "zulip::profile::thumbor",
"zulip::voyager": "zulip::profile::standalone",
}
classes = re.split(r"\s*,\s*", get_config(config_file, "machine", "puppet_classes"))

View File

@ -87,8 +87,6 @@ else:
worker_status.check_returncode()
workers = [status_line.split()[0] for status_line in worker_status.stdout.splitlines()]
if os.path.exists("/etc/supervisor/conf.d/zulip/thumbor.conf"):
workers.append("zulip-thumbor")
if os.path.exists("/etc/supervisor/conf.d/zulip/zulip_db.conf"):
workers.append("process-fts-updates")

View File

@ -23,7 +23,6 @@ AUTOGENERATED_SETTINGS = [
"avatar_salt",
"rabbitmq_password",
"shared_secret",
"thumbor_key",
]

View File

@ -25,9 +25,6 @@ services = []
if os.path.exists("/etc/supervisor/conf.d/zulip/zulip_db.conf"):
services.append("process-fts-updates")
if os.path.exists("/etc/supervisor/conf.d/zulip/thumbor.conf"):
services.append("zulip-thumbor")
# Contrary to the order in (re)start-server, we stop django before the
# workers, to increase the chance that we finish processing any work
# that may have been enqueued by the Django, leaving the final state

View File

@ -234,7 +234,6 @@ export function parse_image_data(image) {
$source = $parent.attr("data-id");
} else {
$type = "image";
// thumbor supplies the src as thumbnail, data-src-fullsize as full-sized.
if ($image.attr("data-src-fullsize")) {
$source = $image.attr("data-src-fullsize");
} else {

View File

@ -15,11 +15,7 @@ sys.path.append(ZULIP_PATH)
from typing import TYPE_CHECKING, List
from scripts.lib.node_cache import NODE_MODULES_CACHE_PATH, setup_node_modules
from scripts.lib.setup_venv import (
THUMBOR_VENV_DEPENDENCIES,
YUM_THUMBOR_VENV_DEPENDENCIES,
get_venv_dependencies,
)
from scripts.lib.setup_venv import get_venv_dependencies
from scripts.lib.zulip_tools import (
ENDC,
FAIL,
@ -159,7 +155,6 @@ UBUNTU_COMMON_APT_DEPENDENCIES = [
"libxss1",
"xvfb",
# Puppeteer dependencies end here.
*THUMBOR_VENV_DEPENDENCIES,
]
COMMON_YUM_DEPENDENCIES = [
@ -179,7 +174,6 @@ COMMON_YUM_DEPENDENCIES = [
"mesa-libgbm",
"xorg-x11-server-Xvfb",
# Puppeteer dependencies end here.
*YUM_THUMBOR_VENV_DEPENDENCIES,
]
BUILD_PGROONGA_FROM_SOURCE = False

View File

@ -50,7 +50,7 @@ parser.add_argument(
dest="clear_memcached",
help="Do not clear memcached on startup",
)
parser.add_argument("--streamlined", action="store_true", help="Avoid thumbor, etc.")
parser.add_argument("--streamlined", action="store_true", help="Avoid process_queue, etc.")
parser.add_argument(
"--enable-tornado-logging",
action="store_true",
@ -98,7 +98,6 @@ proxy_port = base_port
django_port = base_port + 1
tornado_port = base_port + 2
webpack_port = base_port + 3
thumbor_port = base_port + 4
os.chdir(os.path.join(os.path.dirname(__file__), ".."))
@ -149,7 +148,7 @@ def server_processes() -> List[List[str]]:
if options.streamlined:
# The streamlined operation allows us to do many
# things, but search/thumbor/etc. features won't work.
# things, but search/etc. features won't work.
return main_cmds
other_cmds = [
@ -161,11 +160,6 @@ def server_processes() -> List[List[str]]:
"--quiet",
],
["./manage.py", "deliver_scheduled_messages"],
[
"/srv/zulip-thumbor-venv/bin/thumbor",
"--conf=./zthumbor/thumbor_settings.py",
f"--port={thumbor_port}",
],
]
# NORMAL (but slower) operation:
@ -200,8 +194,6 @@ def transform_url(protocol: str, path: str, query: str, target_port: int, target
host = ":".join((target_host, str(target_port)))
# Here we are going to rewrite the path a bit so that it is in parity with
# what we will have for production
if path.startswith("/thumbor"):
path = path[len("/thumbor") :]
newpath = urlunparse((protocol, host, path, "", query, ""))
return newpath
@ -320,10 +312,6 @@ class TornadoHandler(BaseHandler):
target_port = tornado_port
class ThumborHandler(BaseHandler):
target_port = thumbor_port
class ErrorHandler(BaseHandler):
@web.asynchronous
def prepare(self) -> None:
@ -333,17 +321,12 @@ class ErrorHandler(BaseHandler):
self.finish()
def using_thumbor() -> bool:
return not options.streamlined
class Application(web.Application):
def __init__(self, enable_logging: bool = False) -> None:
handlers = [
(r"/json/events.*", TornadoHandler),
(r"/api/v1/events.*", TornadoHandler),
(r"/webpack.*", WebPackHandler),
(r"/thumbor.*", ThumborHandler if using_thumbor() else ErrorHandler),
(r"/.*", DjangoHandler),
]
super().__init__(handlers, enable_logging=enable_logging)
@ -387,9 +370,6 @@ def print_listeners() -> None:
if not options.test:
ports.append((webpack_port, "webpack"))
if using_thumbor():
ports.append((thumbor_port, "Thumbor"))
for port, label in ports:
print(f" {port}: {label}")
print()

View File

@ -13,11 +13,9 @@ from scripts.lib.zulip_tools import overwrite_symlink
VENV_PATH = "/srv/zulip-py3-venv"
DEV_REQS_FILE = os.path.join(ZULIP_PATH, "requirements", "dev.txt")
THUMBOR_REQS_FILE = os.path.join(ZULIP_PATH, "requirements", "thumbor-dev.txt")
def main() -> None:
setup_virtualenv("/srv/zulip-thumbor-venv", THUMBOR_REQS_FILE, patch_activate_script=True)
cached_venv_path = setup_virtualenv(VENV_PATH, DEV_REQS_FILE, patch_activate_script=True)
overwrite_symlink(cached_venv_path, os.path.join(ZULIP_PATH, "zulip-py3-venv"))

View File

@ -2,7 +2,7 @@
set -e
# Make sure the Zulip dev virtualenv exists, and operate within it.
if [ ! -d /srv/zulip-py3-venv ] || [ ! -d /srv/zulip-thumbor-venv ]; then
if [ ! -d /srv/zulip-py3-venv ]; then
./tools/setup/setup_venvs.py
fi
@ -54,7 +54,3 @@ for name in pip prod mypy docs; do
cp "$OUTPUT_BASE_DIR/dev.txt" "$OUTPUT_BASE_DIR/$name.txt"
compile_requirements "requirements/$name.in" "$OUTPUT_BASE_DIR/$name.txt"
done
compile_requirements requirements/thumbor-dev.in "$OUTPUT_BASE_DIR/thumbor-dev.txt"
cp "$OUTPUT_BASE_DIR/thumbor-dev.txt" "$OUTPUT_BASE_DIR/thumbor.txt"
compile_requirements "requirements/thumbor.in" "$OUTPUT_BASE_DIR/thumbor.txt"

View File

@ -45,4 +45,4 @@ API_FEATURE_LEVEL = 62
# historical commits sharing the same major version, in which case a
# minor version bump suffices.
PROVISION_VERSION = "142.0"
PROVISION_VERSION = "143.0"

View File

@ -507,6 +507,7 @@ def write_instrumentation_reports(full_suite: bool, include_webhooks: bool) -> N
"casper/(?P<path>.+)",
"static/(?P<path>.+)",
"flush_caches",
"external_content/(?P<digest>[^/]+)/(?P<received_url>[^/]+)",
*(webhook.url for webhook in WEBHOOK_INTEGRATIONS if not include_webhooks),
}

View File

@ -1,23 +1,14 @@
# See https://zulip.readthedocs.io/en/latest/subsystems/thumbnailing.html
import base64
import os
import sys
import urllib
from urllib.parse import urljoin
from django.conf import settings
from django.utils.http import url_has_allowed_host_and_scheme
from libthumbor import CryptoURL
ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(ZULIP_PATH)
from zerver.lib.camo import get_camo_url
from zthumbor.loaders.helpers import THUMBOR_EXTERNAL_TYPE, THUMBOR_LOCAL_FILE_TYPE, THUMBOR_S3_TYPE
def is_thumbor_enabled() -> bool:
return settings.THUMBOR_URL != ""
def user_uploads_or_external(url: str) -> bool:
@ -26,58 +17,9 @@ def user_uploads_or_external(url: str) -> bool:
)
def get_source_type(url: str) -> str:
if not url.startswith("/user_uploads/"):
return THUMBOR_EXTERNAL_TYPE
local_uploads_dir = settings.LOCAL_UPLOADS_DIR
if local_uploads_dir:
return THUMBOR_LOCAL_FILE_TYPE
return THUMBOR_S3_TYPE
def generate_thumbnail_url(path: str, size: str = "0x0", is_camo_url: bool = False) -> str:
path = urljoin("/", path)
if not is_thumbor_enabled():
if url_has_allowed_host_and_scheme(path, allowed_hosts=None):
return path
return get_camo_url(path)
if url_has_allowed_host_and_scheme(path, allowed_hosts=None) and not path.startswith(
"/user_uploads/"
):
if url_has_allowed_host_and_scheme(path, allowed_hosts=None):
return path
source_type = get_source_type(path)
safe_url = base64.urlsafe_b64encode(path.encode()).decode("utf-8")
image_url = f"{safe_url}/source_type/{source_type}"
width, height = map(int, size.split("x"))
crypto = CryptoURL(key=settings.THUMBOR_KEY)
smart_crop_enabled = True
apply_filters = ["no_upscale()"]
if is_camo_url:
smart_crop_enabled = False
apply_filters.append("quality(100)")
if size != "0x0":
apply_filters.append("sharpen(0.5,0.2,true)")
encrypted_url = crypto.generate(
width=width,
height=height,
smart=smart_crop_enabled,
filters=apply_filters,
image_url=image_url,
)
if settings.THUMBOR_URL == "http://127.0.0.1:9995":
# If THUMBOR_URL is the default then thumbor is hosted on same machine
# as the Zulip server and we should serve a relative URL.
# We add a /thumbor in front of the relative URL because we make
# use of a proxy pass to redirect request internally in Nginx to 9995
# port where thumbor is running.
thumbnail_url = "/thumbor" + encrypted_url
else:
thumbnail_url = urllib.parse.urljoin(settings.THUMBOR_URL, encrypted_url)
return thumbnail_url
return get_camo_url(path)

View File

@ -1,28 +0,0 @@
from zerver.lib.test_classes import ZulipTestCase
class CamoURLTest(ZulipTestCase):
def test_legacy_camo_url(self) -> None:
# Test with valid hex and URL pair
result = self.client_get(
"/external_content/0f50f0bda30b6e65e9442c83ddb4076c74e75f96/687474703a2f2f7777772e72616e646f6d2e736974652f696d616765732f666f6f6261722e6a706567"
)
self.assertEqual(result.status_code, 302, result)
self.assertIn(
"/filters:no_upscale():quality(100)/aHR0cDovL3d3dy5yYW5kb20uc2l0ZS9pbWFnZXMvZm9vYmFyLmpwZWc=/source_type/external",
result.url,
)
# Test with invalid hex and URL pair
result = self.client_get(
"/external_content/074c5e6c9c6d4ce97db1c740d79dc561cf7eb379/687474703a2f2f7777772e72616e646f6d2e736974652f696d616765732f666f6f6261722e6a706567"
)
self.assertEqual(result.status_code, 403, result)
self.assert_in_response("Not a valid URL.", result)
def test_with_thumbor_disabled(self) -> None:
with self.settings(THUMBOR_SERVES_CAMO=False):
result = self.client_get(
"/external_content/074c5e6c9c6d4ce97db1c740d79dc561cf7eb379/687474703a2f2f7777772e72616e646f6d2e736974652f696d616765732f666f6f6261722e6a706567"
)
self.assertEqual(result.status_code, 404, result)

View File

@ -1,180 +1,12 @@
import base64
from io import StringIO
import orjson
from django.conf import settings
from zerver.lib.test_classes import ZulipTestCase
from zerver.lib.test_helpers import (
create_s3_buckets,
get_test_image_file,
override_settings,
use_s3_backend,
)
from zerver.lib.upload import upload_backend, upload_emoji_image
from zerver.lib.users import get_api_key
class ThumbnailTest(ZulipTestCase):
@use_s3_backend
def test_s3_source_type(self) -> None:
def get_file_path_urlpart(uri: str, size: str = "") -> str:
url_in_result = "smart/filters:no_upscale()%s/%s/source_type/s3"
sharpen_filter = ""
if size:
url_in_result = f"/{size}/{url_in_result}"
sharpen_filter = ":sharpen(0.5,0.2,true)"
hex_uri = base64.urlsafe_b64encode(uri.encode()).decode("utf-8")
return url_in_result % (sharpen_filter, hex_uri)
create_s3_buckets(settings.S3_AUTH_UPLOADS_BUCKET, settings.S3_AVATAR_BUCKET)
hamlet = self.example_user("hamlet")
self.login_user(hamlet)
fp = StringIO("zulip!")
fp.name = "zulip.jpeg"
result = self.client_post("/json/user_uploads", {"file": fp})
self.assert_json_success(result)
json = orjson.loads(result.content)
self.assertIn("uri", json)
uri = json["uri"]
base = "/user_uploads/"
self.assertEqual(base, uri[: len(base)])
# Test full size image.
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri)
self.assertIn(expected_part_url, result.url)
# Test thumbnail size.
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "thumbnail"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri, "0x300")
self.assertIn(expected_part_url, result.url)
# Test custom emoji URLs in Zulip messages.
user_profile = self.example_user("hamlet")
file_name = "emoji.png"
with get_test_image_file("img.png") as image_file:
upload_emoji_image(image_file, file_name, user_profile)
custom_emoji_url = upload_backend.get_emoji_url(file_name, user_profile.realm_id)
emoji_url_base = "/user_avatars/"
self.assertEqual(emoji_url_base, custom_emoji_url[: len(emoji_url_base)])
# Test full size custom emoji image (for emoji link in messages case).
result = self.client_get("/thumbnail", {"url": custom_emoji_url[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
self.assertIn(custom_emoji_url, result.url)
# Tests the /api/v1/thumbnail API endpoint with standard API auth
self.logout()
result = self.api_get(hamlet, "/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri)
self.assertIn(expected_part_url, result.url)
# Test with another user trying to access image using thumbor.
self.login("iago")
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 403, result)
self.assert_in_response("You are not authorized to view this file.", result)
def test_external_source_type(self) -> None:
def run_test_with_image_url(image_url: str) -> None:
# Test full size image.
self.login("hamlet")
encoded_url = base64.urlsafe_b64encode(image_url.encode()).decode("utf-8")
result = self.client_get("/thumbnail", {"url": image_url, "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = (
"/smart/filters:no_upscale()/" + encoded_url + "/source_type/external"
)
self.assertIn(expected_part_url, result.url)
# Test thumbnail size.
result = self.client_get("/thumbnail", {"url": image_url, "size": "thumbnail"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = (
"/0x300/smart/filters:no_upscale():sharpen(0.5,0.2,true)/"
+ encoded_url
+ "/source_type/external"
)
self.assertIn(expected_part_url, result.url)
# Test API endpoint with standard API authentication.
self.logout()
user_profile = self.example_user("hamlet")
result = self.api_get(
user_profile, "/thumbnail", {"url": image_url, "size": "thumbnail"}
)
self.assertEqual(result.status_code, 302, result)
expected_part_url = (
"/0x300/smart/filters:no_upscale():sharpen(0.5,0.2,true)/"
+ encoded_url
+ "/source_type/external"
)
self.assertIn(expected_part_url, result.url)
# Test API endpoint with legacy API authentication.
user_profile = self.example_user("hamlet")
result = self.client_get(
"/thumbnail",
{"url": image_url, "size": "thumbnail", "api_key": get_api_key(user_profile)},
)
self.assertEqual(result.status_code, 302, result)
expected_part_url = (
"/0x300/smart/filters:no_upscale():sharpen(0.5,0.2,true)/"
+ encoded_url
+ "/source_type/external"
)
self.assertIn(expected_part_url, result.url)
# Test a second logged-in user; they should also be able to access it
user_profile = self.example_user("iago")
result = self.client_get(
"/thumbnail",
{"url": image_url, "size": "thumbnail", "api_key": get_api_key(user_profile)},
)
self.assertEqual(result.status_code, 302, result)
expected_part_url = (
"/0x300/smart/filters:no_upscale():sharpen(0.5,0.2,true)/"
+ encoded_url
+ "/source_type/external"
)
self.assertIn(expected_part_url, result.url)
# Test with another user trying to access image using thumbor.
# File should be always accessible to user in case of external source
self.login("iago")
result = self.client_get("/thumbnail", {"url": image_url, "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = (
"/smart/filters:no_upscale()/" + encoded_url + "/source_type/external"
)
self.assertIn(expected_part_url, result.url)
image_url = "https://images.foobar.com/12345"
run_test_with_image_url(image_url)
image_url = "http://images.foobar.com/12345"
run_test_with_image_url(image_url)
image_url = "//images.foobar.com/12345"
run_test_with_image_url(image_url)
def test_local_file_type(self) -> None:
def get_file_path_urlpart(uri: str, size: str = "") -> str:
url_in_result = "smart/filters:no_upscale()%s/%s/source_type/local_file"
sharpen_filter = ""
if size:
url_in_result = f"/{size}/{url_in_result}"
sharpen_filter = ":sharpen(0.5,0.2,true)"
hex_uri = base64.urlsafe_b64encode(uri.encode()).decode("utf-8")
return url_in_result % (sharpen_filter, hex_uri)
def test_thumbnail_redirect(self) -> None:
self.login("hamlet")
fp = StringIO("zulip!")
fp.name = "zulip.jpeg"
@ -187,187 +19,29 @@ class ThumbnailTest(ZulipTestCase):
base = "/user_uploads/"
self.assertEqual(base, uri[: len(base)])
# Test full size image.
# We remove the forward slash infront of the `/user_uploads/` to match
# Markdown behaviour.
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri)
self.assertIn(expected_part_url, result.url)
# Test thumbnail size.
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "thumbnail"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri, "0x300")
self.assertIn(expected_part_url, result.url)
# Test with a Unicode filename.
fp = StringIO("zulip!")
fp.name = "μένει.jpg"
result = self.client_post("/json/user_uploads", {"file": fp})
self.assert_json_success(result)
json = orjson.loads(result.content)
self.assertIn("uri", json)
uri = json["uri"]
# We remove the forward slash infront of the `/user_uploads/` to match
# Markdown behaviour.
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri)
self.assertIn(expected_part_url, result.url)
# Test custom emoji urls in Zulip messages.
user_profile = self.example_user("hamlet")
file_name = "emoji.png"
with get_test_image_file("img.png") as image_file:
upload_emoji_image(image_file, file_name, user_profile)
custom_emoji_url = upload_backend.get_emoji_url(file_name, user_profile.realm_id)
emoji_url_base = "/user_avatars/"
self.assertEqual(emoji_url_base, custom_emoji_url[: len(emoji_url_base)])
# Test full size custom emoji image (for emoji link in messages case).
result = self.client_get("/thumbnail", {"url": custom_emoji_url[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
self.assertIn(custom_emoji_url, result.url)
# Tests the /api/v1/thumbnail API endpoint with HTTP basic auth.
self.logout()
user_profile = self.example_user("hamlet")
result = self.api_get(user_profile, "/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri)
self.assertIn(expected_part_url, result.url)
# Tests the /api/v1/thumbnail API endpoint with ?api_key
# auth.
user_profile = self.example_user("hamlet")
result = self.client_get(
"/thumbnail", {"url": uri[1:], "size": "full", "api_key": get_api_key(user_profile)}
)
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri)
self.assertIn(expected_part_url, result.url)
# Test with another user trying to access image using thumbor.
self.login("iago")
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 403, result)
self.assert_in_response("You are not authorized to view this file.", result)
@override_settings(THUMBOR_URL="127.0.0.1:9995")
def test_with_static_files(self) -> None:
self.login("hamlet")
uri = "/static/images/cute/turtle.png"
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
self.assertEqual(uri, result.url)
def test_with_thumbor_disabled(self) -> None:
self.login("hamlet")
fp = StringIO("zulip!")
fp.name = "zulip.jpeg"
result = self.client_post("/json/user_uploads", {"file": fp})
self.assert_json_success(result)
json = orjson.loads(result.content)
self.assertIn("uri", json)
uri = json["uri"]
base = "/user_uploads/"
self.assertEqual(base, uri[: len(base)])
with self.settings(THUMBOR_URL=""):
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
self.assertEqual(uri, result.url)
self.login("iago")
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 403, result)
self.assert_in_response("You are not authorized to view this file.", result)
uri = "https://www.google.com/images/srpr/logo4w.png"
with self.settings(THUMBOR_URL=""):
result = self.client_get("/thumbnail", {"url": uri, "size": "full"})
result = self.client_get("/thumbnail", {"url": uri, "size": "full"})
self.assertEqual(result.status_code, 302, result)
base = "https://external-content.zulipcdn.net/external_content/56c362a24201593891955ff526b3b412c0f9fcd2/68747470733a2f2f7777772e676f6f676c652e636f6d2f696d616765732f737270722f6c6f676f34772e706e67"
self.assertEqual(base, result.url)
uri = "http://www.google.com/images/srpr/logo4w.png"
with self.settings(THUMBOR_URL=""):
result = self.client_get("/thumbnail", {"url": uri, "size": "full"})
result = self.client_get("/thumbnail", {"url": uri, "size": "full"})
self.assertEqual(result.status_code, 302, result)
base = "https://external-content.zulipcdn.net/external_content/7b6552b60c635e41e8f6daeb36d88afc4eabde79/687474703a2f2f7777772e676f6f676c652e636f6d2f696d616765732f737270722f6c6f676f34772e706e67"
self.assertEqual(base, result.url)
uri = "//www.google.com/images/srpr/logo4w.png"
with self.settings(THUMBOR_URL=""):
result = self.client_get("/thumbnail", {"url": uri, "size": "full"})
result = self.client_get("/thumbnail", {"url": uri, "size": "full"})
self.assertEqual(result.status_code, 302, result)
base = "https://external-content.zulipcdn.net/external_content/676530cf4b101d56f56cc4a37c6ef4d4fd9b0c03/2f2f7777772e676f6f676c652e636f6d2f696d616765732f737270722f6c6f676f34772e706e67"
self.assertEqual(base, result.url)
def test_with_different_THUMBOR_URL(self) -> None:
self.login("hamlet")
fp = StringIO("zulip!")
fp.name = "zulip.jpeg"
result = self.client_post("/json/user_uploads", {"file": fp})
self.assert_json_success(result)
json = orjson.loads(result.content)
self.assertIn("uri", json)
uri = json["uri"]
base = "/user_uploads/"
self.assertEqual(base, uri[: len(base)])
hex_uri = base64.urlsafe_b64encode(uri.encode()).decode("utf-8")
with self.settings(THUMBOR_URL="http://test-thumborhost.com"):
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
base = "http://test-thumborhost.com/"
self.assertEqual(base, result.url[: len(base)])
expected_part_url = "/smart/filters:no_upscale()/" + hex_uri + "/source_type/local_file"
self.assertIn(expected_part_url, result.url)
def test_with_different_sizes(self) -> None:
def get_file_path_urlpart(uri: str, size: str = "") -> str:
url_in_result = "smart/filters:no_upscale()%s/%s/source_type/local_file"
sharpen_filter = ""
if size:
url_in_result = f"/{size}/{url_in_result}"
sharpen_filter = ":sharpen(0.5,0.2,true)"
hex_uri = base64.urlsafe_b64encode(uri.encode()).decode("utf-8")
return url_in_result % (sharpen_filter, hex_uri)
self.login("hamlet")
fp = StringIO("zulip!")
fp.name = "zulip.jpeg"
result = self.client_post("/json/user_uploads", {"file": fp})
self.assert_json_success(result)
json = orjson.loads(result.content)
self.assertIn("uri", json)
uri = json["uri"]
base = "/user_uploads/"
self.assertEqual(base, uri[: len(base)])
# Test with size supplied as a query parameter.
# size=thumbnail should return a 0x300 sized image.
# size=full should return the original resolution image.
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "thumbnail"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri, "0x300")
self.assertIn(expected_part_url, result.url)
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "full"})
self.assertEqual(result.status_code, 302, result)
expected_part_url = get_file_path_urlpart(uri)
self.assertIn(expected_part_url, result.url)
# Test with size supplied as a query parameter where size is anything
# else than 'full' or 'thumbnail'. Result should be an error message.
result = self.client_get("/thumbnail", {"url": uri[1:], "size": "480x360"})
self.assertEqual(result.status_code, 403, result)
self.assert_in_response("Invalid size.", result)
# Test with no size param supplied. In this case as well we show an
# error message.
result = self.client_get("/thumbnail", {"url": uri[1:]})
self.assertEqual(result.status_code, 400, "Missing 'size' argument")

View File

@ -1,18 +1,13 @@
from django.conf import settings
from django.http import HttpRequest, HttpResponse, HttpResponseForbidden, HttpResponseNotFound
from django.http import HttpRequest, HttpResponse, HttpResponseForbidden
from django.shortcuts import redirect
from django.utils.translation import gettext as _
from zerver.lib.camo import is_camo_url_valid
from zerver.lib.thumbnail import generate_thumbnail_url
def handle_camo_url(request: HttpRequest, digest: str, received_url: str) -> HttpResponse:
if not settings.THUMBOR_SERVES_CAMO:
return HttpResponseNotFound()
original_url = bytes.fromhex(received_url).decode()
if is_camo_url_valid(digest, original_url):
return redirect(generate_thumbnail_url(original_url, is_camo_url=True))
else:
return HttpResponseForbidden(_("<p>Not a valid URL.</p>"))
return HttpResponseForbidden("<p>Not a valid URL.</p>")

View File

@ -31,14 +31,5 @@ def backend_serve_thumbnail(
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 = "0x300"
elif size_requested == "full":
size = "0x0"
if size is None:
return HttpResponseForbidden(_("<p>Invalid size.</p>"))
thumbnail_url = generate_thumbnail_url(url, size)
thumbnail_url = generate_thumbnail_url(url)
return redirect(thumbnail_url)

View File

@ -1160,8 +1160,6 @@ CROSS_REALM_BOT_EMAILS = {
"emailgateway@zulip.com",
}
THUMBOR_KEY = get_secret("thumbor_key")
TWO_FACTOR_PATCH_ADMIN = False
# Allow the environment to override the default DSN

View File

@ -158,8 +158,6 @@ REDIS_PORT = 6379
REMOTE_POSTGRES_HOST = ""
REMOTE_POSTGRES_PORT = ""
REMOTE_POSTGRES_SSLMODE = ""
THUMBOR_URL = ""
THUMBOR_SERVES_CAMO = False
THUMBNAIL_IMAGES = False
SENDFILE_BACKEND: Optional[str] = None

View File

@ -157,7 +157,6 @@ if FAKE_LDAP_MODE:
}
AUTHENTICATION_BACKENDS += ("zproject.backends.ZulipLDAPAuthBackend",)
THUMBOR_URL = "http://127.0.0.1:9995"
THUMBNAIL_IMAGES = True
SEARCH_PILLS_ENABLED = bool(os.getenv("SEARCH_PILLS_ENABLED", False))

View File

@ -11,6 +11,7 @@ from django.views.static import serve
from zerver.views.auth import config_error, login_page
from zerver.views.development.cache import remove_caches
from zerver.views.development.camo import handle_camo_url
from zerver.views.development.dev_login import (
api_dev_fetch_api_key,
api_dev_list_users,
@ -86,6 +87,8 @@ urls = [
path("config-error/remoteuser/<error_category_name>", config_error),
# Special endpoint to remove all the server-side caches.
path("flush_caches", remove_caches),
# Redirect camo URLs for development
path("external_content/<digest>/<received_url>", handle_camo_url),
]
v1_api_mobile_patterns = [

View File

@ -523,18 +523,6 @@ SOCIAL_AUTH_SAML_SUPPORT_CONTACT = {
## can also be disabled in a realm's organization settings.
# INLINE_URL_EMBED_PREVIEW = True
## By default, Zulip connects to the thumbor (the thumbnailing software
## we use) service running locally on the machine. If you're running
## thumbor on a different server, you can configure that by setting
## THUMBOR_URL here. Setting THUMBOR_URL='' will let Zulip server know that
## thumbor is not running or configured.
# THUMBOR_URL = 'http://127.0.0.1:9995'
##
## This setting controls whether images shown in Zulip's inline image
## previews should be thumbnailed by thumbor, which saves bandwidth but
## can modify the image's appearance.
# THUMBNAIL_IMAGES = True
########
## Twitter previews.
##

View File

@ -204,9 +204,7 @@ BIG_BLUE_BUTTON_URL = "https://bbb.example.com/bigbluebutton/"
TWO_FACTOR_AUTHENTICATION_ENABLED = False
PUSH_NOTIFICATION_BOUNCER_URL = None
THUMBOR_URL = "http://127.0.0.1:9995"
THUMBNAIL_IMAGES = True
THUMBOR_SERVES_CAMO = True
# Logging the emails while running the tests adds them
# to /emails page.

View File

@ -36,7 +36,6 @@ from zerver.views.auth import (
start_social_login,
start_social_signup,
)
from zerver.views.camo import handle_camo_url
from zerver.views.compatibility import check_global_compatibility
from zerver.views.custom_profile_fields import (
create_realm_custom_profile_field,
@ -666,8 +665,8 @@ urls += [
"user_uploads/<realm_id_str>/<path:filename>",
GET=(serve_file_backend, {"override_api_url_scheme"}),
),
# This endpoint serves thumbnailed versions of images using thumbor;
# it requires an exception for the same reason.
# This endpoint redirects to camo; it requires an exception for the
# same reason.
rest_path("thumbnail", GET=(backend_serve_thumbnail, {"override_api_url_scheme"})),
# Avatars have the same constraint because their URLs are included
# in API data structures used by both the mobile and web clients.
@ -683,14 +682,6 @@ urls += [
path("report/csp_violations", report_csp_violations),
]
# This URL serves as a way to provide backward compatibility to messages
# rendered at the time Zulip used camo for doing http -> https conversion for
# such links with images previews. Now thumbor can be used for serving such
# images.
urls += [
path("external_content/<digest>/<received_url>", handle_camo_url),
]
# Incoming webhook URLs
# We don't create URLs for particular Git integrations here
# because of generic one below

View File

View File

@ -1,13 +0,0 @@
import re
from typing import Tuple
THUMBOR_EXTERNAL_TYPE = "external"
THUMBOR_S3_TYPE = "s3"
THUMBOR_LOCAL_FILE_TYPE = "local_file"
def separate_url_and_source_type(url: str) -> Tuple[str, str]:
THUMBNAIL_URL_PATT = re.compile("^(?P<actual_url>.+)/source_type/(?P<source_type>.+)")
matches = THUMBNAIL_URL_PATT.match(url)
assert matches is not None
return (matches.group("source_type"), matches.group("actual_url"))

View File

@ -1,50 +0,0 @@
# See https://zulip.readthedocs.io/en/latest/subsystems/thumbnailing.html
import base64
import logging
import urllib.parse
from tc_aws.loaders import s3_loader
from thumbor.context import Context
from thumbor.loaders import LoaderResult, file_loader, https_loader
from .helpers import (
THUMBOR_EXTERNAL_TYPE,
THUMBOR_LOCAL_FILE_TYPE,
THUMBOR_S3_TYPE,
separate_url_and_source_type,
)
def get_not_found_result() -> LoaderResult:
result = LoaderResult()
result.error = LoaderResult.ERROR_NOT_FOUND
result.successful = False
return result
async def load(context: Context, url: str) -> LoaderResult:
source_type, encoded_url = separate_url_and_source_type(url)
actual_url = base64.urlsafe_b64decode(urllib.parse.unquote(encoded_url)).decode("utf-8")
if source_type == THUMBOR_S3_TYPE:
if actual_url.startswith("/user_uploads/"):
actual_url = actual_url[len("/user_uploads/") :]
else:
raise AssertionError("Unexpected s3 file.")
return await s3_loader.load(context, actual_url)
elif source_type == THUMBOR_LOCAL_FILE_TYPE:
if actual_url.startswith("/user_uploads/"):
actual_url = actual_url[len("/user_uploads/") :]
local_file_path_prefix = "files/"
else:
raise AssertionError("Unexpected local file.")
patched_local_url = local_file_path_prefix + actual_url
return await file_loader.load(context, patched_local_url)
elif source_type == THUMBOR_EXTERNAL_TYPE:
return await https_loader.load(context, actual_url)
else:
logging.warning("INVALID SOURCE TYPE: " + source_type)
return get_not_found_result()

View File

@ -1,700 +0,0 @@
import configparser
import os
import sys
ZULIP_PATH = os.getcwd() # Thumbor doesnt set __file__ when loading this
sys.path.append(ZULIP_PATH)
from zproject.config import get_secret
os.environ["AWS_ACCESS_KEY_ID"] = get_secret("s3_key", "")
os.environ["AWS_SECRET_ACCESS_KEY"] = get_secret("s3_secret_key", "")
config_file = configparser.RawConfigParser()
config_file.read("/etc/zulip/zulip.conf")
# Whether this instance of Zulip is running in a production environment.
PRODUCTION = config_file.has_option("machine", "deploy_type")
if PRODUCTION:
try:
from zproject.prod_settings import LOCAL_UPLOADS_DIR
except ImportError:
LOCAL_UPLOADS_DIR = None
else:
from zproject.dev_settings import LOCAL_UPLOADS_DIR
IS_LOCAL_STORAGE = bool(LOCAL_UPLOADS_DIR)
################################# File Loader ##################################
## The root path where the File Loader will try to find images
if IS_LOCAL_STORAGE:
if os.path.isabs(LOCAL_UPLOADS_DIR):
FILE_LOADER_ROOT_PATH = LOCAL_UPLOADS_DIR
else:
FILE_LOADER_ROOT_PATH = os.path.join(ZULIP_PATH, LOCAL_UPLOADS_DIR)
################################### Logging ####################################
## Logging configuration as json
## Defaults to: None
# THUMBOR_LOG_CONFIG = None
## Log Format to be used by thumbor when writing log messages.
## Defaults to: '%(asctime)s %(name)s:%(levelname)s %(message)s'
# THUMBOR_LOG_FORMAT = '%(asctime)s %(name)s:%(levelname)s %(message)s'
## Date Format to be used by thumbor when writing log messages.
## Defaults to: '%Y-%m-%d %H:%M:%S'
# THUMBOR_LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
################################################################################
################################### Imaging ####################################
## Max width in pixels for images read or generated by thumbor
## Defaults to: 0
# MAX_WIDTH = 0
## Max height in pixels for images read or generated by thumbor
## Defaults to: 0
# MAX_HEIGHT = 0
## Max pixel count for images read by thumbor
## Defaults to: 75000000.0
# MAX_PIXELS = 75000000.0
## Min width in pixels for images read or generated by thumbor
## Defaults to: 1
# MIN_WIDTH = 1
## Min width in pixels for images read or generated by thumbor
## Defaults to: 1
# MIN_HEIGHT = 1
## Allowed domains for the http loader to download. These are regular
## expressions.
## Defaults to: # [
# ]
# ALLOWED_SOURCES = # [
# ]
## Quality index used for generated JPEG images
## Defaults to: 80
# QUALITY = 80
## Exports JPEG images with the `progressive` flag set.
## Defaults to: True
# PROGRESSIVE_JPEG = True
## Specify subsampling behavior for Pillow (see `subsampling` in
## http://pillow.readthedocs.org/en/latest/handbook/image-file-
## formats.html#jpeg).Be careful to use int for 0,1,2 and string for "4:4:4"
## notation. Will ignore `quality`. Using `keep` will copy the original file's
## subsampling.
## Defaults to: None
# PILLOW_JPEG_SUBSAMPLING = None
## Specify quantization tables for Pillow (see `qtables` in
## http://pillow.readthedocs.org/en/latest/handbook/image-file-
## formats.html#jpeg). Will ignore `quality`. Using `keep` will copy the
## original file's qtables.
## Defaults to: None
# PILLOW_JPEG_QTABLES = None
## Quality index used for generated WebP images. If not set (None) the same level
## of JPEG quality will be used.
## Defaults to: None
# WEBP_QUALITY = None
## Specifies whether WebP format should be used automatically if the request
## accepts it (via Accept header)
## Defaults to: False
# AUTO_WEBP = False
## Specify the ratio between 1in and 1px for SVG images. This is only used
## whenrasterizing SVG images having their size units in cm or inches.
## Defaults to: 150
# SVG_DPI = 150
## Max AGE sent as a header for the image served by thumbor in seconds
## Defaults to: 86400
# MAX_AGE = 86400
## Indicates the Max AGE header in seconds for temporary images (images with
## failed smart detection)
## Defaults to: 0
# MAX_AGE_TEMP_IMAGE = 0
## Indicates whether thumbor should rotate images that have an Orientation EXIF
## header
## Defaults to: False
# RESPECT_ORIENTATION = False
## Ignore errors during smart detections and return image as a temp image (not
## saved in result storage and with MAX_AGE_TEMP_IMAGE age)
## Defaults to: False
# IGNORE_SMART_ERRORS = False
## Sends If-Modified-Since & Last-Modified headers; requires support from result
## storage
## Defaults to: False
# SEND_IF_MODIFIED_LAST_MODIFIED_HEADERS = False
## Preserves exif information in generated images. Increases image size in
## kbytes, use with caution.
## Defaults to: False
# PRESERVE_EXIF_INFO = False
## Indicates whether thumbor should enable the EXPERIMENTAL support for animated
## gifs.
## Defaults to: True
# ALLOW_ANIMATED_GIFS = True
## Indicates whether thumbor should use gifsicle engine. Please note that smart
## cropping and filters are not supported for gifs using gifsicle (but won't
## give an error).
## Defaults to: False
USE_GIFSICLE_ENGINE = True
## Indicates whether thumbor should enable blacklist functionality to prevent
## processing certain images.
## Defaults to: False
# USE_BLACKLIST = False
## Size of the thread pool used for image transformations. The default value is
## 0 (don't use a threadpoool. Increase this if you are seeing your IOLoop
## getting blocked (often indicated by your upstream HTTP requests timing out)
## Defaults to: 0
# ENGINE_THREADPOOL_SIZE = 0
################################################################################
################################ Extensibility #################################
## The metrics backend thumbor should use to measure internal actions. This must
## be the full name of a python module (python must be able to import it)
## Defaults to: 'thumbor.metrics.logger_metrics'
# METRICS = 'thumbor.metrics.logger_metrics'
## The loader thumbor should use to load the original image. This must be the
## full name of a python module (python must be able to import it)
## Defaults to: 'thumbor.loaders.http_loader'
LOADER = "zthumbor.loaders.zloader"
## The file storage thumbor should use to store original images. This must be the
## full name of a python module (python must be able to import it)
## Defaults to: 'thumbor.storages.file_storage'
if IS_LOCAL_STORAGE:
STORAGE = "thumbor.storages.file_storage"
else:
STORAGE = "tc_aws.storages.s3_storage"
## The result storage thumbor should use to store generated images. This must be
## the full name of a python module (python must be able to import it)
## Defaults to: None
if IS_LOCAL_STORAGE:
RESULT_STORAGE = "thumbor.result_storages.file_storage"
else:
RESULT_STORAGE = "tc_aws.result_storages.s3_storage"
## The imaging engine thumbor should use to perform image operations. This must
## be the full name of a python module (python must be able to import it)
## Defaults to: 'thumbor.engines.pil'
# ENGINE = 'thumbor.engines.pil'
## The gif engine thumbor should use to perform image operations. This must be
## the full name of a python module (python must be able to import it)
## Defaults to: 'thumbor.engines.gif'
# GIF_ENGINE = 'thumbor.engines.gif'
## The url signer thumbor should use to verify url signatures.This must be the
## full name of a python module (python must be able to import it)
## Defaults to: 'thumbor.url_signers.base64_hmac_sha1'
# URL_SIGNER = 'thumbor.url_signers.base64_hmac_sha1'
################################################################################
################################### Security ###################################
## The security key thumbor uses to sign image URLs
## Defaults to: 'MY_SECURE_KEY'
SECURITY_KEY = get_secret("thumbor_key")
## Indicates if the /unsafe URL should be available
## Defaults to: True
ALLOW_UNSAFE_URL = False
## Indicates if encrypted (old style) URLs should be allowed
## Defaults to: True
ALLOW_OLD_URLS = False
################################################################################
##################################### HTTP #####################################
## Enables automatically generated etags
## Defaults to: True
# ENABLE_ETAGS = True
################################################################################
################################### Storage ####################################
## Set maximum id length for images when stored
## Defaults to: 32
# MAX_ID_LENGTH = 32
################################################################################
################################### Metrics ####################################
## Host to send statsd instrumentation to
## Defaults to: None
# STATSD_HOST = None
## Port to send statsd instrumentation to
## Defaults to: 8125
# STATSD_PORT = 8125
## Prefix for statsd
## Defaults to: None
# STATSD_PREFIX = None
################################################################################
################################# HTTP Loader ##################################
## The maximum number of seconds libcurl can take to connect to an image being
## loaded
## Defaults to: 5
# HTTP_LOADER_CONNECT_TIMEOUT = 5
## The maximum number of seconds libcurl can take to download an image
## Defaults to: 20
# HTTP_LOADER_REQUEST_TIMEOUT = 20
## Indicates whether libcurl should follow redirects when downloading an image
## Defaults to: True
# HTTP_LOADER_FOLLOW_REDIRECTS = True
## Indicates the number of redirects libcurl should follow when downloading an
## image
## Defaults to: 5
# HTTP_LOADER_MAX_REDIRECTS = 5
## The maximum number of simultaneous HTTP connections the loader can make before
## queuing
## Defaults to: 10
# HTTP_LOADER_MAX_CLIENTS = 10
## Indicates whether thumbor should forward the user agent of the requesting user
## Defaults to: False
# HTTP_LOADER_FORWARD_USER_AGENT = False
## Default user agent for thumbor http loader requests
## Defaults to: 'Thumbor/6.1.5'
# HTTP_LOADER_DEFAULT_USER_AGENT = 'Thumbor/6.1.5'
if config_file.has_option("http_proxy", "host") and config_file.has_option("http_proxy", "port"):
## The proxy host needed to load images through
## Defaults to: None
HTTP_LOADER_PROXY_HOST = config_file.get("http_proxy", "host")
## The proxy port for the proxy host
## Defaults to: None
HTTP_LOADER_PROXY_PORT = int(config_file.get("http_proxy", "port"))
## The proxy username for the proxy host
## Defaults to: None
# HTTP_LOADER_PROXY_USERNAME = None
## The proxy password for the proxy host
## Defaults to: None
# HTTP_LOADER_PROXY_PASSWORD = None
## The filename of CA certificates in PEM format
## Defaults to: None
# HTTP_LOADER_CA_CERTS = None
## The filename for client SSL key
## Defaults to: None
# HTTP_LOADER_CLIENT_KEY = None
## The filename for client SSL certificate
## Defaults to: None
# HTTP_LOADER_CLIENT_CERT = None
## If the CurlAsyncHTTPClient should be used
## Defaults to: False
# HTTP_LOADER_CURL_ASYNC_HTTP_CLIENT = False
################################################################################
################################# File Storage #################################
## Expiration in seconds for the images in the File Storage. Defaults to one
## month
## Defaults to: 2592000
# STORAGE_EXPIRATION_SECONDS = 2592000
## Indicates whether thumbor should store the signing key for each image in the
## file storage. This allows the key to be changed and old images to still be
## properly found
## Defaults to: False
# STORES_CRYPTO_KEY_FOR_EACH_IMAGE = False
## The root path where the File Storage will try to find images
## Defaults to: '/tmp/thumbor/storage'
# FILE_STORAGE_ROOT_PATH = '/tmp/thumbor/storage'
################################################################################
#################################### Upload ####################################
## Max size in Kb for images uploaded to thumbor
## Aliases: MAX_SIZE
## Defaults to: 0
# UPLOAD_MAX_SIZE = 0
## Indicates whether thumbor should enable File uploads
## Aliases: ENABLE_ORIGINAL_PHOTO_UPLOAD
## Defaults to: False
# UPLOAD_ENABLED = False
## The type of storage to store uploaded images with
## Aliases: ORIGINAL_PHOTO_STORAGE
## Defaults to: 'thumbor.storages.file_storage'
# UPLOAD_PHOTO_STORAGE = 'thumbor.storages.file_storage'
## Indicates whether image deletion should be allowed
## Aliases: ALLOW_ORIGINAL_PHOTO_DELETION
## Defaults to: False
# UPLOAD_DELETE_ALLOWED = False
## Indicates whether image overwrite should be allowed
## Aliases: ALLOW_ORIGINAL_PHOTO_PUTTING
## Defaults to: False
# UPLOAD_PUT_ALLOWED = False
## Default filename for image uploaded
## Defaults to: 'image'
# UPLOAD_DEFAULT_FILENAME = 'image'
################################################################################
############################### Memcache Storage ###############################
## List of Memcache storage server hosts
## Defaults to: # [
# 'localhost:11211',
# ]
# MEMCACHE_STORAGE_SERVERS = # [
# 'localhost:11211',
# ]
################################################################################
################################ Mixed Storage #################################
## Mixed Storage file storage. This must be the full name of a python module
## (python must be able to import it)
## Defaults to: 'thumbor.storages.no_storage'
# MIXED_STORAGE_FILE_STORAGE = 'thumbor.storages.no_storage'
## Mixed Storage signing key storage. This must be the full name of a python
## module (python must be able to import it)
## Defaults to: 'thumbor.storages.no_storage'
# MIXED_STORAGE_CRYPTO_STORAGE = 'thumbor.storages.no_storage'
## Mixed Storage detector information storage. This must be the full name of a
## python module (python must be able to import it)
## Defaults to: 'thumbor.storages.no_storage'
# MIXED_STORAGE_DETECTOR_STORAGE = 'thumbor.storages.no_storage'
################################################################################
##################################### Meta #####################################
## The callback function name that should be used by the META route for JSONP
## access
## Defaults to: None
# META_CALLBACK_NAME = None
################################################################################
################################## Detection ###################################
## List of detectors that thumbor should use to find faces and/or features. All
## of them must be full names of python modules (python must be able to import
## it)
## Defaults to: # [
# ]
# DETECTORS = # [
# ]
## The cascade file that opencv will use to detect faces.
## Defaults to: 'haarcascade_frontalface_alt.xml'
# FACE_DETECTOR_CASCADE_FILE = 'haarcascade_frontalface_alt.xml'
## The cascade file that opencv will use to detect glasses.
## Defaults to: 'haarcascade_eye_tree_eyeglasses.xml'
# GLASSES_DETECTOR_CASCADE_FILE = 'haarcascade_eye_tree_eyeglasses.xml'
## The cascade file that opencv will use to detect profile faces.
## Defaults to: 'haarcascade_profileface.xml'
# PROFILE_DETECTOR_CASCADE_FILE = 'haarcascade_profileface.xml'
################################################################################
################################## Optimizers ##################################
## List of optimizers that thumbor will use to optimize images
## Defaults to: # [
# ]
# OPTIMIZERS = # [
# ]
## Path for the jpegtran binary
## Defaults to: '/usr/bin/jpegtran'
# JPEGTRAN_PATH = '/usr/bin/jpegtran'
## Path for the ffmpeg binary used to generate gifv(h.264)
## Defaults to: '/usr/local/bin/ffmpeg'
# FFMPEG_PATH = '/usr/local/bin/ffmpeg'
################################################################################
################################### Filters ####################################
## List of filters that thumbor will allow to be used in generated images. All of
## them must be full names of python modules (python must be able to import
## it)
## Defaults to: # [
# 'thumbor.filters.brightness',
# 'thumbor.filters.colorize',
# 'thumbor.filters.contrast',
# 'thumbor.filters.rgb',
# 'thumbor.filters.round_corner',
# 'thumbor.filters.quality',
# 'thumbor.filters.noise',
# 'thumbor.filters.watermark',
# 'thumbor.filters.equalize',
# 'thumbor.filters.fill',
# 'thumbor.filters.sharpen',
# 'thumbor.filters.strip_icc',
# 'thumbor.filters.frame',
# 'thumbor.filters.grayscale',
# 'thumbor.filters.rotate',
# 'thumbor.filters.format',
# 'thumbor.filters.max_bytes',
# 'thumbor.filters.convolution',
# 'thumbor.filters.blur',
# 'thumbor.filters.extract_focal',
# 'thumbor.filters.focal',
# 'thumbor.filters.no_upscale',
# 'thumbor.filters.saturation',
# 'thumbor.filters.max_age',
# 'thumbor.filters.curve',
# ]
# FILTERS = # [
# 'thumbor.filters.brightness',
# 'thumbor.filters.colorize',
# 'thumbor.filters.contrast',
# 'thumbor.filters.rgb',
# 'thumbor.filters.round_corner',
# 'thumbor.filters.quality',
# 'thumbor.filters.noise',
# 'thumbor.filters.watermark',
# 'thumbor.filters.equalize',
# 'thumbor.filters.fill',
# 'thumbor.filters.sharpen',
# 'thumbor.filters.strip_icc',
# 'thumbor.filters.frame',
# 'thumbor.filters.grayscale',
# 'thumbor.filters.rotate',
# 'thumbor.filters.format',
# 'thumbor.filters.max_bytes',
# 'thumbor.filters.convolution',
# 'thumbor.filters.blur',
# 'thumbor.filters.extract_focal',
# 'thumbor.filters.focal',
# 'thumbor.filters.no_upscale',
# 'thumbor.filters.saturation',
# 'thumbor.filters.max_age',
# 'thumbor.filters.curve',
# ]
################################################################################
################################ Result Storage ################################
## Expiration in seconds of generated images in the result storage
## Defaults to: 0
# RESULT_STORAGE_EXPIRATION_SECONDS = 0
## Path where the Result storage will store generated images
## Defaults to: '/tmp/thumbor/result_storage'
if IS_LOCAL_STORAGE:
RESULT_STORAGE_FILE_STORAGE_ROOT_PATH = os.path.join(FILE_LOADER_ROOT_PATH, "thumbnails")
## Indicates whether unsafe requests should also be stored in the Result Storage
## Defaults to: False
RESULT_STORAGE_STORES_UNSAFE = True
################################################################################
############################ Queued Redis Detector #############################
## Server host for the queued redis detector
## Defaults to: 'localhost'
# REDIS_QUEUE_SERVER_HOST = 'localhost'
## Server port for the queued redis detector
## Defaults to: 6379
# REDIS_QUEUE_SERVER_PORT = 6379
## Server database index for the queued redis detector
## Defaults to: 0
# REDIS_QUEUE_SERVER_DB = 0
## Server password for the queued redis detector
## Defaults to: None
# REDIS_QUEUE_SERVER_PASSWORD = None
################################################################################
############################# Queued SQS Detector ##############################
## AWS key id
## Defaults to: None
# SQS_QUEUE_KEY_ID = None
## AWS key secret
## Defaults to: None
# SQS_QUEUE_KEY_SECRET = None
## AWS SQS region
## Defaults to: 'us-east-1'
# SQS_QUEUE_REGION = 'us-east-1'
################################################################################
#################################### Errors ####################################
## This configuration indicates whether thumbor should use a custom error
## handler.
## Defaults to: False
# USE_CUSTOM_ERROR_HANDLING = False
## Error reporting module. Needs to contain a class called ErrorHandler with a
## handle_error(context, handler, exception) method.
## Defaults to: 'thumbor.error_handlers.sentry'
# ERROR_HANDLER_MODULE = 'thumbor.error_handlers.sentry'
## File of error log as json
## Defaults to: None
# ERROR_FILE_LOGGER = None
## File of error log name is parametrized with context attribute
## Defaults to: False
# ERROR_FILE_NAME_USE_CONTEXT = False
################################################################################
############################### Errors - Sentry ################################
## Sentry thumbor project dsn. i.e.: http://5a63d58ae7b94f1dab3dee740b301d6a:73ee
## a45d3e8649239a973087e8f21f98@localhost:9000/2
## Defaults to: ''
# SENTRY_DSN_URL = ''
################################################################################
################################### General ####################################
## Custom app class to override ThumborServiceApp. This config value is
## overridden by the -a command-line parameter.
## Defaults to: 'thumbor.app.ThumborServiceApp'
# APP_CLASS = 'thumbor.app.ThumborServiceApp'
################################################################################
################################### AWS S3 settings ############################
if not IS_LOCAL_STORAGE:
from zproject.configured_settings import S3_AUTH_UPLOADS_BUCKET, S3_ENDPOINT_URL, S3_REGION
TC_AWS_REGION = S3_REGION # AWS Region
TC_AWS_ENDPOINT = S3_ENDPOINT_URL
TC_AWS_STORAGE_BUCKET = S3_AUTH_UPLOADS_BUCKET # S3 bucket for Storage
TC_AWS_STORAGE_ROOT_PATH = "thumbnails" # S3 path prefix for Storage bucket
TC_AWS_LOADER_BUCKET = S3_AUTH_UPLOADS_BUCKET # S3 bucket for loader
TC_AWS_LOADER_ROOT_PATH = "" # S3 path prefix for Loader bucket
TC_AWS_RESULT_STORAGE_BUCKET = S3_AUTH_UPLOADS_BUCKET # S3 bucket for result Storage
TC_AWS_RESULT_STORAGE_ROOT_PATH = "thumbnails" # S3 path prefix for Result storage bucket
TC_AWS_MAX_RETRY = 0 # Max retries for get image from S3 Bucket. Default is 0
# put data into S3 using the Server Side Encryption functionality to
# encrypt data at rest in S3
# https://aws.amazon.com/about-aws/whats-new/2011/10/04/amazon-s3-announces-server-side-encryption-support/
TC_AWS_STORAGE_SSE = False
# put data into S3 with Reduced Redundancy
# https://aws.amazon.com/about-aws/whats-new/2010/05/19/announcing-amazon-s3-reduced-redundancy-storage/
TC_AWS_STORAGE_RRS = False
# Enable HTTP Loader as well?
# This would allow you to load watermarks in over your images dynamically through a URI
# E.g.
# http://your-thumbor.com/unsafe/filters:watermark(http://example.com/watermark.png,0,0,50)/s3_bucket/photo.jpg
TC_AWS_ENABLE_HTTP_LOADER = False
TC_AWS_ALLOWED_BUCKETS = False # List of allowed bucket to be requested
TC_AWS_STORE_METADATA = False # Store result with metadata (for instance content-type)
################################################################################
# You can override settings in zthumbor/thumbor_local_settings.py
try:
from zthumbor.thumbor_local_settings import *
except ImportError:
pass