Progress.
This commit is contained in:
		
							parent
							
								
									81479e7058
								
							
						
					
					
						commit
						d10768403d
					
				| @ -1,3 +1 @@ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| from aiohttp import web | ||||
| 
 | ||||
| from snek.app import Application | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     web.run_app(Application(), port=8081,host='0.0.0.0') | ||||
| if __name__ == "__main__": | ||||
|     web.run_app(Application(), port=8081, host="0.0.0.0") | ||||
|  | ||||
| @ -3,6 +3,7 @@ import logging | ||||
| import pathlib | ||||
| import time | ||||
| import uuid | ||||
| 
 | ||||
| from snek.view.threads import ThreadsView | ||||
| 
 | ||||
| logging.basicConfig(level=logging.DEBUG) | ||||
| @ -24,7 +25,7 @@ from snek.service import get_services | ||||
| from snek.system import http | ||||
| from snek.system.cache import Cache | ||||
| 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.template import EmojiExtension, LinkifyExtension, PythonExtension | ||||
| 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.rpc import RPCView | ||||
| 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.terminal import TerminalSocketView, TerminalView | ||||
| from snek.view.upload import UploadView | ||||
| from snek.view.web import WebView | ||||
| from snek.webdav import WebdavApplication | ||||
| from snek.view.settings import SettingsView | ||||
| 
 | ||||
| SESSION_KEY = b"c79a0c5fda4b424189c427d28c9f7c34" | ||||
| 
 | ||||
| @ -76,6 +78,7 @@ class Application(BaseApplication): | ||||
|         session_setup(self, EncryptedCookieStorage(SESSION_KEY)) | ||||
|         self.tasks = asyncio.Queue() | ||||
|         self._middlewares.append(session_middleware) | ||||
|         self._middlewares.append(auth_middleware) | ||||
|         self.jinja2_env.add_extension(MarkdownExtension) | ||||
|         self.jinja2_env.add_extension(LinkifyExtension) | ||||
|         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.md", DocsMDView) | ||||
|         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("/login.html", LoginView) | ||||
|         self.router.add_view("/login.json", LoginView) | ||||
| @ -190,7 +195,7 @@ class Application(BaseApplication): | ||||
|         if not context: | ||||
|             context = {} | ||||
| 
 | ||||
|         context['rid'] = str(uuid.uuid4()) | ||||
|         context["rid"] = str(uuid.uuid4()) | ||||
|         if request.session.get("uid"): | ||||
|             async for subscribed_channel in self.services.channel_member.find( | ||||
|                 user_uid=request.session.get("uid"), deleted_at=None, is_banned=False | ||||
|  | ||||
| @ -7,6 +7,7 @@ from snek.mapper.drive import DriveMapper | ||||
| from snek.mapper.drive_item import DriveItemMapper | ||||
| from snek.mapper.notification import NotificationMapper | ||||
| from snek.mapper.user import UserMapper | ||||
| from snek.mapper.user_property import UserPropertyMapper | ||||
| from snek.system.object import Object | ||||
| 
 | ||||
| 
 | ||||
| @ -21,6 +22,7 @@ def get_mappers(app=None): | ||||
|             "notification": NotificationMapper(app=app), | ||||
|             "drive_item": DriveItemMapper(app=app), | ||||
|             "drive": DriveMapper(app=app), | ||||
|             "user_property": UserPropertyMapper(app=app), | ||||
|         } | ||||
|     ) | ||||
| 
 | ||||
|  | ||||
| @ -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.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_property import UserPropertyModel | ||||
| from snek.system.object import Object | ||||
| 
 | ||||
| 
 | ||||
| @ -17,6 +21,10 @@ def get_models(): | ||||
|             "channel_member": ChannelMemberModel, | ||||
|             "channel": ChannelModel, | ||||
|             "channel_message": ChannelMessageModel, | ||||
|             "drive_item": DriveItemModel, | ||||
|             "drive": DriveModel, | ||||
|             "notification": NotificationModel, | ||||
|             "user_property": UserPropertyModel, | ||||
|         } | ||||
|     ) | ||||
| 
 | ||||
