182 lines
6.0 KiB
Python
182 lines
6.0 KiB
Python
import datetime
|
|
import os
|
|
import shutil
|
|
import logging
|
|
from sys import getfilesystemencoding
|
|
|
|
from django.utils.decorators import method_decorator
|
|
|
|
from django_http_auth.decorators import http_basic_auth
|
|
|
|
from djangodav.acls import FullAcl
|
|
from djangodav.base.resources import BaseDavResource, MetaEtagMixIn
|
|
from djangodav.locks import DummyLock
|
|
from djangodav.utils import url_join
|
|
from djangodav.views import DavView
|
|
|
|
from procat2.models import Catalog
|
|
|
|
# from procat2.settings import ASSET_DIR
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
fs_encoding = getfilesystemencoding()
|
|
|
|
|
|
@method_decorator(http_basic_auth, name='dispatch')
|
|
class MarkupDavView(DavView):
|
|
|
|
def __init__(self):
|
|
super(DavView, self).__init__(resource_class=MarkupDavResource, lock_class=DummyLock, acl_class=FullAcl)
|
|
|
|
|
|
class MarkupDavResource(MetaEtagMixIn, BaseDavResource):
|
|
ROOT_FOLDER = ''
|
|
MY_CATS_FOLDER = 'My Catalogs'
|
|
MARKUP_SUBMIT_FOLDER = 'For Markup'
|
|
#root = '/opt/imagebank/mkbeta/webdav' # TODO replace with settings var
|
|
|
|
def __init__(self, path=None, user=None):
|
|
super().__init__(path)
|
|
self.user = user
|
|
|
|
def __str__(self):
|
|
return f"<MarkupDavResource '{self.user}' '{self.path}'>"
|
|
|
|
def get_children(self):
|
|
"""Return an iterator of all direct children of this resource."""
|
|
# make sure the current object is a directory
|
|
path = self.get_path()
|
|
log.info(f"get_children of '{path}'")
|
|
|
|
children = []
|
|
if path == '/':
|
|
children = [self.MY_CATS_FOLDER, self.MARKUP_SUBMIT_FOLDER]
|
|
elif path == f'/{self.MY_CATS_FOLDER}/':
|
|
children = self.user_catalogs()
|
|
elif path == f'/{self.MARKUP_SUBMIT_FOLDER}/':
|
|
children = None
|
|
# else:
|
|
# path = self.get_abs_path()
|
|
# if os.path.isdir(path):
|
|
# children = os.listdir(path)
|
|
|
|
for child in children:
|
|
is_unicode = isinstance(child, str)
|
|
if not is_unicode:
|
|
child = child.decode(fs_encoding)
|
|
child_resource = self.clone(path=url_join(*(self.path + [child])), user=self.user)
|
|
log.info(f'returning kid {child_resource}')
|
|
yield child_resource
|
|
|
|
def user_catalogs(self):
|
|
cats = Catalog.objects.filter(owner=self.user).order_by('-updated')
|
|
return [c.name for c in cats]
|
|
|
|
def get_abs_path(self):
|
|
"""Return the absolute path of the resource. Used internally to interface with
|
|
an actual file system. If you override all other methods, this one will not
|
|
be used."""
|
|
return os.path.join(self.root, *self.path)
|
|
|
|
@property
|
|
def getcontentlength(self):
|
|
"""Return the size of the resource in bytes."""
|
|
if self.is_collection:
|
|
return 0
|
|
else:
|
|
return os.path.getsize(self.get_abs_path())
|
|
|
|
def get_created(self):
|
|
"""Return the create time as datetime object."""
|
|
if self.is_collection:
|
|
return datetime.datetime.now() # TODO last created time of object in there?
|
|
else:
|
|
return datetime.datetime.fromtimestamp(os.stat(self.get_abs_path()).st_ctime)
|
|
|
|
def get_modified(self):
|
|
"""Return the modified time as datetime object."""
|
|
if self.is_collection:
|
|
return datetime.datetime.now() # TODO last modified time of object in there?
|
|
else:
|
|
return datetime.datetime.fromtimestamp(os.stat(self.get_abs_path()).st_mtime)
|
|
|
|
@property
|
|
def is_collection(self):
|
|
"""Return True if this resource is a directory (collection in WebDAV parlance)."""
|
|
path = '/'.join(self.path)
|
|
# log.info(f"is_collection {self.path}")
|
|
|
|
if path in [self.ROOT_FOLDER, self.MY_CATS_FOLDER, self.MARKUP_SUBMIT_FOLDER]:
|
|
return True
|
|
|
|
return False
|
|
# return os.path.isdir(self.get_abs_path())
|
|
|
|
@property
|
|
def is_object(self):
|
|
"""Return True if this resource is a file (resource in WebDAV parlance)."""
|
|
path = '/'.join(self.path)
|
|
log.info(f"is_object {path}")
|
|
|
|
if self.is_collection:
|
|
return False
|
|
|
|
# TODO test catalog pdf
|
|
return True
|
|
#return os.path.isfile(self.get_abs_path())
|
|
|
|
@property
|
|
def exists(self):
|
|
"""Return True if this resource exists."""
|
|
path = '/'.join(self.path)
|
|
log.info(f"exists {path}")
|
|
|
|
if self.is_collection:
|
|
return True
|
|
|
|
# TODO test catalog pdf
|
|
return os.path.exists(self.get_abs_path())
|
|
|
|
# def write(self, content, temp_file=None, range_start=None):
|
|
# raise NotImplementedError
|
|
|
|
# def read(self):
|
|
# raise NotImplementedError
|
|
|
|
# def delete(self):
|
|
# """Delete the resource, recursive is implied."""
|
|
# if self.is_collection:
|
|
# for child in self.get_children():
|
|
# child.delete()
|
|
# os.rmdir(self.get_abs_path())
|
|
# elif self.is_object:
|
|
# os.remove(self.get_abs_path())
|
|
|
|
# def create_collection(self):
|
|
# """Create a directory in the location of this resource."""
|
|
# os.mkdir(self.get_abs_path())
|
|
|
|
# def copy_object(self, destination, depth=0):
|
|
# shutil.copy(self.get_abs_path(), destination.get_abs_path())
|
|
|
|
# def move_object(self, destination):
|
|
# os.rename(self.get_abs_path(), destination.get_abs_path())
|
|
|
|
# def read(self):
|
|
# return open(self.get_abs_path(), 'rb')
|
|
|
|
# def write(self, request, temp_file=None, range_start=None):
|
|
# if temp_file:
|
|
# # move temp file (e.g., coming from nginx)
|
|
# shutil.move(temp_file, self.get_abs_path())
|
|
# elif range_start == None:
|
|
# # open binary file and write to disk
|
|
# with open(self.get_abs_path(), 'wb') as dst:
|
|
# shutil.copyfileobj(request, dst)
|
|
# else:
|
|
# # open binary file and write to disk
|
|
# with open(self.get_abs_path(), 'r+b') as dst:
|
|
# dst.seek(range_start)
|
|
# shutil.copyfileobj(request, dst)
|