summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonah BrĂ¼chert <jbb@kaidan.im>2024-03-28 20:33:01 +0100
committerJonah BrĂ¼chert <jbb@kaidan.im>2024-03-28 20:40:22 +0100
commit7f9ceaa1601b57338fadd93c591d8f837afe7d1f (patch)
treeaeeda9bc463436c077f8efb62c410e971647eb94
parent0a5427cda901cc9a8fc35af992d808dbec02269e (diff)
downloadweb-7f9ceaa1601b57338fadd93c591d8f837afe7d1f.tar.gz
web-7f9ceaa1601b57338fadd93c591d8f837afe7d1f.tar.bz2
web-7f9ceaa1601b57338fadd93c591d8f837afe7d1f.zip
Port to flask 3
Flask 3 doesn't like cookies as bytes any more, so encode everything as bas64 before passing to Flask
-rw-r--r--accounts/forms.py3
-rw-r--r--accounts/utils/sessions.py27
-rw-r--r--requirements.txt7
3 files changed, 21 insertions, 16 deletions
diff --git a/accounts/forms.py b/accounts/forms.py
index a85f382..b59ab64 100644
--- a/accounts/forms.py
+++ b/accounts/forms.py
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
import re
-from flask import Markup, url_for
+from flask import url_for
from flask_wtf import FlaskForm as Form
from flask_login import current_user
from wtforms import StringField, PasswordField, ValidationError, \
BooleanField, validators
from wtforms.form import FormMeta
+from markupsafe import Markup
from .utils import NotRegexp
from accounts.app import accounts_app
diff --git a/accounts/utils/sessions.py b/accounts/utils/sessions.py
index e156f0c..007c928 100644
--- a/accounts/utils/sessions.py
+++ b/accounts/utils/sessions.py
@@ -3,20 +3,21 @@
from Crypto import Random
from Crypto.Cipher import AES
-from flask import Flask
+from flask import Flask, Request
from flask.sessions import TaggedJSONSerializer, SecureCookieSessionInterface
from itsdangerous import BadPayload
+from base64 import b64encode, b64decode
from accounts.app import accounts_app
from typing import cast
-def _pad(value, block_size):
+def _pad(value: str, block_size: int) -> bytes:
padding = block_size - len(value) % block_size
return (value + (padding * chr(padding))).encode("UTF-8")
-def _unpad(value):
+def _unpad(value: str) -> str:
pad_length = ord(value[len(value)-1:])
return value[:-pad_length]
@@ -27,12 +28,12 @@ class EncryptedSerializer(TaggedJSONSerializer):
super(EncryptedSerializer, self).__init__()
self.block_size = AES.block_size
- def _cipher(self, iv):
+ def _cipher(self, iv: bytes):
key = accounts_app.config['SESSION_ENCRYPTION_KEY']
assert len(key) == 32
return AES.new(key, AES.MODE_CBC, iv)
- def dumps(self, value):
+ def dumps(self, value: str) -> str:
"""
Encrypt the serialized values with `config.SESSION_ENCRYPTION_KEY`.
The key must be 32 bytes long.
@@ -40,23 +41,25 @@ class EncryptedSerializer(TaggedJSONSerializer):
serialized_value = super(EncryptedSerializer, self).dumps(value)
raw = _pad(serialized_value, self.block_size)
- iv = Random.new().read(self.block_size)
- return iv + self._cipher(iv).encrypt(raw)
+ iv: bytes = Random.new().read(self.block_size)
+ return b64encode(iv + self._cipher(iv).encrypt(raw)).decode("UTF-8")
- def loads(self, value):
+ def loads(self, value: str):
"""
Decrypt the given serialized session data with
`config.SESSION_ENCRYPTION_KEY`.
"""
- iv = value[:self.block_size]
- raw = self._cipher(iv).decrypt(value[AES.block_size:])
- return super(EncryptedSerializer, self).loads(_unpad(raw))
+ decoded = b64decode(value.encode("UTF-8"))
+ iv = decoded[:self.block_size]
+ raw = self._cipher(iv).decrypt(decoded[AES.block_size:])
+ return super(EncryptedSerializer, self) \
+ .loads(_unpad(raw))
class EncryptedSessionInterface(SecureCookieSessionInterface):
serializer = EncryptedSerializer()
- def open_session(self, app: Flask, request):
+ def open_session(self, app: Flask, request: Request):
session = None
try:
parent = super(EncryptedSessionInterface, self)
diff --git a/requirements.txt b/requirements.txt
index fe08567..2bdaedb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,11 +1,12 @@
-Flask==2.2.2 # >=0.10
+Flask==3.0.2 # >=0.10
Flask-WTF==1.2.1 # none
Flask-Login==0.6.3 # none
-Werkzeug==2.2.2 # >=0.6
+Werkzeug==3.0.1 # >=0.6
Jinja2==3.1.3 # >=2.4
WTForms==3.1.2 # >=1.0
itsdangerous==2.1.2 # none
-email_validator==2.1.0
+email_validator==2.1.1
pycryptodome==3.20.0
ldap3==2.9.1
+markupsafe==2.1.5
types-ldap3