security: закрыть уязвимости аудита (PRJ-6)

- gunicorn вместо dev-сервера Werkzeug; non-root user в Dockerfile
- volume sqlite_data для БД (заявки не теряются при rebuild)
- consultations.db и data/ в .dockerignore (ПДн не попадают в образ)
- Secure-куки по умолчанию (COOKIE_SECURE=1), лимит сессии 12ч
- защитные заголовки: CSP, X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy
- MAX_CONTENT_LENGTH 64КБ
- анти-брутфорс админки: 5 попыток -> блокировка 15 мин + лимит 5/мин
- обязательный чекбокс согласия на обработку ПДн + страница /privacy
- .env.example: понятные плейсхолдеры, COOKIE_SECURE
This commit is contained in:
2026-08-06 16:12:48 +04:00
parent 4e6b655a2b
commit 971e51b6f5
9 changed files with 126 additions and 8 deletions
+1
View File
@@ -160,6 +160,7 @@
</div>
<fieldset class="format-field"><legend>Формат занятий <span>*</span></legend><div class="radio-options"><label><input type="radio" name="format" value="online" required><span>Онлайн</span></label><label><input type="radio" name="format" value="offline"><span>Очно</span></label><label><input type="radio" name="format" value="other"><span>Не знаю</span></label></div></fieldset>
<label>Комментарий <span class="optional">необязательно</span><textarea name="message" rows="3" placeholder="Расскажите, какая цель у занятий..."></textarea></label>
<label class="consent-label"><input type="checkbox" name="consent" value="on" required> <span>Я согласен на обработку персональных данных в соответствии с <a href="{{ url_for('privacy_policy') }}">политикой конфиденциальности</a>. <b>*</b></span></label>
<button class="button button-primary form-button" type="submit">Отправить заявку <span></span></button>
<p class="form-note">Нажимая кнопку, вы соглашаетесь на обработку персональных данных.</p>
</form>
+51
View File
@@ -0,0 +1,51 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Политика конфиденциальности — Анастасия Панкратенкова, математика.">
<title>Политика конфиденциальности — Анастасия Панкратенкова</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body>
<div class="page-shell">
<header class="site-header">
<a class="brand" href="{{ url_for('index') }}" aria-label="На главную">
<span class="brand-mark">АП</span>
<span class="brand-name">Анастасия<br>Панкратенкова</span>
</a>
<nav class="main-nav" aria-label="Основная навигация">
<a href="{{ url_for('index') }}#about">О преподавателе</a>
<a href="{{ url_for('index') }}#subjects">Направления</a>
<a href="{{ url_for('index') }}#contact">Записаться</a>
</nav>
</header>
<main class="privacy-content" style="max-width: 820px; margin: 0 auto; padding: 64px 24px 96px;">
<p class="eyebrow"><span class="eyebrow-dot"></span> Юридическая информация</p>
<h1>Политика<br><em>конфиденциальности</em></h1>
<p class="privacy-lead">Этот сайт использует персональные данные только для обработки заявок на консультации.</p>
<h2>Какие данные собираются</h2>
<p>При заполнении формы могут быть указаны имя, контакт (телефон или Telegram), предмет, экзамен, формат занятий, желаемое время и комментарий к заявке.</p>
<h2>Зачем они нужны</h2>
<p>Данные используются исключительно для связи с заявителем, ответа на вопросы и подготовки к занятиям.</p>
<h2>Хранение и защита</h2>
<p>Заявки хранятся в защищённой базе данных. Доступ к ним имеет только преподаватель. Данные не передаются третьим лицам и не используются для рекламных рассылок.</p>
<h2>Отзыв согласия</h2>
<p>Чтобы уточнить, изменить или удалить сведения из заявки, свяжитесь с преподавателем тем же способом, который был указан при записи.</p>
<a class="button button-primary" href="{{ url_for('index') }}#contact" style="margin-top: 32px;">Вернуться к записи <span></span></a>
</main>
<footer class="site-footer section-wrap">
<a class="brand" href="{{ url_for('index') }}"><span class="brand-mark">АП</span><span class="brand-name">Анастасия<br>Панкратенкова</span></a>
<p>Математика<br>с пониманием.</p>
<span>© {{ current_year }}</span>
</footer>
</div>
</body>
</html>