Arkitektur och teknisk plattform¶
Systemarkitektur¶
Översiktsbild över hur systemets komponenter kommunicerar och var de driftas.
flowchart TD
Users([Användare]) -->|Webbläsare| SWA
subgraph Azure["Azure — swedencentral"]
direction TB
SWA["Azure Static Web App<br/>salieri.se<br/>Blazor WebAssembly SPA"]
DocsUG["Azure Static Web App<br/>anvandarhandledning.salieri.se<br/>Användarhandledning"]
DocsTR["Azure Static Web App<br/>tekniskdokumentation.salieri.se<br/>Teknisk dokumentation"]
SWA -->|HTTPS / REST / JSON| API
API["Azure Container App<br/>api.salieri.se<br/>ASP.NET Core Web API"]
API -.->|WebSocket<br/>BookingChanged| SWA
API -->|TCP 1433| SQL
API -->|REST| ACS
ACS["Azure Communication Services<br/>E-post<br/>(no-reply@smtp.salieri.se)"]
SQL[("Azure SQL Serverless<br/>SalieriDb<br/>(GP_S_Gen5, 8 h auto-paus)")]
end
Driftsmiljöer¶
| Resurs | Produktion | Lokal utveckling |
|---|---|---|
| Klient | Azure Static Web App (salieri.se) |
dotnet run (port 5299) |
| API | Azure Container App (api.salieri.se) |
dotnet run (port 5183) |
| Databas | Azure SQL Serverless | Docker — SQL Server 2022 (port 1433) |
| Realtid | SignalR (in-process) | SignalR (in-process) |
| CI/CD | GitHub Actions | — |
Teknisk plattform¶
Internt bygge av backend- och frontend-lagren.
Backend — ASP.NET Core Web API¶
flowchart TD
Client([Blazor WASM-klient]) -->|"HTTPS / JSON"| Pipeline
subgraph Pipeline["ASP.NET Core-pipeline"]
direction LR
Cors[CORS] --> Auth[Authentication<br/>JWT Bearer] --> AuthZ[Authorization] --> Routing[Routing]
end
Routing --> Controllers
subgraph Controllers["Kontroller"]
direction TB
AccountCtrl["Account<br/>Auth + användarhantering"]
BookingsCtrl["Bookings<br/>Boknings-CRUD"]
ResourceCtrl["Buildings · Floors<br/>Rooms · Locations<br/>Lookups · UserRoles"]
DataCtrl["Data<br/>Import / Export"]
end
Controllers --> DbContext
subgraph Data["Datalager"]
direction TB
DbContext["ApplicationDbContext<br/>(IdentityDbContext<br/><ApplicationUser>)"]
DbContext --> EF["EF Core ORM"]
EF --> Entities["Entiteter<br/>Location → Building<br/> → Floor → Room<br/>Booking<br/>UserRole<br/>Lookup-entiteter"]
EF --> Migrations["Migreringar"]
end
Controllers --> Services
subgraph Services["Tjänster"]
direction TB
TokenService["TokenService<br/>JWT-utstedning<br/>(HMAC-SHA256, 8 h)"]
Startup["DbInitializer → AdminSeeder<br/>Migreringar + bootstrap-admin"]
Email["IEmailSender<br/>AzureEmail / Smtp / File / Noop"]
end
Controllers --> Hub
subgraph SignalR["Realtid"]
Hub["NotificationHub<br/>/hubs/notifications<br/>BookingChanged vid boknings-CRUD"]
end
Frontend — Blazor WebAssembly¶
flowchart TD
Browser([Webbläsare]) --> App
subgraph App["Blazor WASM SPA"]
direction TB
subgraph Pages["Sidor"]
direction TB
Home["Home — Kalendervy<br/>Dag · Vecka<br/>Månad · Lista (stub)"]
Admin["Admin — Administrationsvyer<br/>Locations · Buildings<br/>Floors · Rooms<br/>Users · Lookups"]
end
subgraph Components["Komponenter"]
direction TB
CalViews["DayView · WeekView<br/>MonthView · ListView<br/>BookingBlock · DetailsPane"]
Dialogs["BookingForm · LoginDialog<br/>ChangePasswordDialog<br/>ConfirmDialog<br/>ImportExportDialog<br/>RecurringChoiceDialog"]
Nav["NavigationHeader<br/>CommandBar<br/>ToastContainer"]
end
subgraph ClientServices["Tjänster"]
direction TB
ApiClient["ApiClient<br/>Typad HTTP-klient"]
AppState["AppState<br/>Central state store"]
AuthService["AuthService<br/>JWT + localStorage"]
SignalRClient["SignalRService<br/>Prenumeration på BookingChanged"]
UiSupport["ThemeService<br/>NotificationService<br/>JsInteropService<br/>DateUtils"]
end
Pages --> Components
Components --> ClientServices
end
ClientServices -->|"HTTP / REST / JSON"| API([ASP.NET Core API])
ClientServices -->|"WebSocket (SignalR)"| Hub([SignalR Hub])
Autentiseringsflöde¶
sequenceDiagram
actor User as Användare
participant Client as Blazor WASM
participant API as ASP.NET Core API
participant DB as Azure SQL
User->>Client: Logga in (e-post + lösenord)
Client->>API: POST /api/account/login
API->>DB: UserManager — lösenordsvalidering
DB-->>API: OK
API->>API: Generera JWT (HMAC-SHA256, 8 h, role-claims)
API-->>Client: { token, userProfile }
Client->>Client: Spara i localStorage (nyckel salieri-auth)
alt Nytt konto
User->>Client: Skapa konto (e-post + minst en användarroll)
Client->>API: POST /api/account/register
API-->>Client: 201 (väntar på godkännande)
User->>Client: Hanterare godkänner kontot
Client->>API: POST /api/account/users/{id}/approve
API-->>Client: OK
end
loop Varje API-anrop
Client->>API: Authorization: Bearer {token}
API->>API: Validera JWT + claims (ev. policy ManageUsers/ManageData/ManageSystem)
end
User->>Client: Skapa bokning
Client->>API: POST /api/bookings
API->>API: [Authorize] — giltig JWT krävs
API->>DB: EF Core — spara bokning
API-->>Client: 201 Created
Note over API,Client: Efter sparad bokning sänder API:t BookingChanged via<br/>SignalR-hubben /hubs/notifications — övriga klienter hämtar då om synligt intervall.
E-post och import/export¶
- E-post —
IEmailSendermed leverantörernaAzureEmail(produktion, Azure Communication Services frånno-reply@smtp.salieri.se),Smtp(lokal smtp4dev),File(.eml-filer) ochNoop(CI). Används för tillfälliga lösenord samt notiser vid registrering, godkännande och avslag. E-postfel stoppar aldrig kontooperationen. - Import/export —
DataController(/api/data/export?includeBookings,/api/data/import?clear&includeBookings, policyManageData). Import valideras mot JSON-schemat (schemas/salieri-export.schema.json, även viaGET /api/data/schema) och främmande nycklar, körs i transaktion med UPSERT (IDENTITY_INSERT) i beroendeföljd. - Listning —
GET /api/bookingsstödjer filtrering (from,to,roomId,contact,buildingId) och sidindelning (page,pageSize, svarshuvudenX-Total-Count/X-Page/X-Page-Size).
Teknisk plattform — sammanfattning¶
| Lager | Komponent | Teknologi |
|---|---|---|
| Presentation | SPA-klient | Blazor WebAssembly (.NET 10) |
| Presentation | Dokumentation | Zensical (statiska webbsidor) |
| API | Webbutvecklingsserver | ASP.NET Core Web API (.NET 10) |
| API | Autentisering | ASP.NET Core Identity + JWT Bearer |
| API | Realtid | SignalR (in-process, BookingChanged vid boknings-CRUD) |
| API | E-post | Azure Communication Services via IEmailSender |
| API | Import/export | JSON-schema + transaktionell UPSERT |
| Data | ORM | Entity Framework Core 10 |
| Data | Databas | SQL Server 2022 (Azure SQL Serverless) |
| Infra | Container | Docker (lokal) / Azure Container App (produktion) |
| Infra | Frontend-hosting | Azure Static Web Apps |
| Infra | DNS | Azure DNS (salieri.se) |
| Infra | CI/CD | GitHub Actions |