diff --git a/models.py b/models.py index 1ae0873f..1a332369 100644 --- a/models.py +++ b/models.py @@ -260,7 +260,8 @@ def get_by_id(cls, id, allow_opt_out=False, **kwargs): return user @classmethod - def get_or_create(cls, id, propagate=False, allow_opt_out=False, **kwargs): + def get_or_create(cls, id, propagate=False, allow_opt_out=False, + reload=False, **kwargs): """Loads and returns a :class:`User`. Creates it if necessary. Args: @@ -268,6 +269,7 @@ def get_or_create(cls, id, propagate=False, allow_opt_out=False, **kwargs): protocols, eg ATProto and Nostr. allow_opt_out (bool): whether to allow and create the user if they're currently opted out + reload (bool): whether to reload profile always, vs only if necessary kwargs: passed through to ``cls`` constructor Returns: @@ -279,6 +281,9 @@ def get_or_create(cls, id, propagate=False, allow_opt_out=False, **kwargs): def _run(): user = cls.get_by_id(id, allow_opt_out=True) if user: + if reload: + user.reload_profile(gateway=True, raise_=False) + if user.status and not allow_opt_out: return None user.existing = True diff --git a/tests/test_web.py b/tests/test_web.py index e04983f8..e63eacb0 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -415,7 +415,7 @@ def web_user_gets(domain='user.com'): return [ requests_response(ACTOR_HTML, url=f'https://{domain}/'), requests_response(ACTOR_HTML, url=f'https://{domain}/'), - requests_response('', status=404), # webfinger + requests_response(status=404), # webfinger ] @@ -2826,7 +2826,8 @@ def test_check_web_site(self, mock_create_task, mock_get, _): redir = 'http://localhost/.well-known/webfinger?resource=acct:user.com@user.com' mock_get.side_effect = ( - requests_response('', status=302, redirected_url=redir), + ACTOR_HTML_RESP, + requests_response(status=302, redirected_url=redir), ACTOR_HTML_RESP, ) @@ -2908,6 +2909,23 @@ def test_check_web_site_opted_out(self, _, __): get_flashed_messages()) self.assertEqual(1, Web.query().count()) + def test_check_web_site_opted_out_reloads_ok(self, mock_get, __): + self.user.has_redirects = False + self.user.put() + self.assertIsNotNone(self.user.status) + + mock_get.side_effect = [ + ACTOR_HTML_RESP, + requests_response(status=404), # webfinger + ACTOR_HTML_RESP, + ] + + got = self.post('/web-site', data={'url': 'user.com'}) + self.assert_equals(302, got.status_code) + self.assert_equals('/web/user.com', got.headers['Location']) + + self.assertIsNone(self.user.key.get().status) + @patch('oauth_dropins.webutil.appengine_config.tasks_client.create_task') def test_check_webfinger_redirects_then_fails(self, mock_task, mock_get, __): common.RUN_TASKS_INLINE = False diff --git a/web.py b/web.py index ad792506..e7affb39 100644 --- a/web.py +++ b/web.py @@ -158,11 +158,8 @@ def get_or_create(cls, id, allow_opt_out=False, verify=None, **kwargs): verify (bool): whether to call :meth:`verify` to load h-card, check redirects, etc. Defaults to calling it only if the user is new. """ - key = cls.key_for(id, allow_opt_out=allow_opt_out) - if not key: - return None # opted out - - domain = key.id() + # normalize id (domain) + domain = cls.key_for(id, allow_opt_out=True).id() if util.domain_or_parent_in(domain, [SUPERDOMAIN.strip('.')]): return super().get_by_id(domain) @@ -699,7 +696,7 @@ def check_web_site(): try: user = Web.get_or_create(domain, enabled_protocols=['atproto'], - propagate=True, direct=True, verify=True) + propagate=True, direct=True, reload=True, verify=True) except BaseException as e: code, body = util.interpret_http_exception(e) if code: