Рабочий лист: Организация интерфейса с пользователем — контроль

Дисциплина «ОП.08 Основы проектирования баз данных» — Занятие №24 (СИЭУиП)
Выберите назначенный практический вариант:

Вариант 1. Форма регистрации корпоративного клиента (ИНН, ОГРН, unique_violation)

Предметная область: Регистрация юридических лиц в корпоративном портале B2B. Форма принимает ИНН компании (строго 10 цифр с вычислением контрольного разряда) и ОГРН (строго 13 цифр). В базе данных поле inn защищено уникальным ограничением clients_inn_key.

Часть 1. Клиентская валидация (Frontend UX)

Разработайте JavaScript-логику валидации формы:

  1. Составьте регулярные выражения с обязательными граничными якорями ^ и $ для формата ИНН (10 цифр) и ОГРН (13 цифр).
  2. Опишите функцию проверки контрольной суммы 10-го знака ИНН юрлица по массиву весовых коэффициентов [2, 4, 10, 3, 5, 9, 4, 6, 8].
  3. Опишите логику мгновенной подсветки поля (зеленая рамка / красная рамка с текстом подсказки) и условие блокировки кнопки отправки формы (disabled).

Часть 2. Серверный контур и перехват ошибки СУБД (SQLSTATE 23505)

В схеме базы данных определена таблица:

CREATE TABLE corporate_clients (
    client_id BIGSERIAL PRIMARY KEY,
    company_name VARCHAR(255) NOT NULL,
    inn CHAR(10) NOT NULL CONSTRAINT clients_inn_key UNIQUE,
    ogrn CHAR(13) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT chk_inn_digits CHECK (inn ~ '^\d{10}$'),
    CONSTRAINT chk_ogrn_digits CHECK (ogrn ~ '^\d{13}$')
);

Два разных оператора одновременно попытались зарегистрировать одно и то же юридическое лицо. Ядро СУБД выбросило системное исключение:

ERROR: duplicate key value violates unique constraint "clients_inn_key"
DETAIL: Key (inn)=(7701234567) already exists.
SQLSTATE: 23505
  1. Почему категорически запрещено показывать пользователю этот технический текст? Какие риски ИБ и UX он несет?
  2. Напишите обработчик ошибки на бэкенде (Error Mapper), который перехватывает код 23505 и возвращает пользователю дружественное сообщение: «Клиент с данным ИНН уже зарегистрирован».

Часть 3. Защита от инъекций и самопроверка

Напишите параметризованный запрос (Prepared Statement) для добавления нового клиента и объясните, почему он полностью защищает от SQL-инъекций даже при наличии специальных символов в названии компании.

Вариант 2. Банковский перевод (IBAN/БИК, сумма <= 0, insufficient funds)

Предметная область: Экранная форма межбанковского перевода денежных средств. Включает поля: расчетный счет получателя (20 цифр), БИК банка (9 цифр, начинается с 04), сумма перевода в рублях.

Часть 1. Клиентская валидация (Frontend UX)

  1. Составьте регулярные выражения для проверки БИК (строго 9 цифр, начинается с 04) и расчетного счета (20 цифр) с якорями ^ и $.
  2. Опишите клиентскую валидацию поля суммы: запрет ввода нечисловых символов, мгновенная блокировка отправки при сумме amount <= 0, вывод подсказки: «Сумма перевода должна быть строго больше нуля».
  3. Как организовать автоформатирование счета блоками по 4 цифры для удобства восприятия клиентом?

Часть 2. Серверный контур: ограничение CHECK и блокировка транзакции

Схема таблицы банковских счетов:

CREATE TABLE bank_accounts (
    account_id BIGSERIAL PRIMARY KEY,
    account_number CHAR(20) NOT NULL UNIQUE,
    bik CHAR(9) NOT NULL,
    balance NUMERIC(15,2) NOT NULL DEFAULT 0.00,
    CONSTRAINT chk_positive_balance CHECK (balance >= 0.00)
);

Злоумышленник отправил запрос через curl в обход браузера на сумму 1 000 000 руб. при реальном остатке на счете 500 руб. СУБД выбросила исключение check_violation (SQLSTATE 23514).

А при параллельном списании денег в двух банкоматах возник конфликт транзакций serialization_failure (SQLSTATE 40001).

  1. Составьте таблицу маппинга ошибок (SQLSTATE -> Дружественное сообщение для пользователя).
  2. Напишите SQL-запрос с конструкцией SELECT ... FOR UPDATE для корректной пессимистической блокировки счета отправителя на время выполнения перевода.

