Commit Graph

21 Commits

Author SHA1 Message Date
lokses 0057f367a2 core: кастомные страницы ошибок 404/403/500/503 + режим техработ
Единый стиль портала (логотип, тема, кнопки) через error_base.html:
- 404 — страница не найдена
- 403 — доступ запрещён (+ ссылка на IT-поддержку)
- 500 — внутренняя ошибка (автономна: без request/context-процессоров)
- 503 — технические работы

MaintenanceModeMiddleware: при MAINTENANCE_MODE=True отдаёт 503 всем, кроме
суперпользователей и путей входа/админки/статики (чтобы админ мог войти и
выключить режим). По умолчанию выключен — поведение не меняется.

- tests: рендер всех шаблонов, кастомный 404, режим техработ вкл/выкл/супер

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-21 23:54:34 +03:00
lokses d07b9c6e97 dashboard: кастомизируемый дашборд из виджетов + шаблоны по умолчанию
Дашборд теперь собирается из виджетов (приветствие, метрики, мои задачи,
новости, быстрый доступ). Сотрудник настраивает состав и порядок под себя
(вкл/выкл + перемещение ↑↓), а для тех, кто не настраивал, действует набор
по умолчанию по типу локации (Офис/Аптека/Склад), задаётся в админке.

- core/dashboard.py: реестр виджетов + сборка раскладки
- core/models/dashboard.py: DashboardLayout (персональная), DashboardDefaults
  (синглтон по типу локации)