|  | ||||
| @ -28,6 +28,16 @@ async def cors_allow_middleware(request, handler): | ||||
|     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 | ||||
| async def cors_middleware(request, handler): | ||||
|     if request.headers.get("Allow"): | ||||
|  | ||||
| @ -31,7 +31,7 @@ | ||||
|       <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="/settings/index.html">⚙️</a> | ||||
|       <a class="no-select" href="/logout.html">🔒</a> | ||||
|     </nav> | ||||
| 
 | ||||
|  | ||||
| @ -13,24 +13,14 @@ | ||||
| 
 | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block main %} | ||||
| 
 | ||||
| {% block logo %} | ||||
| <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 %} | ||||
|  | ||||
| @ -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> | ||||
| @ -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') | ||||
| @ -1,9 +1,8 @@ | ||||
| import logging | ||||
| 
 | ||||
| import pathlib | ||||
| 
 | ||||
| logging.basicConfig(level=logging.DEBUG) | ||||
| 
 | ||||
| import asyncio | ||||
| import base64 | ||||
| import datetime | ||||
| import mimetypes | ||||
| @ -31,8 +30,8 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|         self.router.add_route("COPY", "/{filename:.*}", self.handle_copy) | ||||
|         self.router.add_route("PROPFIND", "/{filename:.*}", self.handle_propfind) | ||||
|         self.router.add_route("PROPPATCH", "/{filename:.*}", self.handle_proppatch) | ||||
|         #self.router.add_route("LOCK", "/{filename:.*}", self.handle_lock) | ||||
|         #self.router.add_route("UNLOCK", "/{filename:.*}", self.handle_unlock) | ||||
|         # self.router.add_route("LOCK", "/{filename:.*}", self.handle_lock) | ||||
|         # self.router.add_route("UNLOCK", "/{filename:.*}", self.handle_unlock) | ||||
|         self.parent = parent | ||||
| 
 | ||||
|     @property | ||||
| @ -43,10 +42,9 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|     def services(self): | ||||
|         return self.parent.services | ||||
| 
 | ||||
| 
 | ||||
|     async def authenticate(self, request): | ||||
|         #session = request.session | ||||
|         #if session.get('uid'): | ||||
|         # session = request.session | ||||
|         # if session.get('uid'): | ||||
|         #    request['user'] = await self.services.user.get(uid=session['uid']) | ||||
|         #    try: | ||||
|         #        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] | ||||
|         decoded_creds = base64.b64decode(encoded_creds).decode() | ||||
|         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: | ||||
|             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: | ||||
|             print(ex) | ||||
|             pass | ||||
|         return request['user'] | ||||
|         return request["user"] | ||||
| 
 | ||||
|     async def handle_get(self, request): | ||||
|         if not await self.authenticate(request): | ||||
| @ -75,7 +77,7 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             ) | ||||
| 
 | ||||
|         requested_path = request.match_info.get("filename", "") | ||||
|         abs_path = request['home'] / requested_path | ||||
|         abs_path = request["home"] / requested_path | ||||
| 
 | ||||
