@sustaina/iam-middleware 1.0.1

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.
Files changed (62) hide show
  1. package/README.md +61 -0
  2. package/dist/auth/AuthMiddleware.d.ts +51 -0
  3. package/dist/auth/AuthMiddleware.d.ts.map +1 -0
  4. package/dist/auth/AuthMiddleware.js +312 -0
  5. package/dist/auth/AuthMiddleware.js.map +1 -0
  6. package/dist/auth/ImplementModeMiddleware.d.ts +26 -0
  7. package/dist/auth/ImplementModeMiddleware.d.ts.map +1 -0
  8. package/dist/auth/ImplementModeMiddleware.js +77 -0
  9. package/dist/auth/ImplementModeMiddleware.js.map +1 -0
  10. package/dist/base/BaseMiddleware.d.ts +15 -0
  11. package/dist/base/BaseMiddleware.d.ts.map +1 -0
  12. package/dist/base/BaseMiddleware.js +50 -0
  13. package/dist/base/BaseMiddleware.js.map +1 -0
  14. package/dist/domain/entities/AggregateRoot.d.ts +17 -0
  15. package/dist/domain/entities/AggregateRoot.d.ts.map +1 -0
  16. package/dist/domain/entities/AggregateRoot.js +79 -0
  17. package/dist/domain/entities/AggregateRoot.js.map +1 -0
  18. package/dist/domain/entities/Currency.d.ts +26 -0
  19. package/dist/domain/entities/Currency.d.ts.map +1 -0
  20. package/dist/domain/entities/Currency.js +51 -0
  21. package/dist/domain/entities/Currency.js.map +1 -0
  22. package/dist/domain/entities/OutboxEvent.d.ts +17 -0
  23. package/dist/domain/entities/OutboxEvent.d.ts.map +1 -0
  24. package/dist/domain/entities/OutboxEvent.js +24 -0
  25. package/dist/domain/entities/OutboxEvent.js.map +1 -0
  26. package/dist/domain/event/DomainEvent.d.ts +38 -0
  27. package/dist/domain/event/DomainEvent.d.ts.map +1 -0
  28. package/dist/domain/event/DomainEvent.js +20 -0
  29. package/dist/domain/event/DomainEvent.js.map +1 -0
  30. package/dist/domain/repositories/OutboxRepository.d.ts +7 -0
  31. package/dist/domain/repositories/OutboxRepository.d.ts.map +1 -0
  32. package/dist/domain/repositories/OutboxRepository.js +3 -0
  33. package/dist/domain/repositories/OutboxRepository.js.map +1 -0
  34. package/dist/errors/index.d.ts +71 -0
  35. package/dist/errors/index.d.ts.map +1 -0
  36. package/dist/errors/index.js +150 -0
  37. package/dist/errors/index.js.map +1 -0
  38. package/dist/index.d.ts +7 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +23 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/infrastructure/RedisClient.d.ts +14 -0
  43. package/dist/infrastructure/RedisClient.d.ts.map +1 -0
  44. package/dist/infrastructure/RedisClient.js +69 -0
  45. package/dist/infrastructure/RedisClient.js.map +1 -0
  46. package/dist/logging/EventLogMiddleware.d.ts +4 -0
  47. package/dist/logging/EventLogMiddleware.d.ts.map +1 -0
  48. package/dist/logging/EventLogMiddleware.js +49 -0
  49. package/dist/logging/EventLogMiddleware.js.map +1 -0
  50. package/dist/shared/config.d.ts +2 -0
  51. package/dist/shared/config.d.ts.map +1 -0
  52. package/dist/shared/config.js +5 -0
  53. package/dist/shared/config.js.map +1 -0
  54. package/dist/test.d.ts +4 -0
  55. package/dist/test.d.ts.map +1 -0
  56. package/dist/test.js +80 -0
  57. package/dist/test.js.map +1 -0
  58. package/dist/types/AuthTypes.d.ts +43 -0
  59. package/dist/types/AuthTypes.d.ts.map +1 -0
  60. package/dist/types/AuthTypes.js +3 -0
  61. package/dist/types/AuthTypes.js.map +1 -0
  62. package/package.json +62 -0
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # @sustaina/iam-middleware
2
+
3
+ ## For CD
4
+ add these line in ```kustomization.yaml``` file in ```*-deploy``` repository
5
+ ```
6
+ patch: |-
7
+ - op: add
8
+ path: ...
9
+ value:
10
+ - secretRef:
11
+ name: your-secret
12
+ - secretRef:
13
+ name: iam-middleware-dev-secret # <--- add this
14
+ # change dev to -> sit / uat
15
+ ```
16
+ now you good to go.
17
+ ## Example Usage
18
+ ```
19
+ import "dotenv/config";
20
+ import fastify from "fastify";
21
+ import pino from "pino";
22
+ import { AuthMiddleware } from "./auth/AuthMiddleware";
23
+ import { ImplementModeMiddleware } from "./auth/ImplementModeMiddleware";
24
+
25
+ const logger = pino({
26
+ level: process.env.LOG_LEVEL || "info",
27
+ transport: { target: "pino-pretty", options: { colorize: true } },
28
+ });
29
+
30
+ async function createApp() {
31
+ const app = fastify();
32
+
33
+ const authMiddleware = new AuthMiddleware();
34
+ const implementMode = new ImplementModeMiddleware();
35
+
36
+ // Register standardized routes
37
+ await app.register(
38
+ async (appInstance) => {
39
+ appInstance.get(
40
+ "/test",
41
+ {
42
+ preHandler: [
43
+ authMiddleware.authenticate.bind(authMiddleware), // required for implementMode.authorise and authMiddleware.permissionGuard
44
+ implementMode.authorise.bind(implementMode),
45
+ authMiddleware.permissionGuard([{ access: "canRead", subProgram: "test" }]).bind(authMiddleware),
46
+ ],
47
+ },
48
+ async (request, reply) => {
49
+ return reply.send({
50
+ success: true,
51
+ });
52
+ }
53
+ );
54
+ },
55
+ { prefix: "/api/v1" }
56
+ );
57
+
58
+ return app;
59
+ }
60
+
61
+ ```
@@ -0,0 +1,51 @@
1
+ import { FastifyRequest, FastifyReply } from "fastify";
2
+ import { AuthMiddlewareOptions, JwtPayload, UserInfo, PermissionGuardParams } from "../types/AuthTypes";
3
+ import { BaseMiddleware } from "../base/BaseMiddleware";
4
+ declare module "fastify" {
5
+ interface FastifyRequest {
6
+ user?: UserInfo;
7
+ payload?: JwtPayload;
8
+ }
9
+ }
10
+ export declare class AuthMiddleware extends BaseMiddleware {
11
+ private readonly jwtSecret;
12
+ /**
13
+ * It allows providing the Redis connection through these options
14
+ * 1. a URL string
15
+ * 2. a pre-configured Redis client instance.
16
+ * 3. IAM_REDIS_URL env **(recommended)**
17
+ *
18
+ * And provide jwt secret via IAM_JWT_SECRET env **(recommended)**
19
+ *
20
+ * @param {AuthMiddlewareOptions} [options.serviceName] - An optional unique name for the service using this middleware.
21
+ * @param {AuthMiddlewareOptions} [options.redisUrl] - A optional connection URL for the Redis server (e.g., 'redis://localhost:6379').
22
+ * @param {AuthMiddlewareOptions} [options.redisClient] - A optional pre-configured Redis client instance.
23
+ * @param {AuthMiddlewareOptions} [options.jwtSecret] - A optional jwt secret.
24
+ */
25
+ constructor(options?: AuthMiddlewareOptions);
26
+ private verifyJwt;
27
+ private checkAllowList;
28
+ /**
29
+ * A middleware to check if jwt token is valid and **populate request object with user and payload info**.
30
+ * @example
31
+ * const authMiddleware = new AuthMiddleware()
32
+ * const prehandler = [authMiddleware.authenticate.bind(authMiddleware)]
33
+ */
34
+ authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<undefined>;
35
+ private checkPermission;
36
+ /**
37
+ * A middleware to check if user has permissions.
38
+ * @example
39
+ * const authMiddleware = new AuthMiddleware()
40
+ * const prehandler = [
41
+ * authMiddleware.authenticate.bind(authMiddleware), // required
42
+ * authMiddleware.permissionGuard([
43
+ * { access: "canRead", subProgram: "sub1" },
44
+ * { access: "canRead", subProgram: "sub2" }
45
+ * ]).bind(authMiddleware)
46
+ * ]
47
+ */
48
+ permissionGuard: (params: PermissionGuardParams) => (request: FastifyRequest, reply: FastifyReply) => Promise<undefined>;
49
+ optionalAuth: (request: FastifyRequest) => Promise<void>;
50
+ }
51
+ //# sourceMappingURL=AuthMiddleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthMiddleware.d.ts","sourceRoot":"","sources":["../../src/auth/AuthMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIvD,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,QAAQ,EAER,qBAAqB,EAEtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAKxD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,IAAI,CAAC,EAAE,QAAQ,CAAC;QAChB,OAAO,CAAC,EAAE,UAAU,CAAC;KACtB;CACF;AAED,qBAAa,cAAe,SAAQ,cAAc;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC;;;;;;;;;;;;OAYG;gBACS,OAAO,CAAC,EAAE,qBAAqB;IAK3C,OAAO,CAAC,SAAS,CAEf;IAEF,OAAO,CAAC,cAAc,CAqBpB;IAEF;;;;;OAKG;IACH,YAAY,GAAU,SAAS,cAAc,EAAE,OAAO,YAAY,wBA8HhE;IAEF,OAAO,CAAC,eAAe,CA2ErB;IAEF;;;;;;;;;;;OAWG;IACH,eAAe,GAAI,QAAQ,qBAAqB,MAAY,SAAS,cAAc,EAAE,OAAO,YAAY,wBAwBtG;IAEF,YAAY,GAAU,SAAS,cAAc,mBAqD3C;CACH"}
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AuthMiddleware = void 0;
7
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ const api_1 = require("@opentelemetry/api");
9
+ const pino_1 = __importDefault(require("pino"));
10
+ const BaseMiddleware_1 = require("../base/BaseMiddleware");
11
+ const logger = (0, pino_1.default)({ name: "AuthMiddleware" });
12
+ class AuthMiddleware extends BaseMiddleware_1.BaseMiddleware {
13
+ /**
14
+ * It allows providing the Redis connection through these options
15
+ * 1. a URL string
16
+ * 2. a pre-configured Redis client instance.
17
+ * 3. IAM_REDIS_URL env **(recommended)**
18
+ *
19
+ * And provide jwt secret via IAM_JWT_SECRET env **(recommended)**
20
+ *
21
+ * @param {AuthMiddlewareOptions} [options.serviceName] - An optional unique name for the service using this middleware.
22
+ * @param {AuthMiddlewareOptions} [options.redisUrl] - A optional connection URL for the Redis server (e.g., 'redis://localhost:6379').
23
+ * @param {AuthMiddlewareOptions} [options.redisClient] - A optional pre-configured Redis client instance.
24
+ * @param {AuthMiddlewareOptions} [options.jwtSecret] - A optional jwt secret.
25
+ */
26
+ constructor(options) {
27
+ super({ ...options, name: "AuthMiddleware" });
28
+ this.verifyJwt = (token) => {
29
+ return jsonwebtoken_1.default.verify(token, this.jwtSecret);
30
+ };
31
+ this.checkAllowList = async (payload, token) => {
32
+ const allowlistKey = `auth:session:${payload.id}`;
33
+ const tokenJti = payload.jti;
34
+ if (!tokenJti) {
35
+ logger.warn({ token }, "Missing jti in token");
36
+ return false;
37
+ }
38
+ try {
39
+ const jtiInRedis = await this.redisClient.get(allowlistKey);
40
+ const isAllowlisted = jtiInRedis === tokenJti;
41
+ logger.debug({ allowlistKey, tokenJti, jtiInRedis, isAllowlisted }, "Checked Token allowlist in Redis");
42
+ return isAllowlisted;
43
+ }
44
+ catch (err) {
45
+ logger.error({ err, allowlistKey }, "Redis allowlist check failed");
46
+ throw err;
47
+ }
48
+ };
49
+ /**
50
+ * A middleware to check if jwt token is valid and **populate request object with user and payload info**.
51
+ * @example
52
+ * const authMiddleware = new AuthMiddleware()
53
+ * const prehandler = [authMiddleware.authenticate.bind(authMiddleware)]
54
+ */
55
+ this.authenticate = async (request, reply) => {
56
+ const tracer = api_1.trace.getTracer(this.serviceName);
57
+ const span = tracer.startSpan("AuthMiddleware.authenticate");
58
+ try {
59
+ const authHeader = request.headers.authorization;
60
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
61
+ span.setAttributes({
62
+ "error.type": "missing_token",
63
+ "error.message": "No authorization token provided",
64
+ });
65
+ logger.warn({ url: request.url }, "Authentication failed: No token provided");
66
+ return reply.status(401).send({
67
+ error: "Authentication Error",
68
+ message: "Authorization token is required",
69
+ });
70
+ }
71
+ const token = authHeader.substring(7);
72
+ // Verify JWT token
73
+ let payload;
74
+ try {
75
+ payload = this.verifyJwt(token);
76
+ request.payload = payload;
77
+ }
78
+ catch (jwtError) {
79
+ span.setAttributes({
80
+ "error.type": "invalid_token",
81
+ "error.message": "Token verification failed",
82
+ });
83
+ logger.warn({
84
+ url: request.url,
85
+ error: jwtError instanceof Error ? jwtError.message : "Unknown JWT error",
86
+ }, "Authentication failed: Invalid token");
87
+ return reply.status(401).send({
88
+ error: "Authentication Error",
89
+ message: "Invalid or expired token",
90
+ });
91
+ }
92
+ // Validate payload structure
93
+ if (!payload.id ||
94
+ !payload.name ||
95
+ !payload.email ||
96
+ !payload.tenantId ||
97
+ !payload.type ||
98
+ !payload.tenantLocale ||
99
+ !payload.passwordPolicy ||
100
+ payload.isDenyPasswordChange === undefined ||
101
+ payload.isPasswordSendEmail === undefined) {
102
+ span.setAttributes({
103
+ "error.type": "invalid_payload",
104
+ "error.message": "Token payload is incomplete",
105
+ });
106
+ logger.warn({ url: request.url, payload }, "Authentication failed: Invalid token payload");
107
+ return reply.status(401).send({
108
+ error: "Authentication Error",
109
+ message: "Invalid token payload",
110
+ });
111
+ }
112
+ // Check allowlist (Redis)
113
+ try {
114
+ const result = await this.checkAllowList(payload, token);
115
+ if (!result) {
116
+ return reply.status(401).send({
117
+ error: "Authentication Error",
118
+ message: "Token is not in allow list",
119
+ });
120
+ }
121
+ }
122
+ catch (error) {
123
+ logger.error({ error: error.message, url: request.url }, "Token validation failed in AuthMiddleware");
124
+ return reply.status(500).send({
125
+ error: "Internal Server Error",
126
+ message: "Error while checking token validity",
127
+ });
128
+ }
129
+ // Attach user info to request
130
+ request.user = {
131
+ id: payload.id,
132
+ name: payload.name,
133
+ email: payload.email,
134
+ type: payload.type,
135
+ };
136
+ span.setAttributes({
137
+ "user.id": payload.id,
138
+ "user.email": payload.email,
139
+ "user.name": payload.name,
140
+ "user.username": payload.username,
141
+ "auth.success": true,
142
+ });
143
+ logger.debug({
144
+ userId: payload.id,
145
+ email: payload.email,
146
+ url: request.url,
147
+ }, "User authenticated successfully");
148
+ }
149
+ catch (error) {
150
+ span.recordException(error);
151
+ span.setAttributes({
152
+ "error.type": "middleware_error",
153
+ });
154
+ logger.error({ error, url: request.url }, "Error in authentication middleware");
155
+ return reply.status(500).send({
156
+ error: "Internal Server Error",
157
+ message: "Authentication service error",
158
+ });
159
+ }
160
+ finally {
161
+ span.end();
162
+ }
163
+ };
164
+ this.checkPermission = async ({ userId, access, subProgram }, reply, payload) => {
165
+ // skip if user is admin
166
+ if (payload.type === "administrator") {
167
+ return;
168
+ }
169
+ try {
170
+ const redis = this.redisClient;
171
+ const pipeline = redis.multi();
172
+ const cacheKey = `auth:permission:${subProgram.replace(/\s+/g, "")}:${userId}`;
173
+ const get = await redis.get(cacheKey);
174
+ const accessKey = get ? JSON.parse(get) : null;
175
+ if (!accessKey) {
176
+ return reply.status(403).send({
177
+ error: "PermissionNotFound",
178
+ message: `Permission not found for subprogram ${subProgram}`,
179
+ });
180
+ }
181
+ await pipeline.exec();
182
+ const ErrorCustom = (message) => reply.status(403).send({
183
+ error: "PermissionDenied",
184
+ message,
185
+ });
186
+ switch (access) {
187
+ case "canCreate":
188
+ if (!accessKey.canCreate) {
189
+ return ErrorCustom("Permission denied: cannot create");
190
+ }
191
+ break;
192
+ case "canRead":
193
+ if (!accessKey.canRead) {
194
+ return ErrorCustom("Permission denied: cannot read");
195
+ }
196
+ break;
197
+ case "canEdit":
198
+ if (!accessKey.canEdit) {
199
+ return ErrorCustom("Permission denied: cannot edit");
200
+ }
201
+ break;
202
+ case "canDelete":
203
+ if (!accessKey.canDelete) {
204
+ return ErrorCustom("Permission denied: cannot delete");
205
+ }
206
+ break;
207
+ case "canNotify":
208
+ if (!accessKey.canNotify) {
209
+ return ErrorCustom("Permission denied: cannot notify");
210
+ }
211
+ break;
212
+ case "canCreateDraft":
213
+ if (!accessKey.canCreateDraft) {
214
+ return ErrorCustom("Permission denied: cannot create draft");
215
+ }
216
+ break;
217
+ default:
218
+ return ErrorCustom(`Unknown access type: ${access}`);
219
+ }
220
+ }
221
+ catch (err) {
222
+ logger.error({ err, userId }, "Failed to check user tenant permissions");
223
+ return reply.status(500).send({
224
+ error: "Internal Server Error",
225
+ message: "Redis error while checking permissions",
226
+ });
227
+ }
228
+ };
229
+ /**
230
+ * A middleware to check if user has permissions.
231
+ * @example
232
+ * const authMiddleware = new AuthMiddleware()
233
+ * const prehandler = [
234
+ * authMiddleware.authenticate.bind(authMiddleware), // required
235
+ * authMiddleware.permissionGuard([
236
+ * { access: "canRead", subProgram: "sub1" },
237
+ * { access: "canRead", subProgram: "sub2" }
238
+ * ]).bind(authMiddleware)
239
+ * ]
240
+ */
241
+ this.permissionGuard = (params) => async (request, reply) => {
242
+ let pool = [];
243
+ if (!Array.isArray(params)) {
244
+ pool = [params];
245
+ }
246
+ else {
247
+ pool = params;
248
+ }
249
+ if (!request.user) {
250
+ logger.error("permissionGuard: no user info from AuthMiddleware.authenticate");
251
+ return reply.status(401).send({ error: "Authentication Error", message: "User not authenticated" });
252
+ }
253
+ await Promise.all(pool.map((v) => this.checkPermission({
254
+ userId: request.user.id,
255
+ subProgram: v.subProgram,
256
+ access: v.access,
257
+ }, reply, request.payload)));
258
+ };
259
+ this.optionalAuth = async (request) => {
260
+ const tracer = api_1.trace.getTracer(this.serviceName);
261
+ const span = tracer.startSpan("AuthMiddleware.optionalAuth");
262
+ try {
263
+ const authHeader = request.headers.authorization;
264
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
265
+ span.setAttributes({
266
+ "auth.optional": true,
267
+ "auth.token_present": false,
268
+ });
269
+ return;
270
+ }
271
+ const token = authHeader.substring(7);
272
+ try {
273
+ const payload = this.verifyJwt(token);
274
+ if (payload.id &&
275
+ payload.name &&
276
+ payload.email &&
277
+ payload.tenantId &&
278
+ payload.type &&
279
+ payload.tenantLocale &&
280
+ payload.passwordPolicy &&
281
+ payload.isDenyPasswordChange !== undefined &&
282
+ payload.isPasswordSendEmail !== undefined) {
283
+ request.user = { id: payload.id, name: payload.name, email: payload.email, type: payload.type };
284
+ span.setAttributes({
285
+ "auth.optional": true,
286
+ "auth.token_present": true,
287
+ "user.id": payload.id,
288
+ });
289
+ }
290
+ }
291
+ catch (jwtError) {
292
+ logger.debug({ error: jwtError }, "Optional auth: Invalid token provided");
293
+ span.setAttributes({
294
+ "auth.optional": true,
295
+ "auth.token_present": true,
296
+ "auth.token_valid": false,
297
+ });
298
+ }
299
+ }
300
+ catch (error) {
301
+ span.recordException(error);
302
+ logger.error({ error: error.message || error }, "Error in optional authentication middleware");
303
+ }
304
+ finally {
305
+ span.end();
306
+ }
307
+ };
308
+ this.jwtSecret = options?.jwtSecret ?? process.env.IAM_JWT_SECRET ?? "your_secret";
309
+ }
310
+ }
311
+ exports.AuthMiddleware = AuthMiddleware;
312
+ //# sourceMappingURL=AuthMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthMiddleware.js","sourceRoot":"","sources":["../../src/auth/AuthMiddleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { FastifyRequest, FastifyReply } from "fastify";
2
+ import { BaseMiddleware } from "../base/BaseMiddleware";
3
+ import { ImplementModeMiddlewareOptions } from "../types/AuthTypes";
4
+ export declare class ImplementModeMiddleware extends BaseMiddleware {
5
+ /**
6
+ * It allows providing the Redis connection through these options
7
+ * 1. a URL string
8
+ * 2. a pre-configured Redis client instance.
9
+ * 3. IAM_REDIS_URL env **(recommended)**
10
+ *
11
+ * @param {AuthMiddlewareOptions} [options.serviceName] - An optional unique name for the service using this middleware.
12
+ * @param {AuthMiddlewareOptions} [options.redisUrl] - A optional connection URL for the Redis server (e.g., 'redis://localhost:6379').
13
+ * @param {AuthMiddlewareOptions} [options.redisClient] - A optional pre-configured Redis client instance.
14
+ */
15
+ constructor(options?: ImplementModeMiddlewareOptions);
16
+ private generateTenantImplementModeKey;
17
+ /**
18
+ * A middleware to check if server is in implement mode.
19
+ * Only admin can access resources in implement mode.
20
+ * @example
21
+ * const implModeMiddleware = new ImplementModeMiddleware()
22
+ * const prehandler = [implModeMiddleware.authorise.bind(implModeMiddleware)]
23
+ */
24
+ authorise(request: FastifyRequest, reply: FastifyReply): Promise<FastifyReply | undefined>;
25
+ }
26
+ //# sourceMappingURL=ImplementModeMiddleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImplementModeMiddleware.d.ts","sourceRoot":"","sources":["../../src/auth/ImplementModeMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAKvD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAKpE,qBAAa,uBAAwB,SAAQ,cAAc;IACzD;;;;;;;;;OASG;gBACS,OAAO,CAAC,EAAE,8BAA8B;IAIpD,OAAO,CAAC,8BAA8B;IAItC;;;;;;OAMG;IACG,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;CAuDjG"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ImplementModeMiddleware = void 0;
7
+ const api_1 = require("@opentelemetry/api");
8
+ const pino_1 = __importDefault(require("pino"));
9
+ const config_1 = require("../shared/config");
10
+ const errors_1 = require("../errors");
11
+ const BaseMiddleware_1 = require("../base/BaseMiddleware");
12
+ const RedisClient_1 = require("../infrastructure/RedisClient");
13
+ const logger = (0, pino_1.default)({ name: "ImplementModeMiddleware" });
14
+ class ImplementModeMiddleware extends BaseMiddleware_1.BaseMiddleware {
15
+ /**
16
+ * It allows providing the Redis connection through these options
17
+ * 1. a URL string
18
+ * 2. a pre-configured Redis client instance.
19
+ * 3. IAM_REDIS_URL env **(recommended)**
20
+ *
21
+ * @param {AuthMiddlewareOptions} [options.serviceName] - An optional unique name for the service using this middleware.
22
+ * @param {AuthMiddlewareOptions} [options.redisUrl] - A optional connection URL for the Redis server (e.g., 'redis://localhost:6379').
23
+ * @param {AuthMiddlewareOptions} [options.redisClient] - A optional pre-configured Redis client instance.
24
+ */
25
+ constructor(options) {
26
+ super({ ...options, name: "ImplementModeMiddleware" });
27
+ }
28
+ generateTenantImplementModeKey(tenantId) {
29
+ return RedisClient_1.RedisClient.generateKey("tenant", "implement-mode", `${tenantId}`);
30
+ }
31
+ /**
32
+ * A middleware to check if server is in implement mode.
33
+ * Only admin can access resources in implement mode.
34
+ * @example
35
+ * const implModeMiddleware = new ImplementModeMiddleware()
36
+ * const prehandler = [implModeMiddleware.authorise.bind(implModeMiddleware)]
37
+ */
38
+ async authorise(request, reply) {
39
+ const tracer = api_1.trace.getTracer(config_1.SERVICE_NAME);
40
+ const span = tracer.startSpan("ImplementModeMiddleware.authorise");
41
+ try {
42
+ if (!request.payload?.tenantId) {
43
+ throw new errors_1.CustomError("ImplementModeMiddleware: Missing tenant info from AuthMiddleware.authenticate", 401, "ImplementModeMiddlewareMissingTenantIdError", "middleware_error", "User not authenticated");
44
+ }
45
+ if (!request.user) {
46
+ throw new errors_1.CustomError("ImplementModeMiddleware: Missing user info from AuthMiddleware.authenticate", 401, "ImplementModeMiddlewareMissingUserError", "middleware_error", "User not authenticated");
47
+ }
48
+ // check if user is admin
49
+ if (request.user.type === "administrator") {
50
+ return; // do nothing and progress to next handler
51
+ }
52
+ // check cache
53
+ let implementMode = false;
54
+ // this key is set by authentication-service or authentication-system-settings-consumer-services
55
+ const key = this.generateTenantImplementModeKey(request.payload.tenantId);
56
+ let raw = await this.redisClient.get(key);
57
+ if (raw === null) {
58
+ logger.info(`cache miss on ${key}`);
59
+ raw = "false"; // force to false by default
60
+ }
61
+ const cached = JSON.parse(raw);
62
+ if (!(typeof cached === "boolean")) {
63
+ throw new Error(`Invalid value type for key: ${key}`);
64
+ }
65
+ implementMode = cached;
66
+ // if implementMode is on
67
+ if (implementMode) {
68
+ throw new errors_1.CustomError("ImplementModeMiddleware: Permission Denied, Application is on implement mode", 403, "ImplementModeMiddlewarePermissionDeniedError", "middleware_error", "Application is on implement mode");
69
+ }
70
+ }
71
+ catch (error) {
72
+ return (0, errors_1.ErrorResponse)(error, reply, span, logger);
73
+ }
74
+ }
75
+ }
76
+ exports.ImplementModeMiddleware = ImplementModeMiddleware;
77
+ //# sourceMappingURL=ImplementModeMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImplementModeMiddleware.js","sourceRoot":"","sources":["../../src/auth/ImplementModeMiddleware.ts"],"names":[],"mappings":";;;;;;AACA,4CAA2C;AAC3C,gDAAwB;AACxB,6CAAgD;AAChD,sCAAuD;AACvD,2DAAwD;AAExD,+DAA4D;AAE5D,MAAM,MAAM,GAAG,IAAA,cAAI,EAAC,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;AAEzD,MAAa,uBAAwB,SAAQ,+BAAc;IACzD;;;;;;;;;OASG;IACH,YAAY,OAAwC;QAClD,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;IACzD,CAAC;IAEO,8BAA8B,CAAC,QAAgB;QACrD,OAAO,yBAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAC,OAAuB,EAAE,KAAmB;QAC1D,MAAM,MAAM,GAAG,WAAK,CAAC,SAAS,CAAC,qBAAY,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QACnE,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;gBAC/B,MAAM,IAAI,oBAAW,CACnB,+EAA+E,EAC/E,GAAG,EACH,6CAA6C,EAC7C,kBAAkB,EAClB,wBAAwB,CACzB,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAClB,MAAM,IAAI,oBAAW,CACnB,6EAA6E,EAC7E,GAAG,EACH,yCAAyC,EACzC,kBAAkB,EAClB,wBAAwB,CACzB,CAAC;YACJ,CAAC;YAED,yBAAyB;YACzB,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBAC1C,OAAO,CAAC,0CAA0C;YACpD,CAAC;YACD,cAAc;YACd,IAAI,aAAa,GAAG,KAAK,CAAC;YAC1B,gGAAgG;YAChG,MAAM,GAAG,GAAG,IAAI,CAAC,8BAA8B,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC1E,IAAI,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC;gBACpC,GAAG,GAAG,OAAO,CAAC,CAAC,4BAA4B;YAC7C,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,CAAC,OAAO,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;YACxD,CAAC;YACD,aAAa,GAAG,MAAM,CAAC;YACvB,yBAAyB;YACzB,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,IAAI,oBAAW,CACnB,8EAA8E,EAC9E,GAAG,EACH,8CAA8C,EAC9C,kBAAkB,EAClB,kCAAkC,CACnC,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAA,sBAAa,EAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;CACF;AAjFD,0DAiFC"}
@@ -0,0 +1,15 @@
1
+ import "dotenv/config";
2
+ import { RedisClientType } from "redis";
3
+ import { BaseOptions } from "../types/AuthTypes";
4
+ import { Logger } from "pino";
5
+ export declare class BaseMiddleware {
6
+ readonly logger: Logger;
7
+ protected redisClient: RedisClientType;
8
+ protected serviceName: string;
9
+ constructor(options: BaseOptions & {
10
+ name: string;
11
+ });
12
+ private setupRedisClient;
13
+ private useSingletonClient;
14
+ }
15
+ //# sourceMappingURL=BaseMiddleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseMiddleware.d.ts","sourceRoot":"","sources":["../../src/base/BaseMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAgB,eAAe,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAa,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAIpC,qBAAa,cAAc;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,WAAW,EAAG,eAAe,CAAC;IACxC,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC;gBAElB,OAAO,EAAE,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;YAerC,gBAAgB;YAqBhB,kBAAkB;CAGjC"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BaseMiddleware = void 0;
7
+ require("dotenv/config");
8
+ const redis_1 = require("redis");
9
+ const pino_1 = __importDefault(require("pino"));
10
+ const config_1 = require("../shared/config");
11
+ const RedisClient_1 = require("../infrastructure/RedisClient");
12
+ class BaseMiddleware {
13
+ constructor(options) {
14
+ this.logger = (0, pino_1.default)({ name: options.name });
15
+ this.serviceName = options.serviceName ?? config_1.SERVICE_NAME;
16
+ if ("redisUrl" in options && options.redisUrl) {
17
+ this.setupRedisClient(options.redisUrl);
18
+ }
19
+ else if ("redisClient" in options && options.redisClient) {
20
+ if (!options.redisClient.isOpen) {
21
+ options.redisClient.connect();
22
+ }
23
+ this.redisClient = options.redisClient;
24
+ }
25
+ else {
26
+ this.useSingletonClient();
27
+ }
28
+ }
29
+ async setupRedisClient(redisUrl) {
30
+ this.redisClient = (0, redis_1.createClient)({
31
+ url: redisUrl,
32
+ socket: process.env.NODE_ENV !== "local" ? { tls: true, rejectUnauthorized: false } : undefined,
33
+ });
34
+ this.redisClient.on("error", (err) => {
35
+ this.logger.error(err, "Redis client error");
36
+ });
37
+ this.redisClient.on("connect", () => {
38
+ this.logger.info("Redis client connected");
39
+ });
40
+ this.redisClient.on("disconnect", () => {
41
+ this.logger.info("Redis client disconnected");
42
+ });
43
+ await this.redisClient.connect();
44
+ }
45
+ async useSingletonClient() {
46
+ this.redisClient = await RedisClient_1.RedisClient.getInstance();
47
+ }
48
+ }
49
+ exports.BaseMiddleware = BaseMiddleware;
50
+ //# sourceMappingURL=BaseMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseMiddleware.js","sourceRoot":"","sources":["../../src/base/BaseMiddleware.ts"],"names":[],"mappings":";;;;;;AAAA,yBAAuB;AACvB,iCAAsD;AAEtD,gDAAoC;AACpC,6CAAgD;AAChD,+DAA4D;AAE5D,MAAa,cAAc;IAKzB,YAAY,OAAuC;QACjD,IAAI,CAAC,MAAM,GAAG,IAAA,cAAI,EAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,qBAAY,CAAC;QACvD,IAAI,UAAU,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,aAAa,IAAI,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YAC3D,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;gBAChC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YAChC,CAAC;YACD,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAA8B,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QAC7C,IAAI,CAAC,WAAW,GAAG,IAAA,oBAAY,EAAC;YAC9B,GAAG,EAAE,QAAQ;YACb,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS;SAChG,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC9B,IAAI,CAAC,WAAW,GAAG,MAAM,yBAAW,CAAC,WAAW,EAAE,CAAC;IACrD,CAAC;CACF;AA5CD,wCA4CC"}
@@ -0,0 +1,17 @@
1
+ import { DomainEvent } from "../event/DomainEvent";
2
+ export declare abstract class AggregateRoot {
3
+ readonly id: string;
4
+ readonly createdAt: Date;
5
+ updatedAt: Date;
6
+ private _domainEvents;
7
+ private _version;
8
+ constructor(id: string, createdAt?: Date, updatedAt?: Date);
9
+ get version(): number;
10
+ get domainEvents(): ReadonlyArray<DomainEvent>;
11
+ protected addDomainEvent(event: DomainEvent): void;
12
+ clearDomainEvents(): void;
13
+ protected applyEvent(event: DomainEvent): void;
14
+ static replayEvents<T extends AggregateRoot>(aggregateClass: new (...args: any[]) => T, events: DomainEvent[]): T;
15
+ protected abstract when(event: DomainEvent): void;
16
+ }
17
+ //# sourceMappingURL=AggregateRoot.d.ts.map