- core/views.py: dashboard_view через реестр + dashboard_customize_view
- templates/pages/dashboard_widgets/*: виджеты-партиалы; dashboard.html —
  цикл по виджетам; dashboard_customize.html — настройка (HTMX + ↑↓)
- admin: DashboardDefaults (чекбоксами по локации) + read-only раскладки;
  пункт меню «Дашборд по умолчанию»
- core/tests_dashboard.py: 11 тестов (логика раскладки + view)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-21 18:42:21 +03:00
lokses b2f0c2a1e2 core/portal: сотрудник без группы видит только базовые разделы
Ранее разделы с perm=None (Новости, Задачи, Дислокация, Документы, Чат,
Календарь, HR-портал, Справка) были доступны любому вошедшему — сотрудник
без назначенной группы видел почти весь портал. Теперь такие разделы
требуют хотя бы одной группы; без групп доступны только базовые:
Главная, Профиль, Поддержка IT.

- user_can_access: BASELINE_OPEN_KEYS + gate «есть ли группа» для perm=None
- PortalSectionAccessMiddleware: барьер по префиксу URL (в т.ч. вложенные
  страницы вроде /tasks/5/), /settings/ не гейтим (редирект на свой профиль)
- index.html: пункты меню под can_section (сайдбар, дропдаун, bottom-nav),
  секция «Управление» скрывается целиком, если пусто
- тесты: политика без-группы + прямой заход по URL; тест-фабрики выдают
  группу (реальный сотрудник её имеет)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-21 18:26:15 +03:00
lokses 385fa07eef admin: единое управление ролями в «Группы доступа»
Две сущности (auth.Group + PermissionGroup-профиль) слиты в одну страницу
админки Group: имя, разделы портала (curated), прочие права, описание,
активна, ссылка на матрицу доступа. Отдельный пункт «Группы разрешений»
убран из меню; модель PermissionGroup остаётся профилем под капотом.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-21 15:17:57 +03:00
lokses e885e2924b core: команда авто-очистки (cleanup)
manage.py cleanup [--days N] [--dry-run] — удаляет устаревшие журналы
синхронизации (AD/Carbonio/Nextcloud/Mattermost), просроченные инвайты
паролей и истёкшие сессии. Бизнес-данные не трогает. Срок хранения —
settings.CLEANUP_LOG_RETENTION_DAYS (default 90, env-override). Запуск по cron.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-16 16:44:25 +03:00
lokses c54a3b316a mattermost: журнал синхронизации (как у AD/Carbonio/Nextcloud)
- модель MattermostSyncLog (employee/action/status/message) + read-only админка;
- запись при добавлении в команды/каналы (успех и ошибка) в sync_service;
- пункт «Журнал Mattermost» в меню рядом с прочими журналами.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-16 16:40:08 +03:00
lokses dd1a31b4dd admin: полное и упорядоченное меню сайдбара (UNFOLD)
Навигация покрывает все админки (55 пунктов в 11 группах): Сотрудники,
Найм, Структура компании, Учёт посещений, IT-отдел, Эксплуатация (РРО/
счётчики/энергоактивы), Отчёты, Лента и задачи, База знаний, Mattermost
(вкл. Боты), Интеграции и настройки. Все ссылки проверены на reverse.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-16 16:32:44 +03:00
lokses 704d5d9538 mattermost: синхронизация команд/каналов по типу локации
Добавлен фильтр по user_location_type (Аптека/Склад/Офис) в TeamSyncSettings
и ChannelSyncSettings — наряду с фильтром по отделам. При включении обоих
фильтров условия объединяются по AND.

- поля filter_by_location_type + location_types (ArrayField, чекбоксы в админке);
- логика add_user_to_teams/channels учитывает тип локации;
- django.contrib.postgres в INSTALLED_APPS (для ArrayField).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-16 16:17:16 +03:00
lokses 6f299890d2 fix: таймзона Europe/Kiev → Europe/Kyiv
В свежей tzdata (Debian 13 / Python 3.13) старое имя Europe/Kiev удалено,
Django 6 отвергает его (ValueError: Incorrect timezone setting). Переименовано
во всех местах, включая дефолты Mattermost-таймзоны.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-10 17:11:14 +03:00
lokses 719d0b737b infra: надёжное обнаружение тестов, Redis-кэш и хардненинг прода
- AcoreDiscoverRunner собирает tests/tests_* всех локальных приложений
  (manage.py test находил 38 тестов из ~466 — теперь все).
- CACHES на Redis (отдельная DB от Celery) + обязательный requirepass
  в production, SECURE_HSTS_PRELOAD.
- Фикс stored-XSS в админке: format_html вместо mark_safe + f-string.
- Утилиты безопасности/тестов, шифрование полей.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-09 18:03:11 +03:00
lokses ae5c1f1848 Add RRO, portal section perms, dislocation presets, and hiring intern flow.
Ship cash-register registry, section-based portal access, configurable dislocation columns, and trial-hire intern accounts with credentials PDF.
2026-08-09 14:58:17 +03:00
lokses 19bc2874aa Nextcloud connector: скелет провижининга Group Folders (Фаза 2)
- ConnectorConfig: тип 'nextcloud' (host/username/token, шифруется)
- NextcloudService: OCS-клиент Group Folders (create/ACL/quota, идемпотентный ensure_folder)
- NextcloudSyncService: отделы → 03_Отделы/* ↔ nc-dept-<код>; аптеки → 02_Аптеки/* ↔ nc-svc
- Сигналы Directory/Pharmacy с гейтом на включённый коннектор (по умолч. no-op)
- Celery-задачи + команда nextcloud_sync (dry-run по умолчанию, --apply)
- NextcloudSyncLog + admin; тесты (пути, гейт, идемпотентность ensure_folder)

Членство юзеров идёт через AD/LDAP, коннектор ведёт только папки+ACL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:09:49 +03:00
lokses 4e803c53e0 2FA: обязательная двухфакторная аутентификация (TOTP) для staff
- Модель Employee: totp_secret (шифруется), totp_enabled, totp_backup_codes
- Сервис twofa: генерация секрета/QR, проверка TOTP, резервные коды (sha256)
- TwoFactorMiddleware: enforcement для is_staff на портале и /admin/
- Страницы setup/verify/backup-codes; сброс 2fa_verified при каждом входе
- Админка: колонка статуса 2FA, фильтр, действие «Сбросить 2FA»
- Тесты: enforcement, setup, verify, резервные коды, disable

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 10:41:11 +03:00
lokses 38c8e35a51 Security hardening: обязательный ключ шифрования, fail-closed токены, права API
- FIELD_ENCRYPTION_KEY: production требует явный ключ (ImproperlyConfigured
  при пустом), local — fallback на SECRET_KEY с предупреждением (crypto.py)
- MATTERMOST_INTERACTIVE_TOKEN: fail-closed токен для интерактивных кнопок
  Mattermost (bot_service task-done URL + проверка в mattermost views)
- Ужесточение прав API (employees/visit_manager) + тесты
  (employees, mattermost_connector, visit_manager)
- .env.example с описанием переменных; правки шаблонов (index/dislocation/pharmacies)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 12:23:28 +03:00
lokses 2bc9615ce5 i18n: инфраструктура + переключатель языков + перевод меню (ru/uk/en)
Мультиязычность: русский — базовый (msgid), украинский и английский — переводы.

- Настройки: LocaleMiddleware, LANGUAGES=[ru,uk,en], LOCALE_PATHS, i18n
  context_processor; urls: django.conf.urls.i18n (set_language)
- Шелл index.html: {% load i18n %}, все пункты навигации/меню/пользовательского
  меню/нижней навигации помечены {% trans %}; динамический <html lang>;
  переключатель языков в хедере (select -> set_language)
- Каталоги locale/uk и locale/en: переведены строки меню/шелла (34), собраны .mo
- .gitignore: разрешено трекать locale/**/*.mo (нужны на проде, CI нет)

