Skip to content

Commit

Permalink
Cleanup unused routes and convert auth response to string
Browse files Browse the repository at this point in the history
  • Loading branch information
sainak committed Aug 24, 2024
1 parent 02bec3f commit 941e5c6
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 95 deletions.
4 changes: 2 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ services:
# teleicu_middleware
teleicu_middleware:
restart: always
image: ghcr.io/coronasafe/teleicu_middleware:production-latest
image: ghcr.io/ohcnetwork/teleicu_middleware:production-latest
container_name: teleicu_middleware
depends_on:
- roverr_rtsp_stream
Expand All @@ -37,7 +37,7 @@ services:
# proxies requests to internal services
reverse-proxy:
restart: always
image: ghcr.io/coronasafe/teleicu_nginx/teleicu_nginx:latest
image: ghcr.io/ohcnetwork/teleicu_nginx/teleicu_nginx:latest
container_name: reverse-proxy
depends_on:
- teleicu_middleware
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"main": "src/index.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/coronasafe/teleicu_middleware.git"
"url": "git+https://github.com/ohcnetwork/teleicu_middleware.git"
},
"keywords": [
"teleicu",
Expand All @@ -56,9 +56,9 @@
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/coronasafe/teleicu_middleware/issues"
"url": "https://github.com/ohcnetwork/teleicu_middleware/issues"
},
"homepage": "https://github.com/coronasafe/teleicu_middleware#readme",
"homepage": "https://github.com/ohcnetwork/teleicu_middleware#readme",
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/connect-flash": "^0.0.39",
Expand Down
18 changes: 0 additions & 18 deletions src/controller/CameraController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,24 +353,6 @@ export class CameraController {
});
});

/**
* @swagger
* /get_time:
* get:
* summary: "Get current time"
* description: ""
* tags:
* - BPL
* responses:
* "200":
* description: Return current time
*/
static getTime = catchAsync(async (req: Request, res: Response) => {
res.send({
time: new Date().toISOString(),
});
});

/**
* @swagger
* /preset:
Expand Down
2 changes: 1 addition & 1 deletion src/controller/ConfigController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class ConfigController {
res.render("pages/config", {
req,
csrfToken: res.locals.csrfToken,
hostname: "dev_middleware.coronasafe.live",
hostname: "dev_middleware.ohcnetwork.live",
});
};
}
29 changes: 0 additions & 29 deletions src/controller/ObservationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,35 +175,6 @@ export class ObservationController {

static latestObservation = new ObservationsMap();

static getObservations(req: Request, res: Response) {
const limit = req.query?.limit || DEFAULT_LISTING_LIMIT;
const ip = req.query?.ip;

if (!ip) {
return res.json(staticObservations);
}
// console.log("Filtering");
const filtered = staticObservations.filter(
(observation) => observation.device_id === ip,
);
// Sort the observation by last updated time.
// .sort(
// (a, b) => new Date(a.lastObservationAt) - new Date(b.lastObservationAt)
// )
// // Limit the results
// .slice(0, limit);

return res.json(filtered ?? []);
}

static getLogData(req: Request, res: Response) {
return res.json(logData);
}

static getLastRequestData(req: Request, res: Response) {
return res.json(lastRequestData);
}

static updateObservations = (req: Request, res: Response) => {
// database logic
lastRequestData = req.body;
Expand Down
40 changes: 13 additions & 27 deletions src/controller/StreamAuthApiController.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { Request, Response } from "express";

import { generateJWT, verifyJWT } from "@/lib/jose";
import { generateJWT, verifyJWTWithKey } from "@/lib/jose";

export class StreamAuthApiController {
static getVideoFeedStreamToken = async (req: Request, res: Response) => {
const { stream, ip, _duration } = req.body;
if (!stream || !ip) {
return res.status(400).json({ message: "stream and ip are required" });
const { stream_id } = req.body;
if (!stream_id) {
return res.status(400).json({ message: "stream_id is required" });
}

try {
const duration = parseInt(_duration ?? "5");
if (duration < 0 || duration > 60) {
return res
.status(400)
.json({ message: "duration must be between 0 and 60" });
}

const token = await generateJWT({ stream, ip }, `${duration}m`);
const token = await generateJWT({ stream_id }, "60s");

return res.status(200).json({ token });
} catch (error: any) {
Expand All @@ -26,20 +19,13 @@ export class StreamAuthApiController {
};

static getVitalStreamToken = async (req: Request, res: Response) => {
const { asset_id, ip, _duration } = req.body;
const { asset_id, ip } = req.body;
if (!asset_id || !ip) {
return res.status(400).json({ message: "asset_id and ip are required" });
}

try {
const duration = parseInt(_duration ?? "5");
if (duration < 0 || duration > 60) {
return res
.status(400)
.json({ message: "duration must be between 0 and 60" });
}

const token = await generateJWT({ asset_id, ip }, `${duration}m`);
const token = await generateJWT({ asset_id, ip }, "60s");

return res.status(200).json({ token });
} catch (error: any) {
Expand All @@ -49,19 +35,19 @@ export class StreamAuthApiController {

static validateStreamToken = async (req: Request, res: Response) => {
const { token, ip, stream } = req.body;
if (!token || !ip || !stream) {
if (!token || !stream) {
return res
.status(400)
.json({ message: "token, stream, and ip are required" });
.json({ message: "token and stream are required" });
}

try {
const decoded = await verifyJWT(token);
if (decoded.ip === ip || decoded.stream === stream) {
return res.status(200).json({ status: 1 });
const decoded = await verifyJWTWithKey(token);
if (decoded.stream === stream) {
return res.status(200).json({ status: "1" });
}

return res.status(401).json({ status: 0 });
return res.status(401).json({ status: "0" });
} catch (error: any) {
return res.status(500).json({ message: error.message });
}
Expand Down
50 changes: 49 additions & 1 deletion src/lib/jose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as jose from "jose";
import { v4 as uuidv4 } from "uuid";

import { randomString } from "@/lib/crypto";
import { careApi } from "@/utils/configs";
import { careApi , jwtSecret} from "@/utils/configs";

/**
* Default JSON Web Key (JWK) configuration.
Expand Down Expand Up @@ -151,6 +151,33 @@ export async function generateJWT(
.sign(privateKey);
}

/**
* Generates a JSON Web Token (JWT) with the provided claims and expiration time using the provided key.
* @param claims The payload of the JWT.
* @param expiresIn The expiration time of the JWT. Defaults to "2m" (2 minutes).
* @returns {Promise<string>} The generated JWT.
*/
export async function generateJWTWithKey(
claims: jose.JWTPayload,
expiresIn: string = "2m",
) {
const claimsWithDefaults: jose.JWTPayload = {
// iss: "teleicu-middleware",
// aud: "care",
jti: randomString(20),
...claims,
};

return new jose.SignJWT(claimsWithDefaults)
.setProtectedHeader({
alg: "HS256",
typ: "jwt",
})
.setIssuedAt()
.setExpirationTime(expiresIn)
.sign(jwtSecret);
}

