Alex Mikhalev
7 years ago
11 changed files with 164 additions and 66 deletions
@ -1,52 +0,0 @@ |
|||||||
import PromiseRouter from "express-promise-router"; |
|
||||||
import { serialize} from "serializr"; |
|
||||||
|
|
||||||
import ApiError from "@common/ApiError"; |
|
||||||
import { ErrorCode } from "@common/ErrorCode"; |
|
||||||
import * as schema from "@common/sprinklersRpc/schema"; |
|
||||||
import { ServerState } from "../state"; |
|
||||||
import { authentication, verifyAuthorization } from "./authentication"; |
|
||||||
|
|
||||||
export default function createApi(state: ServerState) { |
|
||||||
const router = PromiseRouter(); |
|
||||||
|
|
||||||
router.get("/devices/:deviceId", verifyAuthorization(), (req, res) => { |
|
||||||
// TODO: authorize device
|
|
||||||
const device = state.mqttClient.getDevice(req.params.deviceId); |
|
||||||
const j = serialize(schema.sprinklersDevice, device); |
|
||||||
res.send(j); |
|
||||||
}); |
|
||||||
|
|
||||||
// router.post("/devices/register", verifyAuthorization({
|
|
||||||
// type: "device_reg",
|
|
||||||
// }), (req, res) => {
|
|
||||||
// res.json({ data: "device registered" });
|
|
||||||
// });
|
|
||||||
|
|
||||||
router.get("/users", verifyAuthorization(), (req, res) => { |
|
||||||
state.database.users.find() |
|
||||||
.then((users) => { |
|
||||||
res.json({ |
|
||||||
data: users, |
|
||||||
}); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
router.get("/api/users/:username", (req, res, next) => { |
|
||||||
const { username } = req.params; |
|
||||||
state.database.users.findByUsername(username) |
|
||||||
.then((user) => { |
|
||||||
if (!user) { |
|
||||||
throw new ApiError(`user ${username} does not exist`, ErrorCode.NotFound); |
|
||||||
} |
|
||||||
res.json({ |
|
||||||
data: user, |
|
||||||
}); |
|
||||||
}) |
|
||||||
.catch(next); |
|
||||||
}); |
|
||||||
|
|
||||||
router.use("/", authentication(state)); |
|
||||||
|
|
||||||
return router; |
|
||||||
} |
|
@ -0,0 +1,35 @@ |
|||||||
|
import PromiseRouter from "express-promise-router"; |
||||||
|
import { serialize} from "serializr"; |
||||||
|
|
||||||
|
import ApiError from "@common/ApiError"; |
||||||
|
import { ErrorCode } from "@common/ErrorCode"; |
||||||
|
import * as schema from "@common/sprinklersRpc/schema"; |
||||||
|
import { AccessOrRefreshToken } from "@common/TokenClaims"; |
||||||
|
import { verifyAuthorization } from "@server/express/authentication"; |
||||||
|
import { ServerState } from "@server/state"; |
||||||
|
|
||||||
|
export function devices(state: ServerState) { |
||||||
|
const router = PromiseRouter(); |
||||||
|
|
||||||
|
router.get("/:deviceId", verifyAuthorization(), async (req, res) => { |
||||||
|
const token = req.token! as AccessOrRefreshToken; |
||||||
|
const userId = token.aud; |
||||||
|
const deviceId = req.params.deviceId; |
||||||
|
const userDevice = await state.database.sprinklersDevices |
||||||
|
.findUserDevice(userId, deviceId); |
||||||
|
if (!userDevice) { |
||||||
|
throw new ApiError("User does not have access to the specified device", ErrorCode.NoPermission); |
||||||
|
} |
||||||
|
const device = state.mqttClient.getDevice(req.params.deviceId); |
||||||
|
const j = serialize(schema.sprinklersDevice, device); |
||||||
|
res.send(j); |
||||||
|
}); |
||||||
|
|
||||||
|
router.post("/register", verifyAuthorization({ |
||||||
|
type: "device_reg", |
||||||
|
}), async (req, res) => { |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
return router; |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
import PromiseRouter from "express-promise-router"; |
||||||
|
|
||||||
|
import ApiError from "@common/ApiError"; |
||||||
|
import { ErrorCode } from "@common/ErrorCode"; |
||||||
|
import { authentication } from "@server/express/authentication"; |
||||||
|
import { ServerState } from "@server/state"; |
||||||
|
import { devices } from "./devices"; |
||||||
|
import { users } from "./users"; |
||||||
|
|
||||||
|
export default function createApi(state: ServerState) { |
||||||
|
const router = PromiseRouter(); |
||||||
|
|
||||||
|
router.use("/devices", devices(state)); |
||||||
|
router.use("/users", users(state)); |
||||||
|
router.use("/token", authentication(state)); |
||||||
|
|
||||||
|
router.use("*", (req, res) => { |
||||||
|
throw new ApiError("API endpoint not found", ErrorCode.NotFound); |
||||||
|
}); |
||||||
|
|
||||||
|
return router; |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
import PromiseRouter from "express-promise-router"; |
||||||
|
|
||||||
|
import ApiError from "@common/ApiError"; |
||||||
|
import { ErrorCode } from "@common/ErrorCode"; |
||||||
|
import { User } from "@server/entities"; |
||||||
|
import { verifyAuthorization } from "@server/express/authentication"; |
||||||
|
import { ServerState } from "@server/state"; |
||||||
|
|
||||||
|
export function users(state: ServerState) { |
||||||
|
const router = PromiseRouter(); |
||||||
|
|
||||||
|
router.use(verifyAuthorization()); |
||||||
|
|
||||||
|
async function getUser(params: { username: string }): Promise<User> { |
||||||
|
const { username } = params; |
||||||
|
const user = await state.database.users |
||||||
|
.findByUsername(username, { devices: true }); |
||||||
|
if (!user) { |
||||||
|
throw new ApiError(`user ${username} does not exist`, ErrorCode.NotFound); |
||||||
|
} |
||||||
|
return user; |
||||||
|
} |
||||||
|
|
||||||
|
router.get("/", (req, res) => { |
||||||
|
state.database.users.findAll() |
||||||
|
.then((users) => { |
||||||
|
res.json({ |
||||||
|
data: users, |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
router.get("/:username", async (req, res) => { |
||||||
|
const user = await getUser(req.params); |
||||||
|
res.json({ |
||||||
|
data: user, |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
router.get("/:username/devices", async (req, res) => { |
||||||
|
const user = await getUser(req.params); |
||||||
|
res.json({ |
||||||
|
data: user.devices, |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
return router; |
||||||
|
} |
@ -1,10 +1,33 @@ |
|||||||
import { EntityRepository, Repository } from "typeorm"; |
import { EntityRepository, Repository } from "typeorm"; |
||||||
|
|
||||||
import { SprinklersDevice } from "../entities"; |
import { SprinklersDevice, User } from "../entities"; |
||||||
|
|
||||||
@EntityRepository(SprinklersDevice) |
@EntityRepository(SprinklersDevice) |
||||||
export class SprinklersDeviceRepository extends Repository<SprinklersDevice> { |
export class SprinklersDeviceRepository extends Repository<SprinklersDevice> { |
||||||
findByName(name: string) { |
findByName(name: string) { |
||||||
return this.findOne({ name }); |
return this.findOne({ name }); |
||||||
} |
} |
||||||
|
|
||||||
|
async userHasAccess(userId: number, deviceId: number): Promise<boolean> { |
||||||
|
const count = await this.manager |
||||||
|
.createQueryBuilder(User, "user") |
||||||
|
.innerJoinAndSelect("user.devices", "sprinklers_device", |
||||||
|
"user.id = :userId AND sprinklers_device.id = :deviceId", |
||||||
|
{ userId, deviceId }) |
||||||
|
.getCount(); |
||||||
|
return count > 0; |
||||||
|
} |
||||||
|
|
||||||
|
async findUserDevice(userId: number, deviceId: number): Promise<SprinklersDevice | null> { |
||||||
|
const user = await this.manager |
||||||
|
.createQueryBuilder(User, "user") |
||||||
|
.innerJoinAndSelect("user.devices", "sprinklers_device", |
||||||
|
"user.id = :userId AND sprinklers_device.id = :deviceId", |
||||||
|
{ userId, deviceId }) |
||||||
|
.getOne(); |
||||||
|
if (!user) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return user.devices![0]; |
||||||
|
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue