sanic-security 1.13.0__py3-none-any.whl → 1.13.2__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.
@@ -86,6 +86,7 @@ async def register(
86
86
  verified=verified,
87
87
  disabled=disabled,
88
88
  )
89
+ logger.info(f"Client {get_ip(request)} has registered account {account.id}.")
89
90
  return account
90
91
 
91
92
 
@@ -128,7 +129,7 @@ async def login(
128
129
  request, account, requires_second_factor=require_second_factor
129
130
  )
130
131
  logger.info(
131
- f"Client {get_ip(request)} has logged into account {account.id} with authentication session {authentication_session.id}."
132
+ f"Client {get_ip(request)} has logged in with authentication session {authentication_session.id}."
132
133
  )
133
134
  return authentication_session
134
135
  except VerifyMismatchError:
@@ -159,8 +160,7 @@ async def logout(request: Request) -> AuthenticationSession:
159
160
  authentication_session.active = False
160
161
  await authentication_session.save(update_fields=["active"])
161
162
  logger.info(
162
- f"Client {get_ip(request)} has logged out {"anonymously" if authentication_session.anonymous
163
- else f"of account {authentication_session.bearer.id}"} with authentication session {authentication_session.id}."
163
+ f"Client {get_ip(request)} has logged out with authentication session {authentication_session.id}."
164
164
  )
165
165
  return authentication_session
166
166
 
@@ -193,6 +193,10 @@ async def fulfill_second_factor(request: Request) -> AuthenticationSession:
193
193
  await two_step_session.check_code(request.form.get("code"))
194
194
  authentication_session.requires_second_factor = False
195
195
  await authentication_session.save(update_fields=["requires_second_factor"])
196
+ logger.info(
197
+ f"Client {get_ip(request)} has fulfilled authentication session {authentication_session.id} "
198
+ "second factor."
199
+ )
196
200
  return authentication_session
197
201
 
198
202
 
@@ -59,6 +59,9 @@ async def check_permissions(
59
59
  """
60
60
  authentication_session = await authenticate(request)
61
61
  if authentication_session.anonymous:
62
+ logger.warning(
63
+ f"Client {get_ip(request)} attempted an unauthorized action anonymously."
64
+ )
62
65
  raise AnonymousError()
63
66
  roles = await authentication_session.bearer.roles.filter(deleted=False).all()
64
67
  for role in roles:
@@ -68,8 +71,7 @@ async def check_permissions(
68
71
  if fnmatch(required_permission, role_permission):
69
72
  return authentication_session
70
73
  logger.warning(
71
- f"Client {get_ip(request)} with account {authentication_session.bearer.id} has insufficient permissions for "
72
- "attempted action."
74
+ f"Client {get_ip(request)} with account {authentication_session.bearer.id} attempted an unauthorized action. "
73
75
  )
74
76
  raise AuthorizationError("Insufficient permissions required for this action.")
75
77
 
@@ -98,14 +100,16 @@ async def check_roles(request: Request, *required_roles: str) -> AuthenticationS
98
100
  """
99
101
  authentication_session = await authenticate(request)
100
102
  if authentication_session.anonymous:
103
+ logger.warning(
104
+ f"Client {get_ip(request)} attempted an unauthorized action anonymously."
105
+ )
101
106
  raise AnonymousError()
102
107
  roles = await authentication_session.bearer.roles.filter(deleted=False).all()
103
108
  for role in roles:
104
109
  if role.name in required_roles:
105
110
  return authentication_session
106
111
  logger.warning(
107
- f"Client {get_ip(request)} with account {authentication_session.bearer.id} has insufficient roles for "
108
- "attempted action."
112
+ f"Client {get_ip(request)} with account {authentication_session.bearer.id} attempted an unauthorized action. "
109
113
  )
110
114
  raise AuthorizationError("Insufficient roles required for this action.")
111
115
 
sanic_security/models.py CHANGED
@@ -336,6 +336,7 @@ class Session(BaseModel):
336
336
  "id": self.id,
337
337
  "date_created": str(self.date_created),
338
338
  "expiration_date": str(self.expiration_date),
339
+ "bearer": self.bearer.id if isinstance(self.bearer, Account) else None,
339
340
  "ip": self.ip,
340
341
  },
341
342
  security_config.SECRET,
@@ -309,4 +309,4 @@ register_tortoise(
309
309
  )
310
310
  initialize_security(app, True)
311
311
  if __name__ == "__main__":
312
- app.run(host="127.0.0.1", port=8000, workers=1)
312
+ app.run(host="127.0.0.1", port=8000, workers=1, debug=True)
@@ -1,18 +1,21 @@
1
1
  import functools
