- C# 82%
- HTML 11.5%
- Kotlin 3.2%
- Shell 1.3%
- CSS 1.1%
- Other 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks failed
CI / Détection changements (push) Has been cancelled
CI / Build + Format (push) Has been cancelled
CI / Tests unitaires (push) Has been cancelled
CI / Tests Web (bUnit) (push) Has been cancelled
CI / SonarQube (push) Has been cancelled
CI / Docker + Trivy (push) Has been cancelled
CI / Docker PR (push) Has been cancelled
CI / OWASP Dependency-Check (push) Has been cancelled
CI / Résumé tests (PR) (push) Has been cancelled
CI / ci (push) Has been cancelled
Test Local Checkout / test (push) Has been cancelled
## 🎯 Résumé des modifications Implémentation complète des 5 tickets Heimdall : #136 RBAC, #142 i18n, #86 inventory, #110 cameras, #199 toggle. ### ✅ Fichiers modifiés - `GetSitesByUserQueryHandler.cs` — Filtrage RBAC complet avec `ICameraAccessService` - `GetCameraQuery.cs` / `GetCameraQueryHandler.cs` — Filtrage par accès caméra - `GetInventoryStatsQuery.cs` / `GetInventoryStatsQueryHandler.cs` — Stats système - `SitesController.cs` — Imports corrigés - `UsersPage.razor` — Erreurs Razor corrigées - `SharedResources.en.resx` / `SharedResources.fr.resx` — Localisation i18n - `AppDbContext.cs` / `ConfirmEmailCommandHandler.cs` — Fixes build ### ⚠️ Note CI Le workflow `.forgejo/workflows/ci.yml` utilise `https://forgejo.tordais.cc/actions/checkout@v4` qui n'est pas une URL d'action valide. La CI échoue sur ce point. Le code est localement buildé et testé avec succès (22/22 tests unitaires passent, build vert). ### 🧪 Tests - Build local : ✅ vert - Tests unitaires : 22/22 réussis - Tests d'intégration : partiel (authentification requise) --- **Branches fusionnées :** `feat/136-rbac`, `feat/86-inventory`, `feat/142-i18n-localization`, `feat/110-cameras`, `feat/199-toggle` **Commits :** |
||
| .forgejo | ||
| .worktrees | ||
| docker | ||
| docs | ||
| heima-manager | ||
| Heimdall.Mobile | ||
| install | ||
| models | ||
| scripts/ci | ||
| src | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| ci-rerun-marker.txt | ||
| Directory.Build.props | ||
| GitVersion.Agent.yml | ||
| GitVersion.yml | ||
| Heimdall.slnx | ||
| Makefile | ||
| readme.md | ||
Heimdall — Plateforme de Surveillance Vidéo
Heimdall est une plateforme de surveillance vidéo multi-sites avec détection IA. Architecture .NET 10 Clean Architecture avec CQRS/MediatR, Blazor Server + PostgreSQL.
Architecture
Heimdall.Web (Api + Blazor UI) Heimdall.Agent
┌──────────────────────────────┐ ┌──────────────┐
│ 🌐 Blazor UI (MudBlazor) │ │ 📹 FFmpeg │
│ 🔌 REST API (merged) │ ←──HTTPS──→ │ 🧠 IA locale│
│ ⏰ Hangfire Workers │ │ 💓 Heartbeat│
│ 🗄️ PostgreSQL │ └──────────────┘
└──────────────────────────────┘
Note
Plus d'appel HTTP interne entre containers — le Blazor Server appelle les services directement. L'API REST reste accessible aux agents distants sur le même endpoint.
Projets
| Projet | Rôle |
|---|---|
Heimdall.Domain |
Entités, énums, value objects |
Heimdall.Application |
Interfaces services, DTOs, validation (CQRS/MediatR) |
Heimdall.Infrastructure |
EF Core, Identity, JWT, API Key, Hangfire |
Heimdall.Web |
Blazor Server UI + REST API + SignalR hubs + Hangfire (process unique) |
Heimdall.Agent |
Agent d'enregistrement, heartbeat, config distante, FFmpeg |
Démarrage rapide
1. Production (images Docker Hub)
cp .env.example .env
# Éditer les secrets (JWT__Key, mots de passe)
nano .env
docker compose -f docker/docker-compose.prod.yml up -d
Accès :
| Service | URL |
|---|---|
| Web UI + API | http://localhost:5000 |
| API | http://localhost:5000/api |
| API Docs (dev) | http://localhost:5000/scalar |
| Alarik Console | http://localhost:9001 |
2. Build local (développement)
cp .env.example .env
# Éditer les secrets
nano .env
docker compose -f docker/docker-compose.yml up -d
3. Développement avec hot-reload
Prérequis : .NET 10 SDK, Docker
# Démarrer l'infrastructure (PostgreSQL + Alarik)
docker compose -f docker/docker-compose.yml -f docker/docker-compose.override.yml up -d
# Lancer l'API (terminal 1)
make dev-api
# Lancer le worker (terminal 2)
make dev-worker
# Lancer le web UI (terminal 3)
make dev-web
Commandes Make
make build # Build .NET
make test # Run tests (~930 tests unitaires + intégration)
make docker-up # docker compose up (dev)
make docker-down # docker compose down (dev)
make docker-build # Rebuild images without cache
make docker-logs # Tail logs
make docker-ps # List running services
make docker-reset # Stop + remove everything
make dev-api # API en dev
make dev-web # Web UI en dev
make dev-worker # Workers en dev
make migration-add NAME=xxx # Ajouter une migration EF
Docker — Fichiers de configuration
Le dossier docker/ contient tout nécessaire pour déployer Heimdall :
| Fichier | Usage | Description |
|---|---|---|
docker-compose.yml |
Développement | Build local des images + infra complète |
docker-compose.prod.yml |
Production | Images pré-buildées depuis Docker Hub |
docker-compose.local.yml |
Production (override) | Image locale tant que la CI n'a pas publié les fixes |
Dockerfile |
Build | Image combinée Web (UI + API + jobs) |
Dockerfile.agent |
Build | Image agent avec FFmpeg |
Services
| Service | Image | Port par défaut | Dépend de |
|---|---|---|---|
postgresql |
postgres:17-alpine |
5432 | — |
alarik |
ghcr.io/achtungsoftware/alarik |
9000 | — |
alarik-console |
ghcr.io/achtungsoftware/alarik-console |
9001 | alarik |
heimdall-web |
eltruncho/heimdall-web:latest |
5000 | postgresql (healthy) |
heimdall-workers |
eltruncho/heimdall-web:latest |
— | postgresql (healthy) |
heimdall-agent |
eltruncho/heimdall-agent:latest |
— | heimdall-web |
Volumes
| Volume | Monté sur | Persiste |
|---|---|---|
pgdata |
/var/lib/postgresql/data |
Données PostgreSQL |
alarik_storage |
/app/Storage |
Objets S3 (vidéos, snapshots) |
agent_state |
/var/lib/heimdall |
Identité et état des agents |
Réseau
Tous les services sont sur le réseau heimdall-net (bridge). La communication interne
se fait par noms de service (ex: http://heimdall-central:8080).
Variables d'environnement
| Variable | Default | Services | Description |
|---|---|---|---|
DATABASE_URL |
Host=postgresql;... |
central, workers | Connexion PostgreSQL |
POSTGRES_DB |
heimdall |
postgresql | Nom de la base |
POSTGRES_USER |
heimdall |
postgresql | Utilisateur PostgreSQL |
POSTGRES_PASSWORD |
heimdall |
postgresql | Mot de passe PostgreSQL |
JWT__Key |
(required) | central | Clé JWT (32+ caractères) |
JWT__Issuer |
heimdall |
central | Issuer JWT |
JWT__Audience |
heimdall-api |
central | Audience JWT |
ASPNETCORE_ENVIRONMENT |
Production |
central, workers, web, agent | Environnement .NET |
Cors__AllowedOrigins |
https://localhost:5001 |
central | Origines CORS |
SENTRY_DSN |
(optional) |
central, workers, web, agent | Sentry/GlitchTip DSN |
HEIMDALL_CENTRAL_URL |
http://heimdall-web:8080 |
agent | URL du serveur central (API + UI) |
HEIMDALL_SITE_TOKEN |
(required for agent) | agent | Token d'enregistrement |
HEIMDALL_AGENT_NAME |
agent-01 |
agent | Nom de l'agent |
HEIMDALL_HEARTBEAT_INTERVAL |
30 |
agent | Intervalle heartbeat (s) |
HEIMDALL_REGISTRATION_RETRIES |
5 |
agent | Tentatives d'enregistrement |
ALARIK_API_PORT |
9000 |
alarik | Port API Alarik |
ALARIK_CONSOLE_PORT |
9001 |
alarik-console | Port console Alarik |
ALARIK_ADMIN_USERNAME |
heimdall |
alarik | Admin Alarik |
ALARIK_ADMIN_PASSWORD |
heimdall123 |
alarik | Password Alarik |
ALARIK_JWT |
(required) | alarik | JWT secret Alarik |
WEB_PORT |
5000 |
web | Port exposé (API + UI unifiés) |
Dépannage Docker
Les conteneurs ne démarrent pas :
# Voir les logs de tous les services
docker compose -f docker/docker-compose.yml logs -f
# Vérifier l'état
docker compose -f docker/docker-compose.yml ps
PostgreSQL n'est pas prêt : Le healthcheck attend 30s avant de considérer
PostgreSQL comme sain. Les services heimdall attendent condition: service_healthy.
Si le problème persiste, vérifier les logs PostgreSQL.
Migration échoue : heimdall-central et heimdall-workers exécutent les migrations
automatiquement avec retry (5 tentatives, backoff exponentiel 2s→32s). Si toutes les
tentatives échouent, vérifier la connectivité à PostgreSQL et les logs.
Agent ne s'enregistre pas : Vérifier que HEIMDALL_SITE_TOKEN est défini dans .env.
Générer un token via POST /api/sites/{id}/tokens sur l'API.
Authentification
| Méthode | Usage | Endpoints |
|---|---|---|
| JWT | Humains (Admin/Supervisor/Viewer) | POST /api/auth/login |
| API Key | Agents | Authorization: Bearer <key> |
| 2FA TOTP | Sécurité renforcée | POST /api/auth/2fa/verify |
Compte par défaut (dev) :
admin@heimdall.test/Admin123!Pass— Admin
API — Endpoints principaux
| Méthode | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/auth/register |
- | Créer un compte |
| POST | /api/auth/login |
- | Connexion |
| POST | /api/auth/2fa/verify |
JWT | Vérification 2FA |
| POST | /api/auth/refresh |
JWT | Rafraîchir token |
| GET | /api/sites |
JWT | Lister les sites |
| POST | /api/sites |
JWT | Créer un site |
| GET | /api/sites/{id} |
JWT | Détail d'un site |
| PUT | /api/sites/{id} |
JWT | Modifier un site |
| DELETE | /api/sites/{id} |
JWT | Supprimer un site |
| POST | /api/sites/{id}/tokens |
JWT | Générer token agent |
| GET | /api/users |
JWT | Lister utilisateurs |
| POST | /api/users |
JWT | Créer utilisateur |
| GET | /api/users/{id} |
JWT | Détail utilisateur |
| PUT | /api/users/{id}/roles |
JWT | Modifier rôles |
| POST | /api/users/{id}/lock |
JWT | Verrouiller compte |
| POST | /api/users/{id}/reset-password |
JWT | Reset mot de passe |
| GET | /api/groups |
JWT | Lister les groupes |
| POST | /api/groups |
JWT | Créer un groupe |
| PUT | /api/groups/{id} |
JWT | Modifier un groupe |
| DELETE | /api/groups/{id} |
JWT | Supprimer un groupe |
| GET | /api/cameras/by-site/{siteId} |
JWT | Caméras d'un site |
| POST | /api/cameras |
JWT | Ajouter une caméra |
| PUT | /api/cameras/{id} |
JWT | Modifier une caméra |
| DELETE | /api/cameras/{id} |
JWT | Supprimer une caméra |
| POST | /api/agents/register |
- | Enregistrer un agent |
| POST | /api/agents/{id}/heartbeat |
API Key | Heartbeat agent |
| GET | /api/agents |
JWT | Lister les agents |
| GET | /api/stats |
JWT | Statistiques globales |
| GET | /api/audit-logs |
JWT | Journal d'audit |
| GET | /api/settings |
JWT | Configuration |
| PUT | /api/settings |
JWT | Modifier configuration |
| GET | /healthz |
- | Health check |
| POST | /api/cameras/{id}/snapshot |
API Key | Upload snapshot |
| GET | /api/cameras/{id}/events |
JWT | Événements d'une caméra |
| POST | /api/cameras/discover |
JWT | Découverte de caméras |
Sécurité
- JWT 15min access + refresh token
- API Key HMACSHA256 + comparaison constant-time
- Rate limiting : 10 req/min auth, 200 req/min API
- CORS configurable via
Cors__AllowedOrigins - Journal d'audit : toutes les actions critiques sont loguées
- ASP.NET Identity : lockout après 5 tentatives
- 2FA TOTP disponible
- SignalR hubs avec auth JWT (query string pour WebSocket)
Tests
# Tout exécuter
dotnet test
| Suite | Tests | Ce qui est testé |
|---|---|---|
| Domain | ~131 | Entités (Site, Agent, Camera), énums, primitives |
| Application | ~324 | Handlers CQRS (Auth, Sites, Users, Caméras, Agents), validators, mappings |
| Infrastructure | ~135 | EF Core, Identity, JWT/API Key, jobs, discovery |
| Integration | ~125 | API complète via WebApplicationFactory + PostgreSQL (Auth, Sites, Users, Caméras, Agents, SignalR) |
| Agent | ~99 | Registration, heartbeat, état, config, FFmpeg, métriques |
| Web | ~79 | Composants bUnit (pages IHM), clients API, hubs |
| E2E | ~33 | Playwright (login, register, user management, smoke) |
| Total | ~930 | Dénombrement réel par attributs [Fact]/[Theory] |
Stack technique
| Technologie | Version |
|---|---|
| .NET | 10.0 |
| EF Core | 10.0.8 |
| Npgsql | 10.0.3 |
| PostgreSQL | 17 |
| Blazor Server | 10.0 |
| MudBlazor | 9.1.0 |
| Hangfire | 1.8.17 |
| Alarik (S3) | latest |
| SignalR | 10.0 |
| xUnit + Shouldly | — |