Backend: Services and API¶
OpenAPI and API Tools¶
The OpenAPI specification is the contract between the backend and clients and is generated directly from Go annotations. A test compares the spec against the registered routes to detect drift early on.
- Specification:
app/backend/api/swagger.yaml(JSON:app/backend/api/swagger.json) - Swagger UI: https://api.sysdf-rooms.f4.htw-berlin.de/swagger/index.html (local:
http://localhost:8081/swagger/index.html) - Generation of specs:
swag init -g cmd/rooms/main.go -o api - Swagger host is set at runtime from
swagger_hostorserver_host/server_port. - Bruno collection for API calls:
app/backend/api/bruno - Test for specification consistency:
app/backend/internal/api/v1/router/router_openapi_test.go
Authentication and Authorization¶
Authentication is based on JWTs issued during login. Authorization is performed via permissions that are loaded into the context during the request and used by the middleware and controllers.
Login/Token¶
When logging in, a JWT is generated that contains the user as uuid and sub. This token must be sent with every protected API request and is both signed and checked for blacklist entries. Token validity can be configured via environment variables (jwt_valid_duration_in_h and refresh_token_valid_duration_in_days).
POST /v1/session/loginreturns JWT (ES256).- Token is sent as
Authorization: Bearer <token>. - Alternatively,
tokenas a query parameter (e.g., for EventSource connections which do not support custom headers).
Logout/Blacklist¶
Logout stores the token in Redis so that it is immediately invalidated without having to wait for token expiration. The middleware checks this blacklist with every request.
DELETE /v1/session/logoutsaves tokens in Redis.AuthRequiredvalidates JWT signature and checks Redis blacklist.
Permissions¶
Permissions are loaded from the roles of the logged-in user. The middleware sets context flags that controllers can use for finer logic (e.g., own data vs. all data). For a complete list of all available permissions, see the Permissions Overview.
PermissionMiddlewareWithoutBypass: blocks requests without permission.PermissionMiddlewareWithBypass: stores flags (hasPermission_*) in the context, but does not block.- Controllers use flags for “self vs. all” logic (e.g., tasks/events).
Services and Endpoints (API /v1)¶
The API is divided into logically separate services. Each service encapsulates a specific area, with permissions enforced in the router layer and controllers triggering DB operations.
User¶
The user service covers self-service, admin management, and verification. When creating a user, a verification token is stored and an email is sent.
GET /user/me,PATCH /user/me,DELETE /user/mePOST /user(create user, email verification),GET /user,GET /user/:uuidPATCH /user/:uuid,DELETE /user/:uuid- User roles:
POST /user/roles,PATCH /user/roles,DELETE /user/roles - Email verification:
GET /user/verify?token=... - Password check:
POST /user/me/validate-password
Role/Permission¶
Roles can be created, customized, and deleted, provided that the caller passes the hierarchy and permission checks. Permissions are read-only and are managed centrally.
- Roles:
GET /roles,POST /roles,GET /roles/:uuid,PATCH /roles/:uuid,DELETE /roles/:uuid - Role permissions:
PATCH /roles/:uuid/permissions,DELETE /roles/:uuid/permissions - Permissions read-only:
GET /permissions,GET /permissions/:uuid
Session¶
Sessions are JWT-based and do not include a server-side session database. Logout is therefore an explicit Redis blacklisting step.
POST /session/loginDELETE /session/logout
Room¶
Rooms are the center of planning. The room preview renders the current display using the Python renderer without generating new QR codes.
GET /rooms,POST /rooms,GET /rooms/:uuid,PUT /rooms/:uuid,DELETE /rooms/:uuidGET /rooms/:uuid/preview(Renderer Preview)POST /rooms/:uuid/clean(RoomStatus)GET /rooms/:uuid/users,POST /rooms/:uuid/users,DELETE /rooms/:uuid/users/:user_uuidGET /rooms/:uuid/checkin,GET /rooms/:uuid/qr-codes
Display¶
Displays register with their MAC address and API key. The content endpoint only delivers new data if the rendered hash has changed.
GET /displays,POST /displays,GET /displays/:uuid,PUT /displays/:uuid,DELETE /displays/:uuidGET /displays/room/:room_uuidGET /displays/:uuid/previewGET /displays/:uuid/content(with headerX-Mac-Address,X-API-Key)GET /displays/handshake/:mac(hardware sync)
Schedule (Tasks/Events/Calendar)¶
The Schedule module manages tasks/events and types and provides a combined calendar view for the dashboard. Optionally, check-in histories can be included in the task responses.
- Tasks:
GET /tasks,POST /tasks,GET /tasks/:uuid,PUT /tasks/:uuid,DELETE /tasks/:uuid - Task Types:
GET /task-types,POST /task-types,PATCH /task-types/:uuid,DELETE /task-types/:uuid - Events:
GET /events,POST /events,GET /events/:uuid,PUT /events/:uuid,DELETE /events/:uuid - Event Types:
GET /event-types,POST /event-types,PATCH /event-types/:uuid,DELETE /event-types/:uuid - Calendar:
GET /calendar,GET /calendar/events,GET /calendar/tasks
CheckIn¶
CheckIns are the interface for QR-based actions. They validate QR codes against their validity window and connect the action to the executing user.
POST /checkin(via QR code or task)GET /checkin,GET /checkin/:uuid,DELETE /checkin/:uuidGET /checkin/meGET /tasks/:uuid/checkinandGET /rooms/:uuid/checkin
QR codes¶
QR codes always belong to a Room (required) and optionally to a Task. They can be generated explicitly via the API or implicitly via the renderer. When a check-in is performed, the QR code is referenced by the CheckIn record. Expired, unused codes are cleaned up by a scheduler.
GET /qr-codes,GET /qr-codes/activePOST /qr-codes,GET /qr-codes/:uuid,PUT /qr-codes/:uuid,DELETE /qr-codes/:uuid- Room/Task views:
GET /rooms/:uuid/qr-codes,GET /tasks/:uuid/qr-codes
Health¶
Health is a simple liveness endpoint used by monitoring or load balancers.
GET /health
Renderer Flow (Display Content)¶
Display content generation is deliberately idempotent and cache-friendly. A hash prevents unnecessary payloads and reduces the load on the renderer.
- Display requests
/displays/:uuid/content(MAC + API key in header). - Backend validates and renders via Python.
- Hash is calculated and stored in
Display.LastRenderHash. - If hash is unchanged and no
force_refresh, 304 is delivered. - Preview endpoints render without new QR codes (read-only).
Validation and error handling¶
Validation is implemented centrally via middleware and reduces duplicate code in controllers. Errors are returned in a structured manner so that frontend clients can display field errors specifically.
ValidateJSON,ValidateURI,ValidateQuerybind and validate requests.- Errors are bundled as an
errorsarray (HTTP 400). - Controllers return specific status codes (404, 409, 403).