You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

58 lines
2.1 KiB

import PromiseRouter from "express-promise-router";
import ApiError from "@common/ApiError";
import { ErrorCode } from "@common/ErrorCode";
import { DEVICE_PREFIX } from "@common/sprinklersRpc/mqtt";
import { DeviceToken, SuperuserToken } from "@common/TokenClaims";
import { verifyToken } from "@server/authentication";
import { ServerState } from "@server/state";
export const SUPERUSER = "sprinklers3";
export function mosquitto(state: ServerState) {
const router = PromiseRouter();
router.post("/auth", async (req, res) => {
const body = req.body;
const { username, password, topic, acc } = body;
if (typeof username !== "string" || typeof password !== "string") {
throw new ApiError("Must specify a username and password", ErrorCode.BadRequest);
}
if (username === SUPERUSER) {
await verifyToken<SuperuserToken>(password, "superuser");
return res.status(200).send({ username });
}
const claims = await verifyToken<DeviceToken>(password, "device");
if (claims.aud !== username) {
throw new ApiError("Username does not match token", ErrorCode.BadRequest);
}
res.status(200).send({
username, id: claims.id,
});
});
router.post("/superuser", async (req, res) => {
const { username } = req.body;
if (typeof username !== "string") {
throw new ApiError("Must specify a username", ErrorCode.BadRequest);
}
if (username !== SUPERUSER) {
return res.status(403).send();
}
res.status(200).send();
});
router.post("/acl", async (req, res) => {
const { username, topic, clientid, acc } = req.body;
if (typeof username !== "string" || typeof topic !== "string") {
throw new ApiError("username and topic must be specified as strings", ErrorCode.BadRequest);
}
const prefix = DEVICE_PREFIX + "/" + username;
if (!topic.startsWith(prefix)) {
throw new ApiError(`device ${username} cannot access topic ${topic}`);
}
res.status(200).send();
});
return router;
}