sanic-security 1.13.5__py3-none-any.whl → 1.14.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.
@@ -223,7 +223,7 @@ async def authenticate(request: Request) -> AuthenticationSession:
223
223
  authentication_session.bearer.validate()
224
224
  except ExpiredError:
225
225
  authentication_session = await authentication_session.refresh(request)
226
- request.ctx.authentication_session = authentication_session
226
+ request.ctx.session = authentication_session
227
227
  return authentication_session
228
228
 
229
229
 
@@ -293,10 +293,10 @@ def initialize_security(app: Sanic, create_root=True) -> None:
293
293
 
294
294
  @app.on_response
295
295
  async def response_handler_middleware(request, response):
296
- if hasattr(request.ctx, "authentication_session"):
296
+ if hasattr(request.ctx, "session"):
297
297
  secure_headers.set_headers(response)
298
- if request.ctx.authentication_session.is_refresh:
299
- request.ctx.authentication_session.encode(response)
298
+ if request.ctx.session.is_refresh:
299
+ request.ctx.session.encode(response)
300
300
 
301
301
  @app.listener("before_server_start")
302
302
  async def audit_configuration(app, loop):
@@ -69,6 +69,7 @@ async def check_permissions(
69
69
  required_permissions, role.permissions.split(", ")
70
70
  ):
71
71
  if fnmatch(required_permission, role_permission):
72
+ request.ctx.session = authentication_session
72
73
  return authentication_session
