mirror of
https://git.pleroma.social/pleroma/relay.git
synced 2024-11-24 15:31:08 +00:00
create admin instances page
This commit is contained in:
parent
7af3b9c20b
commit
e6831f04eb
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,5 +1,41 @@
|
|||
-extends "base.haml"
|
||||
-set page="Instances"
|
||||
-block content
|
||||
.section
|
||||
UvU
|
||||
%details.section
|
||||
%summary << Add Instance
|
||||
%form(target="/admin/instances", method="POST")
|
||||
#add-instance
|
||||
%label(for="domain") << Domain
|
||||
%input(type="domain", name="domain", placeholder="Domain")
|
||||
%label(for="actor") << Actor URL
|
||||
%input(type="url", name="actor", placeholder="Actor URL")
|
||||
%label(for="inbox") << Inbox URL
|
||||
%input(type="url", name="inbox", placeholder="Inbox URL")
|
||||
%label(for="software") << Software
|
||||
%input(name="software", placeholder="software")
|
||||
|
||||
%input(type="submit" value="Add Instance")
|
||||
|
||||
#instances.section
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%td.instance << Instance
|
||||
%td.software << Software
|
||||
%td.date << Joined
|
||||
%td.remove
|
||||
|
||||
%tbody
|
||||
-for instance in instances
|
||||
%tr
|
||||
%td.instance
|
||||
%a(href="https://{{instance.domain}}/" target="_new") -> =instance.domain
|
||||
|
||||
%td.software
|
||||
=instance.software or "n/a"
|
||||
|
||||
%td.date
|
||||
=instance.created.strftime("%Y-%m-%d")
|
||||
|
||||
%td.remove
|
||||
%a(href="/admin/instances/delete/{{instance.domain}}" title="Remove Instance") << ✖
|
||||
|
|
|
@ -32,6 +32,10 @@ a:hover {
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
details summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1em;
|
||||
margin: 0px;
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
form input[type="submit"] {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#instances table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#instances .instance {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#instances .software {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#instances .date {
|
||||
width: max-content;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#instances thead td {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
#add-instance {
|
||||
display: grid;
|
||||
grid-template-columns: max-content auto;
|
||||
grid-gap: var(--spacing);
|
||||
margin-top: var(--spacing);
|
||||
margin-bottom: var(--spacing);
|
||||
}
|
|
@ -18,7 +18,7 @@ from . import logger as logging
|
|||
from .application import Application
|
||||
from .compat import RelayConfig, RelayDatabase
|
||||
from .database import RELAY_SOFTWARE, get_database
|
||||
from .misc import IS_DOCKER, Message
|
||||
from .misc import ACTOR_FORMATS, SOFTWARE, IS_DOCKER, Message
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from tinysql import Row
|
||||
|
@ -33,23 +33,6 @@ CONFIG_IGNORE = (
|
|||
'private-key'
|
||||
)
|
||||
|
||||
ACTOR_FORMATS = {
|
||||
'mastodon': 'https://{domain}/actor',
|
||||
'akkoma': 'https://{domain}/relay',
|
||||
'pleroma': 'https://{domain}/relay'
|
||||
}
|
||||
|
||||
SOFTWARE = (
|
||||
'mastodon',
|
||||
'akkoma',
|
||||
'pleroma',
|
||||
'misskey',
|
||||
'friendica',
|
||||
'hubzilla',
|
||||
'firefish',
|
||||
'gotosocial'
|
||||
)
|
||||
|
||||
|
||||
def check_alphanumeric(text: str) -> str:
|
||||
if not text.isalnum():
|
||||
|
|
|
@ -36,6 +36,23 @@ NODEINFO_NS = {
|
|||
'21': 'http://nodeinfo.diaspora.software/ns/schema/2.1'
|
||||
}
|
||||
|
||||
ACTOR_FORMATS = {
|
||||
'mastodon': 'https://{domain}/actor',
|
||||
'akkoma': 'https://{domain}/relay',
|
||||
'pleroma': 'https://{domain}/relay'
|
||||
}
|
||||
|
||||
SOFTWARE = (
|
||||
'mastodon',
|
||||
'akkoma',
|
||||
'pleroma',
|
||||
'misskey',
|
||||
'friendica',
|
||||
'hubzilla',
|
||||
'firefish',
|
||||
'gotosocial'
|
||||
)
|
||||
|
||||
|
||||
def boolean(value: Any) -> bool:
|
||||
if isinstance(value, str):
|
||||
|
|
|
@ -7,34 +7,21 @@ from argon2.exceptions import VerifyMismatchError
|
|||
|
||||
from .base import View, register_route
|
||||
|
||||
from ..misc import Response
|
||||
from ..misc import ACTOR_FORMATS, Message, Response
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from aiohttp.web import Request
|
||||
|
||||
|
||||
AUTH_ROUTES = {
|
||||
'/admin',
|
||||
'/admin/instances',
|
||||
'/admin/domain_bans',
|
||||
'/admin/software_bans',
|
||||
'/admin/whitelist',
|
||||
'/admin/config',
|
||||
'/logout'
|
||||
}
|
||||
|
||||
|
||||
UNAUTH_ROUTES = {
|
||||
'/',
|
||||
'/login'
|
||||
}
|
||||
|
||||
ALL_ROUTES = {*AUTH_ROUTES, *UNAUTH_ROUTES}
|
||||
|
||||
|
||||
@web.middleware
|
||||
async def handle_frontend_path(request: web.Request, handler: Coroutine) -> Response:
|
||||
if request.path in ALL_ROUTES:
|
||||
if request.path in UNAUTH_ROUTES or request.path.startswith('/admin'):
|
||||
request['token'] = request.cookies.get('user-token')
|
||||
request['user'] = None
|
||||
|
||||
|
@ -57,16 +44,11 @@ async def handle_frontend_path(request: web.Request, handler: Coroutine) -> Resp
|
|||
class HomeView(View):
|
||||
async def get(self, request: Request) -> Response:
|
||||
with self.database.session() as conn:
|
||||
instances = tuple(conn.execute('SELECT * FROM inboxes').all())
|
||||
context = {
|
||||
'instances': tuple(conn.execute('SELECT * FROM inboxes').all())
|
||||
}
|
||||
|
||||
# text = HOME_TEMPLATE.format(
|
||||
# host = self.config.domain,
|
||||
# note = config['note'],
|
||||
# count = len(inboxes),
|
||||
# targets = '<br>'.join(inbox['domain'] for inbox in inboxes)
|
||||
# )
|
||||
|
||||
data = self.template.render('page/home.haml', self, instances = instances)
|
||||
data = self.template.render('page/home.haml', self, **context)
|
||||
return Response.new(data, ctype='html')
|
||||
|
||||
|
||||
|
@ -137,11 +119,64 @@ class Admin(View):
|
|||
|
||||
@register_route('/admin/instances')
|
||||
class AdminInstances(View):
|
||||
async def get(self, request: Request) -> Response:
|
||||
data = self.template.render('page/admin-instances.haml', self)
|
||||
async def get(self,
|
||||
request: Request,
|
||||
error: str | None = None,
|
||||
message: str | None = None) -> Response:
|
||||
|
||||
with self.database.session() as conn:
|
||||
context = {
|
||||
'instances': tuple(conn.execute('SELECT * FROM inboxes').all())
|
||||
}
|
||||
|
||||
if error:
|
||||
context['error'] = error
|
||||
|
||||
if message:
|
||||
context['message'] = message
|
||||
|
||||
data = self.template.render('page/admin-instances.haml', self, **context)
|
||||
return Response.new(data, ctype = 'html')
|
||||
|
||||
|
||||
async def post(self, request: Request) -> Response:
|
||||
data = {key: value for key, value in (await request.post()).items()}
|
||||
|
||||
if not data['actor'] and not data['domain']:
|
||||
return await self.get(request, error = 'Missing actor and/or domain')
|
||||
|
||||
if not data['domain']:
|
||||
data['domain'] = urlparse(data['actor']).netloc
|
||||
|
||||
if not data['software']:
|
||||
nodeinfo = await self.client.fetch_nodeinfo(data['domain'])
|
||||
data['software'] = nodeinfo.sw_name
|
||||
|
||||
if not data['actor'] and data['software'] in ACTOR_FORMATS:
|
||||
data['actor'] = ACTOR_FORMATS[data['software']].format(domain = data['domain'])
|
||||
|
||||
if not data['inbox'] and data['actor']:
|
||||
actor = await self.client.get(data['actor'], sign_headers = True, loads = Message.parse)
|
||||
data['inbox'] = actor.shared_inbox
|
||||
|
||||
with self.database.session(True) as conn:
|
||||
conn.put_inbox(**data)
|
||||
|
||||
return await self.get(request, message = "Added new inbox")
|
||||
|
||||
|
||||
@register_route('/admin/instances/delete/{domain}')
|
||||
class AdminInstancesDelete(View):
|
||||
async def get(self, request: Request, domain: str) -> Response:
|
||||
with self.database.session() as conn:
|
||||
if not (conn.get_inbox(domain)):
|
||||
return await AdminInstances(request).get(request, message = 'Instance not found')
|
||||
|
||||
conn.del_inbox(domain)
|
||||
|
||||
return await AdminInstances(request).get(request, message = 'Removed instance')
|
||||
|
||||
|
||||
@register_route('/admin/whitelist')
|
||||
class AdminWhitelist(View):
|
||||
async def get(self, request: Request) -> Response:
|
||||
|
|
Loading…
Reference in a new issue