YEah..
This commit is contained in:
		
							parent
							
								
									3c0fea6812
								
							
						
					
					
						commit
						02a0253c1d
					
				| @ -1,32 +1,37 @@ | ||||
| import argparse | ||||
| 
 | ||||
| from aiohttp import web | ||||
| 
 | ||||
| from snek.app import Application | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     parser = argparse.ArgumentParser(description="Run the web application.") | ||||
|     parser.add_argument( | ||||
|         "--port", | ||||
|         type=int, | ||||
|         default=8081, | ||||
|         help="Port to run the application on (default: 8081)" | ||||
|         help="Port to run the application on (default: 8081)", | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         "--host", | ||||
|         type=str, | ||||
|         default="0.0.0.0", | ||||
|         help="Host to run the application on (default: 0.0.0.0)" | ||||
|         help="Host to run the application on (default: 0.0.0.0)", | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         "--db_path", | ||||
|         type=str, | ||||
|         default="snek.db", | ||||
|         help="Database path for the application (default: sqlite:///snek.db)" | ||||
|         help="Database path for the application (default: sqlite:///snek.db)", | ||||
|     ) | ||||
| 
 | ||||
|     args = parser.parse_args() | ||||
| 
 | ||||
|     web.run_app(Application(db_path='sqlite:///' + args.db_path), port=args.port, host=args.host) | ||||
|     web.run_app( | ||||
|         Application(db_path="sqlite:///" + args.db_path), port=args.port, host=args.host | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
|  | ||||
| @ -17,8 +17,9 @@ from aiohttp_session import ( | ||||
|     setup as session_setup, | ||||
| ) | ||||
| from aiohttp_session.cookie_storage import EncryptedCookieStorage | ||||
| 
 | ||||
| from app.app import Application as BaseApplication | ||||
| from jinja2 import FileSystemLoader | ||||
| 
 | ||||
| from snek.docs.app import Application as DocsApplication | ||||
| from snek.mapper import get_mappers | ||||
| from snek.service import get_services | ||||
| @ -40,12 +41,12 @@ 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.stats import StatsView | ||||
| 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.view.stats import StatsView | ||||
| from snek.view.user import UserView | ||||
| from snek.view.web import WebView | ||||
| from snek.webdav import WebdavApplication | ||||
| 
 | ||||
| SESSION_KEY = b"c79a0c5fda4b424189c427d28c9f7c34" | ||||
| @ -204,7 +205,6 @@ class Application(BaseApplication): | ||||
|         channels = [] | ||||
|         if not context: | ||||
|             context = {} | ||||
| 
 | ||||
|         context["rid"] = str(uuid.uuid4()) | ||||
|         if request.session.get("uid"): | ||||
|             async for subscribed_channel in self.services.channel_member.find( | ||||
| @ -231,7 +231,6 @@ class Application(BaseApplication): | ||||
|                     item["uid"] = subscribed_channel["channel_uid"] | ||||
|                 item["new_count"] = subscribed_channel["new_count"] | ||||
| 
 | ||||
|                 print(item) | ||||
|                 channels.append(item) | ||||
| 
 | ||||
|             channels.sort(key=lambda x: x["last_message_on"] or "", reverse=True) | ||||
| @ -239,10 +238,37 @@ class Application(BaseApplication): | ||||
|                 context["channels"] = channels | ||||
|             if "user" not in context: | ||||
|                 context["user"] = await self.services.user.get( | ||||
|                     uid=request.session.get("uid") | ||||
|                     request.session.get("uid") | ||||
|                 ) | ||||
| 
 | ||||
|         return await super().render_template(template, request, context) | ||||
|         self.template_path.joinpath(template) | ||||
| 
 | ||||
|         await self.services.user.get_template_path(request.session.get("uid")) | ||||
| 
 | ||||
|         self.original_loader = self.jinja2_env.loader | ||||
| 
 | ||||
|         self.jinja2_env.loader = await self.get_user_template_loader( | ||||
|             request.session.get("uid") | ||||
|         ) | ||||
| 
 | ||||
|         rendered = await super().render_template(template, request, context) | ||||
| 
 | ||||
|         self.jinja2_env.loader = self.original_loader | ||||
| 
 | ||||
|         return rendered | ||||
| 
 | ||||
|     async def get_user_template_loader(self, uid=None): | ||||
|         template_paths = [] | ||||
|         for admin_uid in self.services.user.get_admin_uids(): | ||||
|             user_template_path = await self.services.user.get_template_path(admin_uid) | ||||
|             template_paths.append(user_template_path) | ||||
| 
 | ||||
|         if uid: | ||||
|             user_template_path = await self.services.user.get_template_path(uid) | ||||
|             template_paths.append(user_template_path) | ||||
| 
 | ||||
|         template_paths.append(self.template_path) | ||||
|         return FileSystemLoader(template_paths) | ||||
| 
 | ||||
| 
 | ||||
| app = Application(db_path="sqlite:///snek.db") | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| import pathlib | ||||
| 
 | ||||
| from aiohttp import web | ||||
| 
 | ||||
| from app.app import Application as BaseApplication | ||||
| 
 | ||||
| from snek.system.markdown import MarkdownExtension | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -5,3 +5,16 @@ from snek.system.mapper import BaseMapper | ||||
| class UserMapper(BaseMapper): | ||||
|     table_name = "user" | ||||
|     model_class = UserModel | ||||
| 
 | ||||
|     def get_admin_uids(self): | ||||
|         try: | ||||
|             return [ | ||||
|                 user["uid"] | ||||
|                 for user in self.db.query( | ||||
|                     "SELECT uid FROM user WHERE is_admin = :is_admin", | ||||
|                     {"is_admin": True}, | ||||
|                 ) | ||||
|             ] | ||||
|         except Exception as ex: | ||||
|             print(ex) | ||||
|             return [] | ||||
|  | ||||
| @ -29,6 +29,8 @@ class UserModel(BaseModel): | ||||
| 
 | ||||
|     last_ping = ModelField(name="last_ping", required=False, kind=str) | ||||
| 
 | ||||
|     is_admin = ModelField(name="is_admin", required=False, kind=bool) | ||||
| 
 | ||||
|     async def get_property(self, name): | ||||
|         prop = await self.app.services.user_property.find_one( | ||||
|             user_uid=self["uid"], name=name | ||||
|  | ||||
| @ -11,7 +11,10 @@ class ChannelMemberService(BaseService): | ||||
|         return await self.save(channel_member) | ||||
| 
 | ||||
|     async def get_user_uids(self, channel_uid): | ||||
|         async for model in self.mapper.query("SELECT user_uid FROM channel_member WHERE channel_uid=:channel_uid", {"channel_uid": channel_uid}): | ||||
|         async for model in self.mapper.query( | ||||
|             "SELECT user_uid FROM channel_member WHERE channel_uid=:channel_uid", | ||||
|             {"channel_uid": channel_uid}, | ||||
|         ): | ||||
|             yield model["user_uid"] | ||||
| 
 | ||||
|     async def create( | ||||
|  | ||||
| @ -15,7 +15,7 @@ class SocketService(BaseService): | ||||
|                 return False | ||||
|             try: | ||||
|                 await self.ws.send_json(data) | ||||
|             except Exception as ex: | ||||
|             except Exception: | ||||
|                 self.is_connected = False | ||||
|             return self.is_connected | ||||
| 
 | ||||
| @ -56,7 +56,9 @@ class SocketService(BaseService): | ||||
| 
 | ||||
|     async def broadcast(self, channel_uid, message): | ||||
|         try: | ||||
|             async for user_uid in self.services.channel_member.get_user_uids(channel_uid): | ||||
|             async for user_uid in self.services.channel_member.get_user_uids( | ||||
|                 channel_uid | ||||
|             ): | ||||
|                 print(user_uid, flush=True) | ||||
|                 await self.send_to_user(user_uid, message) | ||||
|         except Exception as ex: | ||||
|  | ||||
| @ -39,6 +39,15 @@ class UserService(BaseService): | ||||
|         model = await self.get(username=username, deleted_at=None) | ||||
|         return model | ||||
| 
 | ||||
|     def get_admin_uids(self): | ||||
|         return self.mapper.get_admin_uids() | ||||
| 
 | ||||
|     async def get_template_path(self, user_uid): | ||||
|         path = pathlib.Path(f"./drive/{user_uid}/snek/templates") | ||||
|         if not path.exists(): | ||||
|             return None | ||||
|         return path | ||||
| 
 | ||||
|     async def get_home_folder(self, user_uid): | ||||
|         folder = pathlib.Path(f"./drive/{user_uid}") | ||||
|         if not folder.exists(): | ||||
|  | ||||
| @ -11,14 +11,16 @@ class UserPropertyService(BaseService): | ||||
|             { | ||||
|                 "user_uid": user_uid, | ||||
|                 "name": name, | ||||
|                 "value": json.dumps(value, default=str) | ||||
|                 "value": json.dumps(value, default=str), | ||||
|             }, | ||||
|             ["user_uid", "name"] | ||||
|             ["user_uid", "name"], | ||||
|         ) | ||||
| 
 | ||||
|     async def get(self, user_uid, name): | ||||
|         try: | ||||
|             return json.loads((await super().get(user_uid=user_uid, name=name))["value"]) | ||||
|             return json.loads( | ||||
|                 (await super().get(user_uid=user_uid, name=name))["value"] | ||||
|             ) | ||||
|         except Exception as ex: | ||||
|             print(ex) | ||||
|             return None | ||||
|  | ||||
| @ -18,7 +18,7 @@ class Cache: | ||||
|         self.version = ((42 + 420 + 1984 + 1990 + 10 + 6 + 71 + 3004 + 7245) ^ 1337) + 4 | ||||
| 
 | ||||
|     async def get(self, args): | ||||
|         await self.update_stat(args, 'get') | ||||
|         await self.update_stat(args, "get") | ||||
|         try: | ||||
|             self.lru.pop(self.lru.index(args)) | ||||
|         except: | ||||
| @ -34,20 +34,28 @@ class Cache: | ||||
|     async def get_stats(self): | ||||
|         all_ = [] | ||||
|         for key in self.lru: | ||||
|             all_.append({'key': key, 'set': self.stats[key]['set'], 'get': self.stats[key]['get'], 'delete': self.stats[key]['delete'],'value': str(self.serialize(self.cache[key].record))}) | ||||
|             all_.append( | ||||
|                 { | ||||
|                     "key": key, | ||||
|                     "set": self.stats[key]["set"], | ||||
|                     "get": self.stats[key]["get"], | ||||
|                     "delete": self.stats[key]["delete"], | ||||
|                     "value": str(self.serialize(self.cache[key].record)), | ||||
|                 } | ||||
|             ) | ||||
|         return all_ | ||||
| 
 | ||||
|     def serialize(self, obj): | ||||
|         cpy = obj.copy() | ||||
|         cpy.pop('created_at', None) | ||||
|         cpy.pop('deleted_at', None) | ||||
|         cpy.pop('email', None) | ||||
|         cpy.pop('password', None) | ||||
|         cpy.pop("created_at", None) | ||||
|         cpy.pop("deleted_at", None) | ||||
|         cpy.pop("email", None) | ||||
|         cpy.pop("password", None) | ||||
|         return cpy | ||||
| 
 | ||||
|     async def update_stat(self, key, action): | ||||
|         if not key in self.stats: | ||||
|             self.stats[key] = {'set':0, 'get':0, 'delete':0} | ||||
|         if key not in self.stats: | ||||
|             self.stats[key] = {"set": 0, "get": 0, "delete": 0} | ||||
|         self.stats[key][action] = self.stats[key][action] + 1 | ||||
| 
 | ||||
|     def json_default(self, value): | ||||
| @ -70,7 +78,7 @@ class Cache: | ||||
|     async def set(self, args, result): | ||||
|         is_new = args not in self.cache | ||||
|         self.cache[args] = result | ||||
|         await self.update_stat(args, 'set') | ||||
|         await self.update_stat(args, "set") | ||||
|         try: | ||||
|             self.lru.pop(self.lru.index(args)) | ||||
|         except (ValueError, IndexError): | ||||
| @ -86,7 +94,7 @@ class Cache: | ||||
|             # print(f"Cache store! {len(self.lru)} items. New version:", self.version, flush=True) | ||||
| 
 | ||||
|     async def delete(self, args): | ||||
|         await self.update_stat(args, 'delete') | ||||
|         await self.update_stat(args, "delete") | ||||
|         if args in self.cache: | ||||
|             try: | ||||
|                 self.lru.pop(self.lru.index(args)) | ||||
|  | ||||
| @ -32,9 +32,8 @@ from urllib.parse import urljoin | ||||
| 
 | ||||
| import aiohttp | ||||
| import imgkit | ||||
| from bs4 import BeautifulSoup | ||||
| 
 | ||||
| from app.cache import time_cache_async | ||||
| from bs4 import BeautifulSoup | ||||
| 
 | ||||
| 
 | ||||
| async def crc32(data): | ||||
|  | ||||
| @ -2,13 +2,12 @@ | ||||
| 
 | ||||
| from types import SimpleNamespace | ||||
| 
 | ||||
| from app.cache import time_cache_async | ||||
| from mistune import HTMLRenderer, Markdown | ||||
| from pygments import highlight | ||||
| from pygments.formatters import html | ||||
| from pygments.lexers import get_lexer_by_name | ||||
| 
 | ||||
| from app.cache import time_cache_async | ||||
| 
 | ||||
| 
 | ||||
| class MarkdownRenderer(HTMLRenderer): | ||||
| 
 | ||||
|  | ||||
| @ -45,7 +45,7 @@ class TerminalSession: | ||||
|     def is_running(self): | ||||
|         if not self.process: | ||||
|             return False | ||||
|         loop = asyncio.get_event_loop() | ||||
|         asyncio.get_event_loop() | ||||
|         return self.process.poll() is None | ||||
| 
 | ||||
|     async def add_websocket(self, ws): | ||||
|  | ||||
| @ -8,7 +8,9 @@ class BaseView(web.View): | ||||
|     login_required = False | ||||
| 
 | ||||
|     async def _iter(self): | ||||
|         if self.login_required and (not self.session.get("logged_in") or not self.session.get("uid")): | ||||
|         if self.login_required and ( | ||||
|             not self.session.get("logged_in") or not self.session.get("uid") | ||||
|         ): | ||||
|             return web.HTTPFound("/") | ||||
|         return await super()._iter() | ||||
| 
 | ||||
|  | ||||
| @ -10,9 +10,11 @@ | ||||
| # MIT License | ||||
| 
 | ||||
| 
 | ||||
| from snek.system.view import BaseView | ||||
| from aiohttp import web | ||||
| 
 | ||||
| from snek.system.view import BaseView | ||||
| 
 | ||||
| 
 | ||||
| class IndexView(BaseView): | ||||
|     async def get(self): | ||||
|         if self.session.get("uid"): | ||||
|  | ||||
| @ -35,6 +35,7 @@ from snek.system.view import BaseFormView | ||||
| class SearchUserView(BaseFormView): | ||||
|     form = SearchUserForm | ||||
|     login_required = True | ||||
| 
 | ||||
|     async def get(self): | ||||
|         users = [] | ||||
|         query = self.request.query.get("query") | ||||
|  | ||||
| @ -17,24 +17,22 @@ class SettingsProfileView(BaseFormView): | ||||
| 
 | ||||
|             return web.json_response(await form.to_json()) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         profile = await self.services.user_property.get(self.session.get("uid"), "profile") | ||||
|         profile = await self.services.user_property.get( | ||||
|             self.session.get("uid"), "profile" | ||||
|         ) | ||||
| 
 | ||||
|         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, "profile": profile or ''} | ||||
|             "settings/profile.html", | ||||
|             {"form": await form.to_json(), "user": user, "profile": profile or ""}, | ||||
|         ) | ||||
| 
 | ||||
|     async def post(self): | ||||
|         data = await self.request.post() | ||||
|         user = await self.services.user.get(uid=self.session.get("uid")) | ||||
| 
 | ||||
|         user['nick'] = data['nick'] | ||||
|         user["nick"] = data["nick"] | ||||
|         await self.services.user.save(user) | ||||
|         await self.services.user_property.set(user["uid"],"profile", data['profile']) | ||||
|         await self.services.user_property.set(user["uid"], "profile", data["profile"]) | ||||
|         return web.HTTPFound("/settings/profile.html") | ||||
|          | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -1,10 +1,13 @@ | ||||
| from snek.system.view import BaseView  | ||||
| import json | ||||
| 
 | ||||
| from aiohttp import web | ||||
| 
 | ||||
| from snek.system.view import BaseView | ||||
| 
 | ||||
| 
 | ||||
| class StatsView(BaseView): | ||||
| 
 | ||||
|     async def get(self): | ||||
|         data = await self.app.cache.get_stats() | ||||
|         data = json.dumps({"total": len(data), "stats": data}, default=str, indent=1) | ||||
|         return web.Response(text=data, content_type='application/json') | ||||
|         return web.Response(text=data, content_type="application/json") | ||||
|  | ||||
| @ -4,11 +4,12 @@ from snek.system.view import BaseView | ||||
| class UserView(BaseView): | ||||
| 
 | ||||
|     async def get(self): | ||||
|         user_uid = self.request.match_info.get('user') | ||||
|         user_uid = self.request.match_info.get("user") | ||||
|         user = await self.services.user.get(uid=user_uid) | ||||
|         profile_content = await self.services.user_property.get(user['uid'],'profile') or '' | ||||
|         return await self.render_template('user.html', { | ||||
|             'user_uid': user_uid, | ||||
|             'user': user.record, | ||||
|             'profile': profile_content   | ||||
|         }) | ||||
|         profile_content = ( | ||||
|             await self.services.user_property.get(user["uid"], "profile") or "" | ||||
|         ) | ||||
|         return await self.render_template( | ||||
|             "user.html", | ||||
|             {"user_uid": user_uid, "user": user.record, "profile": profile_content}, | ||||
|         ) | ||||
|  | ||||
| @ -12,9 +12,8 @@ import uuid | ||||
| import aiofiles | ||||
| import aiohttp | ||||
| import aiohttp.web | ||||
| from lxml import etree | ||||
| 
 | ||||
| from app.cache import time_cache_async | ||||
| from lxml import etree | ||||
| 
 | ||||
| 
 | ||||
| @aiohttp.web.middleware | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user