Compare commits

...

2 Commits

Author SHA1 Message Date
6948220746 Progress 2025-04-03 08:35:25 +02:00
d10768403d Progress. 2025-04-03 08:34:25 +02:00
21 changed files with 246 additions and 93 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.r_history
.vscode .vscode
.history .history
.resources .resources

View File

@ -1,3 +1 @@

View File

@ -1,5 +1,6 @@
from aiohttp import web from aiohttp import web
from snek.app import Application from snek.app import Application
if __name__ == '__main__': if __name__ == "__main__":
web.run_app(Application(), port=8081,host='0.0.0.0') web.run_app(Application(), port=8081, host="0.0.0.0")

View File

@ -3,6 +3,7 @@ import logging
import pathlib import pathlib
import time import time
import uuid import uuid
from snek.view.threads import ThreadsView from snek.view.threads import ThreadsView
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
@ -24,7 +25,7 @@ from snek.service import get_services
from snek.system import http from snek.system import http
from snek.system.cache import Cache from snek.system.cache import Cache
from snek.system.markdown import MarkdownExtension from snek.system.markdown import MarkdownExtension
from snek.system.middleware import cors_middleware from snek.system.middleware import auth_middleware, cors_middleware
from snek.system.profiler import profiler_handler from snek.system.profiler import profiler_handler
from snek.system.template import EmojiExtension, LinkifyExtension, PythonExtension from snek.system.template import EmojiExtension, LinkifyExtension, PythonExtension
from snek.view.about import AboutHTMLView, AboutMDView from snek.view.about import AboutHTMLView, AboutMDView
@ -37,12 +38,13 @@ from snek.view.logout import LogoutView
from snek.view.register import RegisterView from snek.view.register import RegisterView
from snek.view.rpc import RPCView from snek.view.rpc import RPCView
from snek.view.search_user import SearchUserView from snek.view.search_user import SearchUserView
from snek.view.settings.index import SettingsIndexView
from snek.view.settings.profile import SettingsProfileView
from snek.view.status import StatusView from snek.view.status import StatusView
from snek.view.terminal import TerminalSocketView, TerminalView from snek.view.terminal import TerminalSocketView, TerminalView
from snek.view.upload import UploadView from snek.view.upload import UploadView
from snek.view.web import WebView from snek.view.web import WebView
from snek.webdav import WebdavApplication from snek.webdav import WebdavApplication
from snek.view.settings import SettingsView
SESSION_KEY = b"c79a0c5fda4b424189c427d28c9f7c34" SESSION_KEY = b"c79a0c5fda4b424189c427d28c9f7c34"
@ -76,6 +78,7 @@ class Application(BaseApplication):
session_setup(self, EncryptedCookieStorage(SESSION_KEY)) session_setup(self, EncryptedCookieStorage(SESSION_KEY))
self.tasks = asyncio.Queue() self.tasks = asyncio.Queue()
self._middlewares.append(session_middleware) self._middlewares.append(session_middleware)
self._middlewares.append(auth_middleware)
self.jinja2_env.add_extension(MarkdownExtension) self.jinja2_env.add_extension(MarkdownExtension)
self.jinja2_env.add_extension(LinkifyExtension) self.jinja2_env.add_extension(LinkifyExtension)
self.jinja2_env.add_extension(PythonExtension) self.jinja2_env.add_extension(PythonExtension)
@ -138,7 +141,9 @@ class Application(BaseApplication):
self.router.add_view("/docs.html", DocsHTMLView) self.router.add_view("/docs.html", DocsHTMLView)
self.router.add_view("/docs.md", DocsMDView) self.router.add_view("/docs.md", DocsMDView)
self.router.add_view("/status.json", StatusView) self.router.add_view("/status.json", StatusView)
self.router.add_view("/settings.html", SettingsView) self.router.add_view("/settings/index.html", SettingsIndexView)
self.router.add_view("/settings/profile.html", SettingsProfileView)
self.router.add_view("/settings/profile.json", SettingsProfileView)
self.router.add_view("/web.html", WebView) self.router.add_view("/web.html", WebView)
self.router.add_view("/login.html", LoginView) self.router.add_view("/login.html", LoginView)
self.router.add_view("/login.json", LoginView) self.router.add_view("/login.json", LoginView)
@ -189,8 +194,8 @@ class Application(BaseApplication):
channels = [] channels = []
if not context: if not context:
context = {} context = {}
context['rid'] = str(uuid.uuid4()) context["rid"] = str(uuid.uuid4())
if request.session.get("uid"): if request.session.get("uid"):
async for subscribed_channel in self.services.channel_member.find( async for subscribed_channel in self.services.channel_member.find(
user_uid=request.session.get("uid"), deleted_at=None, is_banned=False user_uid=request.session.get("uid"), deleted_at=None, is_banned=False

View File

@ -0,0 +1,14 @@
from snek.system.form import Form, FormInputElement, FormButtonElement, HTMLElement
class SettingsProfileForm(Form):
nick = FormInputElement(name="nick", required=True, place_holder="Your Nickname", min_length=1, max_length=20)
action = FormButtonElement(
name="action", value="submit", text="Save", type="button"
)
title = HTMLElement(tag="h1", text="Profile")
profile = FormInputElement(name="profile", place_holder="Tell about yourself.", required=False,max_length=300)
action = FormButtonElement(
name="action", value="submit", text="Save", type="button"
)

View File

@ -7,6 +7,7 @@ from snek.mapper.drive import DriveMapper
from snek.mapper.drive_item import DriveItemMapper from snek.mapper.drive_item import DriveItemMapper
from snek.mapper.notification import NotificationMapper from snek.mapper.notification import NotificationMapper
from snek.mapper.user import UserMapper from snek.mapper.user import UserMapper
from snek.mapper.user_property import UserPropertyMapper
from snek.system.object import Object from snek.system.object import Object
@ -21,6 +22,7 @@ def get_mappers(app=None):
"notification": NotificationMapper(app=app), "notification": NotificationMapper(app=app),
"drive_item": DriveItemMapper(app=app), "drive_item": DriveItemMapper(app=app),
"drive": DriveMapper(app=app), "drive": DriveMapper(app=app),
"user_property": UserPropertyMapper(app=app),
} }
) )