/**
* Represents a function that validates a JSON Web Token (JWT).
* @param jwt The JWT to be validated.
Expand Down Expand Up @@ -182,6 +209,27 @@ export async function verifyJWT(
return payload;
}


/**
* Verifies a JSON Web Token (JWT) generated by this server using the provided options.
* @param jwt The JWT to verify.
* @param options The options for JWT verification.
* @returns {Promise<jose.JWTPayload>} The payload of the JWT.
*/
export async function verifyJWTWithKey(
jwt: string,
options: jose.JWTVerifyOptions = {},
) {
const { payload } = await jose.jwtVerify(jwt, jwtSecret, {
// issuer: "teleicu-middleware",
// audience: "care",
...options,
});

return payload;
}


/**
* Verifies a JSON Web Token (JWT) generated by care backend using the provided options.
* @param jwt The JWT to verify.
Expand Down
7 changes: 3 additions & 4 deletions src/router/cameraRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import {
} from "@/Validators/cameraValidators";
import { CameraController } from "@/controller/CameraController";
import { validate } from "@/middleware/validate";
import { careJwtAuth } from "@/middleware/auth";

const router = express.Router();

router.use(careJwtAuth());

router.get(
"/presets",
validate(baseGetCameraParamsValidators),
Expand Down Expand Up @@ -49,8 +52,4 @@ router.post(
CameraController.relativeMove,
);

// BPL Integration

router.get("/get_time", CameraController.getTime);

export { router as cameraRouter };
15 changes: 5 additions & 10 deletions src/router/observationRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {
} from "@/Validators/observationValidators";
import { ObservationController } from "@/controller/ObservationController";
import { validate } from "@/middleware/validate";
import { careJwtAuth } from "@/middleware/auth";

const router = express.Router();

router.get("/get_observations", ObservationController.getObservations);

// blocked on nginx
router.post(
"/update_observations",
validate(observationsValidators),
Expand All @@ -19,18 +19,13 @@ router.post(

router.get(
"/vitals",
careJwtAuth(),
validate(vitalsValidator),
ObservationController.getLatestVitals,
);

router.get("/get_time", ObservationController.getTime);

router.get("/devices/status", ObservationController.status);
router.get("/devices/status", careJwtAuth(), ObservationController.status);

// Debugging Endpoints

router.get("/get_log_data", ObservationController.getLogData);

router.get("/get_last_request_data", ObservationController.getLastRequestData);
router.get("/get_time", ObservationController.getTime);

export { router as observationRouter };
4 changes: 4 additions & 0 deletions src/utils/configs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as dotenv from "dotenv";
import crypto from "crypto";

dotenv.config();

Expand All @@ -9,6 +10,9 @@ export const facilityID =
process.env.FACILITY_ID ?? "00000000-0000-0000-0000-000000000000";
export const careApi = process.env.CARE_API ?? "http://localhost:9000";

export const jwtSecret = new TextEncoder().encode
(process.env.JWT_SECRET ?? crypto.randomBytes(32).toString("hex"));

export const adminUsername = process.env.USERNAME ?? "admin";
export const adminPassword = process.env.PASSWORD + facilityID; // good luck brute-forcing this

Expand Down

0 comments on commit 941e5c6

Please sign in to comment.