├── worker ├── requirements.txt ├── docbleach │ ├── __init__.py │ ├── celeryconfig.py │ └── tasks │ │ └── __init__.py ├── .dockerignore ├── entrypoint.sh └── Dockerfile ├── api ├── requirements.txt ├── .dockerignore ├── static │ ├── swagger │ │ ├── swagger-ui.css.map │ │ ├── swagger-ui.js.map │ │ ├── swagger-ui-standalone-preset.js.map │ │ ├── swagger-ui-bundle.js.map │ │ ├── docbleach-conf.js │ │ ├── index.html │ │ ├── swagger-ui.css │ │ └── swagger-ui-standalone-preset.js │ ├── favicon │ │ ├── favicon.ico │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ ├── mstile-70x70.png │ │ ├── apple-touch-icon.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── browserconfig.xml │ │ ├── manifest.json │ │ └── safari-pinned-tab.svg │ ├── css │ │ ├── docbleach.css │ │ └── sweetalert2.min.css │ ├── js │ │ ├── html5shiv.js │ │ ├── respond.min.js │ │ ├── docbleach.js │ │ └── sweetalert2.min.js │ ├── swagger.yaml │ └── index.html ├── docbleach │ ├── controllers │ │ ├── ping.py │ │ ├── static.py │ │ ├── __init__.py │ │ ├── task.py │ │ ├── base.py │ │ └── upload.py │ ├── tasks │ │ └── __init__.py │ ├── config │ │ └── __init__.py │ ├── utils │ │ └── __init__.py │ └── __init__.py ├── docbleach.py └── Dockerfile ├── autoscale ├── requirements.txt ├── .dockerignore ├── entrypoint.sh ├── Dockerfile └── autoscale2.py ├── docs ├── clickhere.png ├── Chooseafile.png └── downloadyourfile.png ├── docker-compose.yml ├── LICENSE ├── .gitignore ├── CONTRIBUTING.md └── README.md /worker/requirements.txt: -------------------------------------------------------------------------------- 1 | celery[redis]==4.3.0 2 | -------------------------------------------------------------------------------- /api/requirements.txt: -------------------------------------------------------------------------------- 1 | celery[redis]~=4.0.2 2 | tornado~=4.4 3 | -------------------------------------------------------------------------------- /autoscale/requirements.txt: -------------------------------------------------------------------------------- 1 | marathon==0.8.9 2 | redis==2.10.5 -------------------------------------------------------------------------------- /worker/docbleach/__init__.py: -------------------------------------------------------------------------------- 1 | # Required for docbleach to be a valid python package 2 | -------------------------------------------------------------------------------- /autoscale/.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | *.iml 3 | .idea 4 | .venv 5 | .git 6 | .gitignore -------------------------------------------------------------------------------- /docs/clickhere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/docs/clickhere.png -------------------------------------------------------------------------------- /api/.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | *.iml 3 | .idea 4 | .venv 5 | .git 6 | .gitignore 7 | Dockerfile -------------------------------------------------------------------------------- /docs/Chooseafile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/docs/Chooseafile.png -------------------------------------------------------------------------------- /worker/.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | *.iml 3 | .idea 4 | .venv 5 | .git 6 | .gitignore 7 | Dockerfile -------------------------------------------------------------------------------- /docs/downloadyourfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/docs/downloadyourfile.png -------------------------------------------------------------------------------- /api/static/swagger/swagger-ui.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.css","sources":[],"mappings":"","sourceRoot":""} -------------------------------------------------------------------------------- /api/static/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/favicon.ico -------------------------------------------------------------------------------- /autoscale/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "Starting the AutoScale thing" 5 | exec python autoscale2.py -------------------------------------------------------------------------------- /worker/docbleach/celeryconfig.py: -------------------------------------------------------------------------------- 1 | # Same TTL as Plik 2 | result_expires = 12 * 3600 3 | task_reject_on_worker_lost = True 4 | -------------------------------------------------------------------------------- /api/static/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /api/static/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /api/static/favicon/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/mstile-144x144.png -------------------------------------------------------------------------------- /api/static/favicon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/mstile-150x150.png -------------------------------------------------------------------------------- /api/static/favicon/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/mstile-310x150.png -------------------------------------------------------------------------------- /api/static/favicon/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/mstile-310x310.png -------------------------------------------------------------------------------- /api/static/favicon/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/mstile-70x70.png -------------------------------------------------------------------------------- /api/static/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /api/static/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /api/static/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docbleach/DocBleach-Web/HEAD/api/static/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /autoscale/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7 2 | 3 | WORKDIR /app/ 4 | COPY . /app/ 5 | 6 | RUN pip3 install -r requirements.txt 7 | 8 | CMD ["/app/entrypoint.sh"] 9 | -------------------------------------------------------------------------------- /api/docbleach/controllers/ping.py: -------------------------------------------------------------------------------- 1 | import tornado.web 2 | 3 | 4 | class PingHandler(tornado.web.RequestHandler): 5 | def get(self): 6 | self.finish('pong') 7 | -------------------------------------------------------------------------------- /api/docbleach/controllers/static.py: -------------------------------------------------------------------------------- 1 | import tornado.web 2 | 3 | from .base import BaseHandler 4 | 5 | 6 | class StaticFileHandler(tornado.web.StaticFileHandler, BaseHandler): 7 | pass 8 | -------------------------------------------------------------------------------- /api/static/swagger/swagger-ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;AAsoGA;AAy4HA;AA67FA;AA4mCA;AAs+BA;AAsiCA;AAm5BA","sourceRoot":""} -------------------------------------------------------------------------------- /api/static/swagger/swagger-ui-standalone-preset.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AAqTA;AAyiGA","sourceRoot":""} -------------------------------------------------------------------------------- /api/docbleach/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import BaseHandler 2 | from .ping import PingHandler 3 | from .static import StaticFileHandler 4 | from .task import TaskHandler 5 | from .upload import UploadHandler 6 | -------------------------------------------------------------------------------- /api/docbleach.py: -------------------------------------------------------------------------------- 1 | import tornado.ioloop 2 | 3 | from docbleach import application 4 | 5 | if __name__ == "__main__": 6 | print("Listening on port 5000") 7 | application.listen(5000) 8 | tornado.ioloop.IOLoop.instance().start() 9 | -------------------------------------------------------------------------------- /api/docbleach/tasks/__init__.py: -------------------------------------------------------------------------------- 1 | from celery import Celery 2 | 3 | from ..config import celery_broker, celery_result_backend 4 | 5 | cel = Celery( 6 | 'docbleach', 7 | broker=celery_broker, 8 | backend=celery_result_backend 9 | ) 10 | -------------------------------------------------------------------------------- /api/static/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #2b5797 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /worker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | export CELERY_WORKER_MAX_TASKS=${CELERY_WORKER_MAX_TASKS:=1000} 5 | export CELERY_QUEUES=${CELERY_QUEUES:=celery} 6 | export C_FORCE_ROOT="true" 7 | 8 | echo "Starting celery worker" 9 | exec celery worker \ 10 | -A docbleach.tasks \ 11 | -Q ${CELERY_QUEUES} \ 12 | --maxtasksperchild=${CELERY_WORKER_MAX_TASKS} \ 13 | --loglevel=INFO 14 | -------------------------------------------------------------------------------- /api/static/favicon/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "icons": [ 4 | { 5 | "src": "\/android-chrome-192x192.png?v=GvJQap5OwL", 6 | "sizes": "192x192", 7 | "type": "image\/png" 8 | }, 9 | { 10 | "src": "\/android-chrome-512x512.png?v=GvJQap5OwL", 11 | "sizes": "512x512", 12 | "type": "image\/png" 13 | } 14 | ], 15 | "theme_color": "#ffffff", 16 | "display": "standalone", 17 | "orientation": "portrait" 18 | } 19 | -------------------------------------------------------------------------------- /api/static/swagger/swagger-ui-bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAsdA;AAkoJA;AAyiCA;;;;;AAskCA;AAq7IA;AAo7FA;AA0wGA;AAgmEA;AA+9CA;AA0gDA;AA0rCA;AAm6DA;AAm4IA;;;;;;;;;;;;;;AAmtFA;AAyoIA;AAiuJA;AAglHA;AA+mGA;AAmkEA;AA42DA;AAwxDA;AA69BA;;;;;;AAixEA;AAo2FA;;;;;AA23CA;AA2qFA;AAo2CA;AAihCA;AAomDA;AAiuEA;AAkjGA;;;;;;;;;AAkpBA;AA2zIA;AAg4DA;AAywDA;;;;;;AAyzBA;AA8iHA;AAipGA","sourceRoot":""} -------------------------------------------------------------------------------- /api/docbleach/controllers/task.py: -------------------------------------------------------------------------------- 1 | import tornado.gen 2 | 3 | from .base import BaseApiHandler 4 | from ..tasks import cel 5 | 6 | 7 | class TaskHandler(BaseApiHandler): 8 | @tornado.gen.coroutine 9 | def get(self, task_id): 10 | data = yield self.get_task_meta(task_id) 11 | result_data = {'result': data['result'], 'status': data['status']} 12 | 13 | self.finish(result_data) 14 | 15 | @staticmethod 16 | @tornado.gen.coroutine 17 | def get_task_meta(task_id): 18 | return cel.backend.get_task_meta(task_id) 19 | -------------------------------------------------------------------------------- /api/docbleach/config/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | __UPLOADS__ = 'uploads/' 4 | 5 | internal_plik_server = os.getenv('INTERNAL_PLIK_SERVER', 'https://plik.root.gg') 6 | 7 | celery_broker = os.getenv('CELERY_BROKER') 8 | 9 | celery_result_backend = os.getenv('CELERY_RESULT_BACKEND') 10 | 11 | debug_mode = os.getenv('DEBUG', 'true').lower() == 'true' 12 | 13 | advertise_server = os.getenv('DOCBLEACH_AS_SERVER_HEADER', 'false') == 'true' 14 | 15 | PLIK_COMMAND = [ 16 | 'plik', 17 | '--server', internal_plik_server, 18 | '-t', '3h', 19 | '-q' 20 | ] 21 | -------------------------------------------------------------------------------- /api/static/swagger/docbleach-conf.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | // Build a system 3 | const ui = SwaggerUIBundle({ 4 | url: "../static/swagger.yaml", 5 | dom_id: '#swagger-ui', 6 | presets: [ 7 | SwaggerUIBundle.presets.apis, 8 | // yay ES6 modules ↘ 9 | Array.isArray(SwaggerUIStandalonePreset) ? SwaggerUIStandalonePreset : SwaggerUIStandalonePreset.default 10 | ], 11 | plugins: [ 12 | SwaggerUIBundle.plugins.DownloadUrl 13 | ], 14 | layout: "StandaloneLayout" 15 | }) 16 | 17 | window.ui = ui 18 | } 19 | -------------------------------------------------------------------------------- /api/docbleach/utils/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import string 3 | from random import SystemRandom 4 | 5 | cryptogen = SystemRandom() 6 | 7 | 8 | def secure_uuid(): 9 | """ 10 | Strength: 6*3 random characters from a list of 62, approx. 64^18 possible 11 | strings, or 2^100. Should be enough to prevent a successful bruteforce, as 12 | download links are only valid for 3 hours 13 | :return: 14 | """ 15 | return id_generator() + "-" + id_generator() + "-" + id_generator() 16 | 17 | 18 | def id_generator(size=6, chars=string.ascii_letters + string.digits): 19 | return ''.join(cryptogen.choice(chars) for _ in range(size)) 20 | 21 | 22 | def static(*args): 23 | return os.path.join('static', *args) 24 | -------------------------------------------------------------------------------- /api/docbleach/__init__.py: -------------------------------------------------------------------------------- 1 | import tornado.web 2 | from tornado.log import enable_pretty_logging 3 | 4 | from .config import debug_mode 5 | from .controllers import * 6 | from .utils import static 7 | 8 | application = tornado.web.Application([ 9 | (r'/static/(.*)', StaticFileHandler, {'path': static()}), 10 | (r'/doc/()', StaticFileHandler, {'path': static('swagger', 'index.html')}), 11 | (r'/doc/(.*)', StaticFileHandler, {'path': static('swagger')}), 12 | (r'/()', StaticFileHandler, {'path': static('index.html')}), 13 | 14 | (r'/ping', PingHandler), 15 | (r'/v1/ping', PingHandler), 16 | (r'/v1/tasks', UploadHandler), 17 | (r'/v1/tasks/(.*)', TaskHandler), 18 | ], debug=debug_mode) 19 | 20 | enable_pretty_logging() 21 | -------------------------------------------------------------------------------- /api/static/css/docbleach.css: -------------------------------------------------------------------------------- 1 | .docbleach_severe { 2 | color: darkred; 3 | font-weight: 600; 4 | } 5 | 6 | .docbleach_warning { 7 | color: red; 8 | } 9 | 10 | .docbleach_info { 11 | color: #0091D7; 12 | } 13 | 14 | /* Used by docbleach's drop zone */ 15 | 16 | .js .inputfile, 17 | .js #subButton { 18 | width: 0; 19 | height: 0; 20 | opacity: 0; 21 | overflow: hidden; 22 | position: absolute; 23 | z-index: -1; 24 | } 25 | 26 | .inputfile + label { 27 | max-width: 80%; 28 | font-size: 1.25rem; 29 | font-weight: 700; 30 | text-overflow: ellipsis; 31 | white-space: nowrap; 32 | cursor: pointer; 33 | display: inline-block; 34 | overflow: hidden; 35 | padding: 0.625rem 1.25rem; 36 | } 37 | 38 | .inputfile + label { 39 | color: #f1e5e6; 40 | background-color: #d3394c; 41 | } 42 | 43 | .inputfile:focus + label, 44 | .inputfile.has-focus + label, 45 | .inputfile + label:hover { 46 | background-color: #722040; 47 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | services: 4 | # Redis 5 | redis: 6 | image: redis 7 | 8 | # Our rest API 9 | web: 10 | build: 11 | context: api 12 | dockerfile: Dockerfile 13 | image: docbleach/api:latest 14 | environment: 15 | - CELERY_BROKER=redis://redis/ 16 | - CELERY_RESULT_BACKEND=redis://redis/ 17 | - INTERNAL_PLIK_SERVER=${FINAL_PLIK_SERVER:-http://plik:8080} 18 | ports: 19 | - "${EXTERNAL_PORT:-9000}:5000" 20 | tmpfs: /tmp 21 | 22 | # Celery worker, the one you should be scaling using, ie to have 10 instances: 23 | # `docker-compose scale worker=10` 24 | worker: 25 | build: 26 | context: worker 27 | dockerfile: Dockerfile 28 | image: docbleach/worker:latest 29 | environment: 30 | - CELERY_BROKER=redis://redis/ 31 | - CELERY_RESULT_BACKEND=redis://redis/ 32 | - FINAL_PLIK_SERVER=${FINAL_PLIK_SERVER:-https://plik.root.gg} 33 | tmpfs: /tmp 34 | 35 | plik: 36 | image: rootgg/plik 37 | expose: 38 | - 8080 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Maxime Guerreiro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-alpine 2 | 3 | EXPOSE 5000 4 | HEALTHCHECK CMD curl --fail http://localhost:5000/ping 5 | 6 | ENV INTERNAL_PLIK_SERVER https://plik.root.gg 7 | 8 | # We add the Plik binary file 9 | ADD https://plik.root.gg/clients/linux-amd64/plik /usr/bin/plik 10 | 11 | RUN apk add -t build --no-cache --update-cache \ 12 | # Having up to date SSL certificates is always a good thing. :) 13 | ca-certificates \ 14 | openssl \ 15 | # For the healthcheck 16 | curl \ 17 | && \ 18 | update-ca-certificates && \ 19 | 20 | # Add glibc, wanted by plik (compiled with Go) 21 | wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \ 22 | wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk && \ 23 | apk add glibc-2.23-r3.apk && \ 24 | 25 | # Remove openssl, only needed for wget 26 | apk del build wget unzip && \ 27 | 28 | # We add an user 29 | adduser -S -u 1000 worker && \ 30 | 31 | # Add default config for Plik, required 32 | chmod o+x /usr/bin/plik && \ 33 | echo 'URL = "https://plik.root.gg"' > /home/worker/.plikrc 34 | 35 | 36 | # Install the python dependencies 37 | ADD requirements.txt /app/ 38 | WORKDIR /app/ 39 | 40 | RUN pip3 install --no-cache-dir -r requirements.txt 41 | 42 | COPY . /app/ 43 | RUN chown -R worker /app/; chmod -R 770 /app/ 44 | 45 | USER worker 46 | ENTRYPOINT ["python3", "/app/docbleach.py"] 47 | -------------------------------------------------------------------------------- /api/docbleach/controllers/base.py: -------------------------------------------------------------------------------- 1 | import tornado.web 2 | 3 | from ..config import advertise_server 4 | 5 | CSP_POLICY = "default-src 'self' https:;" + \ 6 | "style-src 'self' 'unsafe-inline' https:;" + \ 7 | "img-src 'self' data: https:;" + \ 8 | "frame-ancestors 'none';" + \ 9 | "form-action *;" 10 | 11 | REFERRER_POLICY = 'no-referrer, strict-origin-when-cross-origin' 12 | 13 | 14 | class BaseHandler(tornado.web.RequestHandler): 15 | def set_default_headers(self): 16 | super(BaseHandler, self).set_default_headers() 17 | 18 | if advertise_server: 19 | self.set_header('Server', 'DocBleach') 20 | else: 21 | self.clear_header('Server') 22 | 23 | self.set_header('X-Frame-Options', 'DENY') 24 | self.set_header('Referrer-Policy', REFERRER_POLICY) 25 | self.set_header('Content-Security-Policy', CSP_POLICY) 26 | self.set_header('X-Content-Type-Options', 'nosniff') 27 | self.set_header('X-XSS-Protection', '1; mode=block') 28 | 29 | 30 | class BaseApiHandler(BaseHandler): 31 | def set_default_headers(self): 32 | super(BaseApiHandler, self).set_default_headers() 33 | self.set_header('Access-Control-Allow-Origin', '*') 34 | self.set_header('Access-Control-Allow-Headers', 'x-requested-with') 35 | self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') 36 | 37 | def options(self, *args, **kwargs): 38 | self.set_status(204) 39 | self.finish() 40 | 41 | def write_error(self, status_code, **kwargs): 42 | if status_code in [500, 503]: 43 | self.write('Error %s' % status_code) 44 | -------------------------------------------------------------------------------- /api/docbleach/controllers/upload.py: -------------------------------------------------------------------------------- 1 | from subprocess import Popen, PIPE 2 | 3 | import tornado.gen 4 | import tornado.web 5 | 6 | from .base import BaseApiHandler 7 | from ..config import PLIK_COMMAND 8 | from ..tasks import cel 9 | from ..utils import secure_uuid 10 | 11 | 12 | class UploadHandler(BaseApiHandler): 13 | @tornado.gen.coroutine 14 | def post(self): 15 | if 'file' not in self.request.files: 16 | raise tornado.web.HTTPError(404) 17 | 18 | fileinfo = self.request.files['file'] 19 | if isinstance(fileinfo, list): 20 | fileinfo = fileinfo[0] 21 | 22 | filename = str(fileinfo['filename'].strip()) 23 | 24 | link = yield self.store_on_plik(fileinfo) 25 | async_res = yield self.add_task(link, filename) 26 | 27 | self.set_status(202) 28 | self.finish({'task_id': async_res.id}) 29 | 30 | @staticmethod 31 | @tornado.gen.coroutine 32 | def store_on_plik(fileinfo): 33 | p = Popen(PLIK_COMMAND, stdout=PIPE, stdin=PIPE, stderr=PIPE) 34 | link, err = p.communicate(input=fileinfo.body) 35 | 36 | if err: 37 | print(err) 38 | 39 | link = link.strip().decode('utf-8') 40 | 41 | return link 42 | 43 | @staticmethod 44 | @tornado.gen.coroutine 45 | def add_task(link, filename): 46 | task_id = secure_uuid() 47 | args = [link, filename] 48 | return cel.send_task('sanitize', 49 | task_id=task_id, 50 | # TTL for the event, equal to Plik's TTL 51 | expires=3 * 3600, 52 | args=args, 53 | kwargs={}) 54 | -------------------------------------------------------------------------------- /worker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine 2 | 3 | ENTRYPOINT ["/app/entrypoint.sh"] 4 | 5 | HEALTHCHECK CMD /usr/bin/celery inspect ping -A docbleach.tasks -d celery@$HOSTNAME 6 | 7 | ENV FINAL_PLIK_SERVER https://plik.root.gg 8 | 9 | # Stored on Plik for now, as we don't yet have the GitHub Link 10 | ENV DOCBLEACH_JAR https://github.com/docbleach/DocBleach/releases/download/v0.0.9/docbleach.jar 11 | 12 | # We add the Plik binary file 13 | ADD https://plik.root.gg/clients/linux-amd64/plik /usr/bin/plik 14 | 15 | RUN apk add --no-cache --update-cache \ 16 | # Having up to date SSL certificates is always a good thing. :) 17 | ca-certificates \ 18 | openssl \ 19 | python3 \ 20 | && \ 21 | update-ca-certificates && \ 22 | 23 | # Add glibc, wanted by plik (compiled with Go) 24 | wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \ 25 | wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk && \ 26 | apk add glibc-2.23-r3.apk && \ 27 | 28 | # Setup Python 3 29 | python3 -m ensurepip && \ 30 | rm -r /usr/lib/python*/ensurepip && \ 31 | pip3 install --upgrade pip setuptools && \ 32 | rm -r /root/.cache && \ 33 | # Remove openssl, only needed for wget 34 | apk del openssl wget unzip && \ 35 | 36 | # We add an user 37 | adduser -S -u 1000 worker && \ 38 | 39 | # Add default config for Plik, required 40 | chmod o+x /usr/bin/plik && \ 41 | echo 'URL = "https://plik.root.gg"' > /home/worker/.plikrc 42 | 43 | # Install the celery dependency 44 | ADD requirements.txt ${DOCBLEACH_JAR} /app/ 45 | 46 | WORKDIR /app/ 47 | 48 | RUN pip3 install --no-cache-dir -r requirements.txt && \ 49 | chown -R worker /app/; chmod -R 770 /app/ 50 | 51 | USER worker 52 | COPY . /app/ 53 | -------------------------------------------------------------------------------- /autoscale/autoscale2.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import time 4 | 5 | from marathon import MarathonClient 6 | from marathon import MarathonError 7 | from redis import StrictRedis 8 | 9 | dcos_master = os.getenv('DCOS_MASTER') or input("Enter the DNS hostname or IP of your Marathon Instance: ") 10 | userid = os.getenv('MARATHON_USER') or input('Enter the username for the DCOS cluster: ') 11 | password = os.getenv('MARATHON_PWD') or input('Enter the password for the DCOS cluster: ') 12 | marathon_app = os.getenv('APP_NAME') or input("Enter the Marathon Application Name to scale (eg: /worker): ") 13 | redis_uri = os.getenv('REDIS_URI') or input("Enter the Redis URI, including password (eg: redis://localhost:8999/2): ") 14 | max_instances = os.getenv('MAX_INSTANCES') or 10 15 | min_instances = os.getenv('MIN_INSTANCES') or 1 16 | 17 | c = MarathonClient(dcos_master, username=userid, password=password) 18 | r = StrictRedis.from_url(redis_uri) 19 | 20 | while True: 21 | print("Loop!") 22 | app = None 23 | while app is None: 24 | try: 25 | app = c.get_app(marathon_app) 26 | except MarathonError as err: 27 | print(err) 28 | app = None 29 | time.sleep(1) 30 | 31 | waitingDocs = r.llen("celery") 32 | 33 | instances = app.instances 34 | 35 | if waitingDocs == instances: 36 | pass 37 | elif waitingDocs > instances: 38 | instances += 1 39 | else: 40 | instances -= 1 41 | 42 | instances = min(max_instances, max(min_instances, instances)) 43 | print("App instances: ", app.instances, " - New value: ", instances) 44 | if app.instances != instances: 45 | print("Delta: ", (app.instances - instances)) 46 | c.scale_app(marathon_app, instances=instances, force=True) 47 | sys.stdout.flush() 48 | time.sleep(2) 49 | -------------------------------------------------------------------------------- /worker/docbleach/tasks/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | from subprocess import PIPE, Popen 4 | 5 | from celery import Celery 6 | 7 | external_plik_server = os.getenv('FINAL_PLIK_SERVER', 'https://plik.root.gg') 8 | 9 | cel = Celery( 10 | 'docbleach', 11 | broker=os.getenv('CELERY_BROKER'), 12 | backend=os.getenv('CELERY_RESULT_BACKEND') 13 | ) 14 | 15 | cel.config_from_object('docbleach.celeryconfig') 16 | 17 | def get_wget_command(original_uri): 18 | return ['wget', '-qO-', original_uri] 19 | 20 | def get_docbleach_command(): 21 | return ['java', 22 | '-jar', 'docbleach.jar', 23 | '-in', '-', 24 | '-out', '-' 25 | ] 26 | 27 | 28 | def get_plik_command(original_filename): 29 | return ['plik', 30 | '-q', 31 | '--server', external_plik_server, 32 | '-t', '12h', 33 | '-n', original_filename 34 | ] 35 | 36 | 37 | @cel.task(name="sanitize") 38 | def sanitize_task(original_uri, original_filename): 39 | wget_command = get_wget_command(original_uri) 40 | docbleach_command = get_docbleach_command() 41 | plik_command = get_plik_command(original_filename) 42 | 43 | p0 = Popen(wget_command, stdout=PIPE) 44 | p1 = Popen(docbleach_command, stdin=p0.stdout, stdout=PIPE, stderr=PIPE) 45 | p2 = Popen(plik_command, stdin=p1.stdout, stdout=PIPE) 46 | 47 | plik_link, plik_err = p2.communicate() 48 | _, docbleach_output = p1.communicate() 49 | _, _ = p0.communicate() 50 | 51 | # We build a "pretty" output to be displayed 52 | total_output = "" 53 | if docbleach_output: 54 | total_output += docbleach_output.decode('utf-8').strip() 55 | if plik_err: 56 | total_output += "\n" 57 | 58 | if plik_err: 59 | total_output += 'SEVERE ' + plik_err.decode('utf-8').strip() 60 | 61 | if p1.returncode == 0 and p2.returncode == 0: 62 | return { 63 | 'output': total_output, 64 | 'exit_code': 0, 65 | 'final_file': plik_link.decode('utf-8').strip() 66 | } 67 | 68 | # return_code is the first non null exit code 69 | return_code = p1.returncode or p2.returncode 70 | 71 | return { 72 | 'exit_code': return_code, 73 | 'output': total_output 74 | } 75 | 76 | -------------------------------------------------------------------------------- /api/static/js/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f); 8 | if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /api/static/js/respond.min.js: -------------------------------------------------------------------------------- 1 | /*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl 2 | * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT 3 | * */ 4 | 5 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 17 | 23 | 27 | 30 | 34 | 37 | 43 | 61 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | :tada: :+1: *Thanks for reading this \o/ You're already helping us!* :tada: 4 | 5 | 6 | DocBleach is a young project, but contributing means a lot of different things. 7 | Providing feedback on a feature, reporting bugs or even fixing typos in the code are contributions. 8 | Knowing how to code is great, but not a requirement. 9 | 10 | When contributing to this repository, please first discuss the change you wish to make via issue, 11 | email, or any other method with the owners of this repository before making a change. 12 | 13 | Please note we have a code of conduct, please follow it in all your interactions with the project. 14 | 15 | 16 | ## Pull Request Process 17 | 18 | 1. Relax, take your time and be fearless. The PR Process is there to ensure the project moves in one 19 | direction, not to challenge you ;-) 20 | 2. Ensure your code works. 21 | 3. Match the existing code style (PEP 8 for Python files). 22 | 4. Send the PR on GitHub \o/ 23 | 24 | 25 | 26 | ## Code of Conduct 27 | 28 | ### Our Pledge 29 | 30 | In the interest of fostering an open and welcoming environment, we as 31 | contributors and maintainers pledge to making participation in our project and 32 | our community a harassment-free experience for everyone, regardless of age, body 33 | size, disability, ethnicity, gender identity and expression, level of experience, 34 | nationality, personal appearance, race, religion, or sexual identity and 35 | orientation. 36 | 37 | ### Our Standards 38 | 39 | Examples of behavior that contributes to creating a positive environment 40 | include: 41 | 42 | * Using welcoming and inclusive language 43 | * Being respectful of differing viewpoints and experiences 44 | * Gracefully accepting constructive criticism 45 | * Focusing on what is best for the community 46 | * Showing empathy towards other community members 47 | 48 | Examples of unacceptable behavior by participants include: 49 | 50 | * The use of sexualized language or imagery and unwelcome sexual attention or 51 | advances 52 | * Trolling, insulting/derogatory comments, and personal or political attacks 53 | * Public or private harassment 54 | * Publishing others' private information, such as a physical or electronic 55 | address, without explicit permission 56 | * Other conduct which could reasonably be considered inappropriate in a 57 | professional setting 58 | 59 | ### Our Responsibilities 60 | 61 | Project maintainers are responsible for clarifying the standards of acceptable 62 | behavior and are expected to take appropriate and fair corrective action in 63 | response to any instances of unacceptable behavior. 64 | 65 | Project maintainers have the right and responsibility to remove, edit, or 66 | reject comments, commits, code, wiki edits, issues, and other contributions 67 | that are not aligned to this Code of Conduct, or to ban temporarily or 68 | permanently any contributor for other behaviors that they deem inappropriate, 69 | threatening, offensive, or harmful. 70 | 71 | ### Scope 72 | 73 | This Code of Conduct applies both within project spaces and in public spaces 74 | when an individual is representing the project or its community. Examples of 75 | representing a project or community include using an official project e-mail 76 | address, posting via an official social media account, or acting as an appointed 77 | representative at an online or offline event. Representation of a project may be 78 | further defined and clarified by project maintainers. 79 | 80 | ### Enforcement 81 | 82 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 83 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 84 | complaints will be reviewed and investigated and will result in a response that 85 | is deemed necessary and appropriate to the circumstances. The project team is 86 | obligated to maintain confidentiality with regard to the reporter of an incident. 87 | Further details of specific enforcement policies may be posted separately. 88 | 89 | Project maintainers who do not follow or enforce the Code of Conduct in good 90 | faith may face temporary or permanent repercussions as determined by other 91 | members of the project's leadership. 92 | 93 | ### Attribution 94 | 95 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 96 | available at [http://contributor-covenant.org/version/1/4][version]. 97 | 98 | [homepage]: http://contributor-covenant.org 99 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /api/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | DocBleach 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 68 | 69 | 70 |
71 |
72 |
73 |

