fix db connections, logging, token deletion, etc
This commit is contained in:
parent
b7d400d774
commit
e1756fe901
|
@ -118,6 +118,7 @@ def settings(data):
|
|||
if k == 'port':
|
||||
try:
|
||||
new_data.update({k: int(v)})
|
||||
|
||||
except ValueError:
|
||||
logging.warning(f'{v} is not a valid value for \'port\'')
|
||||
|
||||
|
@ -126,8 +127,7 @@ def settings(data):
|
|||
|
||||
put.config(new_data)
|
||||
|
||||
#logging.level = eval(f'logger.{data["log_level"]}')
|
||||
#logging.debug('heck')
|
||||
logging.setLevel(data["log_level"])
|
||||
|
||||
def ban(data):
|
||||
domain = data['name']
|
||||
|
|
|
@ -54,6 +54,9 @@ else:
|
|||
|
||||
# Web forward config
|
||||
SECRET={ranchars}
|
||||
|
||||
# Development mode
|
||||
#UNCIA_DEV=False
|
||||
'''
|
||||
|
||||
with open(envfile, 'w') as newenvfile:
|
||||
|
@ -75,3 +78,4 @@ dbconfig = {
|
|||
}
|
||||
|
||||
fwsecret = env.get('SECRET')
|
||||
development = env.get('UNCIA_DEV')
|
||||
|
|
|
@ -6,17 +6,16 @@ from DBUtils.PooledPg import PooledPg
|
|||
from pg import DatabaseError
|
||||
from passlib.context import CryptContext
|
||||
|
||||
from ..config import dbconfig, script_path, stor_path
|
||||
from ..log import logging
|
||||
from ..config import dbconfig, script_path, stor_path
|
||||
from ..functions import LRUCache
|
||||
|
||||
|
||||
CONFIG = {}
|
||||
class cache_dicts():
|
||||
config = {}
|
||||
key = LRUCache()
|
||||
|
||||
|
||||
def baguette_path(path):
|
||||
return path.replace('🥖', '/')
|
||||
|
||||
dbsql = baguette_path(f'{script_path}🥖database🥖database.sql')
|
||||
dbcache = cache_dicts()
|
||||
|
||||
|
||||
def dbconn(database, pooled=True):
|
||||
|
@ -34,7 +33,7 @@ def dbconn(database, pooled=True):
|
|||
|
||||
if pooled:
|
||||
cached = 5 if dbconfig['connum'] >= 5 else 0
|
||||
return PooledPg(maxconnections=dbconfig['connum'], mincached=cached, maxusage=2, **options)
|
||||
return PooledPg(maxconnections=dbconfig['connum'], mincached=cached, maxusage=1, **options)
|
||||
|
||||
else:
|
||||
return pg.DB(**options)
|
||||
|
@ -64,54 +63,34 @@ def db_check():
|
|||
if 'skipdbcheck' not in sys.argv:
|
||||
db_check()
|
||||
|
||||
newcon = dbconn(dbconfig['name'])
|
||||
dbpool = dbconn(dbconfig['name'])
|
||||
|
||||
|
||||
def connection(func):
|
||||
def inner(*arg, **kwargs):
|
||||
trans = newcon.connection()
|
||||
def inner(*args, **kwargs):
|
||||
conn = kwargs.get('db', dbpool.connection())
|
||||
|
||||
try:
|
||||
result = func(*arg, **kwargs, db=trans)
|
||||
result = func(*args, **kwargs, db=conn)
|
||||
|
||||
except:
|
||||
result = None
|
||||
traceback.print_exc()
|
||||
|
||||
trans.close()
|
||||
conn.close()
|
||||
|
||||
return result
|
||||
return inner
|
||||
|
||||
|
||||
def newtrans(func):
|
||||
def inner(*arg, **kwargs):
|
||||
trans = newcon.connection()
|
||||
trans.begin()
|
||||
|
||||
try:
|
||||
result = func(*arg, **kwargs, db=trans)
|
||||
|
||||
except:
|
||||
result = None
|
||||
logging.error(f'DB command failed')
|
||||
traceback.print_exc()
|
||||
|
||||
trans.end()
|
||||
trans.close()
|
||||
|
||||
return result
|
||||
return inner
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def setup(db=None):
|
||||
dbcheck = db.query('SELECT * FROM config WHERE key = \'setup\'').dictresult()
|
||||
|
||||
if dbcheck == []:
|
||||
|
||||
settings = {
|
||||
'host': 'relaydev.barkshark.xyz',
|
||||
'host': 'relay.example.com',
|
||||
'address': '0.0.0.0',
|
||||
'port': 3621,
|
||||
'name': 'Uncia Relay',
|
||||
|
@ -143,7 +122,8 @@ def query(table, data, one=True, sort=None, db=None):
|
|||
row = db.query(f"SELECT * FROM {table} WHERE {k} = '{v}' {SORT}")
|
||||
|
||||
try:
|
||||
return row.singledict() if one else row.dictresult()
|
||||
result = row.dictresult()
|
||||
return result[0] if one and len(result)> 0 else result
|
||||
|
||||
except pg.NoResultError:
|
||||
return
|
||||
|
@ -231,7 +211,7 @@ class HashContext:
|
|||
|
||||
def randomgen(chars=20):
|
||||
if type(chars) != int:
|
||||
logging.warning(f'Invalid character length. Must be an int: {chars}')
|
||||
logging.warn(f'Invalid character length. Must be an int: {chars}')
|
||||
chars = 20
|
||||
|
||||
return ''.join(random.choices(string.ascii_letters + string.digits, k=chars))
|
||||
|
@ -251,4 +231,4 @@ def bool_check(value):
|
|||
return value
|
||||
|
||||
|
||||
__all__ = ['newtrans', 'connection', 'HashContext', 'randomgen', 'query', 'query_all', 'query_or', 'query_and']
|
||||
__all__ = ['connection', 'HashContext', 'randomgen', 'query', 'query_all', 'query_or', 'query_and']
|
||||
|
|
|
@ -3,22 +3,20 @@ import pg
|
|||
from Crypto.PublicKey import RSA
|
||||
|
||||
from . import *
|
||||
from . import bool_check as bcheck, CONFIG
|
||||
from . import bool_check as bcheck, dbcache
|
||||
from ..log import logging
|
||||
from ..functions import LRUCache
|
||||
|
||||
Hash = HashContext()
|
||||
Hash.setsalt()
|
||||
|
||||
KEY = LRUCache()
|
||||
auth_code = None
|
||||
|
||||
@connection
|
||||
def rsa_key(actor, db=None):
|
||||
cachedkey = KEY.fetch(actor)
|
||||
def rsa_key(actor, db=None, cached=True):
|
||||
if cached == True:
|
||||
cachedkey = dbcache.key.fetch(actor)
|
||||
|
||||
if cachedkey:
|
||||
return cachedkey
|
||||
if cachedkey:
|
||||
return cachedkey
|
||||
|
||||
actor_key = query('keys', {'actor': actor})
|
||||
|
||||
|
@ -42,22 +40,22 @@ def rsa_key(actor, db=None):
|
|||
'PUBKEY': RSA.importKey(actor_key['pubkey'])
|
||||
})
|
||||
|
||||
KEY.store(actor, actor_key)
|
||||
dbcache.key.store(actor, actor_key)
|
||||
return actor_key
|
||||
|
||||
|
||||
@connection
|
||||
def config(data, cache=True, db=None):
|
||||
if len(CONFIG.keys()) < 1 and cache:
|
||||
if len(dbcache.config.keys()) < 1 and cache:
|
||||
update_config()
|
||||
|
||||
if type(data) == list or data == 'all':
|
||||
settings = {}
|
||||
|
||||
if data == 'all':
|
||||
if CONFIG and cache:
|
||||
if dbcache.config and cache:
|
||||
logging.debug('Returning cached config')
|
||||
return CONFIG
|
||||
return dbcache.config
|
||||
|
||||
rows = query_all('config')
|
||||
|
||||
|
@ -68,7 +66,7 @@ def config(data, cache=True, db=None):
|
|||
for k,v in data.items():
|
||||
if cache:
|
||||
logging.debug('Returning cached config')
|
||||
row = [{'key': key, 'value': value} for key, value in CONFIG.items()]
|
||||
row = [{'key': key, 'value': value} for key, value in dbcache.config.items()]
|
||||
|
||||
else:
|
||||
query_data = {'key': k, 'value': v}
|
||||
|
@ -83,7 +81,7 @@ def config(data, cache=True, db=None):
|
|||
return settings
|
||||
|
||||
elif type(data) == str:
|
||||
cached = CONFIG.get(data)
|
||||
cached = dbcache.config.get(data)
|
||||
|
||||
if cached and cache:
|
||||
return cached
|
||||
|
@ -92,7 +90,7 @@ def config(data, cache=True, db=None):
|
|||
|
||||
if row:
|
||||
value = bcheck(row['value'])
|
||||
CONFIG[data] = value
|
||||
dbcache.config[data] = value
|
||||
return value
|
||||
|
||||
|
||||
|
@ -104,7 +102,7 @@ def update_config(db=None):
|
|||
key = row['key']
|
||||
value = bcheck(row['value'])
|
||||
|
||||
CONFIG[key] = value
|
||||
dbcache.config[key] = value
|
||||
|
||||
|
||||
@connection
|
||||
|
@ -172,11 +170,11 @@ def user(data, db=None):
|
|||
|
||||
|
||||
@connection
|
||||
def token(data, db=None):
|
||||
def token(data, *args, db=None, **kwargs):
|
||||
if type(data) == str:
|
||||
query_string = {'token': data}
|
||||
|
||||
if type(data) == int:
|
||||
elif type(data) == int:
|
||||
query_string = {'id': data}
|
||||
|
||||
elif type(data) == dict:
|
||||
|
@ -191,6 +189,10 @@ def token(data, db=None):
|
|||
logging.error(f'Invalid data for get.token: {data}')
|
||||
return
|
||||
|
||||
else:
|
||||
logging.warning(f'Invalid data type: {type(data)}')
|
||||
return
|
||||
|
||||
return query('tokens', query_string)
|
||||
|
||||
|
||||
|
@ -198,6 +200,10 @@ def token(data, db=None):
|
|||
def verify_password(username, password, db=None):
|
||||
user_data = user(username)
|
||||
|
||||
if not user_data:
|
||||
logging.verbose(f'Invalid user when trying to verify password: {username}')
|
||||
return
|
||||
|
||||
return Hash.verify(password, user_data['password'])
|
||||
|
||||
|
||||
|
@ -211,16 +217,26 @@ def code(action=None):
|
|||
|
||||
|
||||
# generate an auth code if there are no admin users
|
||||
if len(user('all')) < 1:
|
||||
users = user('all')
|
||||
if not users or len(users) < 1:
|
||||
code('regen')
|
||||
host = config('host')
|
||||
port = config('port')
|
||||
address = config('address')
|
||||
|
||||
if config('setup'):
|
||||
logging.warn(f'There are no admin users in the database. Please register an account at https://{host}/register?code={auth_code}')
|
||||
address = '127.0.0.1' if address == '0.0.0.0' else address
|
||||
|
||||
else:
|
||||
logging.warn(f'The relay is not configured. Please set it up at https://{host}/setup?code={auth_code}')
|
||||
if host:
|
||||
if config('setup'):
|
||||
logging.warning(f'There are no admin users in the database. Please register an account at https://{host}/register?code={auth_code}')
|
||||
|
||||
else:
|
||||
logging.warning(f'The relay is not configured. Please set it up at http://{address}:{port}/setup?code={auth_code}')
|
||||
|
||||
else:
|
||||
auth_code = None
|
||||
|
||||
|
||||
# Set log level from config
|
||||
log_level = config('log_level')
|
||||
logging.setLevel(log_level)
|
||||
|
|
|
@ -4,7 +4,7 @@ import ujson as json
|
|||
from datetime import datetime
|
||||
|
||||
from . import *
|
||||
from . import get, bool_check, CONFIG
|
||||
from . import get, bool_check, dbcache
|
||||
from ..log import logging
|
||||
from ..functions import format_urls
|
||||
|
||||
|
@ -13,43 +13,42 @@ Hash = HashContext()
|
|||
Hash.setsalt()
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def config(data, db=None):
|
||||
configs = get.config('all', cache=False)
|
||||
db.begin()
|
||||
|
||||
for k,v in data.items():
|
||||
value = bool_check(v)
|
||||
row = query('config', {'key': k})
|
||||
|
||||
if configs and configs.get(k) == value:
|
||||
continue
|
||||
data = {
|
||||
'key': k,
|
||||
'value': value
|
||||
}
|
||||
|
||||
if not configs or k not in configs:
|
||||
data = {
|
||||
'key': k,
|
||||
'value': value
|
||||
}
|
||||
if row:
|
||||
data['id'] = row['id']
|
||||
|
||||
db.insert('config', data)
|
||||
|
||||
else:
|
||||
row = query('config', {'key': k})
|
||||
db.update('config', {'value': value}, id=row['id'])
|
||||
db.upsert('config', data)
|
||||
|
||||
db.end()
|
||||
get.update_config()
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def rsa_key(name, keys, db=None):
|
||||
actor_key = get.rsa_key('default')
|
||||
key = {
|
||||
'actor': name,
|
||||
'pubkey': keys['pubkey'],
|
||||
'privkey': keys['privkey']
|
||||
}
|
||||
|
||||
if not actor_key:
|
||||
db.update('keys', {
|
||||
'pubkey': keys['pubkey'],
|
||||
'privkey': keys['privkey']
|
||||
}, actor='default')
|
||||
if db.upsert('keys', key, actor=name):
|
||||
dbcache.key.store(name, get.rsa_key(name, cached=False))
|
||||
return True
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def inbox(action, urls, timestamp=None, db=None):
|
||||
actor, inbox, domain = format_urls(urls)
|
||||
row = get.inbox(actor)
|
||||
|
@ -76,7 +75,7 @@ def inbox(action, urls, timestamp=None, db=None):
|
|||
return True
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def request(action, urls, followid=None, db=None):
|
||||
actor, inbox, domain = format_urls(urls)
|
||||
row = get.request(domain)
|
||||
|
@ -102,7 +101,7 @@ def request(action, urls, followid=None, db=None):
|
|||
return True
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def add_retry(msgid, inbox, data, headers, db=None):
|
||||
row = get.retries({'msgid': msgid, 'inbox': inbox})
|
||||
|
||||
|
@ -121,7 +120,7 @@ def add_retry(msgid, inbox, data, headers, db=None):
|
|||
return True
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def del_retries(data, db=None):
|
||||
if type(data) == int:
|
||||
rows = [get.retries(data)]
|
||||
|
@ -138,7 +137,7 @@ def del_retries(data, db=None):
|
|||
return True
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def ban(action, data, reason=None, db=None):
|
||||
if '@' in data:
|
||||
if data.startswith('@'):
|
||||
|
@ -176,8 +175,8 @@ def ban(action, data, reason=None, db=None):
|
|||
return True if db.delete(bantype, id=row['id']) else False
|
||||
|
||||
|
||||
@newtrans
|
||||
def whitelist(action, data, reason=None, db=None):
|
||||
@connection
|
||||
def whitelist(action, data, db=None):
|
||||
domain = urlparse(data).netloc if data.startswith('https://') else data
|
||||
|
||||
row = get.whitelist(domain)
|
||||
|
@ -201,7 +200,7 @@ def whitelist(action, data, reason=None, db=None):
|
|||
db.delete('whitelist', id=row['id'])
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def user(username, password, db=None):
|
||||
handle = username.lower()
|
||||
timestamp = datetime.now().timestamp()
|
||||
|
@ -219,7 +218,7 @@ def user(username, password, db=None):
|
|||
return db.insert('users', data)
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def del_user(token=None, username=None, db=None):
|
||||
if not username and not token:
|
||||
return
|
||||
|
@ -243,7 +242,7 @@ def del_user(token=None, username=None, db=None):
|
|||
db.delete('users', id=userid)
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def token(username, db=None):
|
||||
userdata = get.user(username)
|
||||
|
||||
|
@ -259,17 +258,18 @@ def token(username, db=None):
|
|||
return db.insert('tokens', tokendata)
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def del_token(token, db=None):
|
||||
row = get.token(token)
|
||||
|
||||
if not row:
|
||||
return
|
||||
|
||||
db.delete('tokens', id=row['id'])
|
||||
if db.delete('tokens', id=row['id']):
|
||||
return True
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def acct_name(handle, username, db=None):
|
||||
data = {'username': username}
|
||||
user = get.user(handle)
|
||||
|
@ -282,7 +282,7 @@ def acct_name(handle, username, db=None):
|
|||
return True
|
||||
|
||||
|
||||
@newtrans
|
||||
@connection
|
||||
def password(handle, password, db=None):
|
||||
user = get.user(handle)
|
||||
|
||||
|
|
|
@ -27,9 +27,13 @@
|
|||
{{token.timestamp}}
|
||||
|
||||
%td{'class': 'col2'}
|
||||
%form{'action': 'https://{{config.host}}/account/token', 'method': 'post'}
|
||||
%input{'type': 'hidden', 'name': 'token', 'value': '{{token.token}}'}
|
||||
%input{'type': 'submit', 'value': 'Delete'}
|
||||
-if current != 'active'
|
||||
%form{'action': 'https://{{config.host}}/account/token', 'method': 'post'}
|
||||
%input{'type': 'hidden', 'name': 'token', 'value': '{{token.token}}'}
|
||||
%input{'type': 'submit', 'value': 'Delete'}
|
||||
|
||||
-else
|
||||
n/a
|
||||
|
||||
%div{'class': 'section account profile'}
|
||||
%h2{'class': 'title'} Display Name
|
||||
|
|
|
@ -349,7 +349,7 @@
|
|||
|
||||
%label Log Level
|
||||
%select{'name': 'log_level'}
|
||||
- for level in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
|
||||
- for level in ['MERP', 'DEBUG', 'VERB', 'INFO', 'WARN', 'ERROR', 'CRIT']
|
||||
-if config.log_level == level
|
||||
%option{'value': '{{level}}', selected: None}
|
||||
{{level}}
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
- set title = 'Setup'
|
||||
|
||||
- block content
|
||||
- if config.setup
|
||||
-if config.setup
|
||||
%div{'class': 'section setup'}
|
||||
%p{'class': 'sec-header'} Setup
|
||||
%p<
|
||||
The relay has been successfully setup. Please start the relay again and setup an admin account via the register url that shows up in the console log
|
||||
|
||||
-else
|
||||
%div{'class': 'section setup'}
|
||||
%p{'class': 'sec-header'} Setup
|
||||
%p<
|
||||
|
|
101
uncia/log.py
101
uncia/log.py
|
@ -3,26 +3,102 @@ import logging as logger
|
|||
import logging.config as logconf
|
||||
|
||||
from os import environ as env
|
||||
from datetime import datetime
|
||||
|
||||
def verb(self, message, *args, **kws):
|
||||
if self.isEnabledFor(15):
|
||||
self._log(15, message, args, **kws)
|
||||
|
||||
LOG_BASE = '%(asctime)s %(process)d %(levelname)s'
|
||||
DATE_FMT = "%Y-%m-%d %H:%M:%S" if not env.get('INVOCATION_ID') else ''
|
||||
# Custom logger
|
||||
class Log():
|
||||
def __init__(self, minimum='INFO', datefmt='%Y-%m-%d %H:%M:%S', date=True):
|
||||
self.levels = {
|
||||
'CRIT': 60,
|
||||
'ERROR': 50,
|
||||
'WARN': 40,
|
||||
'INFO': 30,
|
||||
'VERB': 20,
|
||||
'DEBUG': 10,
|
||||
'MERP': 0
|
||||
}
|
||||
|
||||
self.datefmt = datefmt
|
||||
self.minimum = self._lvlCheck(minimum)
|
||||
|
||||
# make sure the minimum logging level is an int
|
||||
def _lvlCheck(self, level):
|
||||
try:
|
||||
value = int(level)
|
||||
|
||||
except ValueError:
|
||||
value = self.levels.get(level)
|
||||
|
||||
if value not in self.levels.values():
|
||||
raise InvalidLevel(f'Invalid logging level: {level}')
|
||||
|
||||
return value
|
||||
|
||||
def setLevel(self, level):
|
||||
self.minimum = self._lvlCheck(level)
|
||||
|
||||
def log(self, level, msg):
|
||||
levelNum = self._lvlCheck(level)
|
||||
|
||||
if type(level) == int:
|
||||
for k,v in self.levels.items():
|
||||
if v == levelNum:
|
||||
level = k
|
||||
|
||||
if levelNum < self.minimum:
|
||||
return
|
||||
|
||||
date = datetime.now().strftime(self.datefmt)
|
||||
output = f'{date} {level}: {msg}\n'
|
||||
|
||||
stdout = sys.stdout
|
||||
stdout.write(output)
|
||||
stdout.flush()
|
||||
|
||||
|
||||
def critical(self, msg):
|
||||
self.log('CRIT', msg)
|
||||
|
||||
def error(self, msg):
|
||||
self.log('ERROR', msg)
|
||||
|
||||
def warning(self, msg):
|
||||
self.log('WARN', msg)
|
||||
|
||||
def info(self, msg):
|
||||
self.log('INFO', msg)
|
||||
|
||||
def verbose(self, msg):
|
||||
self.log('VERB', msg)
|
||||
|
||||
def debug(self, msg):
|
||||
self.log('DEBUG', msg)
|
||||
|
||||
def merp(self, msg):
|
||||
self.log('MERP', msg)
|
||||
|
||||
|
||||
class InvalidType(Exception):
|
||||
'''Raise when the log level isn't a str or an int'''
|
||||
|
||||
class InvalidLevel(Exception):
|
||||
'''Raise when an invalid logging level was specified'''
|
||||
|
||||
|
||||
# Set logger for sanic
|
||||
LOG = dict(
|
||||
version=1,
|
||||
disable_existing_loggers=False,
|
||||
loggers={
|
||||
"sanic.root": {
|
||||
"level": 'INFO',
|
||||
"level": 'CRITICAL',
|
||||
"handlers": ["console"],
|
||||
"propagate": False,
|
||||
},
|
||||
|
||||
"sanic.error": {
|
||||
"level": "INFO",
|
||||
"level": "CRITICAL",
|
||||
"handlers": ["error_console"],
|
||||
"propagate": False,
|
||||
"qualname": "sanic.error",
|
||||
|
@ -32,7 +108,7 @@ LOG = dict(
|
|||
handlers={
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
'level': 'INFO',
|
||||
'level': 'CRITICAL',
|
||||
"formatter": "generic",
|
||||
"stream": sys.stdout,
|
||||
},
|
||||
|
@ -44,16 +120,13 @@ LOG = dict(
|
|||
},
|
||||
formatters={
|
||||
"generic": {
|
||||
"format": F"{LOG_BASE} %(message)s",
|
||||
"datefmt": DATE_FMT,
|
||||
"format": f"%(asctime)s %(process)d %(levelname)s %(message)s",
|
||||
"datefmt": "%Y-%m-%d %H:%M:%S" if not env.get('INVOCATION_ID') else '',
|
||||
"class": "logging.Formatter",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
logconf.dictConfig(LOG)
|
||||
logger.addLevelName(15, 'VERBOSE')
|
||||
logger.Logger.verb = verb
|
||||
logger.Logger.verbose = verb
|
||||
|
||||
logging = logger.getLogger("sanic.root")
|
||||
logging = Log()
|
||||
|
|
|
@ -10,7 +10,7 @@ from .database import get, put
|
|||
from .config import version, pyv
|
||||
|
||||
|
||||
host = get.config('host', 'relaydev.barkshark.xyz')
|
||||
host = get.config('host')
|
||||
|
||||
|
||||
def defhead():
|
||||
|
@ -239,21 +239,19 @@ def push(inbox, data, headers, *args):
|
|||
response = httpclient.request('POST', inbox, body=body, headers=headers)
|
||||
|
||||
if response.status not in [200, 202]:
|
||||
logging.warning(f'Failed to push to {inbox}: Error {response.status}')
|
||||
logging.verbose(f'Failed to push to {inbox}: Error {response.status}')
|
||||
logging.debug(f'Response: {response.data.decode()}')
|
||||
|
||||
if response.status not in [401, 403]:
|
||||
logging.debug(f'Adding message to retries: {inbox}')
|
||||
put.add_retry(url, inbox, data, orig_head)
|
||||
|
||||
else:
|
||||
logging.debug(f'Successfully sent message to {inbox}')
|
||||
logging.verbose(f'Successfully sent message to {inbox}')
|
||||
put.del_retries({'inbox': inbox, 'msgid': url})
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.warning(f'Connection error when pushing to {inbox}: {e}')
|
||||
logging.debug(f'Adding message to retries: {inbox}')
|
||||
logging.verbose(f'Connection error when pushing to {inbox}: {e}')
|
||||
put.add_retry(url, inbox, data, orig_head)
|
||||
|
||||
|
||||
|
|
130
uncia/migrate.py
130
uncia/migrate.py
|
@ -1,40 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
import sys, ujson as json
|
||||
import time, sys, ujson as json
|
||||
|
||||
from json.decoder import JSONDecodeError
|
||||
from os.path import isfile, abspath
|
||||
from datetime import datetime
|
||||
|
||||
from tinydb import TinyDB, Query
|
||||
from configobj import ConfigObj
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from .config import stor_path
|
||||
from .database import db as pgdb, get, put
|
||||
from .database import get, put
|
||||
|
||||
|
||||
oldpath = abspath('config')
|
||||
if 'pleroma' in sys.argv:
|
||||
import yaml
|
||||
|
||||
try:
|
||||
with open('relay.yaml') as f:
|
||||
config = yaml.load(f, Loader=yaml.SafeLoader)
|
||||
|
||||
try:
|
||||
db = TinyDB(f'{oldpath}/db.json', ensure_ascii=False, escape_forward_slashes=False, indent=4)
|
||||
except Exception as e:
|
||||
print(f'Failed to open "relay.yaml": {e}')
|
||||
sys.exit()
|
||||
|
||||
except JSONDecodeError as e:
|
||||
print(f'Failed to load DB: {e}')
|
||||
print(f'Exiting...')
|
||||
dbfile = config['db']
|
||||
domainbans = config['ap']['blocked_instances']
|
||||
whitelist = config['ap']['whitelist']
|
||||
settings = {
|
||||
'address': config['listen'],
|
||||
'port': config['port'],
|
||||
'host': config['ap']['host'],
|
||||
'whitelist': config['ap']['whitelist_enabled']
|
||||
}
|
||||
|
||||
try:
|
||||
jsondb = json.load(open(dbfile))
|
||||
|
||||
except Exception as e:
|
||||
print(f'Failed to open "{dbfile}": {e}')
|
||||
sys.exit()
|
||||
|
||||
inboxes = jsondb['relay-list']
|
||||
key = {
|
||||
'privkey': jsondb['actorKeys']['privateKey'],
|
||||
'pubkey': jsondb['actorKeys']['publicKey']
|
||||
}
|
||||
|
||||
else:
|
||||
print('heck')
|
||||
sys.exit()
|
||||
|
||||
query = Query()
|
||||
|
||||
class table:
|
||||
inbox = db.table('inbox')
|
||||
key = db.table('key')
|
||||
message = db.table('message')
|
||||
fail = db.table('fail')
|
||||
discon = db.table('discon')
|
||||
follows = db.table('follows')
|
||||
# migrate inboxes
|
||||
for row in inboxes:
|
||||
if type(row) == str:
|
||||
domain = urlparse(row).netloc
|
||||
row = {
|
||||
'actor': f'https://{domain}/actor',
|
||||
'inbox': f'https://{domain}/inbox',
|
||||
'domain': domain
|
||||
}
|
||||
|
||||
|
||||
for row in table.inbox.all():
|
||||
if not get.inbox(row['domain']):
|
||||
urls = {
|
||||
'actor': row['actor'],
|
||||
|
@ -46,63 +69,20 @@ for row in table.inbox.all():
|
|||
|
||||
put.inbox('add', urls, timestamp=timestamp)
|
||||
|
||||
db_actor_key = table.key.get(query.user == 'relay')
|
||||
|
||||
if not db_actor_key:
|
||||
print('heck')
|
||||
|
||||
else:
|
||||
actor_key_data = {
|
||||
'actor': 'default',
|
||||
'pubkey': db_actor_key['pubkey'],
|
||||
'privkey': db_actor_key['privkey']
|
||||
}
|
||||
|
||||
pgdb.upsert('keys', actor_key_data, actor='default')
|
||||
# migrate actor key
|
||||
put.rsa_key('default', key)
|
||||
|
||||
|
||||
configfile = f'{oldpath}/config.ini'
|
||||
listfile = f'{oldpath}/lists.ini'
|
||||
infofile = f'{oldpath}/templates/info.md'
|
||||
rulesfile = f'{oldpath}/templates/rules.md'
|
||||
# migrate config
|
||||
put.config(settings)
|
||||
|
||||
|
||||
if isfile(infofile):
|
||||
info = open(infofile).read()
|
||||
|
||||
if isfile(rulesfile):
|
||||
rules = open(rulesfile).read()
|
||||
|
||||
if isfile(configfile):
|
||||
config = ConfigObj(configfile)
|
||||
|
||||
cfg = {
|
||||
'address': config['network']['listen'],
|
||||
'port': config['network']['port'],
|
||||
'host': config['network']['host'],
|
||||
'name': config['settings']['name'],
|
||||
'admin': config['settings']['admin_acct'],
|
||||
'email': config['settings']['email'],
|
||||
'show_domainblocks': config['settings']['show_instance_blocks'],
|
||||
'show_userblocks': config['settings']['show_user_blocks'],
|
||||
'whitelist': config['settings']['whitelist_enabled'],
|
||||
'require_approval': config['settings']['require_approval'],
|
||||
'block_relays': config['settings']['block_relays'],
|
||||
'notifications': config['settings']['notif'],
|
||||
'log_level': config['internals']['log_level'],
|
||||
'info': info,
|
||||
'rules': rules,
|
||||
'setup': False
|
||||
}
|
||||
|
||||
put.config(cfg)
|
||||
# migrate domain bans
|
||||
for domain in domainbans:
|
||||
put.ban('add', domain)
|
||||
|
||||
|
||||
if isfile(listfile):
|
||||
config = ConfigObj(listfile)
|
||||
|
||||
for domain in config['blocked_instances']:
|
||||
put.ban('add', domain)
|
||||
|
||||
for user in config['blocked_users']:
|
||||
put.ban('add', user)
|
||||
# migrate whitelist
|
||||
for domain in whitelist:
|
||||
put.whitelist('add', domain)
|
||||
|
|
|
@ -8,8 +8,8 @@ from watchdog.observers import Observer
|
|||
from watchdog.events import FileSystemEventHandler
|
||||
|
||||
from .log import logging, LOG
|
||||
from .config import script_path, fwsecret
|
||||
from .database import get, setup, randomgen
|
||||
from .config import script_path, fwsecret, development
|
||||
from .database import get, setup
|
||||
from .messages import run_retries
|
||||
from .admin import bool_check
|
||||
from .templates import build_templates
|
||||
|
@ -72,14 +72,11 @@ class WatchHandler(FileSystemEventHandler):
|
|||
build_templates()
|
||||
|
||||
|
||||
def start_template_watcher():
|
||||
def setup_template_watcher():
|
||||
tplpath = f'{script_path}/frontend/templates'
|
||||
observer = Observer()
|
||||
observer.schedule(WatchHandler(), tplpath, recursive=False)
|
||||
|
||||
logging.info('Starting template watcher')
|
||||
observer.start()
|
||||
|
||||
return observer
|
||||
|
||||
|
||||
|
@ -97,8 +94,14 @@ def main():
|
|||
dbport = int(get.config('port'))
|
||||
|
||||
build_templates()
|
||||
observer = start_template_watcher()
|
||||
observer = setup_template_watcher()
|
||||
|
||||
if bool_check(development):
|
||||
logging.info('Starting template watcher')
|
||||
observer.start()
|
||||
|
||||
logging.info(f'Starting Uncia at {dblisten}:{dbport}')
|
||||
app.run(host=dblisten, port=dbport, workers=1, debug=False, access_log=False)
|
||||
|
||||
logging.info('Stopping template watcher')
|
||||
observer.stop()
|
||||
|
|
|
@ -73,8 +73,7 @@ def sign_sigstring(sigstring, key, hashalg='SHA256'):
|
|||
if not sign_key:
|
||||
return
|
||||
|
||||
privkey = RSA.importKey(sign_key)
|
||||
pkcs = PKCS1_v1_5.new(privkey)
|
||||
pkcs = PKCS1_v1_5.new(sign_key['PRIVKEY'])
|
||||
h = HASHES[hashalg.lower()].new()
|
||||
h.update(sigstring.encode('ascii'))
|
||||
|
||||
|
|
|
@ -224,8 +224,7 @@ class Home(HTTPMethodView):
|
|||
|
||||
class Faq(HTTPMethodView):
|
||||
async def get(self, request):
|
||||
data = {'msg': 'UvU', 'instances': {}}
|
||||
return render('faq.html', request, data)
|
||||
return render('faq.html', request, {})
|
||||
|
||||
|
||||
class Admin(HTTPMethodView):
|
||||
|
@ -293,9 +292,9 @@ class Account(HTTPMethodView):
|
|||
|
||||
if action == 'delete':
|
||||
if None in [password, token, user]:
|
||||
return response.redirect('/account')
|
||||
return self.get(request, msg='Missing password, token, or username')
|
||||
|
||||
print(put.del_user(token))
|
||||
put.del_user(token)
|
||||
resp = response.redirect('/')
|
||||
del resp.cookies['token']
|
||||
return resp
|
||||
|
@ -327,6 +326,18 @@ class Account(HTTPMethodView):
|
|||
else:
|
||||
return await self.get(request, msg='Failed to update display name')
|
||||
|
||||
if action == 'token':
|
||||
form_token = request['form'].get('token')
|
||||
|
||||
if not form_token:
|
||||
return await self.get(request, msg='Failed to provide token to delete')
|
||||
|
||||
if put.del_token(form_token):
|
||||
return await self.get(request, msg='Deleted token')
|
||||
|
||||
else:
|
||||
return await self.get(request, msg='Failed to delete token')
|
||||
|
||||
return response.redirect('/account')
|
||||
|
||||
|
||||
|
@ -358,15 +369,20 @@ class Login(HTTPMethodView):
|
|||
password = request['form'].get('password')
|
||||
|
||||
if None in [username, password]:
|
||||
return await reterror(Login, request, 'Missing username or password')
|
||||
return await self.get(request, msg='Missing username or password')
|
||||
|
||||
if not get.user(username):
|
||||
return await self.get(request, msg='Invalid username')
|
||||
|
||||
if not get.verify_password(username, password):
|
||||
return await reterror(Login, request, 'Invalid username or password')
|
||||
return await self.get(request, msg='Invalid password')
|
||||
|
||||
tokendata = put.token(username)
|
||||
|
||||
if not tokendata:
|
||||
return await reterror(Login, request, 'Failed to create token')
|
||||
return await self.get(request, msg='Failed to create token')
|
||||
|
||||
print(tokendata)
|
||||
|
||||
resp = response.redirect('/admin')
|
||||
resp.cookies['token'] = tokendata['token']
|
||||
|
|
Loading…
Reference in a new issue