iunno tbh

This commit is contained in:
Izalia Mae 2021-09-17 09:03:25 -04:00
parent 7f76724806
commit 51cddac201
7 changed files with 229 additions and 64 deletions

View file

@ -6,3 +6,4 @@
envbash==1.2.0
pyyaml==5.4.1
pg8000=1.21.2

View file

@ -1,16 +1,14 @@
from izzylib import logging
from izzylib.http_requests_client.signature import generate_rsa_key
from izzylib.sql import SqlDatabase
from izzylib.sql.generic import OperationalError
from izzylib.http_urllib_client.signatures import generate_rsa_key
from izzylib.sql import Database
from .base import Session, tables
from ..config import config, dbconfig
db = SqlDatabase(
db = Database(
config.dbtype,
tables = tables,
session_class = Session,
**dbconfig
)
@ -19,12 +17,12 @@ with db.session as s:
try:
version = s.get.config('version')
except OperationalError:
except KeyError:
version = 0
if version == 0:
keys = generate_rsa_key()
db.create_database()
db.create_database(tables)
s.put.config('version', config.version)
s.put.config('pubkey', keys.pubkey)
s.put.config('privkey', keys.privkey)

View file

@ -3,7 +3,6 @@ import json
from datetime import datetime
from functools import partial
from izzylib import DotDict, boolean, logging
from izzylib.http_requests_client.signature import generate_rsa_key
from izzylib.sql import SqlDatabase, SqlSession
from izzylib.sql import SqlColumn as Column
from urllib.parse import urlparse
@ -32,7 +31,8 @@ tables = {
Column('msgid', 'text', nullable=False),
Column('inboxid', 'integer', nullable=False, fkey='inbox.id'),
Column('data', 'json', nullable=False),
Column('headers', 'json')
Column('headers', 'json'),
Column('timestamp')
],
'user': [
Column('id'),

View file

@ -1,35 +1,23 @@
import json
from functools import wraps
from izzylib import HttpRequestsClient, LruCache, logging
from izzylib import LruCache, logging
from izzylib.http_urllib_client import HttpUrllibClient
from . import __version__
from .config import config
from .database import db
client = HttpRequestsClient(appagent=f'UnciaRelay/{__version__}; https://{config.host}')
client = HttpUrllibClient(
appagent = f'UnciaRelay/{__version__}; https://{config.host}',
headers = {
'accept': 'application/activity+json,application/json'
}
)
client.set_global()
cache = LruCache()
def cache_fetch(func):
@wraps(func)
def inner_func(url, *args, **kwargs):
cached = cache.fetch(url)
if cached:
return cached
response = func(url, *args, **kwargs)
if not response:
return
cache.store(url, response)
return response
return inner_func
fetch_cache = LruCache()
def fetch_actor(url):
@ -40,15 +28,13 @@ def fetch_actor(url):
return cached.data
try:
response = client.json(url, activity=True)
data = response.json
data = fetch(url, cache=False)
except:
data = None
if response.status not in [200, 202]:
logging.verbose(f'Signing headers to fetch actor: {url}')
data = fetch_auth(url)
if not data:
data = fetch(url, sign=True, cache=False)
if not data:
return
@ -57,20 +43,39 @@ def fetch_actor(url):
return data
@cache_fetch
def fetch_auth(url):
with db.session as s:
response = client.signed_request(
s.get.config('privkey'),
f'https://{config.host}/actor#main-key',
url,
headers = {'accept': 'application/activity+json'}
)
def fetch(url, sign=False, cache=True):
cached_data = fetch_cache.fetch(url)
try:
return response.json
except json.decoder.JSONDecodeError:
return {}
if cached_data and cache:
return cached_data
if sign:
with db.session as s:
response = client.request(url,
privkey = s.get.config('privkey'),
keyid = f'https://{config.host}/actor#main-key'
)
else:
response = client.request(url)
try:
data = response.dict
except json.decoder.JSONDecodeError:
return {}
if not data:
return {}
if cache:
fetch_cache.store(url, data)
return data
def fetch_auth(url):
return fetch(url, sign=True)
def get_inbox(actor):
@ -90,13 +95,12 @@ def push_message(inbox, message):
f'https://{config.host}/actor#main-key',
inbox,
data = message.to_json(),
method = 'post',
headers = {'accept': 'application/json'}
method = 'post'
)
if response.status not in [200, 202]:
try:
body = response.json
body = response.dict
except:
body = response.text

View file

@ -1,10 +1,15 @@
import json, sys, yaml
import json, sys
from datetime import datetime
from envbash import load_envbash
from getpass import getuser
from izzylib import DotDict, Path, boolean, logging, prompt
from izzylib.sql import Database
from os import environ as env
from urllib.parse import urlparse
from . import __version__
from .config import dbconfig, config, write_config
from .config import config, dbconfig, path, write_config
from .database import db
from .functions import fetch_actor, get_inbox
from .messages import Message
@ -253,7 +258,128 @@ python3 -m uncia.manage convert [pleroma or uncia]:
def convert_uncia(self):
pass
cfg = load_old_uncia_config()
pgdb = Database('postgresql', **cfg)
new_cfg = cfg.copy()
new_cfg.pop('name', None)
dbconfig.update(new_cfg)
with pgdb.session as s:
oldcfg = DotDict({row.key: row.value for row in s.search('config')})
inboxes = s.search('inboxes')
requests = s.search('requests')
retries = s.search('retries')
users = s.search('users')
whitelist = s.search('whitelist')
domainbans = s.search('domainbans')
userbans = s.search('userbans')
actorkey = s.fetch('keys', actor='default')
config.host = oldcfg.host
config.listen = oldcfg.address
config.port = oldcfg.port
write_config()
with db.session as s:
s.put.config('name', oldcfg.name)
s.put.config('admin', oldcfg.admin)
s.put.config('show_domain_bans', boolean(oldcfg.show_domainbans))
s.put.config('show_user_bans', boolean(oldcfg.show_userbans))
s.put.config('whitelist', boolean(oldcfg.whitelist))
s.put.config('block_relays', boolean(oldcfg.block_relays))
s.put.config('require_approval', boolean(oldcfg.require_approval))
s.put.config('privkey', actorkey.privkey)
s.put.config('pubkey', actorkey.pubkey)
for inbox in [*inboxes, *requests]:
try:
timestamp = datetime.fromtimestamp(inbox.timestamp)
except:
timestamp = datetime.now()
s.insert('inbox',
actor = inbox.actor,
inbox = inbox.inbox,
domain = inbox.domain,
followid = inbox.get('followid'),
timestamp = timestamp
)
for retry in retries:
try:
timestamp = datetime.fromtimestamp(retry.timestamp)
except:
timestamp = datetime.now()
instance = s.fetch('inbox', inbox=retry.inbox)
if not instance:
continue
s.insert('retry',
inboxid = instance.id,
msgid = retry.msgid,
headers = json.loads(retry.headers),
data = json.loads(retry.data),
timestamp = timestamp
)
for user in users:
try:
timestamp = datetime.fromtimestamp(user.timestamp)
except:
timestamp = datetime.now()
s.insert('user',
handle = user.handle,
username = user.username,
hash = user.password,
level = 30,
timestamp = timestamp
)
for instance in whitelist:
try:
timestamp = datetime.fromtimestamp(instance.timestamp)
except:
timestamp = datetime.now()
s.insert('whitelist',
domain = instance.domain,
timestamp = timestamp
)
for row in [*domainbans, *userbans]:
try:
timestamp = datetime.fromtimestamp(row.timestamp)
except:
timestamp = datetime.now()
s.insert('ban',
handle = row.get('username'),
domain = None if row.domain.lower() == 'any' else row.domain,
reason = row.reason,
timestamp = timestamp
)
pgdb.close()
delete_old = prompt('Config and database successfully converted. Delete old files and drop the old database?', default='no', valtype=boolean, options=['yes', 'no'])
if delete_old:
path.data.join('production.env').delete()
pgdb._connect_args[0]['name'] = 'postgres'
pgdb.open()
with pgdb.session as s:
s.execute(f'DROP DATABASE {cfg.name}')
pgdb.close()
return f'Successfully dropped database: {cfg.name}'
def convert_pleroma(self):
@ -294,6 +420,33 @@ python3 -m uncia.manage convert [pleroma or uncia]:
pl_cfg.db.delete()
def load_old_uncia_config():
try:
load_envbash(path.config.join('production.env'))
except FileNotFoundError as e:
pass
cfg = DotDict(
host = env.get('DBHOST'),
port = int(env.get('DBPORT', 5432)),
user = env.get('DBUSER', getuser()),
password = env.get('DBPASS'),
name = env.get('DBNAME', 'uncia'),
maxconnections = int(env.get('DBCONNUM', 15))
)
#for k,v in cfg.items():
#if v == None:
#del cfg[k]
#if k == 'host' and Path(v).exists():
#cfg['unix_socket'] = v
#del cfg[k]
return cfg
def load_pleroma_relay_config():
with open('relay.yaml') as f:
yaml_file = yaml.load(f, Loader=yaml.FullLoader)

View file

@ -1,5 +1,5 @@
from izzylib import logging
from izzylib.http_requests_client import parse_signature, verify_request
from izzylib.http_urllib_client import parse_signature, verify_request
from izzylib.http_server import MiddlewareBase
from .database import db

View file

@ -5,7 +5,7 @@ from tldextract import extract
from urllib.parse import urlparse
from .database import db
from .functions import fetch_actor, fetch_auth, get_inbox, push_message
from .functions import fetch, fetch_actor, get_inbox, push_message
from .messages import Message
@ -76,7 +76,7 @@ class ProcessData:
if self.actor.type.lower() != 'application':
return
object = fetch_auth(self.data.object) if isinstance(self.data.object, str) else self.data.object
object = fetch(self.data.object, sign=True) if isinstance(self.data.object, str) else self.data.object
if object.type != 'Follow':
return
@ -87,14 +87,23 @@ class ProcessData:
def cmd_announce(self):
object = fetch_auth(self.data.object) if isinstance(self.data.object, str) else self.data.object
obj_actor = fetch_auth(object.attributedTo)
if isinstance(self.data.object, dict):
object = self.data.object
object_id = self.data.object.id
if not obj_actor:
logging.verbose('Failed to fetch actor:', obj_actor)
else:
object = fetch(self.data.object, sign=True)
object_id = self.data.object
if not object:
obj_actor = None
logging.verbose('Failed to fetch object:', object_id)
else:
obj_actor = fetch(object.attributedTo, sign=True)
# I'm pretty sure object.attributedTo is a string, but leaving this here just in case
#obj_actor = fetch_auth(object.attributedTo) if isinstance(object.attributedTo, str) else object.attributedTo
#obj_actor = fetch(object.attributedTo, sign=True) if isinstance(object.attributedTo, str) else object.attributedTo
if object.id in relayed_objects:
logging.verbose('Already relayed object:', object.id)
@ -120,4 +129,4 @@ class ProcessData:
logging.debug(f'Server error {response.status}: {response.text}')
else:
logging.verbose(f'Send "{object.id}" to {instance.domain}')
logging.verbose(f'Sent "{object.id}" to {instance.domain}')