django-esi 8.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_esi-8.1.0.dist-info/METADATA +93 -0
- django_esi-8.1.0.dist-info/RECORD +100 -0
- django_esi-8.1.0.dist-info/WHEEL +4 -0
- django_esi-8.1.0.dist-info/licenses/LICENSE +674 -0
- esi/__init__.py +7 -0
- esi/admin.py +42 -0
- esi/aiopenapi3/client.py +79 -0
- esi/aiopenapi3/plugins.py +224 -0
- esi/app_settings.py +112 -0
- esi/apps.py +11 -0
- esi/checks.py +56 -0
- esi/clients.py +657 -0
- esi/decorators.py +271 -0
- esi/errors.py +22 -0
- esi/exceptions.py +51 -0
- esi/helpers.py +63 -0
- esi/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- esi/locale/cs_CZ/LC_MESSAGES/django.po +53 -0
- esi/locale/de/LC_MESSAGES/django.mo +0 -0
- esi/locale/de/LC_MESSAGES/django.po +58 -0
- esi/locale/en/LC_MESSAGES/django.mo +0 -0
- esi/locale/en/LC_MESSAGES/django.po +54 -0
- esi/locale/es/LC_MESSAGES/django.mo +0 -0
- esi/locale/es/LC_MESSAGES/django.po +59 -0
- esi/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
- esi/locale/fr_FR/LC_MESSAGES/django.po +59 -0
- esi/locale/it_IT/LC_MESSAGES/django.mo +0 -0
- esi/locale/it_IT/LC_MESSAGES/django.po +59 -0
- esi/locale/ja/LC_MESSAGES/django.mo +0 -0
- esi/locale/ja/LC_MESSAGES/django.po +58 -0
- esi/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
- esi/locale/ko_KR/LC_MESSAGES/django.po +58 -0
- esi/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
- esi/locale/nl_NL/LC_MESSAGES/django.po +53 -0
- esi/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
- esi/locale/pl_PL/LC_MESSAGES/django.po +53 -0
- esi/locale/ru/LC_MESSAGES/django.mo +0 -0
- esi/locale/ru/LC_MESSAGES/django.po +61 -0
- esi/locale/sk/LC_MESSAGES/django.mo +0 -0
- esi/locale/sk/LC_MESSAGES/django.po +55 -0
- esi/locale/uk/LC_MESSAGES/django.mo +0 -0
- esi/locale/uk/LC_MESSAGES/django.po +57 -0
- esi/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- esi/locale/zh_Hans/LC_MESSAGES/django.po +58 -0
- esi/management/commands/__init__.py +0 -0
- esi/management/commands/esi_clear_spec_cache.py +21 -0
- esi/management/commands/generate_esi_stubs.py +661 -0
- esi/management/commands/migrate_to_ssov2.py +188 -0
- esi/managers.py +303 -0
- esi/managers.pyi +85 -0
- esi/migrations/0001_initial.py +55 -0
- esi/migrations/0002_scopes_20161208.py +56 -0
- esi/migrations/0003_hide_tokens_from_admin_site.py +23 -0
- esi/migrations/0004_remove_unique_access_token.py +18 -0
- esi/migrations/0005_remove_token_length_limit.py +23 -0
- esi/migrations/0006_remove_url_length_limit.py +18 -0
- esi/migrations/0007_fix_mysql_8_migration.py +18 -0
- esi/migrations/0008_nullable_refresh_token.py +18 -0
- esi/migrations/0009_set_old_tokens_to_sso_v1.py +18 -0
- esi/migrations/0010_set_new_tokens_to_sso_v2.py +18 -0
- esi/migrations/0011_add_token_indices.py +28 -0
- esi/migrations/0012_fix_token_type_choices.py +18 -0
- esi/migrations/0013_squashed_0012_fix_token_type_choices.py +57 -0
- esi/migrations/__init__.py +0 -0
- esi/models.py +349 -0
- esi/openapi_clients.py +1225 -0
- esi/rate_limiting.py +107 -0
- esi/signals.py +21 -0
- esi/static/esi/img/EVE_SSO_Login_Buttons_Large_Black.png +0 -0
- esi/static/esi/img/EVE_SSO_Login_Buttons_Large_White.png +0 -0
- esi/static/esi/img/EVE_SSO_Login_Buttons_Small_Black.png +0 -0
- esi/static/esi/img/EVE_SSO_Login_Buttons_Small_White.png +0 -0
- esi/stubs.py +2 -0
- esi/stubs.pyi +6807 -0
- esi/tasks.py +78 -0
- esi/templates/esi/select_token.html +116 -0
- esi/templatetags/__init__.py +0 -0
- esi/templatetags/scope_tags.py +8 -0
- esi/tests/__init__.py +134 -0
- esi/tests/client_authed_pilot.py +63 -0
- esi/tests/client_public_pilot.py +53 -0
- esi/tests/factories.py +47 -0
- esi/tests/factories_2.py +60 -0
- esi/tests/jwt_factory.py +135 -0
- esi/tests/test_checks.py +48 -0
- esi/tests/test_clients.py +1019 -0
- esi/tests/test_decorators.py +578 -0
- esi/tests/test_management_command.py +307 -0
- esi/tests/test_managers.py +673 -0
- esi/tests/test_models.py +403 -0
- esi/tests/test_openapi.json +854 -0
- esi/tests/test_openapi.py +1017 -0
- esi/tests/test_swagger.json +489 -0
- esi/tests/test_swagger_full.json +51112 -0
- esi/tests/test_tasks.py +116 -0
- esi/tests/test_templatetags.py +22 -0
- esi/tests/test_views.py +331 -0
- esi/tests/threading_pilot.py +69 -0
- esi/urls.py +9 -0
- esi/views.py +129 -0
esi/tests/jwt_factory.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Factory for generating Eve Onlie conformant JWTs for testing."""
|
|
2
|
+
|
|
3
|
+
import datetime as dt
|
|
4
|
+
|
|
5
|
+
from jose import jwt
|
|
6
|
+
from pytz import utc
|
|
7
|
+
|
|
8
|
+
_RSA_PRIVATE_KEY = """
|
|
9
|
+
-----BEGIN PRIVATE KEY-----
|
|
10
|
+
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7VJTUt9Us8cKj
|
|
11
|
+
MzEfYyjiWA4R4/M2bS1GB4t7NXp98C3SC6dVMvDuictGeurT8jNbvJZHtCSuYEvu
|
|
12
|
+
NMoSfm76oqFvAp8Gy0iz5sxjZmSnXyCdPEovGhLa0VzMaQ8s+CLOyS56YyCFGeJZ
|
|
13
|
+
qgtzJ6GR3eqoYSW9b9UMvkBpZODSctWSNGj3P7jRFDO5VoTwCQAWbFnOjDfH5Ulg
|
|
14
|
+
p2PKSQnSJP3AJLQNFNe7br1XbrhV//eO+t51mIpGSDCUv3E0DDFcWDTH9cXDTTlR
|
|
15
|
+
ZVEiR2BwpZOOkE/Z0/BVnhZYL71oZV34bKfWjQIt6V/isSMahdsAASACp4ZTGtwi
|
|
16
|
+
VuNd9tybAgMBAAECggEBAKTmjaS6tkK8BlPXClTQ2vpz/N6uxDeS35mXpqasqskV
|
|
17
|
+
laAidgg/sWqpjXDbXr93otIMLlWsM+X0CqMDgSXKejLS2jx4GDjI1ZTXg++0AMJ8
|
|
18
|
+
sJ74pWzVDOfmCEQ/7wXs3+cbnXhKriO8Z036q92Qc1+N87SI38nkGa0ABH9CN83H
|
|
19
|
+
mQqt4fB7UdHzuIRe/me2PGhIq5ZBzj6h3BpoPGzEP+x3l9YmK8t/1cN0pqI+dQwY
|
|
20
|
+
dgfGjackLu/2qH80MCF7IyQaseZUOJyKrCLtSD/Iixv/hzDEUPfOCjFDgTpzf3cw
|
|
21
|
+
ta8+oE4wHCo1iI1/4TlPkwmXx4qSXtmw4aQPz7IDQvECgYEA8KNThCO2gsC2I9PQ
|
|
22
|
+
DM/8Cw0O983WCDY+oi+7JPiNAJwv5DYBqEZB1QYdj06YD16XlC/HAZMsMku1na2T
|
|
23
|
+
N0driwenQQWzoev3g2S7gRDoS/FCJSI3jJ+kjgtaA7Qmzlgk1TxODN+G1H91HW7t
|
|
24
|
+
0l7VnL27IWyYo2qRRK3jzxqUiPUCgYEAx0oQs2reBQGMVZnApD1jeq7n4MvNLcPv
|
|
25
|
+
t8b/eU9iUv6Y4Mj0Suo/AU8lYZXm8ubbqAlwz2VSVunD2tOplHyMUrtCtObAfVDU
|
|
26
|
+
AhCndKaA9gApgfb3xw1IKbuQ1u4IF1FJl3VtumfQn//LiH1B3rXhcdyo3/vIttEk
|
|
27
|
+
48RakUKClU8CgYEAzV7W3COOlDDcQd935DdtKBFRAPRPAlspQUnzMi5eSHMD/ISL
|
|
28
|
+
DY5IiQHbIH83D4bvXq0X7qQoSBSNP7Dvv3HYuqMhf0DaegrlBuJllFVVq9qPVRnK
|
|
29
|
+
xt1Il2HgxOBvbhOT+9in1BzA+YJ99UzC85O0Qz06A+CmtHEy4aZ2kj5hHjECgYEA
|
|
30
|
+
mNS4+A8Fkss8Js1RieK2LniBxMgmYml3pfVLKGnzmng7H2+cwPLhPIzIuwytXywh
|
|
31
|
+
2bzbsYEfYx3EoEVgMEpPhoarQnYPukrJO4gwE2o5Te6T5mJSZGlQJQj9q4ZB2Dfz
|
|
32
|
+
et6INsK0oG8XVGXSpQvQh3RUYekCZQkBBFcpqWpbIEsCgYAnM3DQf3FJoSnXaMhr
|
|
33
|
+
VBIovic5l0xFkEHskAjFTevO86Fsz1C2aSeRKSqGFoOQ0tmJzBEs1R6KqnHInicD
|
|
34
|
+
TQrKhArgLXX4v3CddjfTRJkFWDbE/CkvKZNOrcf1nhaGCPspRJj2KUkj1Fhl9Cnc
|
|
35
|
+
dn/RsYEONbwQSjIfMPkvxF+8HQ==
|
|
36
|
+
-----END PRIVATE KEY-----
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
_RSA_PUBLIC_KEY = """
|
|
40
|
+
-----BEGIN PUBLIC KEY-----
|
|
41
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo
|
|
42
|
+
4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u
|
|
43
|
+
+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyeh
|
|
44
|
+
kd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ
|
|
45
|
+
0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdg
|
|
46
|
+
cKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbc
|
|
47
|
+
mwIDAQAB
|
|
48
|
+
-----END PUBLIC KEY-----
|
|
49
|
+
"""
|
|
50
|
+
_JWK_PUBLIC_KEY = """u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw""" # noqa: E501
|
|
51
|
+
_ALGORITHM = jwt.ALGORITHMS.RS256
|
|
52
|
+
_AUDIENCE = "EVE Online"
|
|
53
|
+
_HEADERS = {"alg": "RS256", "kid": "JWT-Signature-Key", "typ": "JWT"}
|
|
54
|
+
_ISSUER = "login.eveonline.com"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def generate_jwk():
|
|
58
|
+
return {
|
|
59
|
+
"alg": _ALGORITHM,
|
|
60
|
+
"e": "AQAB",
|
|
61
|
+
"kid": "JWT-Signature-Key",
|
|
62
|
+
"kty": "RSA",
|
|
63
|
+
"n": _JWK_PUBLIC_KEY,
|
|
64
|
+
"use": "sig",
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _generate_claims(
|
|
69
|
+
issued_at: dt.datetime,
|
|
70
|
+
character_id: int,
|
|
71
|
+
character_name: str,
|
|
72
|
+
issuer=None,
|
|
73
|
+
audience=None,
|
|
74
|
+
) -> dict:
|
|
75
|
+
if not issuer:
|
|
76
|
+
issuer = _ISSUER
|
|
77
|
+
expires_at = issued_at + dt.timedelta(minutes=20)
|
|
78
|
+
claims = {
|
|
79
|
+
"scp": "esi-characters.read_medals.v1",
|
|
80
|
+
"jti": "xxx",
|
|
81
|
+
"kid": "JWT-Signature-Key",
|
|
82
|
+
"sub": f"CHARACTER:EVE:{character_id}",
|
|
83
|
+
"azp": "yyy",
|
|
84
|
+
"tenant": "tranquility",
|
|
85
|
+
"tier": "live",
|
|
86
|
+
"region": "world",
|
|
87
|
+
"name": str(character_name),
|
|
88
|
+
"owner": "OWNER-HASH",
|
|
89
|
+
"exp": int(expires_at.timestamp()),
|
|
90
|
+
"iat": int(issued_at.timestamp()),
|
|
91
|
+
"iss": _ISSUER,
|
|
92
|
+
}
|
|
93
|
+
if audience is None:
|
|
94
|
+
audience = _AUDIENCE
|
|
95
|
+
if audience:
|
|
96
|
+
claims["aud"] = audience
|
|
97
|
+
return claims
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def generate_token(
|
|
101
|
+
character_id: int,
|
|
102
|
+
character_name: str,
|
|
103
|
+
issued_at: dt.datetime = None,
|
|
104
|
+
issuer=None,
|
|
105
|
+
audience=None,
|
|
106
|
+
) -> tuple[str, dict]:
|
|
107
|
+
"""Generate a JWT for Eve Online."""
|
|
108
|
+
if not issued_at:
|
|
109
|
+
issued_at = dt.datetime.now(tz=utc)
|
|
110
|
+
claims = _generate_claims(
|
|
111
|
+
issued_at=issued_at,
|
|
112
|
+
character_id=character_id,
|
|
113
|
+
character_name=character_name,
|
|
114
|
+
issuer=issuer,
|
|
115
|
+
audience=audience,
|
|
116
|
+
)
|
|
117
|
+
token_string = jwt.encode(
|
|
118
|
+
claims=claims, key=_RSA_PRIVATE_KEY, algorithm=_ALGORITHM, headers=_HEADERS
|
|
119
|
+
)
|
|
120
|
+
return token_string, claims
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def validate():
|
|
124
|
+
issued_at = dt.datetime.now(tz=utc)
|
|
125
|
+
token, claims = generate_token(
|
|
126
|
+
issued_at=issued_at, character_id=1001, character_name="Bruce Wayne"
|
|
127
|
+
)
|
|
128
|
+
new_claims = jwt.decode(
|
|
129
|
+
token=token, key=generate_jwk(), audience=_AUDIENCE, issuer=_ISSUER
|
|
130
|
+
)
|
|
131
|
+
print("Validate successful: ", claims == new_claims)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
validate()
|
esi/tests/test_checks.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""unit tests for esi checks"""
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.test import TestCase, override_settings
|
|
5
|
+
|
|
6
|
+
from ..checks import check_sso_application_settings
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestCheckSsoApplicationSettings(TestCase):
|
|
10
|
+
|
|
11
|
+
@override_settings(
|
|
12
|
+
ESI_SSO_CLIENT_ID='123', ESI_SSO_CLIENT_SECRET='abc', ESI_SSO_CALLBACK_URL='xyz'
|
|
13
|
+
)
|
|
14
|
+
def test_settings_ok(self):
|
|
15
|
+
errors = check_sso_application_settings()
|
|
16
|
+
self.assertEqual(len(errors), 0)
|
|
17
|
+
|
|
18
|
+
@override_settings(ESI_SSO_CLIENT_SECRET='abc', ESI_SSO_CALLBACK_URL='xyz')
|
|
19
|
+
def test_settings_incomplete_ESI_SSO_CLIENT_ID(self):
|
|
20
|
+
del settings.ESI_SSO_CLIENT_ID
|
|
21
|
+
errors = check_sso_application_settings()
|
|
22
|
+
self.assertEqual(len(errors), 1)
|
|
23
|
+
|
|
24
|
+
@override_settings(ESI_SSO_CLIENT_ID='123', ESI_SSO_CALLBACK_URL='xyz')
|
|
25
|
+
def test_settings_incomplete_ESI_SSO_CLIENT_SECRET(self):
|
|
26
|
+
del settings.ESI_SSO_CLIENT_SECRET
|
|
27
|
+
errors = check_sso_application_settings()
|
|
28
|
+
self.assertEqual(len(errors), 1)
|
|
29
|
+
|
|
30
|
+
@override_settings(ESI_SSO_CLIENT_ID='123', ESI_SSO_CLIENT_SECRET='abc')
|
|
31
|
+
def test_settings_incomplete_ESI_SSO_CALLBACK_URL(self):
|
|
32
|
+
del settings.ESI_SSO_CALLBACK_URL
|
|
33
|
+
errors = check_sso_application_settings()
|
|
34
|
+
self.assertEqual(len(errors), 1)
|
|
35
|
+
|
|
36
|
+
@override_settings(ESI_SSO_CLIENT_ID='123', ESI_SSO_CLIENT_SECRET='abc', DEBUG=True)
|
|
37
|
+
def test_settings_incomplete_debug_mode(self):
|
|
38
|
+
del settings.ESI_SSO_CALLBACK_URL
|
|
39
|
+
errors = check_sso_application_settings()
|
|
40
|
+
self.assertEqual(len(errors), 1)
|
|
41
|
+
|
|
42
|
+
@override_settings(
|
|
43
|
+
ESI_SSO_CLIENT_ID='123', ESI_SSO_CLIENT_SECRET='abc', DEBUG=False
|
|
44
|
+
)
|
|
45
|
+
def test_settings_incomplete_non_debug_mode(self):
|
|
46
|
+
del settings.ESI_SSO_CALLBACK_URL
|
|
47
|
+
errors = check_sso_application_settings()
|
|
48
|
+
self.assertEqual(len(errors), 1)
|