Skip to content

Latest commit

 

History

History
164 lines (127 loc) · 8.17 KB

File metadata and controls

164 lines (127 loc) · 8.17 KB

University App

Открытая платформа студенческого приложения на Flutter. Репозиторий можно адаптировать под другой университет без форка бизнес-логики: tenant, публичный брендинг и deep links задаются конфигурацией, а университетские источники данных подключаются через нормализованный ingest-контракт Supabase.

Конфигурация по умолчанию сохраняет совместимость с РТУ МИРЭА. Встроенный MIREA-фетчер выключен по умолчанию и не должен использоваться для другого tenant.

Технологии и архитектура

  • Flutter 3.44.2 и Dart 3.12 с null safety.
  • Feature-first BLoC-архитектура: UI и BLoC находятся в lib/<feature>, а переиспользуемые клиенты, модели и репозитории — в Dart workspace packages/.
  • bloc/hydrated_bloc для состояния, yx_scope для dependency injection и go_router для навигации.
  • Freezed и json_serializable для генерируемых immutable-моделей и JSON DTO.
  • Supabase Auth, Storage, миграции, RPC и Edge Functions как серверный контракт.
  • Отдельный Python 3.12 worker для официальных новостей, Telegram-публикаций и Telegram Stories.

Основной поток данных:

внешний источник -> Python worker -> Edge Function /ingest
                 -> Supabase RPC/таблицы -> repository -> BLoC -> Flutter UI

Flutter не должен обращаться к внутренним таблицам или использовать service_role. Привилегированная запись контента проходит через защищённую функцию supabase/functions/ingest, а схема БД изменяется только миграциями из supabase/migrations.

Быстрый старт

Нужны Flutter, FVM и Java 17 для Android. Версия Flutter закреплена в .fvmrc.

dart pub global activate fvm
fvm install
fvm flutter pub get

Создайте две локальные compile-time конфигурации:

cp .env.example .env
cp config/university.example.json config/university.local.json

В PowerShell используйте Copy-Item вместо cp. В .env укажите публичные SUPABASE_URL и SUPABASE_PUBLISHABLE_KEY. В config/university.local.json задайте tenant и брендинг. Затем проверьте конфигурацию и сгенерируйте код:

fvm dart run tool/configure_university.dart
fvm dart run build_runner build

Запуск development flavor на Android/iOS/macOS:

fvm flutter run \
  --flavor development \
  --target lib/main/main_development.dart \
  --dart-define-from-file=.env \
  --dart-define-from-file=config/university.local.json \
  --dart-define-from-file=config/firebase.local.json

Firebase-файл опционален: без него Analytics и FCM корректно отключаются. Нативные google-services.json, GoogleService-Info.plist и сгенерированный firebase_options.dart не являются частью открытого исходного кода.

Для Windows уберите --flavor development. Подробности о схеме конфигурации и режиме --check описаны в docs/university-configuration.md.

Локальные .env, tenant-файлы, Firebase-конфигурация, ключи подписи и Telegram session-файлы нельзя коммитить. Пример university config содержит только публичные значения и не заменяет настройку собственных Firebase/Supabase проектов.

Supabase

Локальная конфигурация находится в supabase/config.toml. Для работы с миграциями нужен Supabase CLI и Docker:

supabase start
supabase db reset

Не изменяйте уже применённые миграции: создавайте новую через supabase migration new <name>. Секрет ingest-функции хранится только на сервере и в локальном окружении worker.

Для одного tenant задайте Edge secrets INGEST_API_KEY и INGEST_ORGANIZATION_ID. Общий backend нескольких университетов должен использовать INGEST_TENANT_KEYS — JSON-карту organization_id к отдельному ключу каждого worker. Не используйте один неприкреплённый ключ для всех tenant.

Фетчер контента

Worker находится в tools/social_media_fetcher и использует uv. Он нормализует контент и отправляет его в Edge ingest; напрямую в БД не пишет.

Для RSS/Atom и официальных API предпочтителен no-code путь через self-hosted n8n: импортируйте готовый rss-to-ingest.json и используйте HTTP Request node для Facebook Graph API, YouTube, Mastodon или иного документированного API. Python-коннектор оставлен для источников, которым нужна пользовательская сессия или особая обработка, например Telegram Stories. Полный контракт и правила расширения — в tools/social_media_fetcher/docs/architecture.md.

cd tools/social_media_fetcher
cp .env.example .env
uv sync --locked
uv run python worker.py

MIREA_ENABLED=true допустим только при APP_ORGANIZATION_ID=mirea. Telegram подключается явно через TELEGRAM_CHANNELS и TELEGRAM_STORY_CHANNELS. Для пользовательской Telegram-сессии используйте отдельный согласованный аккаунт и setup_telegram_session.py; полученный session string считается секретом и не должен попадать в логи, issues или Git.

Stories-медиа загружается только через подписанные Storage URL. Workflow cleanup-story-media.yml независимо от Telegram-сессии удаляет истёкшие и осиротевшие объекты; для него задаются SUPABASE_URL, INGEST_ORGANIZATION_ID и tenant-bound INGEST_API_KEY.

Проверки

fvm dart analyze --fatal-warnings
fvm flutter test

cd tools/social_media_fetcher
uv run ruff format --check .
uv run ruff check .
uv run pytest

CI повторяет анализ и тесты Flutter и ключевых workspace-пакетов, проверки Python worker, format/lint/type-check Edge ingest и fresh replay Supabase миграций. CI имеет только read-доступ к репозиторию. Релиз Shorebird запускается только вручную отдельным workflow.

Участие

Перед pull request прочитайте CONTRIBUTING.md и CODE_OF_CONDUCT.md. Уязвимости нельзя публиковать в обычных issues — используйте SECURITY.md.

Проект распространяется по лицензии MIT.