Remediate the 2026-09-03 feature-test findings
This commit is contained in:
59
plugins/usb/migrations/versions/0004_checkin_identity.py
Normal file
59
plugins/usb/migrations/versions/0004_checkin_identity.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""Record who handed a drive back, not just when.
|
||||
|
||||
usbcheckouts held the checkout identity (sso, checkoutname) and, for the
|
||||
return, only checkintime. Returning a drive for a colleague is a supported
|
||||
kiosk flow - usb_kiosk_allow_return_for_others gates it and the kiosk asks for
|
||||
confirmation - but the row it wrote attributed the check-in to the HOLDER. The
|
||||
person who actually walked the drive back was recorded nowhere, so the custody
|
||||
history and the audit report both named somebody who was not there.
|
||||
|
||||
Two columns rather than one: the badge is what the scanner emits and what joins
|
||||
to a directory, and the name is what a report has to print when the directory
|
||||
no longer resolves that badge.
|
||||
|
||||
Nullable, and not backfilled. A row closed before this column existed is one
|
||||
where the returner was not recorded; copying the holder's badge into it would
|
||||
manufacture evidence that the holder returned it, which is the exact claim this
|
||||
migration exists to stop making.
|
||||
|
||||
Idempotent, so a re-run on an already-migrated database is a no-op.
|
||||
|
||||
Revision ID: usb0004checkinidentity
|
||||
Revises: usb0003scanfields
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = 'usb0004checkinidentity'
|
||||
down_revision = 'usb0003scanfields'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
NEW_COLUMNS = (
|
||||
('checkinsso', sa.String(length=20)),
|
||||
('checkinname', sa.String(length=100)),
|
||||
)
|
||||
|
||||
|
||||
def upgrade():
|
||||
bind = op.get_bind()
|
||||
insp = sa.inspect(bind)
|
||||
if 'usbcheckouts' not in insp.get_table_names():
|
||||
return
|
||||
cols = {c['name'] for c in insp.get_columns('usbcheckouts')}
|
||||
for name, coltype in NEW_COLUMNS:
|
||||
if name not in cols:
|
||||
op.add_column('usbcheckouts',
|
||||
sa.Column(name, coltype, nullable=True))
|
||||
|
||||
|
||||
def downgrade():
|
||||
bind = op.get_bind()
|
||||
insp = sa.inspect(bind)
|
||||
if 'usbcheckouts' not in insp.get_table_names():
|
||||
return
|
||||
cols = {c['name'] for c in insp.get_columns('usbcheckouts')}
|
||||
for name, _ in NEW_COLUMNS:
|
||||
if name in cols:
|
||||
op.drop_column('usbcheckouts', name)
|
||||
Reference in New Issue
Block a user