File size: 2,412 Bytes
50094a0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import time

import pytest

from finbot.auth import Claims, TokenError, dashboard_url, issue, verify

SECRET = "a-test-signing-secret"


class TestRoundTrip:
    def test_issue_and_verify(self):
        token = issue(42, SECRET)
        claims = verify(token, SECRET)
        assert claims.user_id == 42

    def test_large_user_ids(self):
        # Telegram ids are well past 32-bit.
        assert verify(issue(7_000_000_123, SECRET), SECRET).user_id == 7_000_000_123

    def test_tokens_are_url_safe(self):
        token = issue(42, SECRET)
        assert "/" not in token and "+" not in token and "=" not in token

    def test_seconds_left(self):
        claims = Claims(user_id=1, expires_at=int(time.time()) + 60)
        assert 55 <= claims.seconds_left <= 60


class TestRejection:
    def test_wrong_secret(self):
        token = issue(42, SECRET)
        with pytest.raises(TokenError, match="bad signature"):
            verify(token, "a-different-secret")

    def test_tampered_payload(self):
        # Swap the user id for someone else's and the signature must fail.
        token = issue(42, SECRET)
        forged = issue(99, SECRET).split(".")[0] + "." + token.split(".")[1]
        with pytest.raises(TokenError):
            verify(forged, SECRET)

    def test_expired(self):
        past = int(time.time()) - 100
        token = issue(42, SECRET, ttl_seconds=1, now=past)
        with pytest.raises(TokenError, match="expired"):
            verify(token, SECRET)

    def test_still_valid_just_before_expiry(self):
        now = int(time.time())
        token = issue(42, SECRET, ttl_seconds=60, now=now)
        assert verify(token, SECRET, now=now + 59).user_id == 42

    @pytest.mark.parametrize("bad", ["", "nonsense", "no-dot", "a.b.c.d", "...."])
    def test_malformed(self, bad):
        with pytest.raises(TokenError):
            verify(bad, SECRET)

    def test_no_secret_configured(self):
        with pytest.raises(TokenError):
            verify(issue(42, SECRET), "")

    def test_cannot_issue_without_a_secret(self):
        with pytest.raises(TokenError):
            issue(42, "")


class TestURL:
    def test_builds_a_query_url(self):
        assert dashboard_url("https://x.hf.space/", "abc") == "https://x.hf.space/?t=abc"

    def test_handles_missing_trailing_slash(self):
        assert dashboard_url("https://x.hf.space", "abc") == "https://x.hf.space/?t=abc"