Merge pull request #3 from UnstableVortexSecurity/content

Created /content endpoint
This commit is contained in:
Torma Kristóf 2020-11-28 21:01:06 +01:00 committed by GitHub
commit 3ce60047ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 2 deletions

View File

@ -10,7 +10,7 @@ from flask_mail import Mail
from utils import Config from utils import Config
from utils import health_database_status, init_security_real_good from utils import health_database_status, init_security_real_good
from utils import storage from utils import storage
from views import ItemView, ProfileView, UploadView, IndexView from views import ItemView, ProfileView, UploadView, IndexView, ContentView
from models import db from models import db
@ -45,7 +45,7 @@ CORS(app)
Mail(app) Mail(app)
storage.init_app(app) storage.init_app(app)
for view in [ItemView, ProfileView, UploadView, IndexView]: for view in [ItemView, ProfileView, UploadView, IndexView, ContentView]:
view.register(app, trailing_slash=False) view.register(app, trailing_slash=False)
health.add_check(health_database_status) health.add_check(health_database_status)

View File

@ -2,3 +2,4 @@ from .profileview import ProfileView
from .uploadview import UploadView from .uploadview import UploadView
from .itemview import ItemView from .itemview import ItemView
from .indexview import IndexView from .indexview import IndexView
from .contentview import ContentView

50
src/views/contentview.py Normal file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
import string
from flask import abort, Response, current_app
from flask_classful import FlaskView
from flask_security import login_required, current_user
from utils import storage
from minio.error import NoSuchKey
from models import db, Item, Purchase
class ContentView(FlaskView):
"""
This is just a simple content proxy with access control
"""
def _stream_from_minio(self, bucket: str, id_: int, filename: str = None):
try:
data = storage.connection.get_object(bucket, str(id_))
except NoSuchKey:
abort(404)
headers = {}
if filename:
headers['Content-Disposition'] = f'attachment; filename="{filename}"'
return Response(data.stream(), mimetype=data.headers['Content-type'], headers=headers)
def preview(self, id_: int):
i = Item.query.get_or_404(id_)
return self._stream_from_minio(current_app.config['MINIO_PREVIEW_BUCKET_NAME'], i.id)
@login_required
def caff(self, id_: int):
p = Purchase.query.filter(db.and_(Purchase.purchaser_id == current_user.id, Purchase.item_id == id_)).first()
if not p:
abort(403)
allowed_chars = string.ascii_lowercase + string.ascii_uppercase + string.digits
filename = ''.join(filter(lambda x: x in allowed_chars, p.item.name)).lower()
if not filename:
filename = str(p.item.id)
filename += f'_{p.id}.caff'
return self._stream_from_minio(current_app.config['MINIO_CAFF_BUCKET_NAME'], p.item.id, filename)