@tickrorg/common 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/errors/bad-request-error.js +10 -0
- package/dist/errors/custom-error.js +2 -0
- package/dist/errors/database-connection-error.js +11 -0
- package/dist/errors/not-authorized-error.js +10 -0
- package/dist/errors/not-found-error.js +12 -0
- package/dist/errors/request-validation-error.js +17 -0
- package/dist/index.js +10 -0
- package/dist/middlewares/current-user.js +8 -0
- package/dist/middlewares/error-handler.js +9 -0
- package/dist/middlewares/require-auth.js +10 -0
- package/dist/middlewares/validate-request.js +9 -0
- package/dist/services/token.js +73 -0
- package/package.json +5 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CustomError } from "./custom-error";
|
|
2
|
+
export class DatabaseConnectionError extends CustomError {
|
|
3
|
+
statusCode = 500;
|
|
4
|
+
reason = "Error connecting to database";
|
|
5
|
+
constructor() {
|
|
6
|
+
super("Error connecting to db");
|
|
7
|
+
}
|
|
8
|
+
serializeErrors() {
|
|
9
|
+
return [{ message: this.reason }];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CustomError } from "./custom-error";
|
|
2
|
+
export class NotFoundError extends CustomError {
|
|
3
|
+
message;
|
|
4
|
+
statusCode = 404;
|
|
5
|
+
constructor(message = "Not Found") {
|
|
6
|
+
super("Route not found");
|
|
7
|
+
this.message = message;
|
|
8
|
+
}
|
|
9
|
+
serializeErrors() {
|
|
10
|
+
return [{ message: this.message }];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CustomError } from "./custom-error";
|
|
2
|
+
export class RequestValidationError extends CustomError {
|
|
3
|
+
errors;
|
|
4
|
+
statusCode = 400;
|
|
5
|
+
constructor(errors) {
|
|
6
|
+
super("Invalid request parameters");
|
|
7
|
+
this.errors = errors;
|
|
8
|
+
}
|
|
9
|
+
serializeErrors() {
|
|
10
|
+
return this.errors.map((err) => {
|
|
11
|
+
if (err.type === "field") {
|
|
12
|
+
return { message: err.msg, field: err.path };
|
|
13
|
+
}
|
|
14
|
+
return { message: err.msg };
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./errors/bad-request-error";
|
|
2
|
+
export * from "./errors/custom-error";
|
|
3
|
+
export * from "./errors/database-connection-error";
|
|
4
|
+
export * from "./errors/not-authorized-error";
|
|
5
|
+
export * from "./errors/not-found-error";
|
|
6
|
+
export * from "./errors/request-validation-error";
|
|
7
|
+
export * from "./middlewares/current-user";
|
|
8
|
+
export * from "./middlewares/error-handler";
|
|
9
|
+
export * from "./middlewares/require-auth";
|
|
10
|
+
export * from "./middlewares/validate-request";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CustomError } from "../errors/custom-error";
|
|
2
|
+
export const errorHandler = (err, req, res, next) => {
|
|
3
|
+
if (err instanceof CustomError) {
|
|
4
|
+
return res.status(err.statusCode).send({ errors: err.serializeErrors() });
|
|
5
|
+
}
|
|
6
|
+
res.status(400).send({
|
|
7
|
+
errors: [{ message: "Something went wrong" }],
|
|
8
|
+
});
|
|
9
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Token } from "../services/token";
|
|
2
|
+
import { NotAuthorizedError } from "../errors/not-authorized-error";
|
|
3
|
+
export const requireAuth = (req, res, next) => {
|
|
4
|
+
const payload = Token.fromRequest(req);
|
|
5
|
+
if (!payload) {
|
|
6
|
+
throw new NotAuthorizedError();
|
|
7
|
+
}
|
|
8
|
+
req.currentUser = payload;
|
|
9
|
+
next();
|
|
10
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { validationResult } from "express-validator";
|
|
2
|
+
import { RequestValidationError } from "../errors/request-validation-error";
|
|
3
|
+
export const validateRequest = (req, res, next) => {
|
|
4
|
+
const errors = validationResult(req);
|
|
5
|
+
if (!errors.isEmpty()) {
|
|
6
|
+
throw new RequestValidationError(errors.array());
|
|
7
|
+
}
|
|
8
|
+
next();
|
|
9
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
export class Token {
|
|
3
|
+
static generateAccess(payload) {
|
|
4
|
+
console.log("Generating access token with payload :", payload);
|
|
5
|
+
return jwt.sign(payload, process.env.JWT_ACCESS_KEY, { expiresIn: "15m" });
|
|
6
|
+
}
|
|
7
|
+
static generateRefresh(payload) {
|
|
8
|
+
return jwt.sign(payload, process.env.JWT_REFRESH_KEY, { expiresIn: "7d" });
|
|
9
|
+
}
|
|
10
|
+
static generatePair(payload) {
|
|
11
|
+
return {
|
|
12
|
+
accessToken: Token.generateAccess(payload),
|
|
13
|
+
refreshToken: Token.generateRefresh(payload),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
static verifyAccess(token) {
|
|
17
|
+
try {
|
|
18
|
+
return jwt.verify(token, process.env.JWT_ACCESS_KEY);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
static verifyRefresh(token) {
|
|
25
|
+
try {
|
|
26
|
+
return jwt.verify(token, process.env.JWT_REFRESH_KEY);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
static refresh(req, res) {
|
|
33
|
+
const refreshToken = req.cookies.refresh_token;
|
|
34
|
+
if (!refreshToken)
|
|
35
|
+
return null;
|
|
36
|
+
const payload = Token.verifyRefresh(refreshToken);
|
|
37
|
+
if (!payload)
|
|
38
|
+
return null;
|
|
39
|
+
const { id, email } = payload;
|
|
40
|
+
const { accessToken, refreshToken: newRefreshToken } = Token.generatePair({
|
|
41
|
+
id,
|
|
42
|
+
email,
|
|
43
|
+
});
|
|
44
|
+
Token.setCookies(res, accessToken, newRefreshToken);
|
|
45
|
+
return { id, email };
|
|
46
|
+
}
|
|
47
|
+
static fromRequest(req) {
|
|
48
|
+
const token = req.cookies.access_token;
|
|
49
|
+
if (!token)
|
|
50
|
+
return null;
|
|
51
|
+
return Token.verifyAccess(token);
|
|
52
|
+
}
|
|
53
|
+
static setCookies(res, accessToken, refreshToken) {
|
|
54
|
+
res.cookie("access_token", accessToken, {
|
|
55
|
+
httpOnly: true,
|
|
56
|
+
secure: process.env.NODE_ENV === "production",
|
|
57
|
+
sameSite: "lax",
|
|
58
|
+
maxAge: 15 * 60 * 1000,
|
|
59
|
+
path: "/",
|
|
60
|
+
});
|
|
61
|
+
res.cookie("refresh_token", refreshToken, {
|
|
62
|
+
httpOnly: true,
|
|
63
|
+
secure: process.env.NODE_ENV === "production",
|
|
64
|
+
sameSite: "lax",
|
|
65
|
+
maxAge: 7 * 24 * 60 * 60 * 1000,
|
|
66
|
+
path: "/",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
static clearCookies(res) {
|
|
70
|
+
res.clearCookie("access_token");
|
|
71
|
+
res.clearCookie("refresh_token", { path: "/api/auth/refresh" });
|
|
72
|
+
}
|
|
73
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tickrorg/common",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "",
|
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
"main": "./build/index.js",
|
|
9
9
|
"types": "./build/index.d.ts",
|
|
10
10
|
"files": [
|
|
11
|
-
"
|
|
11
|
+
"dist/**/*",
|
|
12
|
+
"README.md",
|
|
13
|
+
"package.json"
|
|
12
14
|
],
|
|
13
15
|
"scripts": {
|
|
14
16
|
"build": "npm run clean && tsc",
|
|
15
17
|
"clean": "del-cli dist",
|
|
16
|
-
"pub": "git add . && git commit -m 'update' && npm version patch && npm run build &&npm publish"
|
|
18
|
+
"pub": "git add . && git commit -m 'update' && npm version patch && npm run build && npm publish"
|
|
17
19
|
},
|
|
18
20
|
"dependencies": {
|
|
19
21
|
"@types/cookie-parser": "^1.4.10",
|