diff --git a/relay/application.py b/relay/application.py index 3743612..b3da393 100644 --- a/relay/application.py +++ b/relay/application.py @@ -140,25 +140,6 @@ class Application(web.Application): return '; '.join(data) + ';' - # data = { - # 'base-uri': '\'none\'', - # 'default-src': '\'none\'', - # 'frame-ancestors': '\'none\'', - # 'font-src': f'\'self\' https://{self.config.domain}', - # 'img-src': f'\'self\' https://{self.config.domain}', - # 'style-src': f'\'self\' https://{self.config.domain} \'nonce-randomstringhere\'', - # 'media-src': f'\'self\' https://{self.config.domain}', - # 'frame-src': f'\'self\' https:', - # 'manifest-src': f'\'self\' https://{self.config.domain}', - # 'form-action': f'\'self\'', - # 'child-src': f'\'self\' https://{self.config.domain}', - # 'worker-src': f'\'self\' https://{self.config.domain}', - # 'connect-src': f'\'self\' https://{self.config.domain} wss://{self.config.domain}', - # 'script-src': f'\'self\' https://{self.config.domain}' - # } - # - # return '; '.join(f'{key} {value}' for key, value in data.items()) + ';' - def push_message(self, inbox: str, message: Message, instance: Row) -> None: self['push_queue'].put((inbox, message, instance)) @@ -305,6 +286,7 @@ async def handle_response_headers(request: web.Request, handler: Callable) -> Re resp = await handler(request) resp.headers['Server'] = 'ActivityRelay' + # Still have to figure out how csp headers work # if resp.content_type == 'text/html': # resp.headers['Content-Security-Policy'] = Application.DEFAULT.get_csp(request) diff --git a/relay/frontend/page/admin-domain_bans.haml b/relay/frontend/page/admin-domain_bans.haml index 104ce15..43636ae 100644 --- a/relay/frontend/page/admin-domain_bans.haml +++ b/relay/frontend/page/admin-domain_bans.haml @@ -2,7 +2,7 @@ -set page="Domain Bans" -block head - %script(type="application/javascript" src="/static/domain_ban.js" nonce="{{view.request['hash']}}", defer) + %script(type="application/javascript" src="/static/domain_ban.js" nonce="{{view.request['hash']}}") -block content %details.section @@ -23,7 +23,7 @@ %legend << Domain Bans .data-table - %table#table + %table %thead %tr %td.domain << Domain @@ -38,11 +38,11 @@ %summary -> =ban.domain .grid-2col - .reason << Reason - %textarea.reason(id="{{ban.domain}}-reason" name="reason") << {{ban.reason or ""}} + %label.reason(for="{{ban.domain}}-reason") << Reason + %textarea.reason(id="{{ban.domain}}-reason") << {{ban.reason or ""}} - .note << Note - %textarea.note(id="{{ban.domain}}-note" name="note") << {{ban.note or ""}} + %label.note(for="{{ban.domain}}-note") << Note + %textarea.note(id="{{ban.domain}}-note") << {{ban.note or ""}} %input(type="button" value="Update" onclick="update_ban('{{ban.domain}}')") @@ -50,4 +50,4 @@ =ban.created.strftime("%Y-%m-%d") %td.remove - %a(href="#", onclick="unban('{{ban.domain}}')" title="Unban domain") << ✖ + %a(href="#" onclick="unban('{{ban.domain}}')" title="Unban domain") << ✖ diff --git a/relay/frontend/page/admin-software_bans.haml b/relay/frontend/page/admin-software_bans.haml index 1ce5664..cf1576c 100644 --- a/relay/frontend/page/admin-software_bans.haml +++ b/relay/frontend/page/admin-software_bans.haml @@ -1,5 +1,9 @@ -extends "base.haml" -set page="Software Bans" + +-block head + %script(type="application/javascript" src="/static/software_ban.js" nonce="{{view.request['hash']}}") + -block content %details.section %summary << Ban Software diff --git a/relay/frontend/static/domain_ban.js b/relay/frontend/static/domain_ban.js index 82434af..b7ae6b6 100644 --- a/relay/frontend/static/domain_ban.js +++ b/relay/frontend/static/domain_ban.js @@ -3,9 +3,9 @@ function create_ban_object(domain, reason, note) { text += `${domain}\n`; text += '
\n'; text += `\n`; - text += `\n`; + text += `\n`; text += `\n`; - text += `\n`; + text += `\n`; text += ``; text += ''; @@ -14,7 +14,7 @@ function create_ban_object(domain, reason, note) { async function ban() { - var table = document.getElementById("table"); + var table = document.querySelector("table"); var row = table.insertRow(-1); var elems = { @@ -59,25 +59,42 @@ async function ban() { elems.reason.value = null; elems.note.value = null; - document.querySelectorAll("details.section").forEach((elem) => { - elem.open = false; - }); + row.querySelector("details").open = false; } async function update_ban(domain) { var row = document.getElementById(domain); + + var elems = { + "reason": row.querySelector("textarea.reason"), + "note": row.querySelector("textarea.note") + } + + var values = { + "domain": domain, + "reason": elems.reason.value, + "note": elems.note.value + } + + try { + await client.request("PATCH", "v1/domain_ban", values) + + } catch (error) { + alert(error); + return; + } + + row.querySelector("details").open = false; } async function unban(domain) { - console.log(domain); - try { await client.unban(domain); - } catch (err) { - alert(err); + } catch (error) { + alert(error); return; } diff --git a/relay/views/api.py b/relay/views/api.py index 4b9dc6c..9428d47 100644 --- a/relay/views/api.py +++ b/relay/views/api.py @@ -274,6 +274,54 @@ class DomainBan(View): return Response.new(bans, ctype = 'json') + async def post(self, request: Request) -> Response: + data = await self.get_api_data(['domain'], ['note', 'reason']) + + if isinstance(data, Response): + return data + + with self.database.session() as conn: + if conn.get_domain_ban(data['domain']): + return Response.new_error(400, 'Domain already banned', 'json') + + ban = conn.put_domain_ban(**data) + + return Response.new(ban, ctype = 'json') + + + async def patch(self, request: Request) -> Response: + with self.database.session() as conn: + data = await self.get_api_data(['domain'], ['note', 'reason']) + + if isinstance(data, Response): + return data + + if not conn.get_domain_ban(data['domain']): + return Response.new_error(404, 'Domain not banned', 'json') + + if not any([data.get('note'), data.get('reason')]): + return Response.new_error(400, 'Must include note and/or reason parameters', 'json') + + ban = conn.update_domain_ban(**data) + + return Response.new(ban, ctype = 'json') + + + async def delete(self, request: Request) -> Response: + with self.database.session() as conn: + data = await self.get_api_data(['domain'], []) + + if isinstance(data, Response): + return data + + if not conn.get_domain_ban(data['domain']): + return Response.new_error(404, 'Domain not banned', 'json') + + conn.del_domain_ban(data['domain']) + + return Response.new({'message': 'Unbanned domain'}, ctype = 'json') + + @register_route('/api/v1/software_ban') class SoftwareBan(View): async def get(self, request: Request) -> Response: