This commit is contained in:
retoor 2025-06-14 12:34:26 +02:00
parent a4d29b9d6f
commit 2c182ad48d
7 changed files with 42 additions and 21 deletions

View File

@ -408,6 +408,11 @@ class Application(BaseApplication):
self.jinja2_env.loader = await self.get_user_template_loader(
request.session.get("uid")
)
try:
context["nonce"] = request['csp_nonce']
except:
context['nonce'] = '?'
rendered = await super().render_template(template, request, context)

View File

@ -113,6 +113,12 @@ class ChannelService(BaseService):
channel = await self.get(uid=channel_member["channel_uid"])
yield channel
async def clear(self, channel_uid):
model = await self.get(uid=channel_uid)
model['history_from'] = datetime.now()
await self.save(model)
async def ensure_public_channel(self, created_by_uid):
model = await self.get(is_listed=True, tag="public")
is_moderator = False

View File

@ -1,4 +1,4 @@
import { NjetComponent} from "/njext.ks"
import { NjetComponent} from "/njet.js"
class NjetEditor extends NjetComponent {
constructor() {

View File

@ -33,6 +33,7 @@ class BaseMapper:
try:
return func(*args, **kwargs)
except Exception as ex:
await asyncio.sleep(0)
database_exception = ex
raise database_exception
return await self.loop.run_in_executor(None, lambda: func(*args, **kwargs))

View File

@ -10,28 +10,25 @@ import secrets
from aiohttp import web
csp_policy = (
"default-src 'self'; "
"script-src 'self' https://*.cloudflare.com https://molodetz.nl 'nonce-{nonce}'; "
"style-src 'self' https://*.cloudflare.com https://molodetz.nl; "
"img-src 'self' https://*.cloudflare.com https://molodetz.nl data:; "
"connect-src 'self' https://*.cloudflare.com https://molodetz.nl;"
)
def generate_nonce():
return secrets.token_hex(16)
@web.middleware
async def csp_middleware(request, handler):
nonce = str(secrets.token_hex(16))
print("Nonce:", nonce)
csp_policy = (
"default-src 'self'; "
f"script-src 'self' https://umami.molodetz.nl 'nonce-{nonce}'; "
"style-src 'self'; "
"img-src *; "
"connect-src 'self'; https://umami.molodetz.nl; 'nonce-{nonce}';"
"font-src 'self'; "
"object-src 'none'; "
"base-uri 'self'; "
"form-action 'self';"
)
request['csp_nonce'] = nonce
response = await handler(request)
return response
nonce = generate_nonce()
response.headers["Content-Security-Policy"] = csp_policy.format(nonce=nonce)
return response
response.headers['Content-Security-Policy'] = csp_policy
return response
@web.middleware
async def no_cors_middleware(request, handler):

View File

@ -31,7 +31,7 @@
<link rel="stylesheet" href="/base.css">
<link rel="icon" type="image/png" href="/image/snek_logo_32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/image/snek_logo_64x64.png" sizes="64x64">
<script defer src="https://umami.molodetz.nl/script.js" data-website-id="d127c3e4-dc70-4041-a1c8-bcc32c2492ea"></script>
<script nonce="{{nonce}}" defer src="https://umami.molodetz.nl/script.js" data-website-id="d127c3e4-dc70-4041-a1c8-bcc32c2492ea"></script>
</head>
<body>
<header>

View File

@ -343,6 +343,18 @@ class RPCView(BaseView):
return {"success": True}
async def clear_channel(self, channel_uid):
self._require_login()
user = await self.services.user.get(uid=self.user_uid)
if not user["is_admin"]:
raise Exception("Not allowed")
channel = await self.services.channel.get(uid=channel_uid)
if not channel:
raise Exception("Channel not found")
channel['history_start'] = datetime.now()
await self.services.channel.save(channel)
return await self.services.channel_message.clear(channel_uid)
async def send_message(self, channel_uid, message, is_final=True):
self._require_login()
message = await self.services.chat.send(