View File

@ -0,0 +1,7 @@
from snek.model.user_property import UserPropertyModel
from snek.system.mapper import BaseMapper
class UserPropertyMapper(BaseMapper):
table_name = "user_property"
model_class = UserPropertyModel

View File

@ -5,7 +5,11 @@ from snek.model.channel_member import ChannelMemberModel
# from snek.model.channel_message import ChannelMessageModel # from snek.model.channel_message import ChannelMessageModel
from snek.model.channel_message import ChannelMessageModel from snek.model.channel_message import ChannelMessageModel
from snek.model.drive import DriveModel
from snek.model.drive_item import DriveItemModel
from snek.model.notification import NotificationModel
from snek.model.user import UserModel from snek.model.user import UserModel
from snek.model.user_property import UserPropertyModel
from snek.system.object import Object from snek.system.object import Object
@ -17,6 +21,10 @@ def get_models():
"channel_member": ChannelMemberModel, "channel_member": ChannelMemberModel,
"channel": ChannelModel, "channel": ChannelModel,
"channel_message": ChannelMessageModel, "channel_message": ChannelMessageModel,
"drive_item": DriveItemModel,
"drive": DriveModel,
"notification": NotificationModel,
"user_property": UserPropertyModel,
} }
) )

View File

@ -0,0 +1,10 @@
import mimetypes
from snek.system.model import BaseModel, ModelField
class UserPropertyModel(BaseModel):
user_uid = ModelField(name="user_uid", required=True, kind=str)
name = ModelField(name="name", required=True, kind=str)
value = ModelField(name="path", required=True, kind=str)

View File

@ -28,6 +28,16 @@ async def cors_allow_middleware(request, handler):
return response return response
@web.middleware
async def auth_middleware(request, handler):
request["user"] = None
if request.session.get("uid") and request.session.get("logged_in"):
request["user"] = await request.app.services.user.get(
uid=request.app.session.get("uid")
)
return await handler(request)
@web.middleware @web.middleware
async def cors_middleware(request, handler): async def cors_middleware(request, handler):
if request.headers.get("Allow"): if request.headers.get("Allow"):

View File

@ -31,7 +31,7 @@
<a class="no-select" href="/search-user.html">🔍</a> <a class="no-select" href="/search-user.html">🔍</a>
<a class="no-select" style="display:none" id="install-button" href="#">📥</a> <a class="no-select" style="display:none" id="install-button" href="#">📥</a>
<a class="no-select" href="/threads.html">👥</a> <a class="no-select" href="/threads.html">👥</a>
<a class="no-select" href="#">⚙️</a> <a class="no-select" href="/settings/index.html">⚙️</a>
<a class="no-select" href="/logout.html">đź”’</a> <a class="no-select" href="/logout.html">đź”’</a>
</nav> </nav>

