import base64 import requests from flask import render_template, redirect, url_for, flash, request, jsonify from flask_atlas_auth import claims_required, current_user from webargs import fields from webargs.flaskparser import use_kwargs from core_notifications.auth.claims import Role from core_notifications.helpers.ordering import QueryOrdering from core_notifications.helpers.pagination import QueryPagination from core_notifications.helpers.s3 import upload_file_to_s3 from core_notifications.logs import logger from core_notifications.models import DNAAccount, Image from core_notifications.settings import Settings from . import images from .forms import ImageForm from .services import ( CreateImageService, ) @images.route("/images", methods=["GET"]) @claims_required([Role(Role.Values.admin)]) @use_kwargs( { "page": fields.Int(load_default=1), "per_page": fields.Int(load_default=Settings.ITEMS_PER_PAGE), "order": fields.Str(load_default=""), }, location="query", ) def list_images(page, per_page, order): ordering = QueryOrdering( Image.query.with_relations(), [Image.id, Image.name, Image.created_at, Image.created_by_name], order, default_is_desc=True, ) pagination = QueryPagination( page=page, per_page=per_page, query=ordering.query ) return render_template( "images/list_images.html", images=pagination.items, ordering=ordering, pagination=pagination, ) @images.route("/images/upload", methods=["GET", "POST"]) @claims_required([Role(Role.Values.admin)]) def upload_image(): is_ajax = "is_ajax" in request.args dna_account = DNAAccount.from_user(current_user) form = ImageForm() if form.validate_on_submit(): file = form.file.data output = upload_file_to_s3(file) if output.is_right: image = CreateImageService.execute( name=output.value, dna_account=dna_account ) if is_ajax: return jsonify( { "success": True, "name": image.name, "url": image.url, "fallbackbase64": url_for( "images.base64_image", image_id=image.id ), } ) else: flash("Successful upload", "positive") else: if is_ajax: return jsonify({"success": False, "error": "Failed upload"}) else: flash("Failed upload", "negative") else: if is_ajax: return jsonify( {"success": False, "error": ", ".join(form.flat_errors)} ) else: flash(", ".join(form.flat_errors), "negative") return redirect(url_for(".list_images")) @images.route("/images/", methods=["GET", "POST"]) @claims_required([Role(Role.Values.admin)]) def view_image(image_id): image = Image.query.get_or_404(image_id) return render_template("images/view_image.html", image=image) @images.route("/images//base64", methods=["GET", "POST"]) @claims_required([Role(Role.Values.admin)]) def base64_image(image_id): """ Fallback endpoint to get image as base64. There are some cors/caching issues on Cloudfront with this. """ image = Image.query.get_or_404(image_id) try: content = base64.b64encode(requests.get(image.url).content) except Exception as e: logger.bind(url=image.url, error=e).warning( "Unable to convert to Base64" ) content = "" return content