@eratu/common 1.0.15 → 1.0.16
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/build/errors/forbidden-error.d.ts +9 -0
- package/build/errors/forbidden-error.js +16 -0
- package/build/errors/not-authorized-error.d.ts +2 -2
- package/build/errors/not-authorized-error.js +3 -3
- package/build/errors/not-found-error.d.ts +3 -2
- package/build/errors/not-found-error.js +4 -3
- package/build/events/event-types/auth/author-deleted-event.d.ts +2 -1
- package/build/events/event-types/auth/author-signed-in-event.d.ts +2 -2
- package/build/events/event-types/auth/author-updated-event.d.ts +3 -1
- package/build/events/event-types/auth/{author-created-event.d.ts → author-verified-event.d.ts} +5 -3
- package/build/events/event-types/auth/reader-deleted-event.d.ts +2 -1
- package/build/events/event-types/auth/reader-signed-in-event.d.ts +2 -1
- package/build/events/event-types/auth/reader-updated-event.d.ts +3 -1
- package/build/events/event-types/auth/{reader-created-event.d.ts → reader-verified-event.d.ts} +5 -3
- package/build/events/subjects.d.ts +2 -2
- package/build/events/subjects.js +2 -2
- package/build/index.d.ts +11 -8
- package/build/index.js +15 -8
- package/build/middlewares/allow-roles.d.ts +3 -0
- package/build/middlewares/allow-roles.js +18 -0
- package/build/middlewares/current-user.d.ts +11 -0
- package/build/middlewares/current-user.js +59 -1
- package/build/middlewares/validation.d.ts +1 -1
- package/build/middlewares/validation.js +3 -3
- package/build/redis-wrapper.d.ts +20 -0
- package/build/redis-wrapper.js +77 -0
- package/package.json +4 -2
- /package/build/events/event-types/auth/{author-created-event.js → author-verified-event.js} +0 -0
- /package/build/events/event-types/auth/{reader-created-event.js → reader-verified-event.js} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ForbiddenError = void 0;
|
|
4
|
+
const custom_error_1 = require("./custom-error");
|
|
5
|
+
class ForbiddenError extends custom_error_1.CustomError {
|
|
6
|
+
constructor(message = "Forbidden") {
|
|
7
|
+
super(message);
|
|
8
|
+
this.message = message;
|
|
9
|
+
this.statusCode = 403;
|
|
10
|
+
Object.setPrototypeOf(this, ForbiddenError.prototype);
|
|
11
|
+
}
|
|
12
|
+
serializeErrors() {
|
|
13
|
+
return [{ message: this.message }];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.ForbiddenError = ForbiddenError;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CustomError } from
|
|
1
|
+
import { CustomError } from "./custom-error";
|
|
2
2
|
export declare class NotAuthorizedError extends CustomError {
|
|
3
3
|
statusCode: number;
|
|
4
|
-
constructor();
|
|
4
|
+
constructor(message?: string);
|
|
5
5
|
serializeErrors(): {
|
|
6
6
|
message: string;
|
|
7
7
|
}[];
|
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NotAuthorizedError = void 0;
|
|
4
4
|
const custom_error_1 = require("./custom-error");
|
|
5
5
|
class NotAuthorizedError extends custom_error_1.CustomError {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(
|
|
6
|
+
constructor(message = "Not Authorized") {
|
|
7
|
+
super(message);
|
|
8
8
|
this.statusCode = 401;
|
|
9
9
|
Object.setPrototypeOf(this, NotAuthorizedError.prototype);
|
|
10
10
|
}
|
|
11
11
|
serializeErrors() {
|
|
12
|
-
return [{ message:
|
|
12
|
+
return [{ message: this.message }];
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
exports.NotAuthorizedError = NotAuthorizedError;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { CustomError } from
|
|
1
|
+
import { CustomError } from "./custom-error";
|
|
2
2
|
export declare class NotFoundError extends CustomError {
|
|
3
|
+
message: string;
|
|
3
4
|
statusCode: number;
|
|
4
|
-
constructor();
|
|
5
|
+
constructor(message?: string);
|
|
5
6
|
serializeErrors(): {
|
|
6
7
|
message: string;
|
|
7
8
|
}[];
|
|
@@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NotFoundError = void 0;
|
|
4
4
|
const custom_error_1 = require("./custom-error");
|
|
5
5
|
class NotFoundError extends custom_error_1.CustomError {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(
|
|
6
|
+
constructor(message = "Not Found") {
|
|
7
|
+
super("Route not found");
|
|
8
|
+
this.message = message;
|
|
8
9
|
this.statusCode = 404;
|
|
9
10
|
Object.setPrototypeOf(this, NotFoundError.prototype);
|
|
10
11
|
}
|
|
11
12
|
serializeErrors() {
|
|
12
|
-
return [{ message:
|
|
13
|
+
return [{ message: this.message }];
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
exports.NotFoundError = NotFoundError;
|
|
@@ -2,9 +2,10 @@ import { Streams } from "../../streams";
|
|
|
2
2
|
import { Subjects } from "../../subjects";
|
|
3
3
|
export interface AuthorDeletedEvent {
|
|
4
4
|
subject: Subjects.AuthorDeleted;
|
|
5
|
-
stream: Streams.
|
|
5
|
+
stream: Streams.AuthServiceStream;
|
|
6
6
|
data: {
|
|
7
7
|
id: string;
|
|
8
8
|
version: number;
|
|
9
|
+
authorVersion: number;
|
|
9
10
|
};
|
|
10
11
|
}
|
|
@@ -2,11 +2,13 @@ import { Streams } from "../../streams";
|
|
|
2
2
|
import { Subjects } from "../../subjects";
|
|
3
3
|
export interface AuthorUpdatedEvent {
|
|
4
4
|
subject: Subjects.AuthorUpdated;
|
|
5
|
-
stream: Streams.
|
|
5
|
+
stream: Streams.AuthServiceStream;
|
|
6
6
|
data: {
|
|
7
7
|
id: string;
|
|
8
8
|
firstName: string;
|
|
9
9
|
lastName: string;
|
|
10
10
|
email: string;
|
|
11
|
+
version: number;
|
|
12
|
+
authorVersion: number;
|
|
11
13
|
};
|
|
12
14
|
}
|
package/build/events/event-types/auth/{author-created-event.d.ts → author-verified-event.d.ts}
RENAMED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Streams } from "../../streams";
|
|
2
2
|
import { Subjects } from "../../subjects";
|
|
3
|
-
export interface
|
|
4
|
-
subject: Subjects.
|
|
5
|
-
stream: Streams.
|
|
3
|
+
export interface AuthorVerifiedEvent {
|
|
4
|
+
subject: Subjects.AuthorVerified;
|
|
5
|
+
stream: Streams.AuthServiceStream;
|
|
6
6
|
data: {
|
|
7
7
|
id: string;
|
|
8
8
|
firstName: string;
|
|
9
9
|
lastName: string;
|
|
10
10
|
email: string;
|
|
11
|
+
version: number;
|
|
12
|
+
authorVersion: number;
|
|
11
13
|
};
|
|
12
14
|
}
|
|
@@ -2,9 +2,10 @@ import { Streams } from "../../streams";
|
|
|
2
2
|
import { Subjects } from "../../subjects";
|
|
3
3
|
export interface ReaderDeletedEvent {
|
|
4
4
|
subject: Subjects.ReaderDeleted;
|
|
5
|
-
stream: Streams.
|
|
5
|
+
stream: Streams.AuthServiceStream;
|
|
6
6
|
data: {
|
|
7
7
|
id: string;
|
|
8
8
|
version: number;
|
|
9
|
+
readerVersion: number;
|
|
9
10
|
};
|
|
10
11
|
}
|
|
@@ -2,11 +2,13 @@ import { Streams } from "../../streams";
|
|
|
2
2
|
import { Subjects } from "../../subjects";
|
|
3
3
|
export interface ReaderUpdatedEvent {
|
|
4
4
|
subject: Subjects.ReaderUpdated;
|
|
5
|
-
stream: Streams.
|
|
5
|
+
stream: Streams.AuthServiceStream;
|
|
6
6
|
data: {
|
|
7
7
|
id: string;
|
|
8
8
|
firstName: string;
|
|
9
9
|
lastName: string;
|
|
10
10
|
email: string;
|
|
11
|
+
version: number;
|
|
12
|
+
readerVersion: number;
|
|
11
13
|
};
|
|
12
14
|
}
|
package/build/events/event-types/auth/{reader-created-event.d.ts → reader-verified-event.d.ts}
RENAMED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Streams } from "../../streams";
|
|
2
2
|
import { Subjects } from "../../subjects";
|
|
3
|
-
export interface
|
|
4
|
-
subject: Subjects.
|
|
5
|
-
stream: Streams.
|
|
3
|
+
export interface ReaderVerifiedEvent {
|
|
4
|
+
subject: Subjects.ReaderVerified;
|
|
5
|
+
stream: Streams.AuthServiceStream;
|
|
6
6
|
data: {
|
|
7
7
|
id: string;
|
|
8
8
|
firstName: string;
|
|
9
9
|
lastName: string;
|
|
10
10
|
email: string;
|
|
11
|
+
version: number;
|
|
12
|
+
readerVersion: number;
|
|
11
13
|
};
|
|
12
14
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
export declare enum Subjects {
|
|
2
|
-
AuthorCreated = "author:created",
|
|
3
2
|
AuthorUpdated = "author:updated",
|
|
4
3
|
AuthorDeleted = "author:deleted",
|
|
5
4
|
AuthorSignedUp = "author:signed-up",
|
|
6
5
|
AuthorSignedIn = "author:signed-in",
|
|
7
6
|
AuthorSignedOut = "author:signed-out",
|
|
7
|
+
AuthorVerified = "author:verified",
|
|
8
8
|
ReaderSignedUp = "reader:signed-up",
|
|
9
9
|
ReaderSignedIn = "reader:signed-in",
|
|
10
10
|
ReaderSignedOut = "reader:signed-out",
|
|
11
|
-
ReaderCreated = "reader:created",
|
|
12
11
|
ReaderUpdated = "reader:updated",
|
|
13
12
|
ReaderDeleted = "reader:deleted",
|
|
13
|
+
ReaderVerified = "reader:verified",
|
|
14
14
|
BookCreated = "book:created",
|
|
15
15
|
BookUpdated = "book:updated",
|
|
16
16
|
BookDeleted = "book:deleted",
|
package/build/events/subjects.js
CHANGED
|
@@ -4,19 +4,19 @@ exports.Subjects = void 0;
|
|
|
4
4
|
var Subjects;
|
|
5
5
|
(function (Subjects) {
|
|
6
6
|
// Authors related event subjects
|
|
7
|
-
Subjects["AuthorCreated"] = "author:created";
|
|
8
7
|
Subjects["AuthorUpdated"] = "author:updated";
|
|
9
8
|
Subjects["AuthorDeleted"] = "author:deleted";
|
|
10
9
|
Subjects["AuthorSignedUp"] = "author:signed-up";
|
|
11
10
|
Subjects["AuthorSignedIn"] = "author:signed-in";
|
|
12
11
|
Subjects["AuthorSignedOut"] = "author:signed-out";
|
|
12
|
+
Subjects["AuthorVerified"] = "author:verified";
|
|
13
13
|
// Readers related event subjects
|
|
14
14
|
Subjects["ReaderSignedUp"] = "reader:signed-up";
|
|
15
15
|
Subjects["ReaderSignedIn"] = "reader:signed-in";
|
|
16
16
|
Subjects["ReaderSignedOut"] = "reader:signed-out";
|
|
17
|
-
Subjects["ReaderCreated"] = "reader:created";
|
|
18
17
|
Subjects["ReaderUpdated"] = "reader:updated";
|
|
19
18
|
Subjects["ReaderDeleted"] = "reader:deleted";
|
|
19
|
+
Subjects["ReaderVerified"] = "reader:verified";
|
|
20
20
|
// Books related event subjects
|
|
21
21
|
Subjects["BookCreated"] = "book:created";
|
|
22
22
|
Subjects["BookUpdated"] = "book:updated";
|
package/build/index.d.ts
CHANGED
|
@@ -4,29 +4,32 @@ export * from "./errors/database-connection-error";
|
|
|
4
4
|
export * from "./errors/not-authorized-error";
|
|
5
5
|
export * from "./errors/not-found-error";
|
|
6
6
|
export * from "./errors/request-validation-error";
|
|
7
|
+
export * from "./errors/forbidden-error";
|
|
7
8
|
export * from "./middlewares/current-user";
|
|
8
|
-
export * from "./middlewares/error-handler";
|
|
9
9
|
export * from "./middlewares/require-auth";
|
|
10
10
|
export * from "./middlewares/validation";
|
|
11
|
+
export * from "./middlewares/error-handler";
|
|
12
|
+
export * from "./middlewares/allow-roles";
|
|
11
13
|
export * from "./enum/roles";
|
|
12
14
|
export * from "./events/listeners/base-listener";
|
|
13
15
|
export * from "./events/publishers/base-publisher";
|
|
14
16
|
export * from "./events/event-types/books/book-created-event";
|
|
15
17
|
export * from "./events/event-types/books/book-updated-event";
|
|
16
18
|
export * from "./events/event-types/books/book-deleted-event";
|
|
17
|
-
export * from "./events/event-types/auth/reader-created-event";
|
|
18
|
-
export * from "./events/event-types/auth/reader-updated-event";
|
|
19
|
-
export * from "./events/event-types/auth/reader-deleted-event";
|
|
20
|
-
export * from "./events/event-types/auth/author-created-event";
|
|
21
19
|
export * from "./events/event-types/auth/author-updated-event";
|
|
22
20
|
export * from "./events/event-types/auth/author-deleted-event";
|
|
23
|
-
export * from "./events/event-types/auth/
|
|
24
|
-
export * from "./events/event-types/auth/reader-signed-in-event";
|
|
25
|
-
export * from "./events/event-types/auth/reader-signed-out-event";
|
|
21
|
+
export * from "./events/event-types/auth/author-verified-event";
|
|
26
22
|
export * from "./events/event-types/auth/author-signed-up-event";
|
|
27
23
|
export * from "./events/event-types/auth/author-signed-in-event";
|
|
28
24
|
export * from "./events/event-types/auth/author-signed-out-event";
|
|
25
|
+
export * from "./events/event-types/auth/reader-updated-event";
|
|
26
|
+
export * from "./events/event-types/auth/reader-deleted-event";
|
|
27
|
+
export * from "./events/event-types/auth/reader-signed-up-event";
|
|
28
|
+
export * from "./events/event-types/auth/reader-signed-in-event";
|
|
29
|
+
export * from "./events/event-types/auth/reader-signed-out-event";
|
|
30
|
+
export * from "./events/event-types/auth/reader-verified-event";
|
|
29
31
|
export * from "./events/event-types/orders/order-created-event";
|
|
30
32
|
export * from "./events/subjects";
|
|
31
33
|
export * from "./events/streams";
|
|
32
34
|
export * from "./nats-wrapper";
|
|
35
|
+
export * from "./redis-wrapper";
|
package/build/index.js
CHANGED
|
@@ -14,16 +14,20 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Errors
|
|
17
18
|
__exportStar(require("./errors/bad-request-error"), exports);
|
|
18
19
|
__exportStar(require("./errors/custom-error"), exports);
|
|
19
20
|
__exportStar(require("./errors/database-connection-error"), exports);
|
|
20
21
|
__exportStar(require("./errors/not-authorized-error"), exports);
|
|
21
22
|
__exportStar(require("./errors/not-found-error"), exports);
|
|
22
23
|
__exportStar(require("./errors/request-validation-error"), exports);
|
|
24
|
+
__exportStar(require("./errors/forbidden-error"), exports);
|
|
25
|
+
// Middlewares
|
|
23
26
|
__exportStar(require("./middlewares/current-user"), exports);
|
|
24
|
-
__exportStar(require("./middlewares/error-handler"), exports);
|
|
25
27
|
__exportStar(require("./middlewares/require-auth"), exports);
|
|
26
28
|
__exportStar(require("./middlewares/validation"), exports);
|
|
29
|
+
__exportStar(require("./middlewares/error-handler"), exports);
|
|
30
|
+
__exportStar(require("./middlewares/allow-roles"), exports);
|
|
27
31
|
// Enums
|
|
28
32
|
__exportStar(require("./enum/roles"), exports);
|
|
29
33
|
__exportStar(require("./events/listeners/base-listener"), exports);
|
|
@@ -31,19 +35,22 @@ __exportStar(require("./events/publishers/base-publisher"), exports);
|
|
|
31
35
|
__exportStar(require("./events/event-types/books/book-created-event"), exports);
|
|
32
36
|
__exportStar(require("./events/event-types/books/book-updated-event"), exports);
|
|
33
37
|
__exportStar(require("./events/event-types/books/book-deleted-event"), exports);
|
|
34
|
-
|
|
35
|
-
__exportStar(require("./events/event-types/auth/reader-updated-event"), exports);
|
|
36
|
-
__exportStar(require("./events/event-types/auth/reader-deleted-event"), exports);
|
|
37
|
-
__exportStar(require("./events/event-types/auth/author-created-event"), exports);
|
|
38
|
+
// Author events
|
|
38
39
|
__exportStar(require("./events/event-types/auth/author-updated-event"), exports);
|
|
39
40
|
__exportStar(require("./events/event-types/auth/author-deleted-event"), exports);
|
|
40
|
-
__exportStar(require("./events/event-types/auth/
|
|
41
|
-
__exportStar(require("./events/event-types/auth/reader-signed-in-event"), exports);
|
|
42
|
-
__exportStar(require("./events/event-types/auth/reader-signed-out-event"), exports);
|
|
41
|
+
__exportStar(require("./events/event-types/auth/author-verified-event"), exports);
|
|
43
42
|
__exportStar(require("./events/event-types/auth/author-signed-up-event"), exports);
|
|
44
43
|
__exportStar(require("./events/event-types/auth/author-signed-in-event"), exports);
|
|
45
44
|
__exportStar(require("./events/event-types/auth/author-signed-out-event"), exports);
|
|
45
|
+
// Reader events
|
|
46
|
+
__exportStar(require("./events/event-types/auth/reader-updated-event"), exports);
|
|
47
|
+
__exportStar(require("./events/event-types/auth/reader-deleted-event"), exports);
|
|
48
|
+
__exportStar(require("./events/event-types/auth/reader-signed-up-event"), exports);
|
|
49
|
+
__exportStar(require("./events/event-types/auth/reader-signed-in-event"), exports);
|
|
50
|
+
__exportStar(require("./events/event-types/auth/reader-signed-out-event"), exports);
|
|
51
|
+
__exportStar(require("./events/event-types/auth/reader-verified-event"), exports);
|
|
46
52
|
__exportStar(require("./events/event-types/orders/order-created-event"), exports);
|
|
47
53
|
__exportStar(require("./events/subjects"), exports);
|
|
48
54
|
__exportStar(require("./events/streams"), exports);
|
|
49
55
|
__exportStar(require("./nats-wrapper"), exports);
|
|
56
|
+
__exportStar(require("./redis-wrapper"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allowRoles = void 0;
|
|
4
|
+
const not_authorized_error_1 = require("../errors/not-authorized-error");
|
|
5
|
+
const forbidden_error_1 = require("../errors/forbidden-error");
|
|
6
|
+
const allowRoles = (roles) => {
|
|
7
|
+
return (req, res, next) => {
|
|
8
|
+
const currentUser = req.currentUser;
|
|
9
|
+
if (!currentUser) {
|
|
10
|
+
throw new not_authorized_error_1.NotAuthorizedError();
|
|
11
|
+
}
|
|
12
|
+
if (!roles.includes(currentUser.role)) {
|
|
13
|
+
throw new forbidden_error_1.ForbiddenError();
|
|
14
|
+
}
|
|
15
|
+
return next();
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
exports.allowRoles = allowRoles;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from "express";
|
|
2
2
|
import { UserRoles } from "../enum/roles";
|
|
3
|
+
import { RedisWrapper } from "../redis-wrapper";
|
|
4
|
+
import NodeCache from "node-cache";
|
|
3
5
|
export interface UserJwtPayload {
|
|
4
6
|
id: string;
|
|
5
7
|
email: string;
|
|
@@ -26,4 +28,13 @@ declare global {
|
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
}
|
|
31
|
+
export declare class CurrentUserMiddleware {
|
|
32
|
+
private readonly redisClient;
|
|
33
|
+
private readonly localCache;
|
|
34
|
+
constructor(params?: {
|
|
35
|
+
redisClient?: RedisWrapper;
|
|
36
|
+
localCache?: NodeCache;
|
|
37
|
+
});
|
|
38
|
+
getMiddleware(): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
39
|
+
}
|
|
29
40
|
export declare const currentUser: (req: Request, res: Response, next: NextFunction) => void;
|
|
@@ -1,10 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
5
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.currentUser = void 0;
|
|
15
|
+
exports.currentUser = exports.CurrentUserMiddleware = void 0;
|
|
7
16
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
17
|
+
class CurrentUserMiddleware {
|
|
18
|
+
constructor(params) {
|
|
19
|
+
this.localCache = (params === null || params === void 0 ? void 0 : params.localCache) || null;
|
|
20
|
+
this.redisClient = (params === null || params === void 0 ? void 0 : params.redisClient) || null;
|
|
21
|
+
}
|
|
22
|
+
getMiddleware() {
|
|
23
|
+
return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
var _a, _b, _c, _d;
|
|
25
|
+
try {
|
|
26
|
+
const token = (_a = req.headers["authorization"]) === null || _a === void 0 ? void 0 : _a.split(" ")[1];
|
|
27
|
+
if (!token) {
|
|
28
|
+
return next();
|
|
29
|
+
}
|
|
30
|
+
const payload = jsonwebtoken_1.default.verify(token, process.env.JWT_KEY);
|
|
31
|
+
const userData = {
|
|
32
|
+
id: payload.sub,
|
|
33
|
+
email: payload.email,
|
|
34
|
+
firstName: payload.firstName,
|
|
35
|
+
lastName: payload.lastName,
|
|
36
|
+
role: payload.role,
|
|
37
|
+
};
|
|
38
|
+
// If JWT has jti claim — it’s important for revocation
|
|
39
|
+
const jti = payload.jti;
|
|
40
|
+
if (!jti) {
|
|
41
|
+
return next();
|
|
42
|
+
}
|
|
43
|
+
// Check local cache first (fast)
|
|
44
|
+
if ((_b = this.localCache) === null || _b === void 0 ? void 0 : _b.get(jti)) {
|
|
45
|
+
return next();
|
|
46
|
+
}
|
|
47
|
+
// Then check Redis
|
|
48
|
+
const redisResult = yield ((_c = this.redisClient) === null || _c === void 0 ? void 0 : _c.get(`revoked:${jti}`));
|
|
49
|
+
if (redisResult) {
|
|
50
|
+
// store in local cache to reduce redis lookups
|
|
51
|
+
(_d = this.localCache) === null || _d === void 0 ? void 0 : _d.set(jti, true, 60 * 5); // cache for 5 min
|
|
52
|
+
return next();
|
|
53
|
+
}
|
|
54
|
+
// All good — attach user
|
|
55
|
+
req.currentUser = userData;
|
|
56
|
+
next();
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.error("Auth error:", err);
|
|
60
|
+
return next();
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.CurrentUserMiddleware = CurrentUserMiddleware;
|
|
8
66
|
const currentUser = (req, res, next) => {
|
|
9
67
|
var _a;
|
|
10
68
|
const token = (_a = req.headers["authorization"]) === null || _a === void 0 ? void 0 : _a.split(" ")[1];
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
import { ClassConstructor } from 'class-transformer';
|
|
3
|
-
export declare function validationMiddleware<T extends object>(type: ClassConstructor<T>, skipMissingProperties?: boolean): (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
3
|
+
export declare function validationMiddleware<T extends object>(type: ClassConstructor<T>, field?: 'body' | 'query' | 'params', skipMissingProperties?: boolean): (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
@@ -12,11 +12,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.validationMiddleware = validationMiddleware;
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
|
-
function validationMiddleware(type, skipMissingProperties = false) {
|
|
15
|
+
function validationMiddleware(type, field = 'body', skipMissingProperties = false) {
|
|
16
16
|
return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
17
17
|
try {
|
|
18
18
|
// Transform plain object to class instance
|
|
19
|
-
const dto = (0, class_transformer_1.plainToClass)(type, req
|
|
19
|
+
const dto = (0, class_transformer_1.plainToClass)(type, req[field]);
|
|
20
20
|
// Validate the DTO
|
|
21
21
|
const errors = yield (0, class_validator_1.validate)(dto, {
|
|
22
22
|
skipMissingProperties,
|
|
@@ -43,7 +43,7 @@ function validationMiddleware(type, skipMissingProperties = false) {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
// Attach the validated and transformed DTO to the request
|
|
46
|
-
req.body = dto;
|
|
46
|
+
req.body = (0, class_transformer_1.instanceToPlain)(dto, { exposeUnsetFields: false });
|
|
47
47
|
next();
|
|
48
48
|
}
|
|
49
49
|
catch (error) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Redis } from "ioredis";
|
|
2
|
+
declare class RedisWrapper {
|
|
3
|
+
private _client;
|
|
4
|
+
private host;
|
|
5
|
+
private port;
|
|
6
|
+
private username;
|
|
7
|
+
private password;
|
|
8
|
+
constructor(params?: {
|
|
9
|
+
host?: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
username?: string;
|
|
12
|
+
password?: string;
|
|
13
|
+
});
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
disconnect(): Promise<void>;
|
|
16
|
+
set(key: string, value: string, expireInSeconds: number): Promise<void>;
|
|
17
|
+
get(key: string): Promise<string | null>;
|
|
18
|
+
get client(): Redis;
|
|
19
|
+
}
|
|
20
|
+
export { RedisWrapper };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RedisWrapper = void 0;
|
|
13
|
+
const ioredis_1 = require("ioredis");
|
|
14
|
+
class RedisWrapper {
|
|
15
|
+
constructor(params) {
|
|
16
|
+
this._client = null;
|
|
17
|
+
this.host = (params === null || params === void 0 ? void 0 : params.host) || "localhost";
|
|
18
|
+
this.port = (params === null || params === void 0 ? void 0 : params.port) || 6379;
|
|
19
|
+
this.username = (params === null || params === void 0 ? void 0 : params.username) || "";
|
|
20
|
+
this.password = (params === null || params === void 0 ? void 0 : params.password) || "";
|
|
21
|
+
}
|
|
22
|
+
connect() {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
try {
|
|
25
|
+
this._client = new ioredis_1.Redis({
|
|
26
|
+
host: this.host,
|
|
27
|
+
port: this.port,
|
|
28
|
+
username: this.username,
|
|
29
|
+
password: this.password,
|
|
30
|
+
lazyConnect: true,
|
|
31
|
+
});
|
|
32
|
+
yield this._client.connect();
|
|
33
|
+
console.log("✅ Connected to Redis");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
console.error("❌ Error connecting to Redis:", e.message);
|
|
38
|
+
}
|
|
39
|
+
console.log("❌ Failed to connect to Redis");
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
disconnect() {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
try {
|
|
45
|
+
if (this._client) {
|
|
46
|
+
yield this._client.quit();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
console.error("❌ Error disconnecting from Redis:", e.message);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
set(key, value, expireInSeconds) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
if (!this._client) {
|
|
57
|
+
throw new Error("Redis not connected");
|
|
58
|
+
}
|
|
59
|
+
yield this._client.set(key, value, "EX", expireInSeconds);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
get(key) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
if (!this._client) {
|
|
65
|
+
throw new Error("Redis not connected");
|
|
66
|
+
}
|
|
67
|
+
return yield this._client.get(key);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
get client() {
|
|
71
|
+
if (!this._client) {
|
|
72
|
+
throw new Error("Cannot access Redis client before connecting");
|
|
73
|
+
}
|
|
74
|
+
return this._client;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.RedisWrapper = RedisWrapper;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eratu/common",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "A package for shared code across microservices",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
"cookie-session": "^2.1.0",
|
|
29
29
|
"express": "^4.21.2",
|
|
30
30
|
"express-validator": "^7.2.1",
|
|
31
|
+
"ioredis": "^5.8.2",
|
|
31
32
|
"jsonwebtoken": "^9.0.2",
|
|
32
|
-
"nats": "^2.29.3"
|
|
33
|
+
"nats": "^2.29.3",
|
|
34
|
+
"node-cache": "^5.1.2"
|
|
33
35
|
}
|
|
34
36
|
}
|
|
File without changes
|
|
File without changes
|