diff --git a/deployment/database/migrations/1.1.2_AlterCardIdToVarchar.sql b/deployment/database/migrations/1.1.2_AlterCardIdToVarchar.sql index 4dc48be..4665493 100644 --- a/deployment/database/migrations/1.1.2_AlterCardIdToVarchar.sql +++ b/deployment/database/migrations/1.1.2_AlterCardIdToVarchar.sql @@ -7,95 +7,3 @@ ALTER TABLE activation_logs ALTER COLUMN card_id TYPE VARCHAR(9); -- Drop the old procedure which accepted UUID DROP FUNCTION IF EXISTS activate_payment_card(UUID, TEXT, INET, JSONB); --- Recreate it to accept VARCHAR(9) -CREATE OR REPLACE FUNCTION activate_payment_card( - p_card_id VARCHAR(9), -- 9 digit string de la tarjeta - p_input_code TEXT, -- El código que mete el usuario, puede ser incorrecto en este punto - p_ip_address INET, -- Datos de origen de la activación - p_device_info JSONB -- Datos del dispositivo de origen -) -RETURNS TABLE ( - success BOOLEAN, - message TEXT -) AS $$ -DECLARE - v_code_hash TEXT; - v_is_used BOOLEAN; - v_is_blocked BOOLEAN; - v_expires_at TIMESTAMPTZ; - v_failed_attempts INT; - v_max_attempts CONSTANT INT := 3; -BEGIN - -- 1. Obtener datos del código y bloquear la fila para actualización (FOR UPDATE) - -- sería raro que 2 clientes intentasen modificar la tarjeta a la vez. - SELECT code_hash, is_used, is_blocked, expires_at, failed_attempts - INTO v_code_hash, v_is_used, v_is_blocked, v_expires_at, v_failed_attempts - FROM activation_codes - WHERE card_id = p_card_id - FOR UPDATE; - - -- 2. Validaciones: - -- 2.1 Si no existe ninguna tarjeta con ese card_id - IF NOT FOUND THEN - RETURN QUERY SELECT FALSE, 'CARD_NOT_FOUND'; - RETURN; - END IF; - - -- 2.2 Si el código introducido ya ha sido usado - IF v_is_used THEN - RETURN QUERY SELECT FALSE, 'ALREADY_ACTIVATED'; - RETURN; - END IF; - - -- 2.3 Si el código ya ha sido bloqueado o se ha intentado demasiadas veces - IF v_is_blocked OR v_failed_attempts >= v_max_attempts THEN - RETURN QUERY SELECT FALSE, 'CODE_BLOCKED'; - RETURN; - END IF; - - -- 2.4 Si el código es demasiado viejo - IF v_expires_at < NOW() THEN - RETURN QUERY SELECT FALSE, 'CODE_EXPIRED'; - RETURN; - END IF; - - -- 3. Verificación del Hash del codigo que ha introducido el usuario - -- En la bdd guardo el hash, al procedimiento se introduce el codigo per-se - -- Si el código NO coincide: - IF v_code_hash != crypt(p_input_code, v_code_hash) THEN - UPDATE activation_codes - -- 3.1 Control de intentos - SET failed_attempts = failed_attempts + 1, - is_blocked = (failed_attempts + 1 >= v_max_attempts) - WHERE card_id = p_card_id; - -- 3.2 Se loguea el fallo - INSERT INTO activation_logs (card_id, action_type, ip_address, device_info) - VALUES (p_card_id, 'FAILED_ATTEMPT', p_ip_address, p_device_info); - - RETURN QUERY SELECT FALSE, 'INVALID_CODE'; - RETURN; - END IF; - - -- 4. Si el código ES correcto: - -- Marcar código como usado - UPDATE activation_codes - SET is_used = TRUE - WHERE card_id = p_card_id; - - -- Activar la tarjeta - UPDATE payment_cards - SET status = 'ACTIVE', - activated_at = NOW() - WHERE card_id = p_card_id; - - -- Registrar éxito en auditoría - INSERT INTO activation_logs (card_id, action_type, ip_address, device_info) - VALUES (p_card_id, 'ACTIVATION_SUCCESS', p_ip_address, p_device_info); - - RETURN QUERY SELECT TRUE, 'SUCCESS'; - -EXCEPTION WHEN OTHERS THEN - -- En caso de error inesperado, Postgres hace rollback automático - RETURN QUERY SELECT FALSE, 'INTERNAL_ERROR: ' || SQLERRM; -END; -$$ LANGUAGE plpgsql;