Source code for fardel.core.panel.views.media

"""

Objects
=======

1. File
    :name: 
    :url:
    :path:


2. Directory
    :name: Name of the directory
    :path: Path of the folder


"""

import os

from flask import request, current_app
from flask_jwt_extended import jwt_required

from fardel.core.rest import create_api, abort, Resource
from fardel.ext import db

from .. import mod, staff_required_rest, permission_required
from ...base import BaseResource
from ...media.models import File


panel_media_api = create_api(mod)

panel_decorators = [staff_required_rest, jwt_required]

def rest_resource(resource_cls):
    """ Decorator for adding resources to Api App """
    panel_media_api.add_resource(resource_cls, *resource_cls.endpoints)
    return resource_cls


def is_safe_path(basedir, path, follow_symlinks=True):
    # resolves symbolic links
    if follow_symlinks:
        return os.path.realpath(path).startswith(basedir)
    return os.path.abspath(path).startswith(basedir)


[docs]@rest_resource class FileApi(Resource): """ :URL: ``/api/panel/files/`` """ endpoints = ['/files/'] method_decorators = { 'get': [permission_required('can_see_directory')] + panel_decorators, 'post': [permission_required('can_create_files')] + panel_decorators, 'delete': [permission_required('can_delete_files')] + panel_decorators, }
[docs] def get(self): """ Directory listing of upload folder :user permission required: can_see_directory """ uploads_folder = current_app.config['UPLOAD_FOLDER'] path = request.args.get('path', '') lookup_folder = uploads_folder / path if not os.path.exists(str(os.getcwd() / lookup_folder)): return {"message": "No such a folder"}, 404 if is_safe_path(str(os.getcwd() / uploads_folder), str(lookup_folder)): response = {'files': [], 'directories':[]} for obj in os.listdir(lookup_folder): if os.path.isdir(lookup_folder / obj): response['directories'].append({'name':obj, 'path':os.path.join(path, obj)}) else: file = File(path, file_name=obj) file = { 'name':obj, 'url':file.url, 'path':os.path.join(path, obj) } response['files'].append(file) return response return {"message":"Invalid path"}, 422
[docs] def post(self): """ To create file """ file = request.files.get('file') path = request.form.get('path', '') if not file: return {"message":"No file to upload"}, 422 uploads_folder = current_app.config['UPLOAD_FOLDER'] lookup_folder = uploads_folder / path if is_safe_path(str(os.getcwd() / lookup_folder), str(lookup_folder)): file = File(path, file=file) file.save() return {'message':'File saved successfully', 'file':{"url":file.url}} return {"message":"Invalid path"}, 422
[docs] def delete(self): """ To delete file """ data = request.get_json() if not data.get('url'): return {"message": "No file url specified"}, 422 url = data['url'] path_to_file = current_app.config['UPLOAD_FOLDER'] / url.replace('/uploads/', '', 1) if os.path.isdir(path_to_file): try: os.rmdir(path_to_file) except: return {"message":"Directory must be empty"}, 422 return {"message":"File deleted successfully"} if os.path.isfile(path_to_file): os.remove(path_to_file) return {"message":"File deleted successfully"} return {"message":"File not found"}, 404
[docs]@rest_resource class ImageAlbumApi(BaseResource): """ :URL: ``/api/panel/image_album/`` """ endpoints = ['/image_album/'] method_decorators = { 'get': [permission_required('can_see_directory')] + panel_decorators, 'post': [permission_required('can_create_files')] + panel_decorators, 'delete': [permission_required('can_delete_files')] + panel_decorators, }
[docs] def get(self): """ Directory listing of upload folder """ uploads_folder = current_app.config['UPLOAD_FOLDER'] path = 'images' lookup_folder = uploads_folder / path response = {'images': []} for obj in os.listdir(lookup_folder): if not os.path.isdir(lookup_folder / obj): file = File(path, file_name=obj) file = {'name':obj, 'url':file.url} response['images'].append(file) return response
[docs] def post(self): """ To create file """ file = request.files.get('file') path = 'images' if not file: return {"message":"No file to upload"}, 422 uploads_folder = current_app.config['UPLOAD_FOLDER'] lookup_folder = uploads_folder / path file = File(path, file=file) file.save() return {'message':'Image saved successfully', 'file':{"url":file.url}}
[docs] def delete(self): """ To delete file """ data = request.get_json() if not data.get('url'): return {"message": "No file url specified"}, 422 url = data['url'] path_to_file = current_app.config['UPLOAD_FOLDER'] / url.replace('/uploads', 'images', 1) if os.path.isfile(path_to_file): os.remove(path_to_file) return {"message":"Image deleted successfully"} return {"message":"Image not found"}, 404