diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-05-30 17:27:04 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-05-30 17:27:04 +0200 |
| commit | 0890fdd951d021308550a0db2e7b6f2593512957 (patch) | |
| tree | a0050b153242ccde662fc0a957a79fc7a7edc4b4 /cli/app/controllers | |
initial site copied in
Diffstat (limited to 'cli/app/controllers')
| -rw-r--r-- | cli/app/controllers/collection_controller.py | 20 | ||||
| -rw-r--r-- | cli/app/controllers/crud_controller.py | 150 | ||||
| -rw-r--r-- | cli/app/controllers/upload_controller.py | 142 |
3 files changed, 312 insertions, 0 deletions
diff --git a/cli/app/controllers/collection_controller.py b/cli/app/controllers/collection_controller.py new file mode 100644 index 0000000..7206bd8 --- /dev/null +++ b/cli/app/controllers/collection_controller.py @@ -0,0 +1,20 @@ +from flask import request, jsonify, redirect +from flask_classful import route +from werkzeug.datastructures import MultiDict + +from app.sql.common import db, Session +from app.sql.models.collection import Collection, CollectionForm, getMediaCounts +from app.controllers.crud_controller import CrudView + +from app.data.export import export_zip + +class CollectionView(CrudView): + model = Collection + form = CollectionForm + + def on_index(self, session, data): + data['counts'] = getMediaCounts(session) + return data + + def on_destroy(self, session, item): + session.query(CollectionMedia).filter(CollectionMedia.collection_id == item.id).delete(synchronize_session=False) diff --git a/cli/app/controllers/crud_controller.py b/cli/app/controllers/crud_controller.py new file mode 100644 index 0000000..28b2a25 --- /dev/null +++ b/cli/app/controllers/crud_controller.py @@ -0,0 +1,150 @@ +from flask import request, jsonify +from flask_classful import FlaskView, route +from werkzeug.datastructures import MultiDict + +from app.sql.common import db, Session +from app.server.helpers import parse_search_args, parse_sort_args + +class CrudView(FlaskView): + # to subclass CrudView, specify the model + form: + # model = Collection + # form = CollectionForm + index_all = True + excluded_methods = ['on_index', 'on_show', 'on_create', 'on_update', 'on_destroy'] + + # implement these methods: + def on_index(self, session, data): + return data + def on_show(self, session, data): + return data + def on_create(self, session, form, item): + pass + def on_update(self, session, form, item): + pass + def on_destroy(self, session, item): + pass + + def index(self): + """ + List all {model}s + """ + session = Session() + if self.index_all: + items = session.query(self.model).all() + else: + offset, limit = parse_search_args(request.args) + sort, order, order_by, order_by_id = parse_sort_args(request.args, self.model) + query = session.query(self.model) + if order_by_id is not None: + query = query.order_by(order_by, order_by_id) + else: + query = query.order_by(order_by) + items = query.offset(offset).limit(limit).all() + + res = self.on_index(session, { + 'status': 'ok', + 'res': [ item.toJSON() for item in items ], + }) + session.close() + return jsonify(res) + + def get(self, id: int): + """ + Fetch a single {model}. + """ + session = Session() + item = session.query(self.model).get(id) + if not item: + session.close() + return jsonify({ + 'status': 'error', + 'error': 'item not found' + }) + result = self.on_show(session, { + 'status': 'ok', + 'res': item.toFullJSON() if hasattr(item, 'toFullJSON') else item.toJSON(), + }) + session.close() + return jsonify(result) + + def post(self): + """ + Create a new {model}. + + * JSON params: {jsonparams} + """ + session = Session() + raw_form = MultiDict(request.json) if request.json is not None else request.form + form = self.form(raw_form) + if form.validate(): + item = self.model() + form.populate_obj(item) + self.on_create(session, raw_form, item) + session.add(item) + session.commit() + res = { + 'status': 'ok', + 'res': item.toJSON(), + } + else: + res = { + 'error': 'error', + 'errors': form.errors, + } + session.close() + return jsonify(res) + + def put(self, id: int): + """ + Update a {model}. + + * JSON params: {jsonparams} + """ + session = Session() + item = session.query(self.model).get(id) + if item: + raw_form = MultiDict(request.json) if request.json is not None else request.form + form = self.form(raw_form, obj=item) + print(item.toJSON()) + if form.validate(): + form.populate_obj(item) + self.on_update(session, raw_form, item) + session.add(item) + session.commit() + res = { + 'status': 'ok', + 'res': item.toJSON(), + } + else: + res = { + 'status': 'error', + 'error': form.errors, + } + else: + res = { + 'status': 'error', + 'error': 'not found', + } + session.close() + return jsonify(res) + + def delete(self, id: int): + """ + Delete a {model}. + """ + session = Session() + item = session.query(self.model).get(id) + if item: + self.on_destroy(session, item) + session.delete(item) + session.commit() + res = { + 'status': 'ok', + } + else: + res = { + 'status': 'error', + 'error': 'not found', + } + session.close() + return jsonify(res) diff --git a/cli/app/controllers/upload_controller.py b/cli/app/controllers/upload_controller.py new file mode 100644 index 0000000..5463fc6 --- /dev/null +++ b/cli/app/controllers/upload_controller.py @@ -0,0 +1,142 @@ +from flask import request, jsonify +from flask_classful import FlaskView, route +from werkzeug.datastructures import MultiDict +from werkzeug.utils import secure_filename +import os +import numpy as np +import cv2 as cv + +from app.settings import app_cfg +from app.sql.common import db, Session +from app.sql.models.upload import Upload +from app.utils.file_utils import sha256_stream, sha256_tree, VALID_IMAGE_EXTS +from app.server.decorators import APIError + +class UploadView(FlaskView): + def index(self): + """ + List all uploaded files. + + * Query string params: offset, limit, sort (id, date), order (asc, desc) + """ + session = Session() + uploads = session.query(Upload).all() + response = { + 'status': 'ok', + 'res': [ upload.toJSON() for upload in uploads ], + } + session.close() + return jsonify(response) + + def get(self, id): + """ + Fetch a single upload. + """ + session = Session() + upload = session.query(Upload).get(id) + response = { + 'status': 'ok', + 'res': upload.toJSON(), + } + session.close() + return jsonify(response) + + def post(self): + """ + Upload a new file. + + * JSON params: username + """ + + try: + username = request.form.get('username') + except: + raise APIError('No username specified') + + param_name = 'image' + if param_name not in request.files: + raise APIError('No file uploaded') + + file = request.files[param_name] + + # get sha256 + sha256 = sha256_stream(file) + _, ext = os.path.splitext(file.filename) + if ext == '.jpeg': + ext = '.jpg' + + # TODO: here check sha256 + # upload = Upload.query.get(id) + + if ext[1:] not in VALID_IMAGE_EXTS: + return jsonify({ 'status': 'error', 'error': 'Not a valid image' }) + + # convert string of image data to uint8 + file.seek(0) + nparr = np.fromstring(file.read(), np.uint8) + + # decode image + try: + im = cv.imdecode(nparr, cv.IMREAD_COLOR) + except: + return jsonify({ 'status': 'error', 'error': 'Image parse error' }) + + session = Session() + upload = session.query(Upload).filter_by(sha256=sha256).first() + if upload is not None: + print("Already uploaded image") + response = { + 'status': 'ok', + 'notes': 'Image already uploaded', + 'res': upload.toJSON(), + } + session.close() + return jsonify(response) + + uploaded_im_fn = secure_filename(sha256 + ext) + uploaded_im_abspath = os.path.join(app_cfg.DIR_UPLOADS, sha256_tree(sha256)) + uploaded_im_fullpath = os.path.join(uploaded_im_abspath, uploaded_im_fn) + + os.makedirs(uploaded_im_abspath, exist_ok=True) + nparr.tofile(uploaded_im_fullpath) + + upload = Upload(username=username, sha256=sha256, ext=ext) + session.add(upload) + session.commit() + response = { + 'status': 'ok', + 'res': upload.toJSON(), + } + session.close() + return jsonify(response) + + def delete(self, id): + """ + Delete an uploaded file. + """ + session = Session() + upload = session.query(Upload).get(id) + if not upload: + session.close() + return jsonify({ + 'status': 'error', + 'error': 'not found', + }) + + sha256 = upload.sha256 + + uploaded_im_fn = secure_filename(sha256 + upload.ext) + uploaded_im_abspath = os.path.join(app_cfg.DIR_UPLOADS, sha256_tree(sha256)) + uploaded_im_fullpath = os.path.join(uploaded_im_abspath, uploaded_im_fn) + if os.path.exists(uploaded_im_fullpath): + print("Removing " + uploaded_im_fullpath) + os.remove(uploaded_im_fullpath) + + session.delete(upload) + session.commit() + response = { + 'status': 'ok', + 'id': id, + } + session.close() + return jsonify(response) |