Остальные страницы пока на украинском (хардкод) — переводятся дальше поэтапно.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 11:46:40 +03:00
lokses 242f0c95e0 Админка: отдельный раздел «Системи доступу» для баз/систем доступа
Системы доступа (1С, почта, CRM…) — записи справочника Directory
(access_system), которые выбираются в заявке на найм. Раньше их можно было
редактировать только внутри общего «Довідники» с фильтром — неочевидно.

- AccessSystem: proxy над Directory (фильтр по access_system), свой раздел
  админки со списком/добавлением; directory_type проставляется автоматически
- SILENCED_SYSTEM_CHECKS=['models.E016'] — гасит ложноположительный E016
  (proxy наследует treenode-индекс по _path; на реальной таблице всё корректно)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 01:12:07 +03:00
lokses b788bc2a7c Шифрование секретов ConnectorConfig (password/token) в БД
- EncryptedCharField (core/models/fields.py): прозрачное Fernet-шифрование
  на границе с БД, читатели и админка не меняются
- ConnectorConfig.password/token переведены на EncryptedCharField,
  колонки расширены под шифртекст
- Миграция 0004: расширение колонок -> шифрование существующих значений -> смена типа
- FIELD_ENCRYPTION_KEY в settings (default = SECRET_KEY); на проде задавать отдельно ДО migrate

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 15:31:37 +03:00
lokses 78475b58e9 Инфраструктура: Celery, общие утилиты, виджеты, шелл портала
- acore: Celery-приложение (брокер из env, eager без брокера), настройки
  CELERY_*, регистрация всех новых приложений в INSTALLED_APPS, маршруты
- core/utils: render_page (HTMX-фрагмент/полный layout), is_owner/
  is_owner_or_staff; templatetags common_tags (initials, clean_excerpt,
  is_it_staff); UpdateLastSeenMiddleware
- static: people-picker (дерево отделов с аватарками), searchable-select
  (одиночный выбор с поиском), directory-quick-add, it-manager, pagination;
  тема Tailwind v4 пересобрана, лого
- templates: новый шелл index.html (мобильный сайдбар, темы, фон,
  user-dropdown) и login с брендингом

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 17:31:01 +03:00
lokses c3f56f8a3e Portal redesign from template, real-data pages, test suite, Celery config
- templates: new shell from ACORE-template (mobile sidebar + bottom nav,
  themes, wallpaper, user dropdown), Django-ized nav with push-url;
  login rebranding; ACORE-template/ gitignored
- new pages wired to real data: databases (Directory types/counts),
  it-support (Ticket create form + my tickets), dashboard (live counters),
  structure (departments with head heuristic + pharmacy staffing status);
  static mockups for news/tasks/email/chat/purchases/hr-portal/help
- tests: 57 tests — ad_connector (ldap3 MOCK_SYNC client, sync scenarios,
  signals, mapping page), mattermost_connector (sync on mocks, bare-except
  regression), core (pages smoke, tickets, directories, tree rebuild)
- celery: add missing acore/celery.py app + CELERY_* settings (broker from
  env, eager mode without broker locally); wrap signal .delay calls so an
  unreachable broker no longer breaks employee saves

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 22:41:46 +03:00
lokses faa06b9f82 Security hardening: fix open redirect, API auth, MIME validation, PII exposure
- core/views.py: fix open redirect in login — validate next_url with
  url_has_allowed_host_and_scheme before redirecting
- visit_manager/api/views.py: add explicit permission_classes/
  authentication_classes on all 3 API views; add MIME magic-byte
  validation + Pillow verify for photo uploads; validate employee_id/
  location_id/date query params; restrict photo access to is_staff,
  own record, or direct manager
- employees/serializers.py: split into EmployeeSerializer (public
  fields only) and EmployeeDetailSerializer (PII fields, for HR/admin)
- mattermost_service.py: sanitize sensitive fields (password, token)
  before logging; log only error message not full response body
- settings/base.py: add SESSION/CSRF cookie HttpOnly + SameSite flags;
  set file upload size limits (15MB); remove BasicAuthentication from
  DRF (sends credentials in plaintext)
2026-05-31 18:05:54 +03:00
lokses 131cb27d16 Initial commit — ACORE pharmacy network management system
Django project: employees, locations, visit_manager, it_manager,
mattermost_connector and stub connectors (ad, mail, portal).
2026-05-31 14:21:47 +03:00