Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feautres (form visibility feature + simple auth + deleting images) #2

Merged
merged 8 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ http://some.host/somename.png?w=320&h=240
```
returns the image cropped to the desired size

Deleting an image, it requires `TOKEN_REQUIRED` to be `True` and `BEARER_TOKEN` set (e.g. `test` like below):
```
curl --location --request DELETE 'http://some.host/somename.png' --header 'Authorization: Bearer test'
```

## Running
imgpush requires docker

Expand Down Expand Up @@ -107,17 +112,20 @@ livenessProbe:


## Configuration
| Setting | Default value | Description |
| ------------- | ------------- |------------- |
| OUTPUT_TYPE | Same as Input file | An image type supported by imagemagick, e.g. png or jpg |
| MAX_SIZE_MB | "16" | Integer, Max size per uploaded file in megabytes |
| MAX_UPLOADS_PER_DAY | "1000" | Integer, max per IP address |
| MAX_UPLOADS_PER_HOUR | "100" | Integer, max per IP address |
| MAX_UPLOADS_PER_MINUTE | "20" | Integer, max per IP address |
| ALLOWED_ORIGINS | "['*']" | array of domains, e.g ['https://a.com'] |
| VALID_SIZES | Any size | array of integers allowed in the h= and w= parameters, e.g "[100,200,300]". You should set this to protect against being bombarded with requests! |
| NAME_STRATEGY | "randomstr" | `randomstr` for random 5 chars, `uuidv4` for UUIDv4 |
| NUDE_FILTER_MAX_THRESHOLD | None | max unsafe value returned from nudenet library(https://github.com/notAI-tech/NudeNet), range is from 0-0.99. Blocks nudity from being uploaded. |
| Setting | Default value | Description |
|---------------------------|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| OUTPUT_TYPE | Same as Input file | An image type supported by imagemagick, e.g. png or jpg |
| MAX_SIZE_MB | "16" | Integer, Max size per uploaded file in megabytes |
| MAX_UPLOADS_PER_DAY | "1000" | Integer, max per IP address |
| MAX_UPLOADS_PER_HOUR | "100" | Integer, max per IP address |
| MAX_UPLOADS_PER_MINUTE | "20" | Integer, max per IP address |
| ALLOWED_ORIGINS | "['*']" | array of domains, e.g ['https://a.com'] |
| VALID_SIZES | Any size | array of integers allowed in the h= and w= parameters, e.g "[100,200,300]". You should set this to protect against being bombarded with requests! |
| NAME_STRATEGY | "randomstr" | `randomstr` for random 5 chars, `uuidv4` for UUIDv4 |
| NUDE_FILTER_MAX_THRESHOLD | None | max unsafe value returned from nudenet library(https://github.com/notAI-tech/NudeNet), range is from 0-0.99. Blocks nudity from being uploaded. |
| SHOW_UPLOAD_FORM | True | Boolean, whether upload form should be displayed | |
| TOKEN_REQUIRED | False | Boolean, if True then upload requests must be authorized | |
| BEARER_TOKEN | None | String, defines token to authorize upload requests when TOKEN_REQUIRED is True | |

Setting configuration variables is all set through env variables that get passed to the docker container.
### Example:
Expand Down
25 changes: 24 additions & 1 deletion app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from flask_cors import CORS
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_httpauth import HTTPTokenAuth
from wand.exceptions import MissingDelegateError
from wand.image import Image
from werkzeug.middleware.proxy_fix import ProxyFix
Expand All @@ -21,6 +22,7 @@

app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
auth = HTTPTokenAuth(scheme='Bearer')

CORS(app, origins=settings.ALLOWED_ORIGINS)
app.config["MAX_CONTENT_LENGTH"] = settings.MAX_SIZE_MB * 1024 * 1024
Expand All @@ -35,6 +37,10 @@
else:
nude_classifier = None

@auth.verify_token
def verify_token(token):
if token == settings.BEARER_TOKEN:
return 'user'

@app.after_request
def after_request(resp):
Expand Down Expand Up @@ -146,12 +152,14 @@ def resize(img, width, height):

@app.route("/", methods=["GET"])
def root():
return """
if settings.SHOW_UPLOAD_FORM:
return """
<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="file" id="file">
<input type="submit" value="Upload" name="submit">
</form>
"""
return Response(status=200)


@app.route("/liveness", methods=["GET"])
Expand All @@ -169,7 +177,11 @@ def liveness():
]
)
)
@auth.login_required(optional=True)
def upload_image():
user = auth.current_user()
if user is None and settings.TOKEN_REQUIRED:
return jsonify(error="Token required"), 403
_clear_imagemagick_temp_files()

random_string = _get_random_filename()
Expand Down Expand Up @@ -219,6 +231,17 @@ def upload_image():

return jsonify(filename=output_filename)

@app.route("/<string:filename>", methods=["DELETE"])
@auth.login_required
def delete_image(filename):
path = os.path.join(settings.IMAGES_DIR, filename)
if os.path.isfile(path):
os.remove(path)
else:
return jsonify(error="File not found"), 404

return Response(status=202)


@app.route("/<string:filename>")
@limiter.exempt
Expand Down
3 changes: 3 additions & 0 deletions app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
MAX_TMP_FILE_AGE = 5 * 60
RESIZE_TIMEOUT = 5
NUDE_FILTER_MAX_THRESHOLD = None
SHOW_UPLOAD_FORM = True
TOKEN_REQUIRED = False
BEARER_TOKEN = None

VALID_SIZES = []

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ filetype==1.0.5
Flask==1.1.1
flask_cors==3.0.9
flask_limiter==1.0.1
flask_httpauth==4.5.0
wand==0.5.7
Werkzeug==0.16.0
gunicorn==19.9.0
Expand Down