2
2
  from contextlib import suppress
3
3
 
4
+ from sanic.log import logger
4
5
  from sanic.request import Request
5
6
 
6
7
  from sanic_security.exceptions import (
7
8
  JWTDecodeError,
8
9
  NotFoundError,
9
10
  VerifiedError,
11
+ MaxedOutChallengeError,
10
12
  )
11
13
  from sanic_security.models import (
12
14
  Account,
13
15
  TwoStepSession,
14
16
  CaptchaSession,
15
17
  )
18
+ from sanic_security.utils import get_ip
16
19
 
17
20
  """
18
21
  Copyright (c) 2020-present Nicholas Aidan Stewart
@@ -89,7 +92,16 @@ async def two_step_verification(request: Request) -> TwoStepSession:
89
92
  two_step_session = await TwoStepSession.decode(request)
90
93
  two_step_session.validate()
91
94
  two_step_session.bearer.validate()
92
- await two_step_session.check_code(request.form.get("code"))
95
+ try:
96
+ await two_step_session.check_code(request.form.get("code"))
97
+ except MaxedOutChallengeError as e:
98
+ logger.warning(
99
+ f"Client {get_ip(request)} has exceeded maximum two-step session {two_step_session.id} challenge attempts."
100
+ )
101
+ raise e
102
+ logger.info(
103
+ f"Client {get_ip(request)} has completed two-step session {two_step_session.id} challenge."
104
+ )
93
105
  return two_step_session
94
106
 
95
107
 
@@ -153,9 +165,19 @@ async def verify_account(request: Request) -> TwoStepSession:
153
165
  if two_step_session.bearer.verified:
154
166
  raise VerifiedError()
155
167
  two_step_session.validate()
156
- await two_step_session.check_code(request.form.get("code"))
168
+ try:
169
+ await two_step_session.check_code(request.form.get("code"))
170
+ except MaxedOutChallengeError as e:
171
+ logger.warning(
172
+ f"Client {get_ip(request)} has exceeded maximum two-step session {two_step_session.id} challenge attempts "
173
+ "during account verification."
174
+ )
175
+ raise e
157
176
  two_step_session.bearer.verified = True
158
177
  await two_step_session.bearer.save(update_fields=["verified"])
178
+ logger.info(
179
+ f"Client {get_ip(request)} has verified account {two_step_session.bearer.id}."
180
+ )
159
181
  return two_step_session
160
182
 
161
183
 
@@ -197,7 +219,16 @@ async def captcha(request: Request) -> CaptchaSession:
197
219
  """
198
220
  captcha_session = await CaptchaSession.decode(request)
199
221
  captcha_session.validate()
200
- await captcha_session.check_code(request.form.get("captcha"))
222
+ try:
223
+ await captcha_session.check_code(request.form.get("captcha"))
224
+ except MaxedOutChallengeError as e:
225
+ logger.warning(
226
+ f"Client {get_ip(request)} has exceeded maximum captcha session {captcha_session.id} challenge attempts."
227
+ )
228
+ raise e
229
+ logger.info(
230
+ f"Client {get_ip(request)} has completed captcha session {captcha_session.id} challenge."
231
+ )
201
232
  return captcha_session
202
233
 
203
234
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sanic-security
3
- Version: 1.13.0
3
+ Version: 1.13.2
4
4
  Summary: An async security library for the Sanic framework.
5
5
  Author-email: Aidan Stewart <me@na-stewart.com>
6
6
  Project-URL: Documentation, https://security.na-stewart.com/
