Django Library Mycreole
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

views.py 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. from .context import context_adaption
  2. from django.conf import settings
  3. from django.shortcuts import render, redirect, HttpResponse
  4. from django.http import HttpResponseNotFound, HttpResponseForbidden
  5. import fstools
  6. import importlib
  7. import mimetypes
  8. from mycreole import url_upload, url_attachment, url_delete
  9. import logging
  10. import mycreole
  11. import os
  12. import stringtools
  13. import themes
  14. from django.contrib import messages
  15. try:
  16. from config import APP_NAME as ROOT_LOGGER_NAME
  17. except ImportError:
  18. ROOT_LOGGER_NAME = 'root'
  19. logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
  20. def get_method(import_string):
  21. class_data = import_string.split(".")
  22. module_path = ".".join(class_data[:-1])
  23. class_str = class_data[-1]
  24. #
  25. module = importlib.import_module(module_path)
  26. return getattr(module, class_str)
  27. def get_next(request):
  28. if not request.POST:
  29. return request.GET.get('next', '/')
  30. else:
  31. return request.POST.get('next', '/')
  32. def access(access_type, request, rel_path):
  33. def log_warning(access_type, e):
  34. logger.warning('Could not import %s_access method for checking access rights: %s - %s', access_type, type(e).__name__, e)
  35. try:
  36. method_name = settings.MYCREOLE_ATTACHMENT_ACCESS[access_type]
  37. except (AttributeError, KeyError) as e:
  38. log_warning(access_type, e)
  39. return False
  40. else:
  41. if method_name in [True, None]:
  42. return True
  43. elif method_name is False:
  44. return False
  45. else:
  46. try:
  47. return get_method(method_name)(request, rel_path)
  48. except AttributeError as e:
  49. log_warning(access_type, e)
  50. return False
  51. def mycreole_attachment(request, rel_path):
  52. full_path = mycreole.get_full_path(rel_path)
  53. if access('read', request, rel_path):
  54. if os.path.isfile(full_path):
  55. mimetypes.init()
  56. mime_type = mimetypes.types_map.get(os.path.splitext(full_path)[1])
  57. data = open(full_path, 'rb').read()
  58. return HttpResponse(data, content_type=mime_type)
  59. else:
  60. return HttpResponseNotFound(rel_path)
  61. else:
  62. return HttpResponseForbidden(rel_path)
  63. def mycreole_upload(request, rel_path):
  64. if access('modify', request, rel_path):
  65. if not request.POST:
  66. context = themes.Context(request)
  67. context_adaption(
  68. context,
  69. request,
  70. 'Upload %s' % rel_path,
  71. os.path.dirname(rel_path),
  72. rel_path_is_directory=os.path.isdir(mycreole.get_full_path(rel_path)),
  73. next=request.GET.get('next', '/')
  74. )
  75. return render(request, 'mycreole/upload.html', context=context)
  76. else:
  77. filename = request.POST.get('filename')
  78. full_path = mycreole.get_full_path(rel_path)
  79. if filename is not None:
  80. full_path = os.path.join(full_path, filename)
  81. try:
  82. os.makedirs(os.path.dirname(full_path), exist_ok=True)
  83. except PermissionError:
  84. raise PermissionError("Ensure that we have access to MYCREOLE_ROOT=%s" % repr(settings.MYCREOLE_ROOT))
  85. else:
  86. with open(full_path, 'wb') as fh:
  87. fh.write(request.FILES['file'].read())
  88. messages.info(request, 'File %s successfully uploaded.' % os.path.basename(full_path))
  89. return redirect(request.POST.get('next', '/'))
  90. else:
  91. messages.error(request, "Upload: Access denied!")
  92. return redirect(request.GET.get('next', '/'))
  93. def mycreole_delete(request, rel_path):
  94. context = themes.Context(request) # needs to be executed first because of time mesurement
  95. nxt = get_next(request)
  96. modify_access = access('modify', request, rel_path)
  97. full_path = mycreole.get_full_path(rel_path)
  98. if not modify_access:
  99. messages.error(request, 'Detele Attachment: Access denied!')
  100. else:
  101. if not request.POST:
  102. context_adaption(
  103. context,
  104. request,
  105. 'Delete %s' % os.path.basename(rel_path),
  106. os.path.dirname(rel_path),
  107. next=nxt,
  108. filename=os.path.basename(rel_path)
  109. )
  110. return render(request, 'mycreole/delete.html', context=context)
  111. else:
  112. if request.POST.get('yes') is not None:
  113. try:
  114. os.remove(full_path)
  115. except Exception:
  116. messages.error(request, 'Error while deleting file from filesystem.')
  117. logger.exception('Fatal error while deleting Attachment!')
  118. else:
  119. messages.info(request, "Attachment %s deleted..." % os.path.basename(full_path))
  120. else:
  121. messages.info(request, 'Delete request aborded.')
  122. return redirect(nxt)
  123. def mycreole_manageuploads(request, rel_path):
  124. context = themes.Context(request) # needs to be executed first because of time mesurement
  125. nxt = get_next(request)
  126. read_access = access('read', request, rel_path)
  127. modify_access = access('modify', request, rel_path)
  128. #
  129. if not read_access:
  130. messages.error(request, "Manageupload: Access denied!")
  131. return redirect(nxt)
  132. basepath = mycreole.get_full_path(rel_path)
  133. if not os.path.exists(basepath):
  134. logger.info('Creating path for attachments: %s', basepath)
  135. fstools.mkdir(basepath)
  136. logger.debug("Searching for files in %s", basepath)
  137. attachments = {}
  138. for file in fstools.filelist(basepath):
  139. filename = os.path.basename(file)
  140. actions = []
  141. if modify_access:
  142. actions.append((themes.gray_icon_url(request, 'delete.png'), url_delete(request, os.path.join(rel_path, filename)), 'delete'))
  143. actions.append((themes.gray_icon_url(request, 'shuffle.png'), url_upload(request, os.path.join(rel_path, filename)), 'replace'))
  144. actions.append((themes.gray_icon_url(request, 'view.png'), url_attachment(os.path.join(rel_path, filename)), 'view'))
  145. attachments[filename] = {
  146. 'size': stringtools.physical_value_repr(os.path.getsize(file), 'B'),
  147. 'modify_access': modify_access,
  148. 'actions': actions,
  149. }
  150. logger.debug("%d attachments detected: %s", len(attachments), ', '.join(attachments.keys()))
  151. #
  152. mycreole.context.context_adaption(
  153. context,
  154. request,
  155. 'Manageuploads for %s' % rel_path,
  156. rel_path,
  157. next=nxt,
  158. attachments=attachments
  159. )
  160. return render(request, 'mycreole/manageuploads.html', context=context)