manage: add ban adding and listing, middleware: improve ban checking and return json when on ap endpoints
This commit is contained in:
parent
4b0ac36ecc
commit
369ffe9e2a
|
@ -19,11 +19,11 @@ def cmd_actor(self, url):
|
|||
|
||||
def cmd_ban_list(self, types='domain'):
|
||||
if types == 'domain':
|
||||
return self.search('ban', handle=None)
|
||||
return self.search('ban', handle=None, orderby='domain')
|
||||
|
||||
bans = []
|
||||
|
||||
for row in self.search('ban'):
|
||||
for row in self.search('ban', orderby='domain'):
|
||||
if row.handle:
|
||||
bans.append(row)
|
||||
|
||||
|
|
|
@ -10,20 +10,23 @@ def cmd_ban(self, handle=None, domain=None, reason=None):
|
|||
|
||||
if row:
|
||||
if reason:
|
||||
self.update(row=row, reason=reason)
|
||||
row = self.update(row=row, reason=reason, return_row=True)
|
||||
|
||||
else:
|
||||
logging.verbose('Banned user or instance already exists')
|
||||
return
|
||||
|
||||
else:
|
||||
self.insert('ban',
|
||||
row = self.insert('ban',
|
||||
handle = handle,
|
||||
domain = domain,
|
||||
reason = reason,
|
||||
timestamp = datetime.now()
|
||||
timestamp = datetime.now(),
|
||||
return_row = True
|
||||
)
|
||||
|
||||
return row
|
||||
|
||||
|
||||
def cmd_actor(self, url, actor):
|
||||
row = self.get.actor(url)
|
||||
|
|
|
@ -37,9 +37,11 @@ def fetch_actor(url):
|
|||
error = None
|
||||
|
||||
if error:
|
||||
logging.debug(f'Failed to fetch actor with error: {error}')
|
||||
logging.debug(f'Failed to fetch actor "{url}" with error: {error}')
|
||||
return
|
||||
|
||||
if not data or error:
|
||||
if not data:
|
||||
logging.verbose(f'Failed to fetch actor: {url}')
|
||||
return
|
||||
|
||||
s.put.actor(url, data)
|
||||
|
|
101
uncia/manage.py
101
uncia/manage.py
|
@ -59,6 +59,22 @@ python3 -m add <actor or domain>: *
|
|||
python3 -m remove <actor, inbox, or domain>:
|
||||
Remove an instance and any retries associated with it from the database.
|
||||
|
||||
python3 -m uncia.manage ban <handle@domain or domain> [*reason]:
|
||||
Ban a user or domain. A reason may optionally be specified.
|
||||
|
||||
python3 -m uncia.manage bans ["users" or "domains"]:
|
||||
List the currently banned domains and users. A ban type ("users"/"domains")
|
||||
may be specified to only list that type.
|
||||
|
||||
python3 -m uncia.manage rules [list]:
|
||||
List the current rules.
|
||||
|
||||
python3 -m uncia.manage rules add <rule>:
|
||||
Add a rule to the list.
|
||||
|
||||
python3 -m uncia.manage rules remove <rule number>:
|
||||
Remove a rule from the list.
|
||||
|
||||
python3 -m uncia.manage config [key] [value]:
|
||||
Gets or sets the config. Specify a key and value to set a config option.
|
||||
Only specify a key to get the value of a specific option. Leave out the
|
||||
|
@ -76,15 +92,6 @@ python3 -m uncia.manage accept <actor, inbox, or domain>: *
|
|||
python3 -m uncia.manage deny <actor, inbox, or domain>: *
|
||||
Reject a request.
|
||||
|
||||
python3 -m uncia.manage rules [list]:
|
||||
List the current rules.
|
||||
|
||||
python3 -m uncia.manage rules add <rule>:
|
||||
Add a rule to the list.
|
||||
|
||||
python3 -m uncia.manage rules remove <rule number>:
|
||||
Remove a rule from the list.
|
||||
|
||||
python3 -m uncia.manage convert [pleroma or uncia]:
|
||||
Convert the database and config of another relay. Tries to convert a
|
||||
Pleroma Relay by default.
|
||||
|
@ -249,6 +256,82 @@ python3 -m uncia.manage convert [pleroma or uncia]:
|
|||
return f'Removed rule: {rule_text}'
|
||||
|
||||
|
||||
def cmd_ban(self, string, *args):
|
||||
handle = None
|
||||
domain = None
|
||||
|
||||
data = string.split('@')
|
||||
|
||||
if len(data) == 1:
|
||||
domain = data[0]
|
||||
|
||||
elif len(data) == 2:
|
||||
handle = data[0]
|
||||
domain = data[1]
|
||||
|
||||
elif len(data) == 3:
|
||||
handle = data[1]
|
||||
domain = data[2]
|
||||
|
||||
reason = None if not args else ' '.join(args)
|
||||
|
||||
with db.session as s:
|
||||
row = s.put.ban(handle, domain, reason)
|
||||
|
||||
if row:
|
||||
if handle:
|
||||
return f'Banned {user}@{domain}'
|
||||
|
||||
return f'Banned {domain}'
|
||||
|
||||
else:
|
||||
if handle:
|
||||
return f'Already banned {user}@{domain}'
|
||||
|
||||
return f'Already banned {domain}'
|
||||
|
||||
|
||||
def cmd_bans(self, type=None):
|
||||
if type and type not in ['domains', 'users']:
|
||||
return 'Ban type needs to be "domains" or "users"'
|
||||
|
||||
data = ''
|
||||
user_bans = []
|
||||
domain_bans = []
|
||||
|
||||
with db.session as s:
|
||||
if type == 'domains':
|
||||
domain_bans = s.get.ban_list('domain')
|
||||
|
||||
elif type == 'users':
|
||||
user_bans = s.get.ban_list('user')
|
||||
|
||||
else:
|
||||
domain_bans = s.get.ban_list('domain')
|
||||
user_bans = s.get.ban_list('user')
|
||||
|
||||
if domain_bans:
|
||||
data += 'Domain Bans:\n'
|
||||
|
||||
for ban in domain_bans:
|
||||
if ban.reason:
|
||||
data += f'- {ban.domain}: {ban.reason}\n'
|
||||
else:
|
||||
data += f'- {ban.domain}\n'
|
||||
|
||||
if user_bans:
|
||||
data += '\nUser Bans:\n'
|
||||
|
||||
for ban in user_bans:
|
||||
if ban.reason:
|
||||
data += f'- {ban.handle}@{ban.domain}: {ban.reason}\n'
|
||||
else:
|
||||
data += f'- {ban.handle}@{ban.domain}\n'
|
||||
|
||||
|
||||
return data or 'No banned domains or users yet'
|
||||
|
||||
|
||||
def cmd_convert(self, relay='uncia'):
|
||||
if relay.lower() == 'uncia':
|
||||
return self.convert_uncia()
|
||||
|
|
|
@ -34,6 +34,25 @@ blocked_instances = [
|
|||
]
|
||||
|
||||
|
||||
def ban_check(s, request):
|
||||
if any(map(s.get.ban, [None], [request.signature.domain, request.signature.top_domain])):
|
||||
return True
|
||||
|
||||
if not request.actor:
|
||||
return
|
||||
|
||||
handle = request.actor.preferredUsername
|
||||
|
||||
if s.get.ban(handle):
|
||||
return True
|
||||
|
||||
if s.get.ban(handle, request.signature.domain):
|
||||
return True
|
||||
|
||||
if s.get.ban(handle, request.signature.top_domain):
|
||||
return True
|
||||
|
||||
|
||||
class AuthCheck(MiddlewareBase):
|
||||
attach = 'request'
|
||||
|
||||
|
@ -50,42 +69,38 @@ class AuthCheck(MiddlewareBase):
|
|||
request.actor = None
|
||||
|
||||
if request.signature:
|
||||
domain = request.signature.domain
|
||||
top_domain = request.signature.top_domain
|
||||
actor = request.signature.actor
|
||||
request.instance = s.get.instance(request.signature.domain)
|
||||
request.actor = fetch_actor(request.signature.actor)
|
||||
|
||||
if top_domain in blocked_instances:
|
||||
if request.signature.top_domain in blocked_instances:
|
||||
return response.text(f'This teapot kills fascists', status=418)
|
||||
|
||||
if any(map(s.get.ban, [None], [domain, top_domain])):
|
||||
if ban_check(s, request):
|
||||
return response.text('no', status=403)
|
||||
|
||||
request.instance = s.get.instance(domain)
|
||||
request.actor = fetch_actor(actor)
|
||||
|
||||
if request.path in ['/inbox', '/actor'] and request.method.lower() == 'post':
|
||||
if not request.actor:
|
||||
return response.text('Could not get actor', status=400)
|
||||
return response.json({'error': 'Could not get actor'}, status=400)
|
||||
|
||||
try:
|
||||
data = request.data.json
|
||||
|
||||
except:
|
||||
logging.verbose('Failed to parse post data')
|
||||
return response.text(f'Invalid data', status=400)
|
||||
return response.json({'error': f'Invalid data'}, status=400)
|
||||
|
||||
if type(request.actor).__name__ == 'Row':
|
||||
logging.warning('Actor data is a db row:', actor)
|
||||
return response.text(f'An unknown error happened', status=500)
|
||||
logging.warning('Actor data is a db row:', request.actor)
|
||||
return response.error({'error': f'An unknown error happened'}, status=500)
|
||||
|
||||
if not request.instance and data.get('type', '').lower() != 'follow':
|
||||
return response.text(f'Follow the relay first', status=401)
|
||||
return response.text({'error': f'Follow the relay first'}, status=401)
|
||||
|
||||
validated = verify_request(request, request.actor)
|
||||
|
||||
if not validated:
|
||||
logging.debug(f'Not validated: {actor}')
|
||||
return response.text(f'Failed signature check', status=401)
|
||||
logging.debug(f'Not validated: {request.signature.actor}')
|
||||
return response.text({'error': f'Failed signature check'}, status=401)
|
||||
|
||||
if any(map(request.path.startswith, auth_paths)) and not request.user:
|
||||
return response.redir('/login')
|
||||
|
|
Loading…
Reference in a new issue