@@ -64,7 +64,7 @@ Requires-Dist: cryptography; extra == "dev"
64
64
  * [Usage](#usage)
65
65
  * [Authentication](#authentication)
66
66
  * [Captcha](#captcha)
67
- * [Two-Step Verification](#two-step-verification)
67
+ * [Two-step Verification](#two-step-verification)
68
68
  * [Authorization](#authorization)
69
69
  * [Testing](#testing)
70
70
  * [Tortoise](#tortoise)
@@ -79,10 +79,11 @@ Requires-Dist: cryptography; extra == "dev"
79
79
  Sanic Security is an authentication, authorization, and verification library designed for use with [Sanic](https://github.com/huge-success/sanic).
80
80
 
81
81
  * Login, registration, and authentication with refresh mechanisms
82
+ * Role based authorization with wildcard permissions
82
83
  * Two-factor authentication
83
- * Captcha
84
84
  * Two-step verification
85
- * Role based authorization with wildcard permissions
85
+ * Captcha
86
+ * Logging
86
87
 
87
88
  Visit [security.na-stewart.com](https://security.na-stewart.com) for documentation.
88
89
 
@@ -0,0 +1,16 @@
1
+ sanic_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ sanic_security/authentication.py,sha256=h0Yq2hWFv1GZoqhPQBmoJnqywGQd6fOYu7zyaqfv6wQ,14432
3
+ sanic_security/authorization.py,sha256=1SHx4cU_ibC0o_nEDDYURH_l_K6Q66M0SLzpRQrsIXc,7534
4
+ sanic_security/configuration.py,sha256=br2hI3MHsTBh3yfPer5f3bkKSWfQdCeqfLqWmaDNVoM,5510
5
+ sanic_security/exceptions.py,sha256=JiCaBR2kjE1Cj0fc_08y-32fqJJXa_1UCw205T4_RTY,5493
6
+ sanic_security/models.py,sha256=l3cO5-S1bmE0tqhFXBC9z4IWTCnYNeRvw1VzIFLeaHE,22363
7
+ sanic_security/utils.py,sha256=XAUNalcTi53qTz0D8xiDyDyRlq7Z7ffNBzUONJZqe90,2705
8
+ sanic_security/verification.py,sha256=js2PkqJU6o46atslJ76n-_cYoY5iz5fbyiV0OFwoySo,8668
9
+ sanic_security/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ sanic_security/test/server.py,sha256=79HaNIH1skWTrh2gIbh8WWVNxvYqPA5GlQ8AqRaCsXQ,12094
11
+ sanic_security/test/tests.py,sha256=bW5fHJfsCrg8eBmcSqVMLm0R5XRL1ou-XJJRgz09GOE,21993
12
+ sanic_security-1.13.2.dist-info/LICENSE,sha256=sXlJs9_mG-dCkPfWsDnuzydJWagS82E2gYtkVH9enHA,1100
13
+ sanic_security-1.13.2.dist-info/METADATA,sha256=mcHljpRvZGGTk_hRi2Sf-lqF-QyZIrhn_lNZGkbNjUI,23011
14
+ sanic_security-1.13.2.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
15
+ sanic_security-1.13.2.dist-info/top_level.txt,sha256=ZybkhHXSjfzhmv8XeqLvnNmLmv21Z0oPX6Ep4DJN8b0,15
16
+ sanic_security-1.13.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.5.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,16 +0,0 @@
1
- sanic_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- sanic_security/authentication.py,sha256=ZY4WJDUXbwDdaH_2Ovc9gkR1jCgw52yB9enYp_1LypM,14334
3
- sanic_security/authorization.py,sha256=XbRrnsx-Yqpiemf3bn_djIYIe1khdnfToB7DsBheLtk,7338
4
- sanic_security/configuration.py,sha256=br2hI3MHsTBh3yfPer5f3bkKSWfQdCeqfLqWmaDNVoM,5510
5
- sanic_security/exceptions.py,sha256=JiCaBR2kjE1Cj0fc_08y-32fqJJXa_1UCw205T4_RTY,5493
6
- sanic_security/models.py,sha256=v3tJyL420HEdZXqJCq9uPPSivuYXuQNtqf9QC9wF0TU,22274
7
- sanic_security/utils.py,sha256=XAUNalcTi53qTz0D8xiDyDyRlq7Z7ffNBzUONJZqe90,2705
8
- sanic_security/verification.py,sha256=ebT7QaytHAsw-IKA13W9wyCoqoBAYKgmFA1QJ80N2bE,7476
9
- sanic_security/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- sanic_security/test/server.py,sha256=DmwP5dBs2Sq2qk4UZgWbAqzm96YXvLGI9jWeqzluy_c,12082
11
- sanic_security/test/tests.py,sha256=bW5fHJfsCrg8eBmcSqVMLm0R5XRL1ou-XJJRgz09GOE,21993
12
- sanic_security-1.13.0.dist-info/LICENSE,sha256=sXlJs9_mG-dCkPfWsDnuzydJWagS82E2gYtkVH9enHA,1100
13
- sanic_security-1.13.0.dist-info/METADATA,sha256=VeYHXoqKPrbNAfub2NW3RT78Rt1WSUBCKj2gVJrHplE,23000
14
- sanic_security-1.13.0.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
15
- sanic_security-1.13.0.dist-info/top_level.txt,sha256=ZybkhHXSjfzhmv8XeqLvnNmLmv21Z0oPX6Ep4DJN8b0,15
16
- sanic_security-1.13.0.dist-info/RECORD,,