def put(self):
        """
        This endpoint is used to upload user avatar. All avatars are named after the user's id
        in such format: user_{id}.{ext}.
        It will overwrite the existing avatar.
        """
        data = image_schema.load(request.files)
        filename = f"user_{g.user.id}"
        folder = "avatars"
        avatar_path = image_helper.find_image_any_format(filename, folder)
        if avatar_path:
            try:
                os.remove(avatar_path)
            except:
                return {"message": gettext("avatar_delete_failed")}, 500

        try:
            ext = image_helper.get_extension(data[0]["image"].filename)
            avatar = filename + ext  # use our naming format + true extension
            avatar_path = image_helper.save_image(
                data[0]["image"], folder=folder, name=avatar
            )
            basename = image_helper.get_basename(avatar_path)
            return {"message": gettext("avatar_uploaded").format(basename)}, 200
        except UploadNotAllowed:  # forbidden file type
            extension = image_helper.get_extension(data[0]["image"])
            return {"message": gettext("image_illegal_extension").format(extension)}, 400
 def get(self, filename: str):
     """
     This endpoint returns the requested image if exists. It will use JWT to
     retrieve user information and look for the image inside the user's folder.
     """
     user_id = g.user.id
     folder = f"user_{user_id}"
     # check if filename is URL secure
     if not image_helper.is_filename_safe(filename):
         return {"message": gettext("image_illegal_file_name").format(filename)}, 400
     try:
         # try to send the requested file to the user with status code 200
         return send_file(image_helper.get_path(filename, folder=folder))
     except FileNotFoundError:
         return {"message": gettext("image_not_found").format(filename)}, 404
 def get(cls, user_id: int):
     """
     This endpoint returns the avatar of the user specified by user_id.
     """
     folder = "avatars"
     filename = f"user_{user_id}"
     avatar = image_helper.find_image_any_format(filename, folder)
     if avatar:
         return send_file(avatar)
     return {"message": gettext("avatar_not_found")}, 404
    def delete(self, filename: str):
        """
        This endpoint is used to delete the requested image under the user's folder.
        It uses the JWT to retrieve user information.
        """
        user_id = g.user.id
        folder = f"user_{user_id}"

        # check if filename is URL secure
        if not image_helper.is_filename_safe(filename):
            return {"message": gettext("image_illegal_file_name").format(filename)}, 400

        try:
            os.remove(image_helper.get_path(filename, folder=folder))
            return {"message": gettext("image_deleted").format(filename)}, 200
        except FileNotFoundError:
            return {"message": gettext("image_not_found").format(filename)}, 404
        except:
            traceback.print_exc()
            return {"message": gettext("image_delete_failed")}, 500
 def post(self):
     """
     This endpoint is used to upload an image file. It uses the
     JWT to retrieve user information and save the image in the user's folder.
     If a file with the same name exists in the user's folder, name conflicts
     will be automatically resolved by appending a underscore and a smallest
     unused integer. (eg. filename.png to filename_1.png).
     """
     data = image_schema.load(request.files)
     user_id = g.user.id
     folder = f"user_{user_id}"
     try:
         # save(self, storage, folder=None, name=None)
         image_path = image_helper.save_image(data[0]['image'], folder=folder)
         # here we only return the basename of the image and hide the internal folder structure from our user
         basename = image_helper.get_basename(image_path)
         return {"message": gettext("image_uploaded").format(basename)}, 201
     except UploadNotAllowed:  # forbidden file type
         extension = image_helper.get_extension(data["image"])
         return {"message": gettext("image_illegal_extension").format(extension)}, 400