Sefrone.Api.Alerts 3.5.3
Sefrone.Api.Alerts
Persisted alerts (notifications) that application code publishes and accounts read, acknowledge and dismiss through the API.
An alert is stored once and has an audience:
| Audience | Shown to |
|---|---|
Project |
every account of the project |
Workspace |
every account linked to that workspace |
Account |
a single account, optionally tied to one of its workspaces |
Project and workspace alerts are shown to accounts that join later too, until the alert expires. Reading and dismissing are tracked per account, so one account dismissing a project wide alert does not affect the others.
Setup
Your BaseApiAuthConfigurator must implement ISupportAlertsConfigurator and your permissions class must implement IHasAlertsPermissions.
services.AddApiAlerts<ApiAuthConfigurator, ApiPermissions>();
services.AddApiAlertsJobs(); // optional, background jobs, see Cleanup
app.UseApiAlerts(); // applies the database migrations, pass skipMigrationCheck: true to skip
Publishing alerts
Inject IApiAlertsService anywhere in your application (controllers, jobs, other packages' configurators):
var content = new AlertContent {
Severity = ApiAlertSeverity.Warning,
Category = "maintenance", // free-form key you can use to group or route alerts
Title = "Planned maintenance",
Message = "The service is unavailable on Sunday from 02:00 to 03:00.",
Payload = "{\"from\":\"02:00\"}", // optional, must be valid JSON
ExpiresAt = DateTime.UtcNow.AddDays(7), // optional, defaults to 90 days
};
await alertsService.PublishToProjectAsync(projectId, content);
await alertsService.PublishToWorkspaceAsync(projectId, workspaceId, content);
await alertsService.PublishToAccountAsync(projectId, accountId, content);
Each call stores a single alert and commits on its own, so it works from background jobs and from controllers that do not use the alerts unit of work. It is not part of the caller's transaction. Every alert expires: without an explicit ExpiresAt it lasts 90 days.
RetractAlertAsync(alertId) stops showing an alert to everyone it was addressed to.
The workspace and project ids are not checked against the auth database, publishing to a workspace that does not belong to the project simply reaches nobody.
Cleanup
Expired alerts are hidden right away but kept for 7 days, then a background job deletes them together with what the accounts did with them. The job runs when the application starts and then every hour. It is not registered by AddApiAlerts, add it after it on the hosts that should run background jobs:
services.AddApiAlerts<ApiAuthConfigurator, ApiPermissions>();
services.AddApiAlertsJobs();
Without the job, call IApiAlertsService.PurgeExpiredAlertsAsync() from your own scheduler, it deletes the same alerts and returns how many.
Endpoints
All endpoints require the Alerts permission and only ever act on the caller's own alerts in the caller's project.
| Method | Route | Description |
|---|---|---|
| GET | list |
Lists alerts, newest first. Query: workspaceId, unreadOnly, severity, begin, count |
| GET | unreadCount |
Number of unread alerts. Query: workspaceId |
| PATCH | markRead |
Marks one alert as read. Query: alertId |
| PATCH | markAllRead |
Marks every visible alert as read. Query: workspaceId |
| DELETE | dismiss |
Dismisses one alert for the caller, it no longer appears in list. Query: alertId |
The caller sees project alerts, alerts of every workspace they are linked to and alerts addressed to them. The workspaces come from the caller's token.
The optional workspaceId narrows this to project alerts, account alerts without a workspace and the alerts of that workspace. It must be a workspace the caller is linked to, otherwise the request is forbidden.
Dismissed and expired alerts are hidden from every endpoint but their rows are kept in the database. Read and dismissed times are stored in AlertState, which only has a row for an account once it acted on an alert.
No packages depend on Sefrone.Api.Alerts.
.NET 8.0
- Sefrone.Api.Auth.Identity (>= 3.5.3)
- Sefrone.Api.Core (>= 3.5.3)
- Sefrone.Api.Data (>= 3.5.3)
- Sefrone.Core.Mapper (>= 3.5.3)
- Dapper (>= 2.1.79)
- Dapper.Transaction (>= 2.1.35)
- Swashbuckle.AspNetCore.Annotations (>= 9.0.6)