user page UI: first pass at details for redirect check

for #305
pull/321/head
Ryan Barrett 2022-11-27 17:33:53 -08:00
rodzic fd1b9bddb9
commit 85b1a400ff
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
4 zmienionych plików z 42 dodań i 25 usunięć

Wyświetl plik

@ -20,22 +20,24 @@ logger = logging.getLogger(__name__)
class User(StringIdModel):
"""Stores a user's public/private key pair used for Magic Signatures.
"""Stores a Bridgy Fed user.
The key name is the domain.
The key name is the domain. The key pair is used for both ActivityPub HTTP
Signatures and Salmon Magic Signatures.
The modulus and exponent properties are all encoded as base64url (ie URL-safe
base64) strings as described in RFC 4648 and section 5.1 of the Magic
Signatures spec.
Magic Signatures are used to sign Salmon slaps. Details:
https://tools.ietf.org/html/draft-cavage-http-signatures-07
http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-01.html
http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-salmon-00.html
The key pair's modulus and exponent properties are all encoded as base64url
(ie URL-safe base64) strings as described in RFC 4648 and section 5.1 of the
Magic Signatures spec.
"""
mod = ndb.StringProperty(required=True)
public_exponent = ndb.StringProperty(required=True)
private_exponent = ndb.StringProperty(required=True)
has_redirects = ndb.BooleanProperty()
redirects_error = ndb.TextProperty()
has_hcard = ndb.BooleanProperty()
actor_as2 = ndb.TextProperty()
@ -127,16 +129,22 @@ class User(StringIdModel):
# check webfinger redirect
path = f'/.well-known/webfinger?resource=acct:{domain}@{domain}'
self.has_redirects = False
self.redirects_error = None
try:
resp = util.requests_get(urllib.parse.urljoin(site, path),
allow_redirects=False, gateway=False)
url = urllib.parse.urljoin(site, path)
resp = util.requests_get(url, allow_redirects=False, gateway=False)
domain_urls = ([f'https://{domain}/' for domain in common.DOMAINS] +
[request.host_url])
expected = [urllib.parse.urljoin(url, path) for url in domain_urls]
self.has_redirects = (resp.is_redirect and
resp.headers.get('Location') in expected)
if resp.is_redirect:
got = resp.headers.get('Location')
if got in expected:
self.has_redirects = True
else:
self.redirects_error = f'<code>{url}</code> redirects to <code>{got}</code> ; expected <code>{expected[0]}</code>'
except requests.RequestException:
self.has_redirects = False
pass
# check home page
try:

Wyświetl plik

@ -440,7 +440,6 @@ a img.shadow:hover
box-shadow: 3px 3px 3px #06c !important;
}
.error, .warning {
margin: 10px;
padding: .2em;

Wyświetl plik

@ -7,25 +7,31 @@
{% if user.has_redirects == False %}
<div class="row promo warning">
<form method="post" action="/web-site">
Next step to set up your site:
Next step:
<a href="/docs#redirect+these+URL+paths">
add the .well-known redirects.
</a>
<input type="hidden" name="url" value="https://{{ domain }}" />
<input type="submit" class="retry" value="🔄" title="Check again" />
<input type="submit" class="btn btn-default" value="Check now" />
</form>
{% if user.redirects_error %}
<details class="small">
{{ user.redirects_error|safe }}
</details>
{% endif %}
</div>
{% endif %}
{% if user.has_hcard == False %}
<div class="row promo warning">
<form method="post" action="/web-site">
Next step to set up your site:
Next step:
<a href="https://indiewebify.me/validate-h-card/?url=https://{{ domain }}">
add a representative h-card.
</a>
<input type="hidden" name="url" value="https://{{ domain }}" />
<input type="submit" class="retry" value="🔄" title="Check again" />
<input type="submit" class="btn btn-default" value="Check now" />
</form>
</div>
{% endif %}

Wyświetl plik

@ -57,10 +57,11 @@ class UserTest(testutil.TestCase):
self.assertFalse(self.user.has_redirects)
self.assertFalse(self.user.has_hcard)
def check(redirects, hcard, actor):
def check(redirects, hcard, actor, redirects_error=None):
with app.test_request_context('/'):
self.user.verify()
with self.subTest(redirects=redirects, hcard=hcard, actor=actor):
with self.subTest(redirects=redirects, hcard=hcard, actor=actor,
redirects_error=redirects_error):
self.assert_equals(redirects, bool(self.user.has_redirects))
self.assert_equals(hcard, bool(self.user.has_hcard))
if actor is None:
@ -69,18 +70,21 @@ class UserTest(testutil.TestCase):
got = {k: v for k, v in json_loads(self.user.actor_as2).items()
if k in actor}
self.assert_equals(actor, got)
self.assert_equals(redirects_error, self.user.redirects_error)
# both fail
empty = requests_response('')
empty = requests_response('', allow_redirects=False)
mock_get.side_effect = [empty, empty]
check(False, False, None)
# redirect works but strips query params, no h-card
# redirect strips query params, no h-card
half_redir = requests_response(
status=302, redirected_url='http://localhost/.well-known/webfinger')
status=302, redirected_url='http://localhost/.well-known/webfinger',
allow_redirects=False)
no_hcard = requests_response('<html><body></body></html>')
mock_get.side_effect = [half_redir, no_hcard]
check(False, False, None)
check(False, False, None,
'<code>https://y.z/.well-known/webfinger?resource=acct:y.z@y.z</code> redirects to <code>http://localhost/.well-known/webfinger</code> ; expected <code>https://fed.brid.gy/.well-known/webfinger?resource=acct:y.z@y.z</code>')
# redirect works, non-representative h-card
full_redir = requests_response(
@ -88,7 +92,7 @@ class UserTest(testutil.TestCase):
redirected_url='http://localhost/.well-known/webfinger?resource=acct:y.z@y.z')
bad_hcard = requests_response(
'<html><body><a class="h-card u-url" href="https://a.b/">acct:me@y.z</a></body></html>',
url='https://y.z/',
url='https://y.z/', allow_redirects=False,
)
mock_get.side_effect = [full_redir, bad_hcard]
check(True, False, None)
@ -99,7 +103,7 @@ class UserTest(testutil.TestCase):
<a class="u-url p-name" href="/">me</a>
<a class="u-url" href="acct:myself@y.z">Masto</a>
</body></html>""",
url='https://y.z/',
url='https://y.z/', allow_redirects=False,
)
mock_get.side_effect = [full_redir, hcard]
check(True, True, {