73
74
  logger.warning(
74
75
  f"Client {get_ip(request)} with account {authentication_session.bearer.id} attempted an unauthorized action."
@@ -107,6 +108,7 @@ async def check_roles(request: Request, *required_roles: str) -> AuthenticationS
107
108
  roles = await authentication_session.bearer.roles.filter(deleted=False).all()
108
109
  for role in roles:
109
110
  if role.name in required_roles:
111
+ request.ctx.session = authentication_session
110
112
  return authentication_session
111
113
  logger.warning(
112
114
  f"Client {get_ip(request)} with account {authentication_session.bearer.id} attempted an unauthorized action. "
@@ -168,9 +170,7 @@ def require_permissions(*required_permissions: str):
168
170
  def decorator(func):
169
171
  @functools.wraps(func)
170
172
  async def wrapper(request, *args, **kwargs):
171
- request.ctx.authentication_session = await check_permissions(
172
- request, *required_permissions
173
- )
173
+ await check_permissions(request, *required_permissions)
174
174
  return await func(request, *args, **kwargs)
175
175
 
176
176
  return wrapper
@@ -208,9 +208,7 @@ def require_roles(*required_roles: str):
208
208
  def decorator(func):
209
209
  @functools.wraps(func)
210
210
  async def wrapper(request, *args, **kwargs):
211
- request.ctx.authentication_session = await check_roles(
212
- request, *required_roles
213
- )
211
+ await check_roles(request, *required_roles)
214
212
  return await func(request, *args, **kwargs)
215
213
 
216
214
  return wrapper
@@ -144,16 +144,15 @@ async def on_logout(request):
144
144
  @requires_authentication
145
145
  async def on_authenticate(request):
146
146
  """Authenticate client session and account."""
147
- authentication_session = request.ctx.authentication_session
148
147
  response = json(
149
148
  "Authenticated!",
150
149
  {
151
150
  "bearer": (
152
- authentication_session.bearer.json
153
- if not authentication_session.anonymous
151
+ request.ctx.session.bearer.json
152
+ if not request.ctx.session.anonymous
154
153
  else None
155
154
  ),
156
- "refresh": authentication_session.is_refresh,
155
+ "refresh": request.ctx.session.is_refresh,
157
156
  },
158
157
  )
159
158
  return response
@@ -163,10 +162,9 @@ async def on_authenticate(request):
163
162
  @requires_authentication
164
163
  async def on_authentication_expire(request):
165
164
  """Expire client's session."""
166
- authentication_session = request.ctx.authentication_session
167
- authentication_session.expiration_date = datetime.datetime.now(datetime.UTC)
168
- await authentication_session.save(update_fields=["expiration_date"])
169
- return json("Authentication expired!", authentication_session.json)
165
+ request.ctx.session.expiration_date = datetime.datetime.now(datetime.UTC)
166
+ await request.ctx.session.save(update_fields=["expiration_date"])
167
+ return json("Authentication expired!", request.ctx.session.json)
170
168
 
171
169
 
172
170
  @app.post("api/test/auth/associated")
@@ -174,7 +172,7 @@ async def on_authentication_expire(request):
174
172
  async def on_get_associated_authentication_sessions(request):
175
173
  """Retrieves authentication sessions associated with logged in account."""
176
174
  authentication_sessions = await AuthenticationSession.get_associated(
177
- request.ctx.authentication_session.bearer
175
+ request.ctx.session.bearer
178
176
  )
179
177
  return json(
180
178
  "Associated authentication sessions retrieved!",
@@ -209,7 +207,7 @@ async def on_captcha_audio(request):
209
207
  @requires_captcha
210
208
  async def on_captcha_attempt(request):
211
209
  """Attempt captcha challenge."""
212
- return json("Captcha attempt successful!", request.ctx.captcha_session.json)
210
+ return json("Captcha attempt successful!", request.ctx.session.json)
213
211
 
214
212
 
215
213
  @app.post("api/test/two-step/request")
@@ -225,9 +223,7 @@ async def on_request_verification(request):
225
223
  @requires_two_step_verification
226
224
  async def on_verification_attempt(request):
227
225
  """Attempt two-step verification challenge."""
228
- return json(
229
- "Two step verification attempt successful!", request.ctx.two_step_session.json
230
- )
226
+ return json("Two step verification attempt successful!", request.ctx.session.json)
231
227
 
232
228
 
233
229
  @app.post("api/test/auth/roles")
@@ -248,7 +244,7 @@ async def on_role_assign(request):
248
244
  """Assign authenticated account a role."""
249
245
  await assign_role(
250
246
  request.form.get("name"),
251
- request.ctx.authentication_session.bearer,
247
+ request.ctx.session.bearer,
252
248
  request.form.get("permissions"),
253
249
  "Role used for testing.",
254
250
  )
@@ -102,6 +102,7 @@ async def two_step_verification(request: Request) -> TwoStepSession:
102
102
  logger.info(
103
103
  f"Client {get_ip(request)} has completed two-step session {two_step_session.id} challenge."
104
104
  )
105
+ request.ctx.session = two_step_session
105
106
  return two_step_session
106
107
 
107
108
 
@@ -133,7 +134,7 @@ def requires_two_step_verification(arg=None):
133
134
  def decorator(func):
134
135
  @functools.wraps(func)
135
136
  async def wrapper(request, *args, **kwargs):
136
- request.ctx.two_step_session = await two_step_verification(request)
137
+ await two_step_verification(request)
137
138
  return await func(request, *args, **kwargs)
138
139
 
139
140
  return wrapper
@@ -229,6 +230,7 @@ async def captcha(request: Request) -> CaptchaSession:
229
230
  logger.info(
230
231
  f"Client {get_ip(request)} has completed captcha session {captcha_session.id} challenge."
231
232
  )
233
+ request.ctx.session = captcha_session
232
234
  return captcha_session
233
235
 
234
236
 
@@ -257,7 +259,7 @@ def requires_captcha(arg=None):
257
259
  def decorator(func):
258
260
  @functools.wraps(func)
259
261
  async def wrapper(request, *args, **kwargs):
260
- request.ctx.captcha_session = await captcha(request)
262
+ await captcha(request)
261
263
  return await func(request, *args, **kwargs)
262
264
 
263
265
  return wrapper
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sanic-security
3
- Version: 1.13.5
3
+ Version: 1.14.0
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/
@@ -309,46 +309,15 @@ async def on_authenticate(request):
309
309
  @app.post("api/security/auth")
310
310
  @requires_authentication
311
311
  async def on_authenticate(request):
312
- authentication_session = request.ctx.authentication_session
313
- response = json(
314
- "You have been authenticated.",
315
- authentication_session.json,
316
- )
312
+ response = json("You have been authenticated.", request.ctx.session.json)
317
313
  return response
318
314
  ```
319
315
 
320
316
  ## CAPTCHA
321
317
 
322
- Protects against spam and malicious activities by ensuring that only real humans can complete certain actions, like
323
- submitting a form or creating an account.
324
-
325
- * Fonts
326
-
327
- A font for captcha challenges is included in the repository. You can set a custom font by downloading a .ttf file and
328
- specifying its path in the configuration.
329
-
330
- [1001 Free Fonts](https://www.1001fonts.com/)
331
-
332
- * Voice Library
333
-
334
- A voice library for captcha challenges is included in the repository. You can generate your own using `espeak` and
335
- `ffmpeg`, then specify the library's directory in the configuration.
336
-
337
- ```bash
338
- # Set the language code
339
- export ESLANG=en
340
-
341
- # Create a directory for the specified language code
342
- mkdir "$ESLANG"
343
-
344
- # Loop through each character (A-Z, 0-9) and create a directory for each
345
- for i in {A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,0,1,2,3,4,5,6,7,8,9}; do
346
- mkdir "$ESLANG/$i"
347
- espeak -a 150 -s 100 -p 15 -v "$ESLANG" "$i" -w "$ESLANG/$i/orig_default.wav"
348
- ffmpeg -i "$ESLANG/$i/orig_default.wav" -ar 8000 -ac 1 -acodec pcm_u8 "$ESLANG/$i/default.wav"
349
- rm "$ESLANG/$i/orig_default.wav"
350
- done
351
- ```
318
+ Protects against spam and malicious activities by ensuring that only real humans can complete certain actions like
319
+ submitting a form or creating an account. A font and voice library for CAPTCHA challenges is included in the repository,
320
+ or you can download/create your own and specify its path in the configuration.
352
321
 
353
322
  * Request CAPTCHA
354
323
 
@@ -393,7 +362,7 @@ async def on_captcha(request):
393
362
  @app.post("api/security/captcha")
394
363
  @requires_captcha
395
364
  async def on_captcha(request):
396
- return json("Captcha attempt successful!", request.ctx.captcha_session.json)
365
+ return json("Captcha attempt successful!", request.ctx.session.json)
397
366
  ```
398
367
 
399
368
  ## Two-step Verification
@@ -455,8 +424,7 @@ async def on_two_step_verification(request):
455
424
  @requires_two_step_verification
456
425
  async def on_two_step_verification(request):
457
426
  response = json(
458
- "Two-step verification attempt successful!",
459
- request.ctx.two_step_session.json,
427
+ "Two-step verification attempt successful!", request.ctx.session.json
460
428
  )
461
429
  return response
462
430
  ```
@@ -0,0 +1,16 @@
1
+ sanic_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ sanic_security/authentication.py,sha256=dq7Yt_1xm9_LSZgMZkyzgcvG46NUQsysEb3s5pgO7BE,13165
3
+ sanic_security/authorization.py,sha256=QvLsaOWu3te0Y75tqChrEXQP5CR92nsRU7LXiUWy5cw,7541
4
+ sanic_security/configuration.py,sha256=h-Kh4PalJpjbDcZvVHCzxX5l-GnldP3Fr8OlgGCZNHY,5680
5
+ sanic_security/exceptions.py,sha256=JiCaBR2kjE1Cj0fc_08y-32fqJJXa_1UCw205T4_RTY,5493
6
+ sanic_security/models.py,sha256=bK5daR6Iq7V7aqNSzksH6DGrCXMj2e4feNRhlxlFQMg,22722
7
+ sanic_security/utils.py,sha256=tgewsCAkNl_NkobHaDlZNIgVopQPiD8SWb6UC6tBYNs,3151
8
+ sanic_security/verification.py,sha256=olmpP2AwXKILRVRnDf7AMRJuK5Fs_i5ESHXSH94A-Yk,8694
9
+ sanic_security/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ sanic_security/test/server.py,sha256=hLvT2mG1VXeV7nE6r1avoSOTa1qMSS6jL0qTizyCdOY,12029
11
+ sanic_security/test/tests.py,sha256=bW5fHJfsCrg8eBmcSqVMLm0R5XRL1ou-XJJRgz09GOE,21993
12
+ sanic_security-1.14.0.dist-info/LICENSE,sha256=sXlJs9_mG-dCkPfWsDnuzydJWagS82E2gYtkVH9enHA,1100
13
+ sanic_security-1.14.0.dist-info/METADATA,sha256=ynu6jYXbs9s7ZQi8l2Z2Ilm93Yu8JxQukx-swbOcQIc,23306
14
+ sanic_security-1.14.0.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
15
+ sanic_security-1.14.0.dist-info/top_level.txt,sha256=ZybkhHXSjfzhmv8XeqLvnNmLmv21Z0oPX6Ep4DJN8b0,15
16
+ sanic_security-1.14.0.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- sanic_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- sanic_security/authentication.py,sha256=SbPFze7s86xDsKOwoy37nGB8xffK3pSHGnmGUdlnexA,13225
3
- sanic_security/authorization.py,sha256=ddJWqGJbFIqII5pUW5SxI7h4EyVB-EhrbGM7jsQutOI,7559
4
- sanic_security/configuration.py,sha256=h-Kh4PalJpjbDcZvVHCzxX5l-GnldP3Fr8OlgGCZNHY,5680
5
- sanic_security/exceptions.py,sha256=JiCaBR2kjE1Cj0fc_08y-32fqJJXa_1UCw205T4_RTY,5493
6
- sanic_security/models.py,sha256=bK5daR6Iq7V7aqNSzksH6DGrCXMj2e4feNRhlxlFQMg,22722
7
- sanic_security/utils.py,sha256=tgewsCAkNl_NkobHaDlZNIgVopQPiD8SWb6UC6tBYNs,3151
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=Rh_L12HPCfagvAyqkHziBD1C4WHAKZ9ht4mTCpX2Yik,12240
11
- sanic_security/test/tests.py,sha256=bW5fHJfsCrg8eBmcSqVMLm0R5XRL1ou-XJJRgz09GOE,21993
12
- sanic_security-1.13.5.dist-info/LICENSE,sha256=sXlJs9_mG-dCkPfWsDnuzydJWagS82E2gYtkVH9enHA,1100
13
- sanic_security-1.13.5.dist-info/METADATA,sha256=WBdJdWbBOUphyj-RaEioPjEl8ksycafckhJTF2COCQU,24248
14
- sanic_security-1.13.5.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
15
- sanic_security-1.13.5.dist-info/top_level.txt,sha256=ZybkhHXSjfzhmv8XeqLvnNmLmv21Z0oPX6Ep4DJN8b0,15
16
- sanic_security-1.13.5.dist-info/RECORD,,