Verified Commit dfb4cfea authored by Eliot Berriot's avatar Eliot Berriot
Browse files

WIP

parent 9d7cd006
......@@ -13,6 +13,7 @@ urlpatterns = [
# Django Admin, use {% url 'admin:index' %}
url(settings.ADMIN_URL, admin.site.urls),
url(r"^api/", include(("config.api_urls", "api"), namespace="api")),
url(r"^dav/", include(("funkwhale_api.webdav.urls", "webdav"), namespace="webdav")),
url(
r"^",
include(
......
......@@ -9,7 +9,7 @@ from django import urls
from . import preferences
from . import utils
EXCLUDED_PATHS = ["/api", "/federation", "/.well-known"]
EXCLUDED_PATHS = ["/api", "/federation", "/.well-known", "/dav", "/rest"]
def should_fallback_to_spa(path):
......
from __future__ import unicode_literals
from django.utils import six
from django.utils.xmlutils import SimplerXMLGenerator
from django.utils.six.moves import StringIO
from django.utils.encoding import smart_text
from rest_framework.renderers import BaseRenderer
DATA = """<?xml version="1.0" encoding="utf-8"?>
<d:multistatus xmlns:d="DAV:">
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype>
<d:collection />
</d:resourcetype>
<d:displayname>Products</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:quota-available-bytes>102312153088</d:quota-available-bytes>
<d:quota-used-bytes>26520371200</d:quota-used-bytes>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:getcontenttype />
<d:getcontentlength />
<d:checked-in />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.doc</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype />
<d:displayname>General.doc</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:getcontenttype>application/msword</d:getcontenttype>
<d:getcontentlength>10752</d:getcontentlength>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:checked-in>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.doc?version=1</d:href>
</d:checked-in>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:quota-available-bytes />
<d:quota-used-bytes />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.vsd</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype />
<d:displayname>General.vsd</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:getcontenttype>application/x-visio</d:getcontenttype>
<d:getcontentlength>0</d:getcontentlength>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:checked-in>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.vsd?version=1</d:href>
</d:checked-in>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:quota-available-bytes />
<d:quota-used-bytes />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/Product.mpp</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype />
<d:displayname>Product.mpp</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:getcontenttype>application/vnd.ms-project</d:getcontenttype>
<d:getcontentlength>114176</d:getcontentlength>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:checked-in>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/Product.mpp?version=1</d:href>
</d:checked-in>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:quota-available-bytes />
<d:quota-used-bytes />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
</d:multistatus>
"""
class WebDAVXMLRenderer(BaseRenderer):
"""
Renders WebDAV-compliant XML
"""
media_type = "application/xml"
format = "xml"
charset = "utf-8"
item_tag_name = "list-item"
root_tag_name = "multistatus"
def render(self, data, accepted_media_type=None, renderer_context=None):
"""
Renders `data` into serialized XML.
"""
return DATA.encode("utf-8")
if data is None:
return ""
stream = StringIO()
xml = SimplerXMLGenerator(stream, self.charset)
xml.startDocument()
xml.startElement(self.root_tag_name, {})
self._to_xml(xml, data)
xml.endElement(self.root_tag_name)
xml.endDocument()
return stream.getvalue()
def _to_xml(self, xml, data):
if isinstance(data, (list, tuple)):
for item in data:
self._to_xml(xml, item)
elif isinstance(data, dict):
for key, value in six.iteritems(data):
if isinstance(value, ElementList):
for innerval in value:
xml.startElement(key, {})
self._to_xml(xml, innerval)
xml.endElement(key)
if isinstance(value, ElementGroup):
for innerkey, innerval in value.items():
xml.startElement(key, {}) # key=<propstat>
self._to_xml(xml, innerval)
xml.startElement(innerkey[0], {})
self._to_xml(xml, innerkey[1])
xml.endElement(innerkey[0])
xml.endElement(key)
else:
xml.startElement(key, {})
self._to_xml(xml, value)
xml.endElement(key)
elif data is None:
# Don't output any value
pass
else:
xml.characters(smart_text(data))
from django.conf.urls import url
from . import views
urlpatterns = [url(r"^libraries/(?P<path>.*)$", views.LibraryViewSet.as_view())]
from rest_framework import response, mixins, viewsets
from . import renderers
WEBDAV_METHODS = [
"get",
"put",
"lock",
"unlock",
"propfind",
"proppatch",
"delete",
"head",
"options",
"mkcol",
"copy",
"move",
]
ACTIONS = {m: "action_{}".format(m) for m in WEBDAV_METHODS}
class WebDAVViewSet(viewsets.GenericViewSet):
http_method_names = WEBDAV_METHODS
renderer_classes = (renderers.WebDAVXMLRenderer,)
def dispatch(self, request, *args, **kwargs):
print("BODY", request.body)
response = super().dispatch(request, *args, **kwargs)
response["DAV"] = "1"
return response
@classmethod
def as_view(cls, *args, **kwargs):
actions = {}
for method in WEBDAV_METHODS:
handler_name = "action_{}".format(method)
if hasattr(cls, handler_name):
actions[method] = handler_name
kwargs["actions"] = actions
return super().as_view(*args, **kwargs)
class LibraryViewSet(WebDAVViewSet):
authentication_classes = []
permission_classes = []
def action_propfind(self, request, *args, **kwargs):
return response.Response({})
def action_options(self, request, *args, **kwargs):
return response.Response({})
def action_get(self, request, *args, **kwargs):
return response.Response({})
def action_put(self, request, *args, **kwargs):
return response.Response({})
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment