235 lines
5.5 KiB
Python
235 lines
5.5 KiB
Python
import asyncio, json
|
|
|
|
from izzylib import DotDict, logging
|
|
from izzylib.http_server_async import View
|
|
|
|
from . import __version__
|
|
from .config import config
|
|
from .database import db
|
|
from .processing import ProcessData
|
|
|
|
|
|
### Frontend
|
|
|
|
class UnciaHome(View):
|
|
__path__ = '/'
|
|
|
|
async def get(self, request, response):
|
|
with db.session as s:
|
|
instances = s.get.instance_list()
|
|
|
|
response.set_template('page/home.haml', {'instances': instances})
|
|
|
|
|
|
class UnciaAbout(View):
|
|
__path__ = '/about'
|
|
|
|
async def get(self, request, response):
|
|
response.set_template('page/about.haml')
|
|
|
|
|
|
class UnciaRegister(View):
|
|
__path__ = '/register'
|
|
|
|
async def get(self, request, response, error=None, message=None, form={}):
|
|
data = {
|
|
'form': form,
|
|
'error': error,
|
|
'message': message
|
|
}
|
|
|
|
response.set_template('page/register.haml', data)
|
|
|
|
|
|
async def post(self, request, response):
|
|
return await self.get(request, response, form=await request.form())
|
|
|
|
|
|
class UnciaLogin(View):
|
|
__path__ = '/login'
|
|
|
|
async def get(self, request, response, error=None, message=None, form={}):
|
|
data = {
|
|
'form': form,
|
|
'error': error,
|
|
'message': message
|
|
}
|
|
|
|
response.set_template('page/login.haml', data)
|
|
|
|
|
|
async def post(self, request, response):
|
|
return await self.get(request, response, form=await request.form())
|
|
|
|
|
|
class UnciaLogout(View):
|
|
__path__ = '/logout'
|
|
|
|
async def get(self, request, response):
|
|
response.set_redir('/')
|
|
|
|
|
|
class UnciaUser(View):
|
|
__path__ = '/user'
|
|
|
|
async def get(self, request, response):
|
|
response.set_template('page/user.haml')
|
|
|
|
|
|
async def post(self, request, response):
|
|
return await self.get(request, response)
|
|
|
|
|
|
class UnciaAdmin(View):
|
|
__path__ = '/admin'
|
|
|
|
async def get(self, request, response):
|
|
response.set_template('page/admin.haml')
|
|
|
|
|
|
async def post(self, request, response):
|
|
return await self.get(request, response)
|
|
|
|
|
|
### ActivityPub and AP-related endpoints
|
|
|
|
class UnciaActor(View):
|
|
__path__ = ['/actor', '/inbox']
|
|
|
|
async def get(self, request, response):
|
|
with db.session as s:
|
|
cfg = s.get.config_all()
|
|
|
|
data = {
|
|
'@context': [
|
|
'https://www.w3.org/ns/activitystreams',
|
|
{'manuallyApprovesFollowers': 'as:manuallyApprovesFollowers'},
|
|
],
|
|
'id': f'https://{config.host}/actor',
|
|
#'followers': f'https://{host}/followers',
|
|
#'following': f'https://{host}/following',
|
|
'name': cfg.name,
|
|
'summary': cfg.description,
|
|
'preferredUsername': 'relay',
|
|
'type': 'Application',
|
|
'inbox': f'https://{config.host}/inbox',
|
|
'url': f'https://{config.host}/',
|
|
'manuallyApprovesFollowers': cfg.require_approval,
|
|
'endpoints': {
|
|
'sharedInbox': f"https://{config.host}/inbox"
|
|
},
|
|
'publicKey': {
|
|
'id': f'https://{config.host}/actor#main-key',
|
|
'owner': f'https://{config.host}/actor',
|
|
'publicKeyPem': cfg.pubkey
|
|
}
|
|
}
|
|
|
|
response.set_json(data, activity=True)
|
|
|
|
|
|
async def post(self, request, response):
|
|
if not request.actor:
|
|
logging.verbose(f'Failed to fetch actor')
|
|
response.set_json({'error': 'Failed to fetch actor'})
|
|
return
|
|
|
|
processor = ProcessData(request, response, await request.json())
|
|
|
|
if processor.valid_type():
|
|
loop = asyncio.get_running_loop()
|
|
loop.create_task(processor())
|
|
|
|
else:
|
|
headers = {k: request.headers.getone(k) for k in request.headers}
|
|
logging.verbose('Message type not handled:', processor.type)
|
|
logging.debug(f'Headers: {json.dumps(headers)}')
|
|
logging.debug(f'Body: {request.text}')
|
|
#return response.json({'error': f'Message type unhandled: {processor.type}'}, status=401)
|
|
|
|
response.set_json({'message': 'UvU'})
|
|
response.status = 202
|
|
|
|
|
|
class UnciaNodeinfo(View):
|
|
__path__ = ['/nodeinfo/2.0.json', '/nodeinfo/2.0']
|
|
|
|
async def get(self, request, response):
|
|
with db.session as s:
|
|
instances = s.get.instance_list('domain')
|
|
domainbans = [row.domain for row in s.get.ban_list('domain')]
|
|
userbans = [f"{row.handle}@{row.domain}" for row in s.get.ban_list('user')]
|
|
whitelist = [row.domain for row in s.search('whitelist')]
|
|
wl_enabled = s.get.config('whitelist')
|
|
|
|
data = {
|
|
'openRegistrations': True,
|
|
'protocols': ['activitypub'],
|
|
'services': {
|
|
'inbound': [],
|
|
'outbound': []
|
|
},
|
|
'software': {
|
|
'name': 'unciarelay',
|
|
'version': f'{__version__}'
|
|
},
|
|
'usage': {
|
|
'localPosts': 0,
|
|
'users': {
|
|
'total': 1
|
|
}
|
|
},
|
|
'version': '2.0',
|
|
'metadata': {
|
|
'require_approval': s.get.config('require_approval'),
|
|
'peers': instances,
|
|
'email': s.get.config('email'),
|
|
'federation': {
|
|
'instance_blocks': False if not s.get.config('show_domain_bans') else domainbans,
|
|
'user_blocks': False if not s.get.config('show_user_bans') else userbans,
|
|
'whitelist': whitelist if s.get.config('show_whitelist') and wl_enabled else wl_enabled
|
|
}
|
|
}
|
|
}
|
|
|
|
response.set_json(data)
|
|
|
|
|
|
class UnciaWebfinger(View):
|
|
__path__ = '/.well-known/webfinger'
|
|
|
|
async def get(self, request, response):
|
|
resource = request.query.get('resource')
|
|
|
|
if resource != f'acct:relay@{config.host}':
|
|
response.status = 404
|
|
return
|
|
|
|
response.set_json({
|
|
'subject': f'acct:relay@{config.host}',
|
|
'aliases': [
|
|
f'https://{config.host}/actor'
|
|
],
|
|
'links': [
|
|
{
|
|
'rel': 'self',
|
|
'type': 'application/activity+json',
|
|
'href': f'https://{config.host}/actor'
|
|
}
|
|
]
|
|
})
|
|
|
|
|
|
class UnciaWellknownNodeinfo(View):
|
|
__path__ = '/.well-known/nodeinfo'
|
|
|
|
async def get(self, request, response):
|
|
response.set_json({
|
|
'links': [
|
|
{
|
|
'rel': 'http://nodeinfo.diaspora.software/ns/schema/2.0',
|
|
'href': f'https://{config.host}/nodeinfo/2.0.json'
|
|
}
|
|
]
|
|
})
|