Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
Fixes #134
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Jul 18, 2019
1 parent 82a518b commit 67ac8a1
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 18 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "staart-manager",
"version": "1.0.79",
"version": "1.0.80",
"main": "index.js",
"repository": "[email protected]:AnandChowdhary/staart.git",
"author": "Anand Chowdhary <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion setup/internal/staart-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.79
1.0.80
12 changes: 6 additions & 6 deletions src/helpers/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import Joi from "@hapi/joi";
* Parse default errors and send a safe string
*/
export const safeError = (error: string) => {
const errorString = error.toString();
let errorString = error.toString();
if (errorString.startsWith("Error: "))
errorString = errorString.replace("Error: ", "");
if (errorString.startsWith("joi:")) {
const joiError = JSON.parse(
errorString.split("joi:")[1]
Expand All @@ -18,18 +20,16 @@ export const safeError = (error: string) => {
errorString.startsWith("JsonWebTokenjwt")
)
return sendError(ErrorCode.INVALID_TOKEN);
return sendError(error);
return sendError(errorString);
};

/**
* Send an HTTPError object
*/
export const sendError = (error: string) => {
if (error.includes("/")) {
let status = 500;
try {
status = parseInt(error.split("/")[0]);
} catch (error) {}
let status = parseInt(error.split("/")[0]);
if (isNaN(status)) status = 500;
const code = error.split("/")[1];
return { status, code } as HTTPError;
}
Expand Down
27 changes: 26 additions & 1 deletion src/helpers/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import {
} from "../config";
import { User } from "../interfaces/tables/user";
import { Tokens, ErrorCode, EventType, Templates } from "../interfaces/enum";
import { deleteSensitiveInfoUser, removeFalsyValues } from "./utils";
import {
deleteSensitiveInfoUser,
removeFalsyValues,
includesInCommaList
} from "./utils";
import { checkApprovedLocation } from "../crud/user";
import { Locals } from "../interfaces/general";
import { createEvent } from "../crud/event";
Expand All @@ -27,6 +31,7 @@ import i18n from "../i18n";
import { ApiKey } from "../interfaces/tables/organization";
import cryptoRandomString from "crypto-random-string";
import { createHandyClient } from "handy-redis";
import ipRangeCheck from "ip-range-check";

/**
* Generate a new JWT
Expand Down Expand Up @@ -240,3 +245,23 @@ export const invalidateToken = async (token: string) => {
]
);
};

export const checkIpRestrictions = (apiKey: ApiKeyResponse, locals: Locals) => {
if (!apiKey.ipRestrictions) return;
if (
!ipRangeCheck(
locals.ipAddress,
apiKey.ipRestrictions.split(",").map(range => range.trim())
)
)
throw new Error(ErrorCode.IP_RANGE_CHECK_FAIL);
};

export const checkReferrerRestrictions = (
apiKey: ApiKeyResponse,
domain: string
) => {
if (!apiKey.referrerRestrictions || !domain) return;
if (!includesInCommaList(apiKey.referrerRestrictions, domain))
throw new Error(ErrorCode.REFERRER_CHECK_FAIL);
};
36 changes: 29 additions & 7 deletions src/helpers/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import {
verifyToken,
TokenResponse,
checkInvalidatedToken,
ApiKeyResponse
ApiKeyResponse,
checkIpRestrictions,
checkReferrerRestrictions
} from "./jwt";
import { ErrorCode, Tokens } from "../interfaces/enum";
import {
Expand All @@ -26,7 +28,7 @@ import {
import { isMatch } from "matcher";
import ipRangeCheck from "ip-range-check";
import { ApiKey } from "../interfaces/tables/organization";
import { joiValidate } from "./utils";
import { joiValidate, includesInCommaList } from "./utils";
const store = new Brute.MemoryStore();
const bruteForce = new Brute(store, {
freeRetries: BRUTE_FREE_RETRIES,
Expand Down Expand Up @@ -79,6 +81,7 @@ export const trackingHandler = (
req.socket.remoteAddress;
if (ip === "::1") ip = "2001:67c:2564:a309:f0e0:1ee6:137b:29e8";
res.locals.ipAddress = ip;
res.locals.referrer = req.headers.referer as string;
next();
};

Expand All @@ -100,27 +103,46 @@ export const authHandler = async (
if (userJwt) {
if (userJwt.startsWith("Bearer "))
userJwt = userJwt.replace("Bearer ", "");
const userToken = await verifyToken(userJwt, Tokens.LOGIN);
const userToken = (await verifyToken(
userJwt,
Tokens.LOGIN
)) as TokenResponse;
await checkInvalidatedToken(userJwt);
if (userToken) res.locals.token = userToken;
return next();
}

let apiKeyJwt = req.get("X-Api-Key") as string;
if (apiKeyJwt) {
if (apiKeyJwt.startsWith("Bearer "))
apiKeyJwt = apiKeyJwt.replace("Bearer ", "");
const apiKeyToken = await verifyToken(apiKeyJwt, Tokens.API_KEY);
const apiKeyToken = (await verifyToken(
apiKeyJwt,
Tokens.API_KEY
)) as ApiKeyResponse;
await checkInvalidatedToken(apiKeyJwt);
if (apiKeyToken) res.locals.token = apiKeyToken;
return next();
checkIpRestrictions(apiKeyToken, res.locals);
checkReferrerRestrictions(apiKeyToken, req.hostname);
if (apiKeyToken.referrerRestrictions) {
if (
includesInCommaList(apiKeyToken.referrerRestrictions, req.hostname)
) {
res.setHeader(
"Access-Control-Allow-Origin",
`${req.protocol}://${req.hostname}`
);
}
} else {
res.setHeader("Access-Control-Allow-Origin", "*");
}
if (apiKeyToken && !res.locals.token) res.locals.token = apiKeyToken;
}
} catch (error) {
const jwtError = safeError(error);
res.status(jwtError.status);
return res.json(jwtError);
}

if (res.locals.token) return next();
const error = safeError(ErrorCode.MISSING_TOKEN);
res.status(error.status);
return res.json(error);
Expand Down
5 changes: 5 additions & 0 deletions src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,8 @@ export const removeFalsyValues = (value: any) => {
}
return value;
};

export const includesInCommaList = (commaList: string, value: string) => {
const list = commaList.split(",").map(item => item.trim());
return list.includes(value);
};
1 change: 1 addition & 0 deletions src/interfaces/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export interface HTTPError {
export interface Locals {
userAgent: string;
ipAddress: string;
referrer?: string;
}
2 changes: 0 additions & 2 deletions src/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import "@babel/polyfill";
import cors from "cors";
import helmet from "helmet";
import morgan from "morgan";
import rfs from "rotating-file-stream";
Expand Down Expand Up @@ -35,7 +34,6 @@ export class Staart extends Server {
private setupHandlers() {
this.app.use(helmet({ hsts: { maxAge: 31536000, preload: true } }));
this.app.use(morgan("combined", { stream: accessLogStream }));
this.app.use(cors());
this.app.use(json({ limit: "50mb" }));
this.app.use(urlencoded({ extended: true }));
this.app.use(responseTime());
Expand Down

0 comments on commit 67ac8a1

Please sign in to comment.