Sesame-Server/Sources/App/routes.swift
2023-09-07 14:05:41 +02:00

82 lines
3.1 KiB
Swift
Executable File

import Vapor
extension RouteAPI {
var path: PathComponent {
.init(stringLiteral: rawValue)
}
var pathParameter: PathComponent {
.parameter(rawValue)
}
}
private func messageTransmission(_ req: Request) -> EventLoopFuture<Data> {
guard let body = req.body.data else {
return req.eventLoop.makeSucceededFuture(MessageResult.noBodyData.encoded)
}
guard let message = ServerMessage(decodeFrom: body) else {
return req.eventLoop.makeSucceededFuture(MessageResult.invalidMessageSize.encoded)
}
guard deviceManager.authenticateRemote(message.authToken) else {
return req.eventLoop.makeSucceededFuture(MessageResult.messageAuthenticationFailed.encoded)
}
return deviceManager.sendMessageToDevice(message.message, on: req.eventLoop)
}
private func deviceStatus(_ req: Request) -> EventLoopFuture<MessageResult> {
guard let body = req.body.data else {
return req.eventLoop.makeSucceededFuture(.noBodyData)
}
guard let authToken = ServerMessage.token(from: body) else {
return req.eventLoop.makeSucceededFuture(.invalidMessageSize)
}
guard deviceManager.authenticateRemote(authToken) else {
return req.eventLoop.makeSucceededFuture(.messageAuthenticationFailed)
}
guard deviceManager.deviceIsConnected else {
return req.eventLoop.makeSucceededFuture(.deviceNotConnected)
}
return req.eventLoop.makeSucceededFuture(.deviceConnected)
}
func routes(_ app: Application) throws {
/**
Get the connection status of the device.
The request expects the authentication token of the remote in the body data of the POST request.
The request returns one byte of data, which is the raw value of a `MessageResult`.
Possible results are `noBodyData`, `invalidMessageSize`, `deviceNotConnected`, `deviceConnected`.
*/
app.post(RouteAPI.getDeviceStatus.path) { req in
deviceStatus(req).map {
Response(status: .ok, body: .init(data: $0.encoded))
}
}
/**
Post a message to the device for unlocking.
The expects a `ServerMessage` in the body data of the POST request, containing the valid remote authentication token and the message to send to the device.
The request returns one or `Message.length+1` bytes of data, where the first byte is the raw value of a `MessageResult`,
and the optional following bytes contain the response message of the device. This request does not complete until either the device responds or the request times out. The timeout is specified by `KeyManagement.deviceTimeout`.
*/
app.post(RouteAPI.postMessage.path) { req in
messageTransmission(req).map {
Response(status: .ok, body: .init(data: $0))
}
}
/**
Start a new websocket connection for the device to receive messages from the server
- Returns: Nothing
- Note: The first message from the device over the connection must be a valid auth token.
*/
app.webSocket(RouteAPI.socket.path) { req, socket in
deviceManager.createNewDeviceConnection(socket)
}
}