from .context import context_adaption from django.conf import settings from django.shortcuts import render, redirect, HttpResponse from django.http import HttpResponseNotFound, HttpResponseForbidden import fstools import importlib import mimetypes from mycreole import url_upload, url_attachment, url_delete import logging import mycreole import os import stringtools import themes from django.contrib import messages try: from config import APP_NAME as ROOT_LOGGER_NAME except ImportError: ROOT_LOGGER_NAME = 'root' logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__) def get_method(import_string): class_data = import_string.split(".") module_path = ".".join(class_data[:-1]) class_str = class_data[-1] # module = importlib.import_module(module_path) return getattr(module, class_str) def get_next(request): if not request.POST: return request.GET.get('next', '/') else: return request.POST.get('next', '/') def access(access_type, request, rel_path): def log_warning(access_type, e): logger.warning('Could not import %s_access method for checking access rights: %s - %s', access_type, type(e).__name__, e) try: method_name = settings.MYCREOLE_ATTACHMENT_ACCESS[access_type] except (AttributeError, KeyError) as e: log_warning(access_type, e) return False else: if method_name in [True, None]: return True elif method_name is False: return False else: try: return get_method(method_name)(request, rel_path) except AttributeError as e: log_warning(access_type, e) return False def mycreole_attachment(request, rel_path): full_path = mycreole.get_full_path(rel_path) if access('read', request, rel_path): if os.path.isfile(full_path): mimetypes.init() mime_type = mimetypes.types_map.get(os.path.splitext(full_path)[1]) data = open(full_path, 'rb').read() return HttpResponse(data, content_type=mime_type) else: return HttpResponseNotFound(rel_path) else: return HttpResponseForbidden(rel_path) def mycreole_upload(request, rel_path): if access('modify', request, rel_path): if not request.POST: context = themes.Context(request) context_adaption( context, request, 'Upload %s' % rel_path, os.path.dirname(rel_path), rel_path_is_directory=os.path.isdir(mycreole.get_full_path(rel_path)), next=request.GET.get('next', '/') ) return render(request, 'mycreole/upload.html', context=context) else: filename = request.POST.get('filename') full_path = mycreole.get_full_path(rel_path) if filename is not None: full_path = os.path.join(full_path, filename) try: os.makedirs(os.path.dirname(full_path), exist_ok=True) except PermissionError: raise PermissionError("Ensure that we have access to MYCREOLE_ROOT=%s" % repr(settings.MYCREOLE_ROOT)) else: with open(full_path, 'wb') as fh: fh.write(request.FILES['file'].read()) messages.info(request, 'File %s successfully uploaded.' % os.path.basename(full_path)) return redirect(request.POST.get('next', '/')) else: messages.error(request, "Upload: Access denied!") return redirect(request.GET.get('next', '/')) def mycreole_delete(request, rel_path): context = themes.Context(request) # needs to be executed first because of time mesurement nxt = get_next(request) modify_access = access('modify', request, rel_path) full_path = mycreole.get_full_path(rel_path) if not modify_access: messages.error(request, 'Detele Attachment: Access denied!') else: if not request.POST: context_adaption( context, request, 'Delete %s' % os.path.basename(rel_path), os.path.dirname(rel_path), next=nxt, filename=os.path.basename(rel_path) ) return render(request, 'mycreole/delete.html', context=context) else: if request.POST.get('yes') is not None: try: os.remove(full_path) except Exception: messages.error(request, 'Error while deleting file from filesystem.') logger.exception('Fatal error while deleting Attachment!') else: messages.info(request, "Attachment %s deleted..." % os.path.basename(full_path)) else: messages.info(request, 'Delete request aborded.') return redirect(nxt) def mycreole_manageuploads(request, rel_path): context = themes.Context(request) # needs to be executed first because of time mesurement nxt = get_next(request) read_access = access('read', request, rel_path) modify_access = access('modify', request, rel_path) # if not read_access: messages.error(request, "Manageupload: Access denied!") return redirect(nxt) basepath = mycreole.get_full_path(rel_path) if not os.path.exists(basepath): logger.info('Creating path for attachments: %s', basepath) fstools.mkdir(basepath) logger.debug("Searching for files in %s", basepath) attachments = {} for file in fstools.filelist(basepath): filename = os.path.basename(file) actions = [] if modify_access: actions.append((themes.gray_icon_url(request, 'delete.png'), url_delete(request, os.path.join(rel_path, filename)), 'delete')) actions.append((themes.gray_icon_url(request, 'shuffle.png'), url_upload(request, os.path.join(rel_path, filename)), 'replace')) actions.append((themes.gray_icon_url(request, 'view.png'), url_attachment(os.path.join(rel_path, filename)), 'view')) attachments[filename] = { 'size': stringtools.physical_value_repr(os.path.getsize(file), 'B'), 'modify_access': modify_access, 'actions': actions, } logger.debug("%d attachments detected: %s", len(attachments), ', '.join(attachments.keys())) # mycreole.context.context_adaption( context, request, 'Manageuploads for %s' % rel_path, rel_path, next=nxt, attachments=attachments ) return render(request, 'mycreole/manageuploads.html', context=context)