View File

@ -0,0 +1,13 @@
<div>
<div class="logo no-select">Test</div>
<nav class="no-select" style="float:right;overflow:hidden;scroll-behavior:smooth">
<a class="no-select" href="/web.html">🏠</a>
<a class="no-select" href="/search-user.html">🔍</a>
<a class="no-select" style="display:none" id="install-button" href="#">📥</a>
<a class="no-select" href="/threads.html">👥</a>
<a class="no-select" href="#">⚙️</a>
<a class="no-select" href="/logout.html">đź”’</a>
</nav>
</div>

View File

@ -13,24 +13,14 @@
{% endblock %} {% endblock %}
{% block main %} {% block logo %}
<h1>Setting page</h1> <h1>Setting page</h1>
<div id="profile_description"></div> {% endblock %}
{% block main %}
<script type="module">
require.config({ paths: { 'vs': 'https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.20.0/min/vs' } });
require(['vs/editor/editor.main'], function () {
var editor = monaco.editor.create(document.getElementById('profile_description'), {
value: phpCode,
language: 'php'
});
})
</script>
{% endblock main %} {% endblock main %}

View File

@ -0,0 +1,37 @@
{% extends "app.html" %}
{% block sidebar %}
{% include "settings/sidebar.html" %}
{% endblock %}
{% block header_text %}<h2 style="color:#fff">Settings</h2>{% endblock %}
{% block head %}
<link href="https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.20.0/min/vs/loader.min.js"></script>
{% endblock %}
{% block main %}
<div id="profile_description"></div>
<script type="module">
require.config({ paths: { 'vs': 'https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.20.0/min/vs' } });
require(['vs/editor/editor.main'], function () {
var editor = monaco.editor.create(document.getElementById('profile_description'), {
value: phpCode,
language: 'php'
});
})
</script>
{% endblock main %}

View File

@ -0,0 +1,31 @@
{% extends "settings/index.html" %}
{% block header_text %}<h2 style="color:#fff">Profile</h2>{% endblock %}
{% block main %}
<section>
<form>
<h2>Nickname</h2>
<input type="text" name="nick" placeholder="Your nickname" value="{{ user.nick.value }}" />
</form>
<h2>Description</h2>
<textarea id="profile"></textarea>
</section>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
<script>
const easyMDE = new EasyMDE({element:document.getElementById("profile")});
</script>
<style>
.EasyMDEContainer {
filter: invert(1) !important;
}
</style>
{% endblock %}

View File

@ -0,0 +1,9 @@
<aside class="sidebar" id="channelSidebar">
<h2>You</h2>
<ul>
<li><a class="no-select" href="/settings/profile.html">Profile</a></li>
<li><a class="no-select" href="/settings/gists.html">Gists</a></li>
</ul>
</aside>

View File

@ -1,14 +0,0 @@
<style>
.channel-list-item-highlight {
/* xxx */
}
</style>
<aside class="sidebar" id="channelSidebar">
<h2>Settings</h2>
<ul>
<li><a class="no-select" href="/settings.html">Profile</a></li>
<li><a class="no-select" href="/settings-notifications.html">Notifications</a></li>
<li><a class="no-select" href="/settings-privacy.html">Privacy</a></li>
</ul>
</aside>

View File

@ -1,8 +0,0 @@
from snek.system.view import BaseView
class SettingsView(BaseView):
login_required = True
async def get(self):
return await self.render_template('settings.html')

View File

@ -0,0 +1,8 @@
from snek.system.view import BaseView
class SettingsIndexView(BaseView):
login_required = True
async def get(self):
return await self.render_template('settings/index.html')

View File

@ -0,0 +1,36 @@
from snek.system.view import BaseView,BaseFormView
from snek.form.settings.profile import SettingsProfileForm
from aiohttp import web
class SettingsProfileView(BaseFormView):
form = SettingsProfileForm
login_required = True
async def get(self):
form = self.form(app=self.app)
if self.request.path.endswith(".json"):
form['nick'] = self.request['user']['nick']
return web.json_response(await form.to_json())
user = await self.services.user.get(uid=self.session.get("uid"))
return await self.render_template(
"settings/profile.html", {"form": await form.to_json(), "user": user}
)
async def submit(self, form):
post = await self.request.json()
form.set_user_data(post["form"])
if await form.is_valid:
user = self.request['user']
user["nick"] = form["nick"]
await self.services.user.save(user)
return {"redirect_url": "/settings/profile.html"}
return {"is_valid": False}

