Logica do SistemaSecao 5
Notificacoes
NotificationManager
Arquivo: cargo_fleet.Domain/Notifications/NotificationManager.cs
Metodo CreateAsync(title, message, emitterId):
- Cria e persiste diretamente no banco (
InsertAsynccomautoSave: true). - Usa
[UnitOfWork]attribute para garantir transacao. - Usa
CurrentTenant.Iddo contexto para definir oTenantId.
NotificationAppService
Arquivo: cargo_fleet.Application/Notifications/NotificationAppService.cs
GetListAsync: lista notificacoes do tenant atual, ordenado porCreationTime DESC. Aceitainput.Sortingvia Dynamic LINQ sem whitelist (SEC2-03).GetUnreadCountAsync: conta nao lidas do tenant atual.MarkAllAsReadAsync: carrega todas nao lidas, marca, salva em batch viaUpdateManyAsync.DeleteAsync: deleta por ID sem verificar se pertence ao tenant atual (P-14 — IDOR potencial).
Classe herda de ApplicationService (sem autorizacao base — SEC2-08).
Filtra manualmente por .Where(n => n.TenantId == CurrentTenant.Id) em vez de usar o filtro automatico ABP.
FirebaseNotificationDispatcher
Arquivo: cargo_fleet.Application/Notifications/FirebaseNotificationDispatcher.cs
DispatchAsync(notification)→FirebaseMessagingAppService.SendNotificationToTenantAsync(title, body).DispatchManyAsync(notifications)→ loop sobreDispatchAsync(sequencial, nao em batch).
FirebaseMessagingAppService
Arquivo: cargo_fleet.Application/Messaging/FirebaseMessagingAppService.cs
Fluxo SendNotificationToTenantAsync:
- Carrega todos os
DeviceTokendoTenantIdatual. - Se nao ha tokens: log warning, retorna.
- Monta
MulticastMessagecom todos os tokens. - Chama
FirebaseMessaging.DefaultInstance.SendEachForMulticastAsync(message). - Para cada falha: se erro
UnregisteredouInvalidArgument→ marca token para remocao. - Deleta tokens invalidos em batch via
DeleteManyAsync.
Incoerencias Identificadas
| ID | Descricao |
|---|---|
| P-14 | DeleteAsync sem verificacao de ownership de tenant |
| SEC2-08 | NotificationAppService sem [Authorize], filtro manual de TenantId |
| MED-05 | Notificacoes enviadas para todos os dispositivos do tenant, nao por usuario especifico |
| (escalabilidade) | DispatchManyAsync sequencial — sem batching eficiente |
Entidade Notification
Arquivo:
cargo_fleet.Domain/Notifications/Notification.csTenantIdGuid?TitlestringMessagestringEmitterIdstringIsReadboolMetodo
MarkAsRead(): setaIsRead = truese ainda nao marcado (idempotente).