DocBleach

74 |

Sanitizes a potentially dangerous file (Office Document, PDF), by removing macros and other active contents.

75 |
76 |
77 | 78 |
79 |
80 |

Friendly reminder: do NOT post sensitive documents here, unless you trust this page owner.

81 |
82 |
83 | 84 |
85 |
86 |

Sanitize a file

87 |
88 | 89 | 92 | 93 |
94 |
95 |
96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /api/static/js/docbleach.js: -------------------------------------------------------------------------------- 1 | document.body.classList.add('js'); 2 | var docbleach_endpoint = "/v1/"; 3 | 4 | (function () { 5 | var formElement = document.querySelector("form#uploadForm"); 6 | var labelElement = document.querySelector("form#uploadForm label span"); 7 | var inputElement = document.querySelector("input#file"); 8 | 9 | if (window.FileReader) { 10 | addEventHandler(labelElement, 'dragover', function (e) { 11 | e.preventDefault(); 12 | }); 13 | 14 | addEventHandler(labelElement, 'dragleave', function (e) { 15 | e.preventDefault(); 16 | }); 17 | 18 | addEventHandler(labelElement, 'drop', function (e) { 19 | e = e || window.event; // get window.event if e argument missing (in IE) 20 | e.preventDefault(); 21 | 22 | var dt = e.dataTransfer; 23 | var files = dt.files; 24 | for (var i = 0; i < files.length; i++) { 25 | var file = files[i]; 26 | 27 | var formData = new FormData(); 28 | formData.append("file", file); 29 | convertFile(formData); 30 | } 31 | return false; 32 | }); 33 | } 34 | 35 | addEventHandler(inputElement, "change", function (e) { 36 | convertFile(new FormData(formElement)); 37 | }, false); 38 | 39 | function addEventHandler(obj, evt, handler) { 40 | if (obj === null) { 41 | return; 42 | } 43 | if (obj.addEventListener) { 44 | // W3C method 45 | obj.addEventListener(evt, handler, false); 46 | } else if (obj.attachEvent) { 47 | // IE method. 48 | obj.attachEvent('on' + evt, handler); 49 | } else { 50 | // Old school method. 51 | obj['on' + evt] = handler; 52 | } 53 | } 54 | 55 | function convertFile(formData) { 56 | swal({ 57 | title: "Uploading file", 58 | text: "...", 59 | type: "info", 60 | allowOutsideClick: false, 61 | allowEscapeKey: false 62 | }); 63 | swal.showLoading(); 64 | $.ajax({ 65 | type: "POST", 66 | url: docbleach_endpoint + "tasks", 67 | data: formData, 68 | processData: false, 69 | contentType: false, 70 | success: function (data) { 71 | swal({ 72 | title: "Sanitizing file", 73 | text: "...", 74 | type: "info", 75 | allowOutsideClick: false, 76 | allowEscapeKey: false 77 | }); 78 | swal.showLoading(); 79 | var task_id = data["task_id"]; 80 | console.log("Got a task id: " + task_id); 81 | setTimeout(function () { 82 | checkFileStatus(task_id); 83 | }, 250); 84 | } 85 | }); 86 | } 87 | 88 | function checkFileStatus(task_id) { 89 | $.ajax({ 90 | type: "GET", 91 | url: docbleach_endpoint + "tasks/" + task_id, 92 | success: function (data) { 93 | console.log(data); 94 | console.log("Got a task id state: " + task_id); 95 | if (data.status === "PENDING") { 96 | setTimeout(function () { 97 | checkFileStatus(task_id); 98 | }, 250); 99 | return; 100 | } 101 | displayResponse( 102 | {infos: [data.result.output], link: data.result.final_file}); 103 | } 104 | }); 105 | } 106 | })(); 107 | 108 | function displayResponse(response) { 109 | if (response.errors && response.errors.join) { 110 | console.log(response.errors); 111 | swal("An error occured", "", "error"); 112 | return; 113 | } 114 | if (response.infos && response.infos.join) { 115 | var htmlCode = parseDocbleach(response.infos.join("\n")); 116 | 117 | var modalData = { 118 | title: "Results", 119 | html: htmlCode, 120 | type: "success", 121 | allowOutsideClick: true, 122 | confirmButtonColor: "#73B6D6", 123 | width: "60%" 124 | }; 125 | if (response.link) { 126 | modalData["confirmButtonText"] = "Download the sanitized file"; 127 | } else { 128 | modalData["timer"] = 2000; 129 | } 130 | swal.hideLoading(); 131 | swal(modalData).then(function () { 132 | if (response.link) { 133 | download(response.link); 134 | } 135 | }); 136 | } else if (response.link) { 137 | download(response.link); 138 | swal.hideLoading(); 139 | swal({ 140 | text: "Download started", 141 | type: "success", 142 | timer: 2000 143 | }); 144 | } 145 | } 146 | 147 | function parseDocbleach(infos) { 148 | var parent = document.createElement("div"); 149 | var lines = infos.split(/\r?\n/); // Allow multiple lines per blob 150 | 151 | lines.forEach(function (line) { 152 | var child = document.createElement("p"); 153 | 154 | if (line.indexOf("WARN ") === 0) { 155 | child.classList.add("docbleach_warning"); 156 | line = line.substring("WARN ".length); 157 | } else if (line.indexOf("INFO ") === 0) { 158 | child.classList.add("docbleach_info"); 159 | line = line.substring("INFO ".length); 160 | } else if (line.indexOf("ERROR ") === 0) { 161 | child.classList.add("docbleach_severe"); 162 | line = line.substring("ERROR ".length); 163 | } else if (line.indexOf("FATAL ") === 0) { 164 | child.classList.add("docbleach_severe"); 165 | line = line.substring("FATAL ".length); 166 | } 167 | child.innerText = line; 168 | parent.appendChild(child); 169 | }); 170 | return parent.innerHTML; 171 | } 172 | 173 | function download(link) { 174 | var anchor = document.createElement('a'); 175 | anchor.href = link; 176 | // anchor.target = '_blank'; 177 | anchor.setAttribute("download", ""); 178 | document.body.appendChild(anchor); 179 | anchor.click(); 180 | } 181 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DocBleach aaS - Sanitize your documents in the cloud™ 2 | 3 | [DocBleach][github] allows you to sanitize your Word, Excel, PowerPoint, PDF, ... documents. This repository contains the 4 | DocBleach Web API, packaged as a docker service. Two clicks and you'll feel safer. 5 | 6 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/d44e774ed4df461a97e86e96f6b802c9)](https://www.codacy.com/app/DocBleach/DocBleach-Web?utm_source=github.com&utm_medium=referral&utm_content=docbleach/DocBleach-Web&utm_campaign=Badge_Grade) 7 | 8 | You have files to sanitize but you can't install Java, may it be because you run on an embedded system or you deploy 9 | your PHP app on a shared hosting and Java is not available ... This package is the solution to your issues! 10 | 11 | # Installation 12 | 13 | Three modules are present in this repository: 14 | - *api* 15 | contains the Web API, a lightweight Python Flask app that 16 | receives the files and responds to status requests. 17 | - *worker* contains DocBleach and launches it using Python Celery. 18 | - *autoscale* auto-scaling for Mesos Marathon, documentation still has to be written. 19 | 20 | Thanks to Docker, you are able to easily deploy this app. 21 | 22 | Celery requires a message broker and a backend to store its results. 23 | Using something as easy to setup as Redis is fine, as it is able to serve 24 | both roles, but you may use [another broker][1] or another [backend storage][backend_celery]. 25 | 26 | Configuration is given to each component thru environment variables, 27 | namely `CELERY_BROKER` and `CELERY_RESULT_BACKEND`. They accept URI as 28 | valid values, for instance to use a local Redis server protected by the 29 | password `PASS123` you would use this: 30 | `CELERY_BROKER=redis://:PASS123@127.0.0.1/`. 31 | 32 | In order to pass the files from the API to the Worker, a storage backend is required. 33 | Plik is used, because it is easy to setup (unlike OpenStack/AWS), Open-Source and supports `expire` out of the box. 34 | 35 | By default using Docker Compose, an internal Plik instance is started and the sanitized files are stored on plik.root.gg 36 | 37 | You may change this using the `INTERNAL_PLIK_SERVER` and `FINAL_PLIK_SERVER` env variables. 38 | 39 | # Howto's 40 | To run the containers using Docker Compose, just call `docker-compose up -d` in this project's directory. 41 | Docker will take care of the boring stuff for you! :) 42 | ```bash 43 | $ docbleach-rest$ docker-compose up -d 44 | Starting docbleachrest_worker_1 45 | Starting docbleachrest_plik_1 46 | Starting docbleachrest_web_1 47 | Starting docbleachrest_redis_1 48 | $ docker ps 49 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 50 | 5d258cfac1d6 docbleach/api:latest "/usr/src/app/entrypo" About a minute ago Up 41 seconds 0.0.0.0:9000->5000/tcp docbleachrest_web_1 51 | 5c3d91acba01 docbleach/worker:latest "/usr/src/app/entrypo" About a minute ago Up 41 seconds docbleachrest_worker_1 52 | ebcef5f636d5 rootgg/plik "/bin/sh -c ./plikd" 9 days ago Up 41 seconds 8080/tcp docbleachrest_plik_1 53 | eb69034e73f5 redis "docker-entrypoint.sh" 10 days ago Up 41 seconds 6379/tcp docbleachrest_redis_1 54 | ``` 55 | 56 | As you can see, DocBleach-api is running on your port `5000`. 57 | Just open `127.0.0.1:5000` in your browser to try it out :wink:. 58 | 59 | 60 | ## Get the sources 61 | 62 | ```bash 63 | git clone https://github.com/docbleach/DocBleach-Web.git 64 | cd DocBleach-Web 65 | ``` 66 | 67 | A `Dockerfile` makes it easy to hack on a part of this project. 68 | 69 | You've developed a new cool feature ? Fixed an annoying bug ? We'd be happy 70 | to hear from you ! 71 | 72 | 73 | Documentation uses [Swagger][swagger], and thus is rendered client-side using the specifications in 74 | `api/static/swagger.yaml`. 75 | 76 | # How to Sanitize 77 | 78 | to start sanitizing your file, click on the "pick a file" button 79 | ![click here](docs/clickhere.png) 80 | then choose the file you want to sanitize 81 | ![click here](docs/Chooseafile.png) 82 | Finaly, click "Download the sanitized file" to get your file back 83 | ![click here](docs/downloadyourfile.png) 84 | 85 | # Related links 86 | 87 | * Contribute: https://github.com/docbleach/DocBleach-Web 88 | * Report bugs: https://github.com/docbleach/DocBleach-Web/issues 89 | * Get latest version: https://hub.docker.com/u/docbleach/ 90 | 91 | # License 92 | 93 | See https://github.com/docbleach/DocBleach-Web/blob/master/LICENSE 94 | 95 | # Project status 96 | 97 | This project works, but would be greatly improved with little tweaks. 98 | 99 | For instance, it would be really great to: 100 | - Write more documentation, because there's never enough of it. :-( 101 | - Have an improved design. 102 | - Improve the API once the [code base is rewamped](issue_codebase), to give an extended output, allow configuration... 103 | - Remove dependencies, having Java and Python code in a docker file is a bad practice. For now, it works. 104 | 105 | 106 | 107 | [1]: http://docs.celeryproject.org/en/latest/getting-started/brokers/ 108 | [backend_celery]: http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html#keeping-results 109 | [swagger]: https://swagger.io/ 110 | [github]: https://github.com/docbleach/DocBleach 111 | [logo_link]: https://github.com/docbleach/DocBleach/404 112 | [issue_codebase]: https://github.com/docbleach/DocBleach/issues/2 113 | -------------------------------------------------------------------------------- /api/static/css/sweetalert2.min.css: -------------------------------------------------------------------------------- 1 | .swal2-container,body.swal2-iosfix{position:fixed;left:0;right:0}body.swal2-in{overflow-y:hidden}.swal2-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;top:0;bottom:0;padding:10px;background-color:transparent;z-index:1060}.swal2-container:not(.swal2-in){pointer-events:none}.swal2-container.swal2-fade{-webkit-transition:background-color .1s;transition:background-color .1s}.swal2-container.swal2-in{background-color:rgba(0,0,0,.4)}.swal2-modal{background-color:#fff;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;border-radius:5px;box-sizing:border-box;text-align:center;margin:auto;overflow-x:hidden;overflow-y:auto;display:none;position:relative}.swal2-modal:focus{outline:0}.swal2-modal.swal2-loading{overflow-y:hidden}.swal2-modal .swal2-title{color:#595959;font-size:30px;text-align:center;font-weight:600;text-transform:none;position:relative;margin:0;padding:0;line-height:60px;display:block}.swal2-modal .swal2-spacer{height:10px;color:transparent;border:0}.swal2-modal .swal2-styled{border:0;border-radius:3px;box-shadow:none;color:#fff;cursor:pointer;font-size:17px;font-weight:500;margin:0 5px;padding:10px 32px}.swal2-modal .swal2-styled:not(.swal2-loading)[disabled]{opacity:.4;cursor:no-drop}.swal2-modal .swal2-styled.swal2-loading{box-sizing:border-box;border:4px solid transparent;width:40px;height:40px;padding:0;margin:-2px 30px;vertical-align:top;background-color:transparent!important;color:transparent;cursor:default;border-radius:100%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-modal :not(.swal2-styled).swal2-loading::after{display:inline-block;content:'';margin-left:5px;vertical-align:-1px;height:6px;width:6px;border:3px solid #999;border-right-color:transparent;border-radius:50%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal}.swal2-modal .swal2-checkbox input,.swal2-modal .swal2-checkbox span,.swal2-modal .swal2-radio input,.swal2-modal .swal2-radio span{vertical-align:middle}.swal2-modal .swal2-image{margin:20px auto;max-width:100%}.swal2-modal .swal2-close{font-size:36px;line-height:36px;font-family:serif;position:absolute;top:5px;right:13px;cursor:pointer;color:#ccc;-webkit-transition:color .1s ease;transition:color .1s ease}.swal2-modal .swal2-close:hover{color:#d55}.swal2-modal>.swal2-checkbox,.swal2-modal>.swal2-file,.swal2-modal>.swal2-input,.swal2-modal>.swal2-radio,.swal2-modal>.swal2-select,.swal2-modal>.swal2-textarea{display:none}.swal2-modal .swal2-content{font-size:18px;text-align:center;font-weight:300;position:relative;float:none;margin:0;padding:0;line-height:normal;color:#545454}.swal2-modal .swal2-checkbox,.swal2-modal .swal2-file,.swal2-modal .swal2-input,.swal2-modal .swal2-radio,.swal2-modal .swal2-select,.swal2-modal .swal2-textarea{margin:20px auto}.swal2-modal .swal2-file,.swal2-modal .swal2-input,.swal2-modal .swal2-textarea{width:100%;box-sizing:border-box;border-radius:3px;border:1px solid #d9d9d9;font-size:18px;box-shadow:inset 0 1px 1px rgba(0,0,0,.06);-webkit-transition:border-color box-shadow .3s;transition:border-color box-shadow .3s}.swal2-modal .swal2-file.swal2-inputerror,.swal2-modal .swal2-input.swal2-inputerror,.swal2-modal .swal2-textarea.swal2-inputerror{border-color:#f06e57}.swal2-modal .swal2-file:focus,.swal2-modal .swal2-input:focus,.swal2-modal .swal2-textarea:focus{outline:0;box-shadow:0 0 3px #c4e6f5;border:1px solid #b4dbed}.swal2-modal .swal2-file:focus::-webkit-input-placeholder,.swal2-modal .swal2-input:focus::-webkit-input-placeholder,.swal2-modal .swal2-textarea:focus::-webkit-input-placeholder{-webkit-transition:opacity .3s .03s ease;transition:opacity .3s .03s ease;opacity:.8}.swal2-modal .swal2-file:focus::-moz-placeholder,.swal2-modal .swal2-input:focus::-moz-placeholder,.swal2-modal .swal2-textarea:focus::-moz-placeholder{-webkit-transition:opacity .3s .03s ease;transition:opacity .3s .03s ease;opacity:.8}.swal2-modal .swal2-file:focus:-ms-input-placeholder,.swal2-modal .swal2-input:focus:-ms-input-placeholder,.swal2-modal .swal2-textarea:focus:-ms-input-placeholder{-webkit-transition:opacity .3s .03s ease;transition:opacity .3s .03s ease;opacity:.8}.swal2-modal .swal2-file:focus::placeholder,.swal2-modal .swal2-input:focus::placeholder,.swal2-modal .swal2-textarea:focus::placeholder{-webkit-transition:opacity .3s .03s ease;transition:opacity .3s .03s ease;opacity:.8}.swal2-modal .swal2-file::-webkit-input-placeholder,.swal2-modal .swal2-input::-webkit-input-placeholder,.swal2-modal .swal2-textarea::-webkit-input-placeholder{color:#e6e6e6}.swal2-modal .swal2-file::-moz-placeholder,.swal2-modal .swal2-input::-moz-placeholder,.swal2-modal .swal2-textarea::-moz-placeholder{color:#e6e6e6}.swal2-modal .swal2-file:-ms-input-placeholder,.swal2-modal .swal2-input:-ms-input-placeholder,.swal2-modal .swal2-textarea:-ms-input-placeholder{color:#e6e6e6}.swal2-modal .swal2-file::placeholder,.swal2-modal .swal2-input::placeholder,.swal2-modal .swal2-textarea::placeholder{color:#e6e6e6}.swal2-modal .swal2-range input{float:left;width:80%}.swal2-modal .swal2-range output{float:right;width:20%;font-size:20px;font-weight:600;text-align:center}.swal2-modal .swal2-range input,.swal2-modal .swal2-range output{height:43px;line-height:43px;vertical-align:middle;margin:20px auto;padding:0}.swal2-modal .swal2-input{height:43px;padding:0 12px}.swal2-modal .swal2-input[type=number]{max-width:150px}.swal2-modal .swal2-file{font-size:20px}.swal2-modal .swal2-textarea{height:108px;padding:12px}.swal2-modal .swal2-select{color:#545454;font-size:inherit;padding:5px 10px;min-width:40%;max-width:100%}.swal2-modal .swal2-radio{border:0}.swal2-modal .swal2-radio label:not(:first-child){margin-left:20px}.swal2-modal .swal2-radio input{margin:0 3px 0 0}.swal2-modal .swal2-checkbox{color:#545454}.swal2-modal .swal2-validationerror{background-color:#f0f0f0;margin:0 -20px;overflow:hidden;padding:10px;color:gray;font-size:16px;font-weight:300;display:none}.swal2-modal .swal2-validationerror::before{content:'!';display:inline-block;width:24px;height:24px;border-radius:50%;background-color:#ea7d7d;color:#fff;line-height:24px;text-align:center;margin-right:10px}.swal2-icon.swal2-info,.swal2-icon.swal2-question,.swal2-icon.swal2-warning{font-size:60px;line-height:80px;text-align:center}@supports (-ms-accelerator:true){.swal2-range input{width:100%!important}.swal2-range output{display:none}}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){.swal2-range input{width:100%!important}.swal2-range output{display:none}}.swal2-icon{width:80px;height:80px;border:4px solid transparent;border-radius:50%;margin:20px auto 30px;padding:0;position:relative;box-sizing:content-box;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-icon.swal2-error{border-color:#f27474}.swal2-icon.swal2-error .x-mark{position:relative;display:block}.swal2-icon.swal2-error .line{position:absolute;height:5px;width:47px;background-color:#f27474;display:block;top:37px;border-radius:2px}.swal2-icon.swal2-error .line.left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.swal2-icon.swal2-error .line.right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}.swal2-icon.swal2-warning{font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#f8bb86;border-color:#facea8}.swal2-icon.swal2-info{font-family:'Open Sans',sans-serif;color:#3fc3ee;border-color:#9de0f6}.swal2-icon.swal2-question{font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#87adbd;border-color:#c9dae1}.swal2-icon.swal2-success{border-color:#a5dc86}.swal2-icon.swal2-success::after,.swal2-icon.swal2-success::before{content:'';position:absolute;width:60px;height:120px;background:#fff}.swal2-icon.swal2-success::before{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.swal2-icon.swal2-success::after{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px}.swal2-icon.swal2-success .placeholder{width:80px;height:80px;border:4px solid rgba(165,220,134,.2);border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.swal2-icon.swal2-success .fix{width:7px;height:90px;background-color:#fff;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-icon.swal2-success .line{height:5px;background-color:#a5dc86;display:block;border-radius:2px;position:absolute;z-index:2}.swal2-icon.swal2-success .line.tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swal2-icon.swal2-success .line.long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-progresssteps{font-weight:600;margin:0 0 20px;padding:0}.swal2-progresssteps li{display:inline-block;position:relative}.swal2-progresssteps .swal2-progresscircle{background:#3085d6;border-radius:2em;color:#fff;height:2em;line-height:2em;text-align:center;width:2em;z-index:20}.swal2-progresssteps .swal2-progresscircle:first-child{margin-left:0}.swal2-progresssteps .swal2-progresscircle:last-child{margin-right:0}.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep{background:#3085d6}.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep~.swal2-progresscircle,.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep~.swal2-progressline{background:#add8e6}.swal2-progresssteps .swal2-progressline{background:#3085d6;height:.4em;margin:0 -1px;z-index:10}[class^=swal2]{-webkit-tap-highlight-color:transparent}@-webkit-keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}@keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}.swal2-show{-webkit-animation:showSweetAlert .3s;animation:showSweetAlert .3s}.swal2-show.swal2-noanimation{-webkit-animation:none;animation:none}.swal2-hide{-webkit-animation:hideSweetAlert .15s forwards;animation:hideSweetAlert .15s forwards}.swal2-hide.swal2-noanimation{-webkit-animation:none;animation:none}@-webkit-keyframes animate-success-tip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@keyframes animate-success-tip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@-webkit-keyframes animate-success-long{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@keyframes animate-success-long{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@-webkit-keyframes rotatePlaceholder{0%,5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}100%,12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@keyframes rotatePlaceholder{0%,5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}100%,12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}.animate-success-tip{-webkit-animation:animate-success-tip .75s;animation:animate-success-tip .75s}.animate-success-long{-webkit-animation:animate-success-long .75s;animation:animate-success-long .75s}.swal2-success.animate::after{-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in}@-webkit-keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}@keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}.animate-error-icon{-webkit-animation:animate-error-icon .5s;animation:animate-error-icon .5s}@-webkit-keyframes animate-x-mark{0%,50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}@keyframes animate-x-mark{0%,50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}.animate-x-mark{-webkit-animation:animate-x-mark .5s;animation:animate-x-mark .5s}@-webkit-keyframes pulse-warning{0%{border-color:#f8d486}100%{border-color:#f8bb86}}@keyframes pulse-warning{0%{border-color:#f8d486}100%{border-color:#f8bb86}}.pulse-warning{-webkit-animation:pulse-warning .75s infinite alternate;animation:pulse-warning .75s infinite alternate}@-webkit-keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}} -------------------------------------------------------------------------------- /api/static/js/sweetalert2.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Sweetalert2=t()}(this,function(){"use strict";var e="swal2-",t=function(t){var n={};for(var o in t)n[t[o]]=e+t[o];return n},n=t(["container","in","iosfix","modal","overlay","fade","show","hide","noanimation","close","title","content","spacer","confirm","cancel","icon","image","input","file","range","select","radio","checkbox","textarea","inputerror","validationerror","progresssteps","activeprogressstep","progresscircle","progressline","loading","styled"]),o=t(["success","warning","info","question","error"]),r={title:"",text:"",html:"",type:null,customClass:"",animation:!0,allowOutsideClick:!0,allowEscapeKey:!0,showConfirmButton:!0,showCancelButton:!1,preConfirm:null,confirmButtonText:"OK",confirmButtonColor:"#3085d6",confirmButtonClass:null,cancelButtonText:"Cancel",cancelButtonColor:"#aaa",cancelButtonClass:null,buttonsStyling:!0,reverseButtons:!1,focusCancel:!1,showCloseButton:!1,showLoaderOnConfirm:!1,imageUrl:null,imageWidth:null,imageHeight:null,imageClass:null,timer:null,width:500,padding:20,background:"#fff",input:null,inputPlaceholder:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputClass:null,inputAttributes:{},inputValidator:null,progressSteps:[],currentProgressStep:null,progressStepsDistance:"40px",onOpen:null,onClose:null},i=('\n \n').replace(/(^|\n)\s*/g,""),a=void 0,l=document.getElementsByClassName(n.container);l.length?a=l[0]:(a=document.createElement("div"),a.className=n.container,a.innerHTML=i);var s=function(e,t){e=String(e).replace(/[^0-9a-f]/gi,""),e.length<6&&(e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]),t=t||0;for(var n="#",o=0;o<3;o++){var r=parseInt(e.substr(2*o,2),16);r=Math.round(Math.min(Math.max(0,r+r*t),255)).toString(16),n+=("00"+r).substr(r.length)}return n},c={previousWindowKeyDown:null,previousActiveElement:null,previousBodyPadding:null},u=function(){if("undefined"==typeof document)return void console.error("SweetAlert2 requires document to initialize");if(!document.getElementsByClassName(n.container).length){document.body.appendChild(a);var e=p(),t=P(e,n.input),o=P(e,n.file),r=e.querySelector("."+n.range+" input"),i=e.querySelector("."+n.range+" output"),l=P(e,n.select),s=e.querySelector("."+n.checkbox+" input"),c=P(e,n.textarea);return t.oninput=function(){F.resetValidationError()},t.onkeydown=function(e){setTimeout(function(){13===e.keyCode&&(e.stopPropagation(),F.clickConfirm())},0)},o.onchange=function(){F.resetValidationError()},r.oninput=function(){F.resetValidationError(),i.value=r.value},r.onchange=function(){F.resetValidationError(),r.previousSibling.value=r.value},l.onchange=function(){F.resetValidationError()},s.onchange=function(){F.resetValidationError()},c.oninput=function(){F.resetValidationError()},e}},d=function(e){return a.querySelector("."+e)},p=function(){return document.body.querySelector("."+n.modal)||u()},f=function(){var e=p();return e.querySelectorAll("."+n.icon)},m=function(){return d(n.title)},v=function(){return d(n.content)},h=function(){return d(n.image)},y=function(){return d(n.spacer)},g=function(){return d(n.progresssteps)},b=function(){return d(n.validationerror)},w=function(){return d(n.confirm)},C=function(){return d(n.cancel)},k=function(){return d(n.close)},S=function(t){var n=[w(),C()];return t&&n.reverse(),n.concat(Array.prototype.slice.call(p().querySelectorAll("button:not([class^="+e+"]), input:not([type=hidden]), textarea, select")))},x=function(e,t){return!!e.classList&&e.classList.contains(t)},E=function(e){if(e.focus(),"file"!==e.type){var t=e.value;e.value="",e.value=t}},A=function(e,t){if(e&&t){var n=t.split(/\s+/).filter(Boolean);n.forEach(function(t){e.classList.add(t)})}},B=function(e,t){if(e&&t){var n=t.split(/\s+/).filter(Boolean);n.forEach(function(t){e.classList.remove(t)})}},P=function(e,t){for(var n=0;n"),e.text||e.html){if("object"===D(e.html))if(l.innerHTML="",0 in e.html)for(var d=0;d in e.html;d++)l.appendChild(e.html[d].cloneNode(!0));else l.appendChild(e.html.cloneNode(!0));else e.html?l.innerHTML=e.html:e.text&&(l.innerHTML=(""+e.text).split("\n").join("
"));L(l)}else q(l);e.showCloseButton?L(u):q(u),t.className=n.modal,e.customClass&&A(t,e.customClass);var b=g(),S=parseInt(null===e.currentProgressStep?F.getQueueStep():e.currentProgressStep,10);e.progressSteps.length?(L(b),M(b),S>=e.progressSteps.length&&console.warn("SweetAlert2: Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),e.progressSteps.forEach(function(t,o){var r=document.createElement("li");if(A(r,n.progresscircle),r.innerHTML=t,o===S&&A(r,n.activeprogressstep),b.appendChild(r),o!==e.progressSteps.length-1){var i=document.createElement("li");A(i,n.progressline),i.style.width=e.progressStepsDistance,b.appendChild(i)}})):q(b);for(var x=f(),E=0;Ewindow.innerHeight&&(c.previousBodyPadding=document.body.style.paddingRight,document.body.style.paddingRight=j()+"px")},Y=function(){null!==c.previousBodyPadding&&(document.body.style.paddingRight=c.previousBodyPadding,c.previousBodyPadding=null)},Z=function(){var e=/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream;if(e&&!x(document.body,n.iosfix)){var t=document.body.scrollTop;document.body.style.top=t*-1+"px",A(document.body,n.iosfix)}},J=function(){if(x(document.body,n.iosfix)){var e=parseInt(document.body.style.top,10);B(document.body,n.iosfix),document.body.style.top="",document.body.scrollTop=e*-1}},$=function(){for(var e=arguments.length,t=Array(e),o=0;olabel{font-size:12px;font-weight:700;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:-20px 15px 0 0;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .scheme-container .schemes>label select{min-width:130px;text-transform:uppercase}.swagger-ui .loading-container{padding:40px 0 60px}.swagger-ui .loading-container .loading{position:relative}.swagger-ui .loading-container .loading:after{font-size:10px;font-weight:700;position:absolute;top:50%;left:50%;content:"loading";-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-transform:uppercase;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .loading-container .loading:before{position:absolute;top:50%;left:50%;display:block;width:60px;height:60px;margin:-30px;content:"";-webkit-animation:rotation 1s infinite linear,opacity .5s;animation:rotation 1s infinite linear,opacity .5s;opacity:1;border:2px solid rgba(85,85,85,.1);border-top-color:rgba(0,0,0,.6);border-radius:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden}@-webkit-keyframes rotation{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotation{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes blinker{50%{opacity:0}}@keyframes blinker{50%{opacity:0}}.swagger-ui .btn{font-size:14px;font-weight:700;padding:5px 23px;-webkit-transition:all .3s;transition:all .3s;border:2px solid #888;border-radius:4px;background:transparent;box-shadow:0 1px 2px rgba(0,0,0,.1);font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .btn[disabled]{cursor:not-allowed;opacity:.3}.swagger-ui .btn:hover{box-shadow:0 0 5px rgba(0,0,0,.3)}.swagger-ui .btn.cancel{border-color:#ff6060;font-family:Titillium Web,sans-serif;color:#ff6060}.swagger-ui .btn.authorize{line-height:1;display:inline;color:#49cc90;border-color:#49cc90}.swagger-ui .btn.authorize span{float:left;padding:4px 20px 0 0}.swagger-ui .btn.authorize svg{fill:#49cc90}.swagger-ui .btn.execute{-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite;color:#fff;border-color:#4990e2}@-webkit-keyframes pulse{0%{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,.8)}70%{box-shadow:0 0 0 5px rgba(73,144,226,0)}to{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,0)}}@keyframes pulse{0%{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,.8)}70%{box-shadow:0 0 0 5px rgba(73,144,226,0)}to{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,0)}}.swagger-ui .btn-group{display:-webkit-box;display:-ms-flexbox;display:flex;padding:30px}.swagger-ui .btn-group .btn{-webkit-box-flex:1;-ms-flex:1;flex:1}.swagger-ui .btn-group .btn:first-child{border-radius:4px 0 0 4px}.swagger-ui .btn-group .btn:last-child{border-radius:0 4px 4px 0}.swagger-ui .authorization__btn{padding:0 10px;border:none;background:none}.swagger-ui .authorization__btn.locked{opacity:1}.swagger-ui .authorization__btn.unlocked{opacity:.4}.swagger-ui .expand-methods,.swagger-ui .expand-operation{border:none;background:none}.swagger-ui .expand-methods svg,.swagger-ui .expand-operation svg{width:20px;height:20px}.swagger-ui .expand-methods{padding:0 10px}.swagger-ui .expand-methods:hover svg{fill:#444}.swagger-ui .expand-methods svg{-webkit-transition:all .3s;transition:all .3s;fill:#777}.swagger-ui button{cursor:pointer;outline:none}.swagger-ui select{font-size:14px;font-weight:700;padding:5px 40px 5px 10px;border:2px solid #41444e;border-radius:4px;background:#f7f7f7 url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+ICAgIDxwYXRoIGQ9Ik0xMy40MTggNy44NTljLjI3MS0uMjY4LjcwOS0uMjY4Ljk3OCAwIC4yNy4yNjguMjcyLjcwMSAwIC45NjlsLTMuOTA4IDMuODNjLS4yNy4yNjgtLjcwNy4yNjgtLjk3OSAwbC0zLjkwOC0zLjgzYy0uMjctLjI2Ny0uMjctLjcwMSAwLS45NjkuMjcxLS4yNjguNzA5LS4yNjguOTc4IDBMMTAgMTFsMy40MTgtMy4xNDF6Ii8+PC9zdmc+) right 10px center no-repeat;background-size:20px;box-shadow:0 1px 2px 0 rgba(0,0,0,.25);font-family:Titillium Web,sans-serif;color:#3b4151;-webkit-appearance:none;-moz-appearance:none;appearance:none}.swagger-ui select[multiple]{margin:5px 0;padding:5px;background:#f7f7f7}.swagger-ui .opblock-body select{min-width:230px}.swagger-ui label{font-size:12px;font-weight:700;margin:0 0 5px;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui input[type=email],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text]{min-width:100px;margin:5px 0;padding:8px 10px;border:1px solid #d9d9d9;border-radius:4px;background:#fff}.swagger-ui input[type=email].invalid,.swagger-ui input[type=password].invalid,.swagger-ui input[type=search].invalid,.swagger-ui input[type=text].invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;border-color:#f93e3e;background:#feebeb}@-webkit-keyframes shake{10%,90%{-webkit-transform:translate3d(-1px,0,0);transform:translate3d(-1px,0,0)}20%,80%{-webkit-transform:translate3d(2px,0,0);transform:translate3d(2px,0,0)}30%,50%,70%{-webkit-transform:translate3d(-4px,0,0);transform:translate3d(-4px,0,0)}40%,60%{-webkit-transform:translate3d(4px,0,0);transform:translate3d(4px,0,0)}}@keyframes shake{10%,90%{-webkit-transform:translate3d(-1px,0,0);transform:translate3d(-1px,0,0)}20%,80%{-webkit-transform:translate3d(2px,0,0);transform:translate3d(2px,0,0)}30%,50%,70%{-webkit-transform:translate3d(-4px,0,0);transform:translate3d(-4px,0,0)}40%,60%{-webkit-transform:translate3d(4px,0,0);transform:translate3d(4px,0,0)}}.swagger-ui textarea{font-size:12px;width:100%;min-height:280px;padding:10px;border:none;border-radius:4px;outline:none;background:hsla(0,0%,100%,.8);font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui textarea:focus{border:2px solid #61affe}.swagger-ui textarea.curl{font-size:12px;min-height:100px;margin:0;padding:10px;resize:none;border-radius:4px;background:#41444e;font-family:Source Code Pro,monospace;font-weight:600;color:#fff}.swagger-ui .checkbox{padding:5px 0 10px;-webkit-transition:opacity .5s;transition:opacity .5s;color:#333}.swagger-ui .checkbox label{display:-webkit-box;display:-ms-flexbox;display:flex}.swagger-ui .checkbox p{font-weight:400!important;font-style:italic;margin:0!important;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .checkbox input[type=checkbox]{display:none}.swagger-ui .checkbox input[type=checkbox]+label>.item{position:relative;top:3px;display:inline-block;width:16px;height:16px;margin:0 8px 0 0;padding:5px;cursor:pointer;border-radius:1px;background:#e8e8e8;box-shadow:0 0 0 2px #e8e8e8;-webkit-box-flex:0;-ms-flex:none;flex:none}.swagger-ui .checkbox input[type=checkbox]+label>.item:active{-webkit-transform:scale(.9);transform:scale(.9)}.swagger-ui .checkbox input[type=checkbox]:checked+label>.item{background:#e8e8e8 url("data:image/svg+xml;charset=utf-8,%3Csvg width='10' height='8' viewBox='3 7 10 8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2341474E' fill-rule='evenodd' d='M6.333 15L3 11.667l1.333-1.334 2 2L11.667 7 13 8.333z'/%3E%3C/svg%3E") 50% no-repeat}.swagger-ui .dialog-ux{position:fixed;z-index:9999;top:0;right:0;bottom:0;left:0}.swagger-ui .dialog-ux .backdrop-ux{position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.8)}.swagger-ui .dialog-ux .modal-ux{position:absolute;z-index:9999;top:50%;left:50%;width:100%;min-width:300px;max-width:650px;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);border:1px solid #ebebeb;border-radius:4px;background:#fff;box-shadow:0 10px 30px 0 rgba(0,0,0,.2)}.swagger-ui .dialog-ux .modal-ux-content{overflow-y:auto;max-height:540px;padding:20px}.swagger-ui .dialog-ux .modal-ux-content p{font-size:12px;margin:0 0 5px;color:#41444e;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .dialog-ux .modal-ux-content h4{font-size:18px;font-weight:600;margin:15px 0 0;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .dialog-ux .modal-ux-header{display:-webkit-box;display:-ms-flexbox;display:flex;padding:12px 0;border-bottom:1px solid #ebebeb;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .dialog-ux .modal-ux-header .close-modal{padding:0 10px;border:none;background:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.swagger-ui .dialog-ux .modal-ux-header h3{font-size:20px;font-weight:600;margin:0;padding:0 20px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .model{font-size:12px;font-weight:300;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .model-toggle{font-size:10px;position:relative;top:6px;display:inline-block;margin:auto .3em;cursor:pointer;-webkit-transition:-webkit-transform .15s ease-in;transition:-webkit-transform .15s ease-in;transition:transform .15s ease-in;transition:transform .15s ease-in,-webkit-transform .15s ease-in;-webkit-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:50% 50%;transform-origin:50% 50%}.swagger-ui .model-toggle.collapsed{-webkit-transform:rotate(0deg);transform:rotate(0deg)}.swagger-ui .model-toggle:after{display:block;width:20px;height:20px;content:"";background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E") 50% no-repeat;background-size:100%}.swagger-ui .model-jump-to-path{position:relative;cursor:pointer}.swagger-ui .model-jump-to-path .view-line-link{position:absolute;top:-.4em;cursor:pointer}.swagger-ui .model-title{position:relative}.swagger-ui .model-title:hover .model-hint{visibility:visible}.swagger-ui .model-hint{position:absolute;top:-1.8em;visibility:hidden;padding:.1em .5em;white-space:nowrap;color:#ebebeb;border-radius:4px;background:rgba(0,0,0,.7)}.swagger-ui section.models{margin:30px 0;border:1px solid rgba(59,65,81,.3);border-radius:4px}.swagger-ui section.models.is-open{padding:0 0 20px}.swagger-ui section.models.is-open h4{margin:0 0 5px;border-bottom:1px solid rgba(59,65,81,.3)}.swagger-ui section.models.is-open h4 svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.swagger-ui section.models h4{font-size:16px;display:-webkit-box;display:-ms-flexbox;display:flex;margin:0;padding:10px 20px 10px 10px;cursor:pointer;-webkit-transition:all .2s;transition:all .2s;font-family:Titillium Web,sans-serif;color:#777;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui section.models h4 svg{-webkit-transition:all .4s;transition:all .4s}.swagger-ui section.models h4 span{-webkit-box-flex:1;-ms-flex:1;flex:1}.swagger-ui section.models h4:hover{background:rgba(0,0,0,.02)}.swagger-ui section.models h5{font-size:16px;margin:0 0 10px;font-family:Titillium Web,sans-serif;color:#777}.swagger-ui section.models .model-jump-to-path{position:relative;top:5px}.swagger-ui section.models .model-container{margin:0 20px 15px;-webkit-transition:all .5s;transition:all .5s;border-radius:4px;background:rgba(0,0,0,.05)}.swagger-ui section.models .model-container:hover{background:rgba(0,0,0,.07)}.swagger-ui section.models .model-container:first-of-type{margin:20px}.swagger-ui section.models .model-container:last-of-type{margin:0 20px}.swagger-ui section.models .model-box{background:none}.swagger-ui .model-box{padding:10px;border-radius:4px;background:rgba(0,0,0,.1)}.swagger-ui .model-box .model-jump-to-path{position:relative;top:4px}.swagger-ui .model-title{font-size:16px;font-family:Titillium Web,sans-serif;color:#555}.swagger-ui span>span.model,.swagger-ui span>span.model .brace-close{padding:0 0 0 10px}.swagger-ui .prop-type{color:#55a}.swagger-ui .prop-enum{display:block}.swagger-ui .prop-format{color:#999}.swagger-ui table{width:100%;padding:0 10px;border-collapse:collapse}.swagger-ui table.model tbody tr td{padding:0;vertical-align:top}.swagger-ui table.model tbody tr td:first-of-type{width:100px;padding:0}.swagger-ui table.headers td{font-size:12px;font-weight:300;vertical-align:middle;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui table tbody tr td{padding:10px 0 0;vertical-align:top}.swagger-ui table tbody tr td:first-of-type{width:20%;padding:10px 0}.swagger-ui table thead tr td,.swagger-ui table thead tr th{font-size:12px;font-weight:700;padding:12px 0;text-align:left;border-bottom:1px solid rgba(59,65,81,.2);font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .parameters-col_description p{font-size:14px;margin:0;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .parameters-col_description input[type=text]{width:100%;max-width:340px}.swagger-ui .parameter__name{font-size:16px;font-weight:400;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .parameter__name.required{font-weight:700}.swagger-ui .parameter__name.required:after{font-size:10px;position:relative;top:-6px;padding:5px;content:"required";color:rgba(255,0,0,.6)}.swagger-ui .parameter__in{font-size:12px;font-style:italic;font-family:Source Code Pro,monospace;font-weight:600;color:#888}.swagger-ui .table-container{padding:20px}.swagger-ui .topbar{padding:8px 30px;background-color:#89bf04}.swagger-ui .topbar .topbar-wrapper{-ms-flex-align:center}.swagger-ui .topbar .topbar-wrapper,.swagger-ui .topbar a{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;align-items:center}.swagger-ui .topbar a{font-size:1.5em;font-weight:700;text-decoration:none;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-align:center;font-family:Titillium Web,sans-serif;color:#fff}.swagger-ui .topbar a span{margin:0;padding:0 10px}.swagger-ui .topbar .download-url-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex}.swagger-ui .topbar .download-url-wrapper input[type=text]{min-width:350px;margin:0;border:2px solid #547f00;border-radius:4px 0 0 4px;outline:none}.swagger-ui .topbar .download-url-wrapper .download-url-button{font-size:16px;font-weight:700;padding:4px 40px;border:none;border-radius:0 4px 4px 0;background:#547f00;font-family:Titillium Web,sans-serif;color:#fff}.swagger-ui .info{margin:50px 0}.swagger-ui .info hgroup.main{margin:0 0 20px}.swagger-ui .info hgroup.main a{font-size:12px}.swagger-ui .info p{font-size:14px;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .info code{padding:3px 5px;border-radius:4px;background:rgba(0,0,0,.05);font-family:Source Code Pro,monospace;font-weight:600;color:#9012fe}.swagger-ui .info a{font-size:14px;-webkit-transition:all .4s;transition:all .4s;font-family:Open Sans,sans-serif;color:#4990e2}.swagger-ui .info a:hover{color:#1f69c0}.swagger-ui .info>div{margin:0 0 5px}.swagger-ui .info .base-url{font-size:12px;font-weight:300!important;margin:0;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .info .title{font-size:36px;margin:0;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .info .title small{font-size:10px;position:relative;top:-5px;display:inline-block;margin:0 0 0 5px;padding:2px 4px;vertical-align:super;border-radius:57px;background:#7d8492}.swagger-ui .info .title small pre{margin:0;font-family:Titillium Web,sans-serif;color:#fff}.swagger-ui .auth-btn-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;padding:10px 0;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.swagger-ui .auth-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.swagger-ui .auth-wrapper .authorize{padding-right:20px}.swagger-ui .auth-container{margin:0 0 10px;padding:10px 20px;border-bottom:1px solid #ebebeb}.swagger-ui .auth-container:last-of-type{margin:0;padding:10px 20px;border:0}.swagger-ui .auth-container h4{margin:5px 0 15px!important}.swagger-ui .auth-container .wrapper{margin:0;padding:0}.swagger-ui .auth-container input[type=password],.swagger-ui .auth-container input[type=text]{min-width:230px}.swagger-ui .auth-container .errors{font-size:12px;padding:10px;border-radius:4px;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .scopes h2{font-size:14px;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .scope-def{padding:0 0 20px}.swagger-ui .errors-wrapper{margin:20px;padding:10px 20px;-webkit-animation:scaleUp .5s;animation:scaleUp .5s;border:2px solid #f93e3e;border-radius:4px;background:rgba(249,62,62,.1)}.swagger-ui .errors-wrapper .error-wrapper{margin:0 0 10px}.swagger-ui .errors-wrapper .errors h4{font-size:14px;margin:0;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .errors-wrapper hgroup{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .errors-wrapper hgroup h4{font-size:20px;margin:0;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:Titillium Web,sans-serif;color:#3b4151}@-webkit-keyframes scaleUp{0%{-webkit-transform:scale(.8);transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes scaleUp{0%{-webkit-transform:scale(.8);transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.swagger-ui .Resizer.vertical.disabled{display:none} 2 | /*# sourceMappingURL=swagger-ui.css.map*/ -------------------------------------------------------------------------------- /api/static/swagger/swagger-ui-standalone-preset.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUIStandalonePreset=t():e.SwaggerUIStandalonePreset=t()}(this,function(){return function(e){function t(r){if(o[r])return o[r].exports;var n=o[r]={exports:{},id:r,loaded:!1};return e[r].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var o={};return t.m=e,t.c=o,t.p="/dist",t(0)}([function(e,t,o){e.exports=o(1)},function(e,t,o){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=o(2),i=r(n);o(30);var a=o(34),s=r(a),l=[s.default,function(){return{components:{StandaloneLayout:i.default}}}];t.default=l},function(e,t,o){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var o=0;o1){for(var m=Array(b),x=0;x1){for(var h=Array(w),y=0;y>"),j={array:a("array"),bool:a("boolean"),func:a("function"),number:a("number"),object:a("object"),string:a("string"),symbol:a("symbol"),any:s(),arrayOf:l,element:p(),instanceOf:u,node:g(),objectOf:f,oneOf:c,oneOfType:d,shape:b};n.prototype=Error.prototype,e.exports=j},function(e,t){"use strict";var o="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=o},function(e,t){"use strict";e.exports="15.4.2"},function(e,t,o){"use strict";function r(e){return i.isValidElement(e)?void 0:n("143"),e}var n=o(8),i=o(10);o(9);e.exports=r},function(e,t,o){var r=o(31);"string"==typeof r&&(r=[[e.id,r,""]]);o(33)(r,{});r.locals&&(e.exports=r.locals)},function(e,t,o){t=e.exports=o(32)(),t.push([e.id,"@charset \"UTF-8\";.swagger-ui html{box-sizing:border-box}.swagger-ui *,.swagger-ui :after,.swagger-ui :before{box-sizing:inherit}.swagger-ui body{margin:0;background:#fafafa}.swagger-ui .wrapper{width:100%;max-width:1460px;margin:0 auto;padding:0 20px}.swagger-ui .opblock-tag-section{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.swagger-ui .opblock-tag{display:-webkit-box;display:-ms-flexbox;display:flex;padding:10px 20px 10px 10px;cursor:pointer;-webkit-transition:all .2s;transition:all .2s;border-bottom:1px solid rgba(59,65,81,.3);-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .opblock-tag:hover{background:rgba(0,0,0,.02)}.swagger-ui .opblock-tag{font-size:24px;margin:0 0 5px;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .opblock-tag.no-desc span{-webkit-box-flex:1;-ms-flex:1;flex:1}.swagger-ui .opblock-tag svg{-webkit-transition:all .4s;transition:all .4s}.swagger-ui .opblock-tag small{font-size:14px;font-weight:400;padding:0 10px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .parаmeter__type{font-size:12px;padding:5px 0;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .view-line-link{position:relative;top:3px;width:20px;margin:0 5px;cursor:pointer;-webkit-transition:all .5s;transition:all .5s}.swagger-ui .opblock{margin:0 0 15px;border:1px solid #000;border-radius:4px;box-shadow:0 0 3px rgba(0,0,0,.19)}.swagger-ui .opblock.is-open .opblock-summary{border-bottom:1px solid #000}.swagger-ui .opblock .opblock-section-header{padding:8px 20px;background:hsla(0,0%,100%,.8);box-shadow:0 1px 2px rgba(0,0,0,.1)}.swagger-ui .opblock .opblock-section-header,.swagger-ui .opblock .opblock-section-header label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .opblock .opblock-section-header label{font-size:12px;font-weight:700;margin:0;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .opblock .opblock-section-header label span{padding:0 10px 0 0}.swagger-ui .opblock .opblock-section-header h4{font-size:14px;margin:0;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .opblock .opblock-summary-method{font-size:14px;font-weight:700;min-width:80px;padding:6px 15px;text-align:center;border-radius:3px;background:#000;text-shadow:0 1px 0 rgba(0,0,0,.1);font-family:Titillium Web,sans-serif;color:#fff}.swagger-ui .opblock .opblock-summary-path,.swagger-ui .opblock .opblock-summary-path__deprecated{font-size:16px;display:-webkit-box;display:-ms-flexbox;display:flex;padding:0 10px;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .opblock .opblock-summary-path .view-line-link,.swagger-ui .opblock .opblock-summary-path__deprecated .view-line-link{position:relative;top:2px;width:0;margin:0;cursor:pointer;-webkit-transition:all .5s;transition:all .5s}.swagger-ui .opblock .opblock-summary-path:hover .view-line-link,.swagger-ui .opblock .opblock-summary-path__deprecated:hover .view-line-link{width:18px;margin:0 5px}.swagger-ui .opblock .opblock-summary-path__deprecated{text-decoration:line-through}.swagger-ui .opblock .opblock-summary-description{font-size:13px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .opblock .opblock-summary{display:-webkit-box;display:-ms-flexbox;display:flex;padding:5px;cursor:pointer;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .opblock.opblock-post{border-color:#49cc90;background:rgba(73,204,144,.1)}.swagger-ui .opblock.opblock-post .opblock-summary-method{background:#49cc90}.swagger-ui .opblock.opblock-post .opblock-summary{border-color:#49cc90}.swagger-ui .opblock.opblock-put{border-color:#fca130;background:rgba(252,161,48,.1)}.swagger-ui .opblock.opblock-put .opblock-summary-method{background:#fca130}.swagger-ui .opblock.opblock-put .opblock-summary{border-color:#fca130}.swagger-ui .opblock.opblock-delete{border-color:#f93e3e;background:rgba(249,62,62,.1)}.swagger-ui .opblock.opblock-delete .opblock-summary-method{background:#f93e3e}.swagger-ui .opblock.opblock-delete .opblock-summary{border-color:#f93e3e}.swagger-ui .opblock.opblock-get{border-color:#61affe;background:rgba(97,175,254,.1)}.swagger-ui .opblock.opblock-get .opblock-summary-method{background:#61affe}.swagger-ui .opblock.opblock-get .opblock-summary{border-color:#61affe}.swagger-ui .opblock.opblock-patch{border-color:#50e3c2;background:rgba(80,227,194,.1)}.swagger-ui .opblock.opblock-patch .opblock-summary-method{background:#50e3c2}.swagger-ui .opblock.opblock-patch .opblock-summary{border-color:#50e3c2}.swagger-ui .opblock.opblock-head{border-color:#9012fe;background:rgba(144,18,254,.1)}.swagger-ui .opblock.opblock-head .opblock-summary-method{background:#9012fe}.swagger-ui .opblock.opblock-head .opblock-summary{border-color:#9012fe}.swagger-ui .opblock.opblock-options{border-color:#0d5aa7;background:rgba(13,90,167,.1)}.swagger-ui .opblock.opblock-options .opblock-summary-method{background:#0d5aa7}.swagger-ui .opblock.opblock-options .opblock-summary{border-color:#0d5aa7}.swagger-ui .opblock.opblock-deprecated{opacity:.6;border-color:#ebebeb;background:hsla(0,0%,92%,.1)}.swagger-ui .opblock.opblock-deprecated .opblock-summary-method{background:#ebebeb}.swagger-ui .opblock.opblock-deprecated .opblock-summary{border-color:#ebebeb}.swagger-ui .tab{display:-webkit-box;display:-ms-flexbox;display:flex;margin:20px 0 10px;padding:0;list-style:none}.swagger-ui .tab li{font-size:12px;min-width:100px;min-width:90px;padding:0;cursor:pointer;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .tab li:first-of-type{position:relative;padding-left:0}.swagger-ui .tab li:first-of-type:after{position:absolute;top:0;right:6px;width:1px;height:100%;content:\"\";background:rgba(0,0,0,.2)}.swagger-ui .tab li.active{font-weight:700}.swagger-ui .opblock-description-wrapper,.swagger-ui .opblock-title_normal{padding:15px 20px}.swagger-ui .opblock-description-wrapper,.swagger-ui .opblock-description-wrapper h4,.swagger-ui .opblock-title_normal,.swagger-ui .opblock-title_normal h4{font-size:12px;margin:0 0 5px;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .opblock-description-wrapper p,.swagger-ui .opblock-title_normal p{font-size:14px;margin:0;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .execute-wrapper{padding:20px;text-align:right}.swagger-ui .execute-wrapper .btn{width:100%;padding:8px 40px}.swagger-ui .body-param-options{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.swagger-ui .body-param-options .body-param-edit{padding:10px 0}.swagger-ui .body-param-options label{padding:8px 0}.swagger-ui .body-param-options label select{margin:3px 0 0}.swagger-ui .responses-inner{padding:20px}.swagger-ui .responses-inner h4,.swagger-ui .responses-inner h5{font-size:12px;margin:10px 0 5px;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .response-col_status{font-size:14px;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .response-col_status .response-undocumented{font-size:11px;font-family:Source Code Pro,monospace;font-weight:600;color:#999}.swagger-ui .response-col_description__inner span{font-size:12px;font-style:italic;display:block;margin:10px 0;padding:10px;border-radius:4px;background:#41444e;font-family:Source Code Pro,monospace;font-weight:600;color:#fff}.swagger-ui .response-col_description__inner span p{margin:0}.swagger-ui .opblock-body pre{font-size:12px;margin:0;padding:10px;white-space:pre-wrap;border-radius:4px;background:#41444e;font-family:Source Code Pro,monospace;font-weight:600;color:#fff}.swagger-ui .opblock-body pre span{color:#fff!important}.swagger-ui .scheme-container{margin:0 0 20px;padding:30px 0;background:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.15)}.swagger-ui .scheme-container .schemes{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .scheme-container .schemes>label{font-size:12px;font-weight:700;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:-20px 15px 0 0;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .scheme-container .schemes>label select{min-width:130px;text-transform:uppercase}.swagger-ui .loading-container{padding:40px 0 60px}.swagger-ui .loading-container .loading{position:relative}.swagger-ui .loading-container .loading:after{font-size:10px;font-weight:700;position:absolute;top:50%;left:50%;content:\"loading\";-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-transform:uppercase;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .loading-container .loading:before{position:absolute;top:50%;left:50%;display:block;width:60px;height:60px;margin:-30px;content:\"\";-webkit-animation:rotation 1s infinite linear,opacity .5s;animation:rotation 1s infinite linear,opacity .5s;opacity:1;border:2px solid rgba(85,85,85,.1);border-top-color:rgba(0,0,0,.6);border-radius:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden}@-webkit-keyframes rotation{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotation{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes blinker{50%{opacity:0}}@keyframes blinker{50%{opacity:0}}.swagger-ui .btn{font-size:14px;font-weight:700;padding:5px 23px;-webkit-transition:all .3s;transition:all .3s;border:2px solid #888;border-radius:4px;background:transparent;box-shadow:0 1px 2px rgba(0,0,0,.1);font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .btn[disabled]{cursor:not-allowed;opacity:.3}.swagger-ui .btn:hover{box-shadow:0 0 5px rgba(0,0,0,.3)}.swagger-ui .btn.cancel{border-color:#ff6060;font-family:Titillium Web,sans-serif;color:#ff6060}.swagger-ui .btn.authorize{line-height:1;display:inline;color:#49cc90;border-color:#49cc90}.swagger-ui .btn.authorize span{float:left;padding:4px 20px 0 0}.swagger-ui .btn.authorize svg{fill:#49cc90}.swagger-ui .btn.execute{-webkit-animation:pulse 2s infinite;animation:pulse 2s infinite;color:#fff;border-color:#4990e2}@-webkit-keyframes pulse{0%{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,.8)}70%{box-shadow:0 0 0 5px rgba(73,144,226,0)}to{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,0)}}@keyframes pulse{0%{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,.8)}70%{box-shadow:0 0 0 5px rgba(73,144,226,0)}to{color:#fff;background:#4990e2;box-shadow:0 0 0 0 rgba(73,144,226,0)}}.swagger-ui .btn-group{display:-webkit-box;display:-ms-flexbox;display:flex;padding:30px}.swagger-ui .btn-group .btn{-webkit-box-flex:1;-ms-flex:1;flex:1}.swagger-ui .btn-group .btn:first-child{border-radius:4px 0 0 4px}.swagger-ui .btn-group .btn:last-child{border-radius:0 4px 4px 0}.swagger-ui .authorization__btn{padding:0 10px;border:none;background:none}.swagger-ui .authorization__btn.locked{opacity:1}.swagger-ui .authorization__btn.unlocked{opacity:.4}.swagger-ui .expand-methods,.swagger-ui .expand-operation{border:none;background:none}.swagger-ui .expand-methods svg,.swagger-ui .expand-operation svg{width:20px;height:20px}.swagger-ui .expand-methods{padding:0 10px}.swagger-ui .expand-methods:hover svg{fill:#444}.swagger-ui .expand-methods svg{-webkit-transition:all .3s;transition:all .3s;fill:#777}.swagger-ui button{cursor:pointer;outline:none}.swagger-ui select{font-size:14px;font-weight:700;padding:5px 40px 5px 10px;border:2px solid #41444e;border-radius:4px;background:#f7f7f7 url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+ICAgIDxwYXRoIGQ9Ik0xMy40MTggNy44NTljLjI3MS0uMjY4LjcwOS0uMjY4Ljk3OCAwIC4yNy4yNjguMjcyLjcwMSAwIC45NjlsLTMuOTA4IDMuODNjLS4yNy4yNjgtLjcwNy4yNjgtLjk3OSAwbC0zLjkwOC0zLjgzYy0uMjctLjI2Ny0uMjctLjcwMSAwLS45NjkuMjcxLS4yNjguNzA5LS4yNjguOTc4IDBMMTAgMTFsMy40MTgtMy4xNDF6Ii8+PC9zdmc+) right 10px center no-repeat;background-size:20px;box-shadow:0 1px 2px 0 rgba(0,0,0,.25);font-family:Titillium Web,sans-serif;color:#3b4151;-webkit-appearance:none;-moz-appearance:none;appearance:none}.swagger-ui select[multiple]{margin:5px 0;padding:5px;background:#f7f7f7}.swagger-ui .opblock-body select{min-width:230px}.swagger-ui label{font-size:12px;font-weight:700;margin:0 0 5px;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui input[type=email],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text]{min-width:100px;margin:5px 0;padding:8px 10px;border:1px solid #d9d9d9;border-radius:4px;background:#fff}.swagger-ui input[type=email].invalid,.swagger-ui input[type=password].invalid,.swagger-ui input[type=search].invalid,.swagger-ui input[type=text].invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;border-color:#f93e3e;background:#feebeb}@-webkit-keyframes shake{10%,90%{-webkit-transform:translate3d(-1px,0,0);transform:translate3d(-1px,0,0)}20%,80%{-webkit-transform:translate3d(2px,0,0);transform:translate3d(2px,0,0)}30%,50%,70%{-webkit-transform:translate3d(-4px,0,0);transform:translate3d(-4px,0,0)}40%,60%{-webkit-transform:translate3d(4px,0,0);transform:translate3d(4px,0,0)}}@keyframes shake{10%,90%{-webkit-transform:translate3d(-1px,0,0);transform:translate3d(-1px,0,0)}20%,80%{-webkit-transform:translate3d(2px,0,0);transform:translate3d(2px,0,0)}30%,50%,70%{-webkit-transform:translate3d(-4px,0,0);transform:translate3d(-4px,0,0)}40%,60%{-webkit-transform:translate3d(4px,0,0);transform:translate3d(4px,0,0)}}.swagger-ui textarea{font-size:12px;width:100%;min-height:280px;padding:10px;border:none;border-radius:4px;outline:none;background:hsla(0,0%,100%,.8);font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui textarea:focus{border:2px solid #61affe}.swagger-ui textarea.curl{font-size:12px;min-height:100px;margin:0;padding:10px;resize:none;border-radius:4px;background:#41444e;font-family:Source Code Pro,monospace;font-weight:600;color:#fff}.swagger-ui .checkbox{padding:5px 0 10px;-webkit-transition:opacity .5s;transition:opacity .5s;color:#333}.swagger-ui .checkbox label{display:-webkit-box;display:-ms-flexbox;display:flex}.swagger-ui .checkbox p{font-weight:400!important;font-style:italic;margin:0!important;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .checkbox input[type=checkbox]{display:none}.swagger-ui .checkbox input[type=checkbox]+label>.item{position:relative;top:3px;display:inline-block;width:16px;height:16px;margin:0 8px 0 0;padding:5px;cursor:pointer;border-radius:1px;background:#e8e8e8;box-shadow:0 0 0 2px #e8e8e8;-webkit-box-flex:0;-ms-flex:none;flex:none}.swagger-ui .checkbox input[type=checkbox]+label>.item:active{-webkit-transform:scale(.9);transform:scale(.9)}.swagger-ui .checkbox input[type=checkbox]:checked+label>.item{background:#e8e8e8 url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='10' height='8' viewBox='3 7 10 8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2341474E' fill-rule='evenodd' d='M6.333 15L3 11.667l1.333-1.334 2 2L11.667 7 13 8.333z'/%3E%3C/svg%3E\") 50% no-repeat}.swagger-ui .dialog-ux{position:fixed;z-index:9999;top:0;right:0;bottom:0;left:0}.swagger-ui .dialog-ux .backdrop-ux{position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.8)}.swagger-ui .dialog-ux .modal-ux{position:absolute;z-index:9999;top:50%;left:50%;width:100%;min-width:300px;max-width:650px;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);border:1px solid #ebebeb;border-radius:4px;background:#fff;box-shadow:0 10px 30px 0 rgba(0,0,0,.2)}.swagger-ui .dialog-ux .modal-ux-content{overflow-y:auto;max-height:540px;padding:20px}.swagger-ui .dialog-ux .modal-ux-content p{font-size:12px;margin:0 0 5px;color:#41444e;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .dialog-ux .modal-ux-content h4{font-size:18px;font-weight:600;margin:15px 0 0;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .dialog-ux .modal-ux-header{display:-webkit-box;display:-ms-flexbox;display:flex;padding:12px 0;border-bottom:1px solid #ebebeb;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .dialog-ux .modal-ux-header .close-modal{padding:0 10px;border:none;background:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.swagger-ui .dialog-ux .modal-ux-header h3{font-size:20px;font-weight:600;margin:0;padding:0 20px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .model{font-size:12px;font-weight:300;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .model-toggle{font-size:10px;position:relative;top:6px;display:inline-block;margin:auto .3em;cursor:pointer;-webkit-transition:-webkit-transform .15s ease-in;transition:-webkit-transform .15s ease-in;transition:transform .15s ease-in;transition:transform .15s ease-in,-webkit-transform .15s ease-in;-webkit-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:50% 50%;transform-origin:50% 50%}.swagger-ui .model-toggle.collapsed{-webkit-transform:rotate(0deg);transform:rotate(0deg)}.swagger-ui .model-toggle:after{display:block;width:20px;height:20px;content:\"\";background:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E\") 50% no-repeat;background-size:100%}.swagger-ui .model-jump-to-path{position:relative;cursor:pointer}.swagger-ui .model-jump-to-path .view-line-link{position:absolute;top:-.4em;cursor:pointer}.swagger-ui .model-title{position:relative}.swagger-ui .model-title:hover .model-hint{visibility:visible}.swagger-ui .model-hint{position:absolute;top:-1.8em;visibility:hidden;padding:.1em .5em;white-space:nowrap;color:#ebebeb;border-radius:4px;background:rgba(0,0,0,.7)}.swagger-ui section.models{margin:30px 0;border:1px solid rgba(59,65,81,.3);border-radius:4px}.swagger-ui section.models.is-open{padding:0 0 20px}.swagger-ui section.models.is-open h4{margin:0 0 5px;border-bottom:1px solid rgba(59,65,81,.3)}.swagger-ui section.models.is-open h4 svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.swagger-ui section.models h4{font-size:16px;display:-webkit-box;display:-ms-flexbox;display:flex;margin:0;padding:10px 20px 10px 10px;cursor:pointer;-webkit-transition:all .2s;transition:all .2s;font-family:Titillium Web,sans-serif;color:#777;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui section.models h4 svg{-webkit-transition:all .4s;transition:all .4s}.swagger-ui section.models h4 span{-webkit-box-flex:1;-ms-flex:1;flex:1}.swagger-ui section.models h4:hover{background:rgba(0,0,0,.02)}.swagger-ui section.models h5{font-size:16px;margin:0 0 10px;font-family:Titillium Web,sans-serif;color:#777}.swagger-ui section.models .model-jump-to-path{position:relative;top:5px}.swagger-ui section.models .model-container{margin:0 20px 15px;-webkit-transition:all .5s;transition:all .5s;border-radius:4px;background:rgba(0,0,0,.05)}.swagger-ui section.models .model-container:hover{background:rgba(0,0,0,.07)}.swagger-ui section.models .model-container:first-of-type{margin:20px}.swagger-ui section.models .model-container:last-of-type{margin:0 20px}.swagger-ui section.models .model-box{background:none}.swagger-ui .model-box{padding:10px;border-radius:4px;background:rgba(0,0,0,.1)}.swagger-ui .model-box .model-jump-to-path{position:relative;top:4px}.swagger-ui .model-title{font-size:16px;font-family:Titillium Web,sans-serif;color:#555}.swagger-ui span>span.model,.swagger-ui span>span.model .brace-close{padding:0 0 0 10px}.swagger-ui .prop-type{color:#55a}.swagger-ui .prop-enum{display:block}.swagger-ui .prop-format{color:#999}.swagger-ui table{width:100%;padding:0 10px;border-collapse:collapse}.swagger-ui table.model tbody tr td{padding:0;vertical-align:top}.swagger-ui table.model tbody tr td:first-of-type{width:100px;padding:0}.swagger-ui table.headers td{font-size:12px;font-weight:300;vertical-align:middle;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui table tbody tr td{padding:10px 0 0;vertical-align:top}.swagger-ui table tbody tr td:first-of-type{width:20%;padding:10px 0}.swagger-ui table thead tr td,.swagger-ui table thead tr th{font-size:12px;font-weight:700;padding:12px 0;text-align:left;border-bottom:1px solid rgba(59,65,81,.2);font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .parameters-col_description p{font-size:14px;margin:0;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .parameters-col_description input[type=text]{width:100%;max-width:340px}.swagger-ui .parameter__name{font-size:16px;font-weight:400;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .parameter__name.required{font-weight:700}.swagger-ui .parameter__name.required:after{font-size:10px;position:relative;top:-6px;padding:5px;content:\"required\";color:rgba(255,0,0,.6)}.swagger-ui .parameter__in{font-size:12px;font-style:italic;font-family:Source Code Pro,monospace;font-weight:600;color:#888}.swagger-ui .table-container{padding:20px}.swagger-ui .topbar{padding:8px 30px;background-color:#89bf04}.swagger-ui .topbar .topbar-wrapper{-ms-flex-align:center}.swagger-ui .topbar .topbar-wrapper,.swagger-ui .topbar a{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;align-items:center}.swagger-ui .topbar a{font-size:1.5em;font-weight:700;text-decoration:none;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-align:center;font-family:Titillium Web,sans-serif;color:#fff}.swagger-ui .topbar a span{margin:0;padding:0 10px}.swagger-ui .topbar .download-url-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex}.swagger-ui .topbar .download-url-wrapper input[type=text]{min-width:350px;margin:0;border:2px solid #547f00;border-radius:4px 0 0 4px;outline:none}.swagger-ui .topbar .download-url-wrapper .download-url-button{font-size:16px;font-weight:700;padding:4px 40px;border:none;border-radius:0 4px 4px 0;background:#547f00;font-family:Titillium Web,sans-serif;color:#fff}.swagger-ui .info{margin:50px 0}.swagger-ui .info hgroup.main{margin:0 0 20px}.swagger-ui .info hgroup.main a{font-size:12px}.swagger-ui .info p{font-size:14px;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .info code{padding:3px 5px;border-radius:4px;background:rgba(0,0,0,.05);font-family:Source Code Pro,monospace;font-weight:600;color:#9012fe}.swagger-ui .info a{font-size:14px;-webkit-transition:all .4s;transition:all .4s;font-family:Open Sans,sans-serif;color:#4990e2}.swagger-ui .info a:hover{color:#1f69c0}.swagger-ui .info>div{margin:0 0 5px}.swagger-ui .info .base-url{font-size:12px;font-weight:300!important;margin:0;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .info .title{font-size:36px;margin:0;font-family:Open Sans,sans-serif;color:#3b4151}.swagger-ui .info .title small{font-size:10px;position:relative;top:-5px;display:inline-block;margin:0 0 0 5px;padding:2px 4px;vertical-align:super;border-radius:57px;background:#7d8492}.swagger-ui .info .title small pre{margin:0;font-family:Titillium Web,sans-serif;color:#fff}.swagger-ui .auth-btn-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;padding:10px 0;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.swagger-ui .auth-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.swagger-ui .auth-wrapper .authorize{padding-right:20px}.swagger-ui .auth-container{margin:0 0 10px;padding:10px 20px;border-bottom:1px solid #ebebeb}.swagger-ui .auth-container:last-of-type{margin:0;padding:10px 20px;border:0}.swagger-ui .auth-container h4{margin:5px 0 15px!important}.swagger-ui .auth-container .wrapper{margin:0;padding:0}.swagger-ui .auth-container input[type=password],.swagger-ui .auth-container input[type=text]{min-width:230px}.swagger-ui .auth-container .errors{font-size:12px;padding:10px;border-radius:4px;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .scopes h2{font-size:14px;font-family:Titillium Web,sans-serif;color:#3b4151}.swagger-ui .scope-def{padding:0 0 20px}.swagger-ui .errors-wrapper{margin:20px;padding:10px 20px;-webkit-animation:scaleUp .5s;animation:scaleUp .5s;border:2px solid #f93e3e;border-radius:4px;background:rgba(249,62,62,.1)}.swagger-ui .errors-wrapper .error-wrapper{margin:0 0 10px}.swagger-ui .errors-wrapper .errors h4{font-size:14px;margin:0;font-family:Source Code Pro,monospace;font-weight:600;color:#3b4151}.swagger-ui .errors-wrapper hgroup{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swagger-ui .errors-wrapper hgroup h4{font-size:20px;margin:0;-webkit-box-flex:1;-ms-flex:1;flex:1;font-family:Titillium Web,sans-serif;color:#3b4151}@-webkit-keyframes scaleUp{0%{-webkit-transform:scale(.8);transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes scaleUp{0%{-webkit-transform:scale(.8);transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}",""]); 7 | },function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t=0&&h.splice(t,1)}function s(e){var t=document.createElement("style");return t.type="text/css",i(e,t),t}function l(e){var t=document.createElement("link");return t.rel="stylesheet",i(e,t),t}function p(e,t){var o,r,n;if(t.singleton){var i=w++;o=x||(x=s(t)),r=u.bind(null,o,i,!1),n=u.bind(null,o,i,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(o=l(t),r=f.bind(null,o),n=function(){a(o),o.href&&URL.revokeObjectURL(o.href)}):(o=s(t),r=c.bind(null,o),n=function(){a(o)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else n()}}function u(e,t,o,r){var n=o?"":r.css;if(e.styleSheet)e.styleSheet.cssText=y(t,n);else{var i=document.createTextNode(n),a=e.childNodes;a[t]&&e.removeChild(a[t]),a.length?e.insertBefore(i,a[t]):e.appendChild(i)}}function c(e,t){var o=t.css,r=t.media;t.sourceMap;if(r&&e.setAttribute("media",r),e.styleSheet)e.styleSheet.cssText=o;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(o))}}function f(e,t){var o=t.css,r=(t.media,t.sourceMap);r&&(o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var n=new Blob([o],{type:"text/css"}),i=e.href;e.href=URL.createObjectURL(n),i&&URL.revokeObjectURL(i)}var d={},g=function(e){var t;return function(){return"undefined"==typeof t&&(t=e.apply(this,arguments)),t}},b=g(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),m=g(function(){return document.head||document.getElementsByTagName("head")[0]}),x=null,w=0,h=[];e.exports=function(e,t){t=t||{},"undefined"==typeof t.singleton&&(t.singleton=b()),"undefined"==typeof t.insertAt&&(t.insertAt="bottom");var o=n(e);return r(o,t),function(e){for(var i=[],a=0;a