Skip to content

Commit 62b605c

Browse files
committed
Calculate the cipher length and base64 length ahead of time. (Fixes #853)
We also fix up an existing issue with a user's schedules.details field.
1 parent 2a47a17 commit 62b605c

File tree

5 files changed

+489
-3
lines changed

5 files changed

+489
-3
lines changed

backend/src/appointment/database/models.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,17 @@ class TimeMode(enum.Enum):
9696
h24 = 24
9797

9898

99+
def calculate_encrypted_length(length: int):
100+
"""Calculate the length of the string after it's been encrypted and encoded."""
101+
cipher_length = length + 16 - (length % 16) # Fixed block size of 16 for Aes
102+
return int((cipher_length + 2) / 3) << 2 # Base64 with padding
103+
104+
99105
def encrypted_type(column_type, length: int = 255, **kwargs) -> StringEncryptedType:
100106
"""Helper to reduce visual noise when creating model columns"""
101-
return StringEncryptedType(column_type, secret, AesEngine, 'pkcs5', length=length, **kwargs)
107+
return StringEncryptedType(
108+
column_type, secret, AesEngine, 'pkcs5', length=calculate_encrypted_length(length), **kwargs
109+
)
102110

103111

104112
@as_declarative()
@@ -441,6 +449,7 @@ def is_available(self) -> bool:
441449

442450
class WaitingList(Base):
443451
"""Holds a list of hopefully future-Appointment users"""
452+
444453
__tablename__ = 'waiting_list'
445454

446455
id = Column(Integer, primary_key=True, index=True)

backend/src/appointment/database/schemas.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ class ScheduleBase(BaseModel):
166166
slug: Optional[str] = None
167167
calendar_id: int
168168
location_type: LocationType | None = LocationType.inperson
169-
location_url: str | None = None
170-
details: str | None = None
169+
location_url: str | None = Field(max_length=2048)
170+
details: str | None = Field(max_length=250)
171171
start_date: date | None = None
172172
end_date: date | None = None
173173
start_time: time | None = None
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""clean invalid schedule details
2+
3+
Revision ID: 645fd31f827d
4+
Revises: 4a15d01919b8
5+
Create Date: 2025-02-05 18:39:12.277713
6+
7+
"""
8+
import binascii
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
from sqlalchemy.orm import Session
13+
import base64
14+
15+
# revision identifiers, used by Alembic.
16+
revision = '645fd31f827d'
17+
down_revision = '4a15d01919b8'
18+
branch_labels = None
19+
depends_on = None
20+
21+
22+
def upgrade() -> None:
23+
session = Session(op.get_bind())
24+
bad_fields_found = 0
25+
rows = session.execute(sa.text('SELECT id, details FROM schedules WHERE details is not null;')).all()
26+
for row in rows:
27+
id, details = row
28+
try:
29+
base64.b64decode(details)
30+
except binascii.Error:
31+
bad_fields_found += 1
32+
statement = sa.text('UPDATE schedules SET details = NULL WHERE id = :id')
33+
statement = statement.bindparams(id=id)
34+
op.execute(statement)
35+
36+
print(f'Nulled {bad_fields_found} schedules.details fields.')
37+
38+
39+
def downgrade() -> None:
40+
pass

0 commit comments

Comments
 (0)