Low-code API: Как ваш разработчик может разорить вас одной строчкой кода (почему корзина — это минное поле)

от автора

Привет, друзья!
Вы же любите no-code/low-code, правда? Кликаете мышкой, перетаскиваете блоки, пьёте капучино — и вуаля, ваше приложение готово! Но стоп. А что, если ваш «волшебный» разработчик на low-code случайно (или специально?) сделал так, что любой школьник может купить у вас iPhone за 10 рублей? Давайте разберёмся, как это возможно, и почему выбор разработчика — это как выбор зубного врача: если ошибётесь, будет больно.

История одной корзины, или почему ваш магазин — не благотворительный фонд

Представьте: у вас есть интернет-магазин. Товары, корзина, заказы — всё как у людей. Всё работает на low-code платформе, чтобы сэкономить бюджет. Но вдруг вы замечаете, что дорогие товары улетают со склада, а деньги не приходят. В чём подвох?

Всё дело в том, как передаются данные о заказе.

❌ Пример «гениального» кода (так делать нельзя!):

Ваш разработчик настроил API так, что клиент сам указывает цену товара. Выглядит это примерно так:
Метод POST /orders

 {     "product_id": "123",     "quantity": 1,     "price": 1000 // Ой, а кто это контролирует?   } 

Или например, в вашем приложении при тапе на кнопку «Оформить заказ», вы запускаете цикл и записыавете каждую строку заказа в Supabase (no-code/low-code backend на базе PostgreSQL), указывая product_id, quantity, price.

Что происходит:
Злоумышленник перехватывает API и меняет price на 10 рублей, отправляет запрос — и получает товар за копейки. Ваш магазин превращается в филиал «Пятёрочки» с акцией «Всё за 10 рублей».

Как это исправить? Секреты правильных таблиц и API

🔑 Применая структура данных:

  1. Таблица products:

    • id (уникальный код товара)

    • name

    • price (хранится ТОЛЬКО здесь!)

  2. Таблица orders:

    • id (UUID)

    • total (сумма заказа)

  3. Таблица order_items:

    • order_id (ссылка на заказ)

    • product_id (ссылка на товар)

    • quantity

    • price (цена на момент заказа, берётся из products)

✅ Пример умного API:

Клиент отправляет только ID товара и количество. Цену знает только сервер!

{     "items": [       { "product_id": "8719", "quantity": 2 },       { "product_id": "8720", "quantity": 3 }     ]   } 

Пример API в Supabase

Давайте рассмотрим на примере Supabase, который кстати можно установить на свой сервер. Для простоты будем использовать обычные функции в базе данных.

  1. Создадим SQL-функцию bulk_insert_order_items.
    Эта функция будет принимать на входе id заказа и список позиций заказа (только id товара и количество. Без указания цен!). А внутри она будет брать из базы цены на товары и считать стоимость по каждой позиции, а также стоимость всего заказа.

CREATE OR REPLACE FUNCTION bulk_insert_order_items(     p_order_id UUID,     p_items JSONB ) RETURNS VOID AS $$ DECLARE     v_total REAL := 0;     v_item RECORD; BEGIN     -- Перебираем товары и сохраняем их в order_items     FOR v_item IN SELECT * FROM jsonb_to_recordset(p_items) AS (         product_id BIGINT,         quantity REAL     ) LOOP         INSERT INTO order_items (order_id, product_id, quantity, price)         SELECT p_order_id, v_item.product_id, v_item.quantity, p.price         FROM products p         WHERE p.id = v_item.product_id         RETURNING price * v_item.quantity INTO v_total;     END LOOP;          -- Обновляем сумму заказа     UPDATE orders     SET total = COALESCE(total, 0) + v_total     WHERE id = p_order_id; END; $$ LANGUAGE plpgsql; 

2. Проверим работу функции непосредственно через SQL:

select bulk_insert_order_items(     '0f0cbe98-535f-44e4-b842-2c1f06840e9a',  -- Замените на валидный UUID заказа     '[{"product_id": 8719, "quantity": 2}, {"product_id": 8720, "quantity": 3}]'::jsonb  -- Замените на ваши данные ); 

3. Также вы можете использовать Edge Functions, если требуется более сложная логика или интеграция с внешними сервисами. Преимущество Edge Functions в том, что они позволяют контролировать каждый шаг обработки, добавлять кастомные проверки и легко масштабировать решение, что может быть удобнее, если нужна дополнительная гибкость по сравнению с SQL-функциями.

4. Supabase автоматически генерирует API для вызова этой функции. Указываем номер заказа и передаем список товаров и количество, без цен!

curl -X POST 'https://yourproject.supabase.co/rest/v1/rpc/bulk_insert_order_items' \ -d '{   "p_order_id": "0f0cbe98-535f-44e4-b842-2c1f06840e9a",   "p_items": "[{\"product_id\": 8719, \"quantity\": 2}, {\"product_id\": 8720, \"quantity\": 3}]" }' \ -H "Content-Type: application/json" \ -H "apikey: SUPABASE_KEY" \ -H "Authorization: Bearer SUPABASE_KEY" 

Совет заказчикам: Как не нанять «разрушителя бизнесов»

  1. Спросите: «Где считается цена — на сервере или в телефоне клиента?». Если ответ «В интерфейсе», бегите быстрее света.

  2. Проверьте API: Если в запросе есть price, discount или total — это красная лампочка.

  3. Требуйте логов: Все операции с деньгами должны логироваться на сервере.

  4. Узнайте ИТ-бэкграунд вашего специалиста: имеет ли ваш no-code / low-code- разработчик опыт работы разработчиком или системным аналитиком.

Итог: Low-code — это круто, но…

…если ваш разработчик пришел в low-code без базовых принципов разработки ПО, будьте готовы к небезопасным и не оптимизированным приложениям.

P.S. Если после прочтения статьи вы подумали: «А мой API тоже дырявый?» — давайте проверим! Пишите мне в Telegram: @kirilkindn. Устроим вашему приложению «тест-драйв» — бесплатно, с кофе и полезными фидбеками 😉.


ссылка на оригинал статьи https://habr.com/ru/articles/883170/