Часть 3. Защита от инъекций и самопроверка

Почему конкатенация строк в финансовой транзакции категорически недопустима? Приведите пример опасного запроса и покажите его безопасный аналог на Prepared Statement.

Вариант 3. Оформление заказа в онлайн-магазине (Email, телефон, триггер остатков)

Предметная область: Экранная форма оформления покупки в интернет-магазине. Поля: email покупателя, мобильный телефон по маске +7, количество заказываемого товара.

Часть 1. Клиентская валидация (Frontend UX)

  1. Составьте регулярное выражение для международной проверки адреса электронной почты (RFC-совместимый базовый шаблон).
  2. Составьте шаблон маски мобильного телефона РФ в формате +7 (XXX) XXX-XX-XX и регулярное выражение для очищенных 11 цифр.
  3. Опишите логику валидации поля количества (целое положительное число от 1 до 99).

Часть 2. Серверный триггер остатков и перехват исключения P0001

Два покупателя одновременно нажали кнопку «Купить» на последнюю единицу товара на складе. В СУБД сработал серверный триггер:

CREATE OR REPLACE FUNCTION trg_check_inventory() RETURNS TRIGGER AS $$
DECLARE v_stock INT;
BEGIN
    SELECT stock_quantity INTO v_stock FROM warehouse WHERE product_id = NEW.product_id FOR UPDATE;
    IF v_stock < NEW.quantity THEN
        RAISE EXCEPTION 'OUT_OF_STOCK: Недостаточно товара на складе' USING ERRCODE = 'P0001';
    END IF;
    UPDATE warehouse SET stock_quantity = stock_quantity - NEW.quantity WHERE product_id = NEW.product_id;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
  1. Как ядро СУБД обработает одновременную покупку благодаря FOR UPDATE? Что произойдет со вторым покупателем?
  2. Спроектируйте перехватчик исключения SQLSTATE P0001 на бэкенде: какое дружественное сообщение увидит второй покупатель на экране оформления заказа?

Часть 3. Защита от инъекций и самопроверка

Опишите, как Prepared Statement обрабатывает вредоносные символы в поле email (например, ' OR 1=1; DROP TABLE orders; --). Почему СУБД не выполняет этот код?

Вариант 4. Форма бронирования отеля (Интервалы дат, EXCLUDE gist overlap)

Предметная область: Веб-интерфейс бронирования гостиничных номеров. Поля: выбор категории номера, дата заезда (check-in), дата выезда (check-out).

Часть 1. Клиентская валидация (Frontend UX)

  1. Опишите клиентскую валидацию интервала дат: проверка условия Дата_выезда > Дата_заезда, запрет бронирования в прошлом (дата заезда не может быть раньше сегодняшнего дня).
  2. Как реализовать мгновенную обратную связь в интерфейсе при выборе недопустимой даты выезда (до даты заезда)?
  3. Почему клиентский календарь не может гарантировать 100% отсутствие двойного бронирования номеров?

Часть 2. Серверный контур: ограничение EXCLUDE gist и перехват 23P01

Для предотвращения овербукинга в таблице отеля создано ограничение исключения интервалов:

CREATE EXTENSION IF NOT EXISTS btree_gist;

CREATE TABLE room_bookings (
    booking_id BIGSERIAL PRIMARY KEY,
    room_id INT NOT NULL,
    stay_dates DATERANGE NOT NULL,
    guest_name VARCHAR(100) NOT NULL,
    CONSTRAINT chk_no_overlap EXCLUDE USING gist (
        room_id WITH =,
        stay_dates WITH &&
    )
);

Два гостя параллельно отправили заявки на пересекающиеся даты. База данных отвергла вторую транзакцию системной ошибкой:

ERROR: conflicting key value violates exclusion constraint "chk_no_overlap"
DETAIL: Key (room_id, stay_dates)=(101, [2026-10-10, 2026-10-15)) conflicts with existing key...
SQLSTATE: 23P01
  1. Какую информацию раскрывает злоумышленнику это техническое сообщение СУБД?
  2. Составьте код модуля Error Mapping, который перехватывает SQLSTATE 23P01 и выводит гостю подсказку: «Выбранный номер уже занят на эти даты. Пожалуйста, выберите другие даты или другой номер».

Часть 3. Защита от инъекций и самопроверка

Сформулируйте параметризованный запрос для вставки бронирования с приведением типов $1::int, daterange($2::date, $3::date, '[)') и обоснуйте его надежность.

✓ Ответы успешно сохранены в браузере