From 484c637219d46ccc3136f3ee31dd7e5a71726b06 Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Fri, 9 Feb 2024 16:48:19 -0800 Subject: [PATCH] authorization check: handle domain vs homepage for web users for #566 --- protocol.py | 5 +++- tests/test_protocol.py | 63 ++++++++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/protocol.py b/protocol.py index 49dddb5..f29f500 100644 --- a/protocol.py +++ b/protocol.py @@ -2,6 +2,7 @@ import copy from datetime import timedelta import logging +import re from threading import Lock from urllib.parse import urljoin @@ -16,7 +17,7 @@ from oauth_dropins.webutil.util import json_dumps, json_loads import werkzeug.exceptions import common -from common import add, DOMAIN_BLOCKLIST, DOMAINS, error, subdomain_wrap +from common import add, DOMAIN_BLOCKLIST, DOMAIN_RE, DOMAINS, error, subdomain_wrap from flask_app import app from ids import translate_object_id, translate_user_id from models import Follower, get_originals, Object, PROTOCOLS, Target, User @@ -603,6 +604,8 @@ class Protocol: if authed_as: assert isinstance(authed_as, str) + if util.is_web(actor) and re.match(DOMAIN_RE, authed_as): + authed_as = f'https://{authed_as}/' # TODO: handle domain vs URL for web users, eg # "actor https://tiffwhite.me/ isn't authed user tiffwhite.me" if actor != authed_as: diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 1f3eeb7..199993c 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -1742,6 +1742,41 @@ class ProtocolReceiveTest(TestCase): self.assertEqual('ignored', obj.status) def test_receive_task_handler_authed_as(self): + note = { + 'id': 'fake:post', + 'objectType': 'note', + 'author': 'fake:alice', + } + obj = self.store_object(id='fake:post', our_as1=note, + source_protocol='fake') + + with self.assertLogs() as logs: + self.client.post('/queue/receive', data={ + 'obj': obj.key.urlsafe(), + 'authed_as': 'fake:alice', + }, headers={CLOUD_TASKS_QUEUE_HEADER: ''}) + + self.assertNotIn("isn't authed user", ' '.join(logs.output)) + + def test_receive_task_handler_authed_as_domain_vs_homepage(self): + note = { + 'id': 'https://user.com/c', + 'objectType': 'note', + 'author': 'https://user.com/', + } + user = self.make_user('user.com', cls=Web, obj_id='https://user.com/') + obj = self.store_object(id='https://user.com/c', our_as1=note, + source_protocol='web') + + with self.assertLogs() as logs: + self.client.post('/queue/receive', data={ + 'obj': obj.key.urlsafe(), + 'authed_as': 'user.com', + }, headers={CLOUD_TASKS_QUEUE_HEADER: ''}) + + self.assertNotIn("isn't authed user", ' '.join(logs.output)) + + def test_receive_task_handler_not_authed_as(self): note = { 'id': 'fake:post', 'objectType': 'note', @@ -1760,20 +1795,6 @@ class ProtocolReceiveTest(TestCase): "WARNING:protocol:actor fake:other isn't authed user fake:eve", logs.output) - def test_g_user_opted_out(self): - self.make_followers() - self.user.obj.our_as1 = {'summary': '#nobot'} - self.user.obj.put() - - with self.assertRaises(NoContent): - Fake.receive_as1({ - 'id': 'fake:post', - 'objectType': 'note', - 'author': 'fake:user', - }) - - self.assertEqual([], Fake.sent) - def test_like_not_authed_as_actor(self): Fake.fetchable['fake:post'] = { 'objectType': 'note', @@ -1793,6 +1814,20 @@ class ProtocolReceiveTest(TestCase): "WARNING:protocol:actor fake:user isn't authed user fake:other", logs.output) + def test_user_opted_out(self): + self.make_followers() + self.user.obj.our_as1 = {'summary': '#nobot'} + self.user.obj.put() + + with self.assertRaises(NoContent): + Fake.receive_as1({ + 'id': 'fake:post', + 'objectType': 'note', + 'author': 'fake:user', + }) + + self.assertEqual([], Fake.sent) + @patch('oauth_dropins.webutil.appengine_config.tasks_client.create_task') def test_post_create_send_tasks(self, mock_create_task): common.RUN_TASKS_INLINE = False