diff --git a/cern_access/indico_cern_access/migrations/20241015_1702_92377810f14e_make_reservation_code_unique_and_nullable.py b/cern_access/indico_cern_access/migrations/20241015_1702_92377810f14e_make_reservation_code_unique_and_nullable.py new file mode 100644 index 00000000..6a863579 --- /dev/null +++ b/cern_access/indico_cern_access/migrations/20241015_1702_92377810f14e_make_reservation_code_unique_and_nullable.py @@ -0,0 +1,27 @@ +"""Make reservation code unique and nullable + +Revision ID: 92377810f14e +Revises: ee88b64f9494 +Create Date: 2024-10-15 17:02:59.886902 +""" + +from alembic import op + + +# revision identifiers, used by Alembic. +revision = '92377810f14e' +down_revision = 'ee88b64f9494' +branch_labels = None +depends_on = None + + +def upgrade(): + op.alter_column('access_requests', 'reservation_code', nullable=True, schema='plugin_cern_access') + op.execute("UPDATE plugin_cern_access.access_requests SET reservation_code = NULL WHERE reservation_code = ''") + op.create_unique_constraint(None, 'access_requests', ['reservation_code'], schema='plugin_cern_access') + + +def downgrade(): + op.drop_constraint('uq_access_requests_reservation_code', 'access_requests', schema='plugin_cern_access') + op.execute("UPDATE plugin_cern_access.access_requests SET reservation_code = '' WHERE reservation_code IS NULL") + op.alter_column('access_requests', 'reservation_code', nullable=False, schema='plugin_cern_access') diff --git a/cern_access/indico_cern_access/models/access_requests.py b/cern_access/indico_cern_access/models/access_requests.py index 65eeb310..cffc63a4 100644 --- a/cern_access/indico_cern_access/models/access_requests.py +++ b/cern_access/indico_cern_access/models/access_requests.py @@ -39,7 +39,8 @@ class CERNAccessRequest(db.Model): ) reservation_code = db.Column( db.String, - nullable=False + nullable=True, + unique=True ) adams_nonce = db.Column( db.String, diff --git a/cern_access/indico_cern_access/plugin.py b/cern_access/indico_cern_access/plugin.py index 01864f7c..71f1cc05 100644 --- a/cern_access/indico_cern_access/plugin.py +++ b/cern_access/indico_cern_access/plugin.py @@ -272,7 +272,6 @@ def _registration_created(self, registration, management, **kwargs): license_plate=access_request_data['license_plate'], accompanying_persons=sanitize_accompanying_persons(accompanying_persons, registration), request_state=CERNAccessRequestState.not_requested, - reservation_code='' ) def _event_time_changed(self, sender, obj, **kwargs): diff --git a/cern_access/indico_cern_access/util.py b/cern_access/indico_cern_access/util.py index ed28a0d9..9779978e 100644 --- a/cern_access/indico_cern_access/util.py +++ b/cern_access/indico_cern_access/util.py @@ -269,7 +269,11 @@ def withdraw_event_access_request(req): def get_random_reservation_code(): """Generate random reservation code for data required by ADaMS API.""" charset = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789' - return 'I' + ''.join(random.sample(charset, 6)) + + while True: + reservation_code = 'I' + ''.join(random.sample(charset, 6)) + if not CERNAccessRequest.query.filter_by(reservation_code=reservation_code).has_rows(): + return reservation_code def create_access_request(registration, state, reservation_code, nonce): diff --git a/cern_access/tests/conftest.py b/cern_access/tests/conftest.py index 288bf060..24e43276 100644 --- a/cern_access/tests/conftest.py +++ b/cern_access/tests/conftest.py @@ -159,5 +159,4 @@ def dummy_access_request(dummy_regform, accompanying_persons_field): birth_place='bar', license_plate=None, request_state=CERNAccessRequestState.not_requested, - reservation_code='', accompanying_persons=accompaning_persons)