diff options
| author | Jan Friedli | 2020-07-14 15:28:08 +0200 |
|---|---|---|
| committer | Jan Friedli | 2020-07-14 15:28:08 +0200 |
| commit | 5d1e6b3235f9cddf66611e7cf4f4d0b41ffd7368 (patch) | |
| tree | dc95468b0d3ae3783560dfe3916b5dba2bf775ea | |
| parent | 42f9ede4bf9ee5cf0e7fda74fcd37bea5540c302 (diff) | |
upgrade to oas 3
| -rw-r--r-- | .gitlab-ci.yml | 2 | ||||
| -rw-r--r-- | main.py | 25 | ||||
| -rw-r--r-- | matweb/oas/bulk.yml | 53 | ||||
| -rw-r--r-- | matweb/oas/components.yml | 68 | ||||
| -rw-r--r-- | matweb/oas/download.yml | 49 | ||||
| -rw-r--r-- | matweb/oas/extension.yml | 16 | ||||
| -rw-r--r-- | matweb/oas/upload.yml | 92 | ||||
| -rw-r--r-- | requirements-test.txt | 1 | ||||
| -rw-r--r-- | requirements.txt | 2 | ||||
| -rw-r--r-- | test/test_api.py | 4 |
10 files changed, 178 insertions, 134 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c823b77..6bacabe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml | |||
| @@ -38,7 +38,7 @@ tests:debian: | |||
| 38 | - apt-get -qqy update | 38 | - apt-get -qqy update |
| 39 | - apt-get -qqy install --no-install-recommends mat2 python3-flask python3-coverage python3-pip python3-setuptools | 39 | - apt-get -qqy install --no-install-recommends mat2 python3-flask python3-coverage python3-pip python3-setuptools |
| 40 | - pip3 install wheel | 40 | - pip3 install wheel |
| 41 | - pip3 install -r requirements.txt | 41 | - pip3 install -r requirements.txt -r requirements-test.txt |
| 42 | - python3-coverage run --branch --include main.py,matweb/*.py -m unittest discover -s test | 42 | - python3-coverage run --branch --include main.py,matweb/*.py -m unittest discover -s test |
| 43 | - python3-coverage report -m | 43 | - python3-coverage report -m |
| 44 | 44 | ||
| @@ -1,5 +1,6 @@ | |||
| 1 | import os | 1 | import os |
| 2 | import jinja2 | 2 | import jinja2 |
| 3 | import yaml | ||
| 3 | 4 | ||
| 4 | from matweb import utils, rest_api, frontend | 5 | from matweb import utils, rest_api, frontend |
| 5 | from flask import Flask, request | 6 | from flask import Flask, request |
| @@ -30,17 +31,31 @@ def create_app(test_config=None): | |||
| 30 | app.register_blueprint(rest_api.api_bp) | 31 | app.register_blueprint(rest_api.api_bp) |
| 31 | app.json_encoder = LazyJSONEncoder | 32 | app.json_encoder = LazyJSONEncoder |
| 32 | 33 | ||
| 34 | dirname = os.path.dirname(__file__) | ||
| 35 | with open(os.path.join(dirname, 'matweb/oas/components.yml')) as file: | ||
| 36 | components = yaml.full_load(file) | ||
| 37 | |||
| 33 | template = dict( | 38 | template = dict( |
| 34 | schemes=['https', 'http'], | 39 | servers=[ |
| 35 | host=LazyString(lambda: request.host), | 40 | { |
| 36 | basePath='/', | 41 | 'url': LazyString(lambda: request.host_url), |
| 42 | 'description': 'References the current running server' | ||
| 43 | } | ||
| 44 | ], | ||
| 37 | info={ | 45 | info={ |
| 38 | 'title': 'Mat2 Web API', | 46 | 'title': 'Mat2 Web API', |
| 39 | 'version': '1', | 47 | 'version': '1', |
| 40 | 'description': 'Mat2 Web RESTful API documentation', | 48 | 'description': 'Mat2 Web RESTful API documentation', |
| 41 | } | 49 | }, |
| 50 | components=components | ||
| 42 | ) | 51 | ) |
| 43 | Swagger(app, template=template) | 52 | swagger_config = Swagger.DEFAULT_CONFIG |
| 53 | swagger_config['swagger_ui_bundle_js'] = '//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js' | ||
| 54 | swagger_config['swagger_ui_standalone_preset_js'] = '//unpkg.com/swagger-ui-dist@3/swagger-ui-standalone-preset.js' | ||
| 55 | swagger_config['swagger_ui_css'] = '//unpkg.com/swagger-ui-dist@3/swagger-ui.css' | ||
| 56 | swagger_config['openapi'] = "3.0.3" | ||
| 57 | Swagger(app, template=template, config=swagger_config) | ||
| 58 | |||
| 44 | CORS(app, resources={r"/api/*": {"origins": utils.get_allow_origin_header_value()}}) | 59 | CORS(app, resources={r"/api/*": {"origins": utils.get_allow_origin_header_value()}}) |
| 45 | 60 | ||
| 46 | return app | 61 | return app |
diff --git a/matweb/oas/bulk.yml b/matweb/oas/bulk.yml index 08f346c..bbfe02e 100644 --- a/matweb/oas/bulk.yml +++ b/matweb/oas/bulk.yml | |||
| @@ -6,47 +6,32 @@ description: "This endpoint allows you to bulk download several files | |||
| 6 | which you uploaded beforehand. Note that the `download_list` | 6 | which you uploaded beforehand. Note that the `download_list` |
| 7 | MUST contain more than two files. The max length is configurable | 7 | MUST contain more than two files. The max length is configurable |
| 8 | (default is 10)." | 8 | (default is 10)." |
| 9 | consumes: | 9 | requestBody: |
| 10 | - "application/json" | ||
| 11 | produces: | ||
| 12 | - "application/json" | ||
| 13 | parameters: | ||
| 14 | - in: "body" | ||
| 15 | name: "body" | ||
| 16 | description: "The files that will be combined for one single download" | 10 | description: "The files that will be combined for one single download" |
| 17 | required: true | 11 | required: true |
| 18 | schema: | 12 | content: |
| 19 | $ref: '#/definitions/BulkBody' | 13 | application/json: |
| 14 | schema: | ||
| 15 | $ref: '#/components/schemas/BulkBody' | ||
| 20 | 16 | ||
| 21 | responses: | 17 | responses: |
| 22 | 201: | 18 | 201: |
| 23 | description: "A new resource to download all files as one archive" | 19 | description: "A new resource to download all files as one archive" |
| 24 | schema: | 20 | content: |
| 25 | $ref: '#/definitions/UploadResponse' | 21 | application/json: |
| 22 | schema: | ||
| 23 | $ref: '#/components/schemas/UploadResponse' | ||
| 26 | 400: | 24 | 400: |
| 27 | description: "Invalid input" | 25 | description: "Invalid input" |
| 28 | schema: | 26 | content: |
| 29 | $ref: '#/definitions/ErrorResponse' | 27 | application/json: |
| 28 | schema: | ||
| 29 | oneOf: | ||
| 30 | - $ref: '#/components/schemas/ErrorAtLeastTwoResponse' | ||
| 31 | - $ref: '#/components/schemas/ErrorResponse' | ||
| 30 | 500: | 32 | 500: |
| 31 | description: "Unable to clean the file" | 33 | description: "Unable to clean the file" |
| 32 | schema: | 34 | content: |
| 33 | $ref: '#/definitions/ErrorResponse' | 35 | application/json: |
| 34 | 36 | schema: | |
| 35 | definitions: | 37 | $ref: '#/components/schemas/ErrorResponse' \ No newline at end of file |
| 36 | BulkBody: | ||
| 37 | type: "object" | ||
| 38 | properties: | ||
| 39 | download_list: | ||
| 40 | type: "array" | ||
| 41 | description: "An object containing the files you want to create a bulk download for" | ||
| 42 | items: | ||
| 43 | $ref: '#/definitions/BulkFile' | ||
| 44 | BulkFile: | ||
| 45 | type: "object" | ||
| 46 | properties: | ||
| 47 | file_name: | ||
| 48 | type: "string" | ||
| 49 | key: | ||
| 50 | type: "string" | ||
| 51 | secret: | ||
| 52 | type: "string" \ No newline at end of file | ||
diff --git a/matweb/oas/components.yml b/matweb/oas/components.yml new file mode 100644 index 0000000..82d07fb --- /dev/null +++ b/matweb/oas/components.yml | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | schemas: | ||
| 2 | BulkBody: | ||
| 3 | type: "object" | ||
| 4 | properties: | ||
| 5 | download_list: | ||
| 6 | type: "array" | ||
| 7 | description: "An object containing the files you want to create a bulk download for" | ||
| 8 | items: | ||
| 9 | $ref: '#/components/schemas/BulkFile' | ||
| 10 | BulkFile: | ||
| 11 | type: "object" | ||
| 12 | properties: | ||
| 13 | file_name: | ||
| 14 | type: "string" | ||
| 15 | key: | ||
| 16 | type: "string" | ||
| 17 | secret: | ||
| 18 | type: "string" | ||
| 19 | ErrorAtLeastTwoResponse: | ||
| 20 | type: "object" | ||
| 21 | properties: | ||
| 22 | message: | ||
| 23 | type: "object" | ||
| 24 | description: "A description of the error" | ||
| 25 | properties: | ||
| 26 | download_list: | ||
| 27 | type: "array" | ||
| 28 | items: | ||
| 29 | type: "string" | ||
| 30 | example: "Min length is 2" | ||
| 31 | UploadResponse: | ||
| 32 | type: "object" | ||
| 33 | properties: | ||
| 34 | inactive_after_sec: | ||
| 35 | type: "integer" | ||
| 36 | format: "int64" | ||
| 37 | description: "Defines after how many seconds the download wont be available" | ||
| 38 | output_filename: | ||
| 39 | type: "string" | ||
| 40 | description: "The resulting filename after metadata removal" | ||
| 41 | mime: | ||
| 42 | type: "string" | ||
| 43 | description: "The mime type of the cleaned file" | ||
| 44 | key: | ||
| 45 | type: "string" | ||
| 46 | description: "A key used to guarantee file integrity" | ||
| 47 | secret: | ||
| 48 | type: "string" | ||
| 49 | description: "A secret used to guarantee file integrity" | ||
| 50 | meta: | ||
| 51 | type: "object" | ||
| 52 | description: "An object of the removed metadata where key indicates the metadata type" | ||
| 53 | items: | ||
| 54 | type: "string" | ||
| 55 | meta_after: | ||
| 56 | type: "object" | ||
| 57 | description: "An object of the remaining metadata where key indicates the metadata type" | ||
| 58 | items: | ||
| 59 | type: "string" | ||
| 60 | download_link: | ||
| 61 | type: "string" | ||
| 62 | description: "The link to download the cleaned file" | ||
| 63 | ErrorResponse: | ||
| 64 | type: "object" | ||
| 65 | properties: | ||
| 66 | message: | ||
| 67 | type: "string" | ||
| 68 | description: "A description of the error" \ No newline at end of file | ||
diff --git a/matweb/oas/download.yml b/matweb/oas/download.yml index 899d103..e4a0ca4 100644 --- a/matweb/oas/download.yml +++ b/matweb/oas/download.yml | |||
| @@ -2,30 +2,39 @@ | |||
| 2 | tags: | 2 | tags: |
| 3 | - "File Download" | 3 | - "File Download" |
| 4 | summary: 'Download a single cleaned file or zip archive containing multiple files' | 4 | summary: 'Download a single cleaned file or zip archive containing multiple files' |
| 5 | consumes: | ||
| 6 | - "application/json" | ||
| 7 | produces: | ||
| 8 | - "*/*" | ||
| 9 | parameters: | 5 | parameters: |
| 10 | - name: "key" | 6 | - name: "key" |
| 11 | in: "path" | 7 | in: "path" |
| 12 | description: "A key generated for that resource" | 8 | description: "A key generated for that resource" |
| 13 | required: true | 9 | required: true |
| 14 | type: "string" | 10 | schema: |
| 15 | - name: "secret" | 11 | type: "string" |
| 16 | in: "path" | 12 | - name: "secret" |
| 17 | description: "A secret generated for that resource" | 13 | in: "path" |
| 18 | required: true | 14 | description: "A secret generated for that resource" |
| 19 | type: "string" | 15 | required: true |
| 20 | - name: "filename" | 16 | schema: |
| 21 | in: "path" | 17 | type: "string" |
| 22 | description: "the filename of the cleaned file" | 18 | - name: "filename" |
| 23 | required: true | 19 | in: "path" |
| 24 | type: "string" | 20 | description: "the filename of the cleaned file" |
| 21 | required: true | ||
| 22 | schema: | ||
| 23 | type: "string" | ||
| 25 | 24 | ||
| 26 | 25 | ||
| 27 | responses: | 26 | responses: |
| 28 | 200: | 27 | 200: |
| 29 | description: "" | 28 | description: "The cleaned file as attachment so a browser downloads the file directly" |
| 29 | content: | ||
| 30 | "*/*": | ||
| 31 | schema: | ||
| 32 | format: binary | ||
| 33 | 400: | ||
| 34 | description: "Invalid input" | ||
| 35 | content: | ||
| 36 | application/json: | ||
| 37 | schema: | ||
| 38 | $ref: '#/components/schemas/ErrorResponse' | ||
| 30 | 404: | 39 | 404: |
| 31 | description: "The filename, key or secret are wrong or the link is too old and the file has been deleted" \ No newline at end of file | 40 | description: "The filename, key or secret are wrong or the link is too old and the file has been deleted" \ No newline at end of file |
diff --git a/matweb/oas/extension.yml b/matweb/oas/extension.yml index 3e31034..41314a7 100644 --- a/matweb/oas/extension.yml +++ b/matweb/oas/extension.yml | |||
| @@ -2,16 +2,14 @@ | |||
| 2 | tags: | 2 | tags: |
| 3 | - "Supported Extensions" | 3 | - "Supported Extensions" |
| 4 | summary: 'Returns a list of all supported file extensions' | 4 | summary: 'Returns a list of all supported file extensions' |
| 5 | consumes: | ||
| 6 | - "application/json" | ||
| 7 | produces: | ||
| 8 | - "application/json" | ||
| 9 | 5 | ||
| 10 | responses: | 6 | responses: |
| 11 | 200: | 7 | 200: |
| 12 | description: "A list of all supported file extensions" | 8 | description: "A list of all supported file extensions" |
| 13 | schema: | 9 | content: |
| 14 | type: "array" | 10 | application/json: |
| 15 | items: | 11 | schema: |
| 16 | type: "string" | 12 | type: "array" |
| 17 | example: ".jpeg" \ No newline at end of file | 13 | items: |
| 14 | type: "string" | ||
| 15 | example: ".jpeg" \ No newline at end of file | ||
diff --git a/matweb/oas/upload.yml b/matweb/oas/upload.yml index 71cb87b..4133d08 100644 --- a/matweb/oas/upload.yml +++ b/matweb/oas/upload.yml | |||
| @@ -2,79 +2,43 @@ | |||
| 2 | tags: | 2 | tags: |
| 3 | - "File Upload (Metadata removal)" | 3 | - "File Upload (Metadata removal)" |
| 4 | summary: 'Upload a single file which will be cleaned from metadata' | 4 | summary: 'Upload a single file which will be cleaned from metadata' |
| 5 | consumes: | 5 | requestBody: |
| 6 | - "application/json" | ||
| 7 | produces: | ||
| 8 | - "application/json" | ||
| 9 | parameters: | ||
| 10 | - in: "body" | ||
| 11 | name: "body" | ||
| 12 | description: "The file that will be cleaned from metadata. Note that the file must be base64 encoded" | 6 | description: "The file that will be cleaned from metadata. Note that the file must be base64 encoded" |
| 13 | required: true | 7 | required: true |
| 14 | schema: | 8 | content: |
| 15 | type: "object" | 9 | application/json: |
| 16 | properties: | 10 | schema: |
| 17 | file_name: | 11 | type: "object" |
| 18 | type: "string" | 12 | properties: |
| 19 | example: 'my_example.jpg' | 13 | file_name: |
| 20 | file: | 14 | type: "string" |
| 21 | type: "string" | 15 | example: 'my_example.jpg' |
| 22 | example: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==' | 16 | file: |
| 17 | type: "string" | ||
| 18 | example: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==' | ||
| 23 | 19 | ||
| 24 | responses: | 20 | responses: |
| 25 | 201: | 21 | 201: |
| 26 | description: "An object containing all info about the cleaned file" | 22 | description: "An object containing all info about the cleaned file" |
| 27 | schema: | 23 | content: |
| 28 | $ref: '#/definitions/UploadResponse' | 24 | application/json: |
| 25 | schema: | ||
| 26 | $ref: '#/components/schemas/UploadResponse' | ||
| 29 | 400: | 27 | 400: |
| 30 | description: "Invalid input" | 28 | description: "Invalid input" |
| 31 | schema: | 29 | content: |
| 32 | $ref: '#/definitions/ErrorResponse' | 30 | application/json: |
| 31 | schema: | ||
| 32 | $ref: '#/components/schemas/ErrorResponse' | ||
| 33 | 415: | 33 | 415: |
| 34 | description: "Unsupported file type" | 34 | description: "Unsupported file type" |
| 35 | schema: | 35 | content: |
| 36 | $ref: '#/definitions/ErrorResponse' | 36 | application/json: |
| 37 | schema: | ||
| 38 | $ref: '#/components/schemas/ErrorResponse' | ||
| 37 | 500: | 39 | 500: |
| 38 | description: "Unable to clean the file" | 40 | description: "Unable to clean the file" |
| 39 | schema: | 41 | content: |
| 40 | $ref: '#/definitions/ErrorResponse' | 42 | application/json: |
| 41 | 43 | schema: | |
| 42 | definitions: | 44 | $ref: '#/components/schemas/ErrorResponse' \ No newline at end of file |
| 43 | UploadResponse: | ||
| 44 | type: "object" | ||
| 45 | properties: | ||
| 46 | inactive_after_sec: | ||
| 47 | type: "integer" | ||
| 48 | format: "int64" | ||
| 49 | description: "Defines after how many seconds the download wont be available" | ||
| 50 | output_filename: | ||
| 51 | type: "string" | ||
| 52 | description: "The resulting filename after metadata removal" | ||
| 53 | mime: | ||
| 54 | type: "string" | ||
| 55 | description: "The mime type of the cleaned file" | ||
| 56 | key: | ||
| 57 | type: "string" | ||
| 58 | description: "A key used to guarantee file integrity" | ||
| 59 | secret: | ||
| 60 | type: "string" | ||
| 61 | description: "A secret used to guarantee file integrity" | ||
| 62 | meta: | ||
| 63 | type: "object" | ||
| 64 | description: "An object of the removed metadata where key indicates the metadata type" | ||
| 65 | items: | ||
| 66 | type: "string" | ||
| 67 | meta_after: | ||
| 68 | type: "object" | ||
| 69 | description: "An object of the remaining metadata where key indicates the metadata type" | ||
| 70 | items: | ||
| 71 | type: "string" | ||
| 72 | download_link: | ||
| 73 | type: "string" | ||
| 74 | description: "The link to download the cleaned file" | ||
| 75 | ErrorResponse: | ||
| 76 | type: "object" | ||
| 77 | properties: | ||
| 78 | message: | ||
| 79 | type: "string" | ||
| 80 | description: "A description of the error" \ No newline at end of file | ||
diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..ca44124 --- /dev/null +++ b/requirements-test.txt | |||
| @@ -0,0 +1 @@ | |||
| openapi-spec-validator==0.2.8 \ No newline at end of file | |||
diff --git a/requirements.txt b/requirements.txt index 72ad125..b505376 100644 --- a/requirements.txt +++ b/requirements.txt | |||
| @@ -8,4 +8,4 @@ Flask-Cors==3.0.8 | |||
| 8 | Cerberus==1.3.2 | 8 | Cerberus==1.3.2 |
| 9 | Flask-Testing==0.8.0 | 9 | Flask-Testing==0.8.0 |
| 10 | blinker==1.4 | 10 | blinker==1.4 |
| 11 | flasgger==0.9.4 \ No newline at end of file | 11 | iknl-flasgger==0.9.2.post1 \ No newline at end of file |
diff --git a/test/test_api.py b/test/test_api.py index 039245a..be9cb29 100644 --- a/test/test_api.py +++ b/test/test_api.py | |||
| @@ -7,6 +7,7 @@ import zipfile | |||
| 7 | from six import BytesIO | 7 | from six import BytesIO |
| 8 | 8 | ||
| 9 | from unittest.mock import patch | 9 | from unittest.mock import patch |
| 10 | from openapi_spec_validator import validate_spec | ||
| 10 | 11 | ||
| 11 | import main | 12 | import main |
| 12 | 13 | ||
| @@ -420,6 +421,9 @@ class Mat2APITestCase(unittest.TestCase): | |||
| 420 | self.assertEqual(400, request.status_code) | 421 | self.assertEqual(400, request.status_code) |
| 421 | self.assertEqual("Failed decoding file", error_message) | 422 | self.assertEqual("Failed decoding file", error_message) |
| 422 | 423 | ||
| 424 | def test_valid_opena_api_spec(self): | ||
| 425 | spec = self.app.get('apispec_1.json').get_json() | ||
| 426 | validate_spec(spec) | ||
| 423 | 427 | ||
| 424 | if __name__ == '__main__': | 428 | if __name__ == '__main__': |
| 425 | unittest.main() | 429 | unittest.main() |