|         if not abs_path.exists(): | ||||
|             return aiohttp.web.Response(status=404, text="File not found") | ||||
| @ -95,7 +97,7 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             return aiohttp.web.Response( | ||||
|                 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) | ||||
|         async with aiofiles.open(file_path, "wb") as f: | ||||
|             while chunk := await request.content.read(1024): | ||||
| @ -107,7 +109,7 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             return aiohttp.web.Response( | ||||
|                 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(): | ||||
|             file_path.unlink() | ||||
|             return aiohttp.web.Response(status=204) | ||||
| @ -121,7 +123,7 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             return aiohttp.web.Response( | ||||
|                 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(): | ||||
|             return aiohttp.web.Response(status=405, text="Directory already exists") | ||||
|         dir_path.mkdir(parents=True, exist_ok=True) | ||||
| @ -132,8 +134,8 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             return aiohttp.web.Response( | ||||
|                 status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} | ||||
|             ) | ||||
|         src_path = request['home'] / request.match_info["filename"] | ||||
|         dest_path = request['home'] / request.headers.get("Destination", "").replace( | ||||
|         src_path = request["home"] / request.match_info["filename"] | ||||
|         dest_path = request["home"] / request.headers.get("Destination", "").replace( | ||||
|             "http://localhost:8080/", "" | ||||
|         ) | ||||
|         if not src_path.exists(): | ||||
| @ -146,8 +148,8 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             return aiohttp.web.Response( | ||||
|                 status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} | ||||
|             ) | ||||
|         src_path = request['home'] / request.match_info["filename"] | ||||
|         dest_path = request['home'] / request.headers.get("Destination", "").replace( | ||||
|         src_path = request["home"] / request.match_info["filename"] | ||||
|         dest_path = request["home"] / request.headers.get("Destination", "").replace( | ||||
|             "http://localhost:8080/", "" | ||||
|         ) | ||||
|         if not src_path.exists(): | ||||
| @ -188,14 +190,13 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|         statvfs = os.statvfs(path) | ||||
|         return statvfs.f_bavail * statvfs.f_frsize | ||||
| 
 | ||||
| 
 | ||||
|     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) | ||||
|         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 = href_path.replace("./","/")  | ||||
|         # href_path = href_path.replace("./","/") | ||||
|         href_path = href_path.replace("//", "/") | ||||
|         response = etree.SubElement(response_xml, "{DAV:}response") | ||||
|         href = etree.SubElement(response, "{DAV:}href") | ||||
| @ -213,7 +214,7 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             else self.get_directory_size(full_path) | ||||
|         ) | ||||
|         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:}displayname").text = full_path.name | ||||
| @ -241,10 +242,7 @@ class WebdavApplication(aiohttp.web.Application): | ||||
| 
 | ||||
|         if abs_path.is_dir() and depth != -1: | ||||
|             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): | ||||
|         if not await self.authenticate(request): | ||||
| @ -258,12 +256,11 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|         except ValueError: | ||||
|             pass | ||||
|         requested_path = request.match_info.get("filename", "") | ||||
|         abs_path = request['home'] / requested_path | ||||
|         abs_path = request["home"] / requested_path | ||||
|         if not abs_path.exists(): | ||||
|             return aiohttp.web.Response(status=404, text="Directory not found") | ||||
|         nsmap = {"D": "DAV:"} | ||||
|         response_xml = etree.Element("{DAV:}multistatus", nsmap=nsmap) | ||||
|         directories = [requested_path] | ||||
| 
 | ||||
|         await self.create_node(request, response_xml, abs_path, depth) | ||||
| 
 | ||||
| @ -286,9 +283,9 @@ class WebdavApplication(aiohttp.web.Application): | ||||
|             return aiohttp.web.Response( | ||||
|                 status=401, headers={"WWW-Authenticate": 'Basic realm="WebDAV"'} | ||||
|             ) | ||||
|         resource = request.match_info.get("filename", "/") | ||||
|         request.match_info.get("filename", "/") | ||||
|         lock_id = str(uuid.uuid4()) | ||||
|         #self.locks[resource] = lock_id | ||||
|         # self.locks[resource] = lock_id | ||||
|         xml_response = self.generate_lock_response(lock_id) | ||||
|         headers = { | ||||
|             "Lock-Token": f"opaquelocktoken:{lock_id}", | ||||
| @ -342,7 +339,7 @@ class WebdavApplication(aiohttp.web.Application): | ||||
| 
 | ||||
|         requested_path = request.match_info.get("filename", "") | ||||
|         print(requested_path) | ||||
|         abs_path = request['home'] / requested_path | ||||
|         abs_path = request["home"] / requested_path | ||||
| 
 | ||||
|         if not abs_path.exists(): | ||||
|             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) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user