View File

@ -1,9 +1,8 @@
import logging import logging
import pathlib import pathlib
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
import asyncio
import base64 import base64
import datetime import datetime
import mimetypes import mimetypes
@ -21,7 +20,7 @@ class WebdavApplication(aiohttp.web.Application):
def __init__(self, parent, *args, **kwargs): def __init__(self, parent, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.locks = {} self.locks = {}
self.router.add_route("OPTIONS", "/{filename:.*}", self.handle_options) self.router.add_route("OPTIONS", "/{filename:.*}", self.handle_options)
self.router.add_route("GET", "/{filename:.*}", self.handle_get) self.router.add_route("GET", "/{filename:.*}", self.handle_get)
self.router.add_route("PUT", "/{filename:.*}", self.handle_put) self.router.add_route("PUT", "/{filename:.*}", self.handle_put)
@ -31,22 +30,21 @@ class WebdavApplication(aiohttp.web.Application):
self.router.add_route("COPY", "/{filename:.*}", self.handle_copy) self.router.add_route("COPY", "/{filename:.*}", self.handle_copy)
self.router.add_route("PROPFIND", "/{filename:.*}", self.handle_propfind) self.router.add_route("PROPFIND", "/{filename:.*}", self.handle_propfind)
self.router.add_route("PROPPATCH", "/{filename:.*}", self.handle_proppatch) self.router.add_route("PROPPATCH", "/{filename:.*}", self.handle_proppatch)
#self.router.add_route("LOCK", "/{filename:.*}", self.handle_lock) # self.router.add_route("LOCK", "/{filename:.*}", self.handle_lock)
#self.router.add_route("UNLOCK", "/{filename:.*}", self.handle_unlock) # self.router.add_route("UNLOCK", "/{filename:.*}", self.handle_unlock)
self.parent = parent self.parent = parent
@property @property
def db(self): def db(self):
return self.parent.db return self.parent.db
@property @property
def services(self): def services(self):
return self.parent.services return self.parent.services
async def authenticate(self, request): async def authenticate(self, request):
#session = request.session # session = request.session
#if session.get('uid'): # if session.get('uid'):
# request['user'] = await self.services.user.get(uid=session['uid']) # request['user'] = await self.services.user.get(uid=session['uid'])
# try: # try:
# request['home'] = await self.services.user.get_home_folder(user_uid=request['user']['uid']) # request['home'] = await self.services.user.get_home_folder(user_uid=request['user']['uid'])
@ -60,13 +58,17 @@ class WebdavApplication(aiohttp.web.Application):
encoded_creds = auth_header.split("Basic ")[1] encoded_creds = auth_header.split("Basic ")[1]
decoded_creds = base64.b64decode(encoded_creds).decode() decoded_creds = base64.b64decode(encoded_creds).decode()
username, password = decoded_creds.split(":", 1) username, password = decoded_creds.split(":", 1)
request['user'] = await self.services.user.authenticate(username=username, password=password) request["user"] = await self.services.user.authenticate(
username=username, password=password
)
try: try:
request['home'] = await self.services.user.get_home_folder(request['user']['uid']) request["home"] = await self.services.user.get_home_folder(
request["user"]["uid"]
)
except Exception as ex: except Exception as ex:
print(ex) print(ex)
pass pass
return request['user'] return request["user"]
async def handle_get(self, request): async def handle_get(self, request):
if not await self.authenticate(request): if not await self.authenticate(request):
@ -75,7 +77,7 @@ class WebdavApplication(aiohttp.web.Application):
) )
requested_path = request.match_info.get("filename", "") requested_path = request.match_info.get("filename", "")
abs_path = request['home'] / requested_path abs_path = request["home"] / requested_path
if not abs_path.exists(): if not abs_path.exists():
return aiohttp.web.Response(status=404, text="File not found") return aiohttp.web.Response(status=404, text="File not found")
@ -95,7 +97,7 @@ class WebdavApplication(aiohttp.web.Application):
return aiohttp.web.Response( return aiohttp.web.Response(
status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'}
) )
file_path = request['home'] / request.match_info["filename"] file_path = request["home"] / request.match_info["filename"]
file_path.parent.mkdir(parents=True, exist_ok=True) file_path.parent.mkdir(parents=True, exist_ok=True)
async with aiofiles.open(file_path, "wb") as f: async with aiofiles.open(file_path, "wb") as f:
while chunk := await request.content.read(1024): while chunk := await request.content.read(1024):
@ -107,7 +109,7 @@ class WebdavApplication(aiohttp.web.Application):
return aiohttp.web.Response( return aiohttp.web.Response(
status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'}
) )
file_path = request['home'] / request.match_info["filename"] file_path = request["home"] / request.match_info["filename"]
if file_path.is_file(): if file_path.is_file():
file_path.unlink() file_path.unlink()
return aiohttp.web.Response(status=204) return aiohttp.web.Response(status=204)
@ -121,7 +123,7 @@ class WebdavApplication(aiohttp.web.Application):
return aiohttp.web.Response( return aiohttp.web.Response(
status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'}
) )
dir_path = request['home'] / request.match_info["filename"] dir_path = request["home"] / request.match_info["filename"]
if dir_path.exists(): if dir_path.exists():
return aiohttp.web.Response(status=405, text="Directory already exists") return aiohttp.web.Response(status=405, text="Directory already exists")
dir_path.mkdir(parents=True, exist_ok=True) dir_path.mkdir(parents=True, exist_ok=True)
@ -132,8 +134,8 @@ class WebdavApplication(aiohttp.web.Application):
return aiohttp.web.Response( return aiohttp.web.Response(
status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'}
) )
src_path = request['home'] / request.match_info["filename"] src_path = request["home"] / request.match_info["filename"]
dest_path = request['home'] / request.headers.get("Destination", "").replace( dest_path = request["home"] / request.headers.get("Destination", "").replace(
"http://localhost:8080/", "" "http://localhost:8080/", ""
) )
if not src_path.exists(): if not src_path.exists():
@ -146,8 +148,8 @@ class WebdavApplication(aiohttp.web.Application):
return aiohttp.web.Response( return aiohttp.web.Response(
status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'}
) )
src_path = request['home'] / request.match_info["filename"] src_path = request["home"] / request.match_info["filename"]
dest_path = request['home'] / request.headers.get("Destination", "").replace( dest_path = request["home"] / request.headers.get("Destination", "").replace(
"http://localhost:8080/", "" "http://localhost:8080/", ""
) )
if not src_path.exists(): if not src_path.exists():
@ -188,14 +190,13 @@ class WebdavApplication(aiohttp.web.Application):
statvfs = os.statvfs(path) statvfs = os.statvfs(path)
return statvfs.f_bavail * statvfs.f_frsize return statvfs.f_bavail * statvfs.f_frsize
async def create_node(self, request, response_xml, full_path, depth): async def create_node(self, request, response_xml, full_path, depth):
requested_path = request.match_info.get("filename", "") request.match_info.get("filename", "")
abs_path = pathlib.Path(full_path) abs_path = pathlib.Path(full_path)
relative_path = str(full_path.relative_to(request['home'])) relative_path = str(full_path.relative_to(request["home"]))
href_path = f"{relative_path}".strip("/") href_path = f"{relative_path}".strip("/")
#href_path = href_path.replace("./","/") # href_path = href_path.replace("./","/")
href_path = href_path.replace("//", "/") href_path = href_path.replace("//", "/")
response = etree.SubElement(response_xml, "{DAV:}response") response = etree.SubElement(response_xml, "{DAV:}response")
href = etree.SubElement(response, "{DAV:}href") href = etree.SubElement(response, "{DAV:}href")
@ -213,7 +214,7 @@ class WebdavApplication(aiohttp.web.Application):
else self.get_directory_size(full_path) else self.get_directory_size(full_path)
) )
etree.SubElement(prop, "{DAV:}quota-available-bytes").text = str( etree.SubElement(prop, "{DAV:}quota-available-bytes").text = str(
self.get_disk_free_space(request['home']) self.get_disk_free_space(request["home"])
) )
etree.SubElement(prop, "{DAV:}getlastmodified").text = last_modified etree.SubElement(prop, "{DAV:}getlastmodified").text = last_modified
etree.SubElement(prop, "{DAV:}displayname").text = full_path.name etree.SubElement(prop, "{DAV:}displayname").text = full_path.name
@ -222,10 +223,10 @@ class WebdavApplication(aiohttp.web.Application):
if full_path.is_file(): if full_path.is_file():
etree.SubElement(prop, "{DAV:}contenttype").text = mimetype etree.SubElement(prop, "{DAV:}contenttype").text = mimetype
etree.SubElement(prop, "{DAV:}getcontentlength").text = str( etree.SubElement(prop, "{DAV:}getcontentlength").text = str(
full_path.stat().st_size full_path.stat().st_size
if full_path.is_file() if full_path.is_file()
else self.get_directory_size(full_path) else self.get_directory_size(full_path)
) )
supported_lock = etree.SubElement(prop, "{DAV:}supportedlock") supported_lock = etree.SubElement(prop, "{DAV:}supportedlock")
lock_entry_1 = etree.SubElement(supported_lock, "{DAV:}lockentry") lock_entry_1 = etree.SubElement(supported_lock, "{DAV:}lockentry")
lock_scope_1 = etree.SubElement(lock_entry_1, "{DAV:}lockscope") lock_scope_1 = etree.SubElement(lock_entry_1, "{DAV:}lockscope")
@ -238,13 +239,10 @@ class WebdavApplication(aiohttp.web.Application):
lock_type_2 = etree.SubElement(lock_entry_2, "{DAV:}locktype") lock_type_2 = etree.SubElement(lock_entry_2, "{DAV:}locktype")
etree.SubElement(lock_type_2, "{DAV:}write") etree.SubElement(lock_type_2, "{DAV:}write")
etree.SubElement(propstat, "{DAV:}status").text = "HTTP/1.1 200 OK" etree.SubElement(propstat, "{DAV:}status").text = "HTTP/1.1 200 OK"
if abs_path.is_dir() and depth != -1: if abs_path.is_dir() and depth != -1:
for item in abs_path.iterdir(): for item in abs_path.iterdir():
await self.create_node(request,response_xml, item, depth - 1) await self.create_node(request, response_xml, item, depth - 1)
async def handle_propfind(self, request): async def handle_propfind(self, request):
if not await self.authenticate(request): if not await self.authenticate(request):
@ -257,14 +255,13 @@ class WebdavApplication(aiohttp.web.Application):
depth = int(request.headers.get("Depth", "0")) depth = int(request.headers.get("Depth", "0"))
except ValueError: except ValueError:
pass pass
requested_path = request.match_info.get("filename", "") requested_path = request.match_info.get("filename", "")
abs_path = request['home'] / requested_path abs_path = request["home"] / requested_path
if not abs_path.exists(): if not abs_path.exists():
return aiohttp.web.Response(status=404, text="Directory not found") return aiohttp.web.Response(status=404, text="Directory not found")
nsmap = {"D": "DAV:"} nsmap = {"D": "DAV:"}
response_xml = etree.Element("{DAV:}multistatus", nsmap=nsmap) response_xml = etree.Element("{DAV:}multistatus", nsmap=nsmap)
directories = [requested_path]
await self.create_node(request, response_xml, abs_path, depth) await self.create_node(request, response_xml, abs_path, depth)
xml_output = etree.tostring( xml_output = etree.tostring(
@ -286,9 +283,9 @@ class WebdavApplication(aiohttp.web.Application):
return aiohttp.web.Response( return aiohttp.web.Response(
status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'}
) )
resource = request.match_info.get("filename", "/") request.match_info.get("filename", "/")
lock_id = str(uuid.uuid4()) lock_id = str(uuid.uuid4())
#self.locks[resource] = lock_id # self.locks[resource] = lock_id
xml_response = self.generate_lock_response(lock_id) xml_response = self.generate_lock_response(lock_id)
headers = { headers = {
"Lock-Token": f"opaquelocktoken:{lock_id}", "Lock-Token": f"opaquelocktoken:{lock_id}",
@ -341,8 +338,8 @@ class WebdavApplication(aiohttp.web.Application):
) )
requested_path = request.match_info.get("filename", "") requested_path = request.match_info.get("filename", "")
print(requested_path) print(requested_path)
abs_path = request['home'] / requested_path abs_path = request["home"] / requested_path
if not abs_path.exists(): if not abs_path.exists():
return aiohttp.web.Response(status=404, text="File not found") return aiohttp.web.Response(status=404, text="File not found")
@ -363,5 +360,3 @@ class WebdavApplication(aiohttp.web.Application):
} }
return aiohttp.web.Response(status=200, headers=headers) return aiohttp.web.Response(status=200, headers=headers)