@shadimakhoul/ggcoach 1.0.1 → 1.0.2

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.
@@ -17,8 +17,8 @@ export function initExpress(isDevelopment: boolean) {
17
17
  app.use(express.json({ limit: "10mb" }));
18
18
  app.use(express.urlencoded({ extended: true, limit: "10mb" }));
19
19
 
20
+ app.use(morgan("dev", { stream } as any));
20
21
  if (isDevelopment) {
21
- app.use(morgan("dev", { stream } as any));
22
22
  } else {
23
23
  app.use(morgan("combined", { stream } as any));
24
24
  }
@@ -8,46 +8,43 @@ import { JWTPayload } from "../types";
8
8
 
9
9
  const TOKEN_VERSION_PREFIX = "auth:token-version:";
10
10
 
11
- export const authenticateToken = async (
12
- JWT_SECRET: string,
13
- req: Request,
14
- res: Response,
15
- next: NextFunction,
16
- ): Promise<void> => {
17
- const authHeader = req.headers["authorization"];
18
- const token = authHeader && authHeader.split(" ")[1]; // Bearer TOKEN
11
+ export const authenticateToken = (JWT_SECRET: string) => {
12
+ return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
13
+ const authHeader = req.headers["authorization"];
14
+ const token = authHeader && authHeader.split(" ")[1]; // Bearer TOKEN
19
15
 
20
- if (!token) {
21
- res.status(401).json({
22
- success: false,
23
- message: "Access token required",
24
- });
25
- return;
26
- }
16
+ if (!token) {
17
+ res.status(401).json({
18
+ success: false,
19
+ message: "Access token required",
20
+ });
21
+ return;
22
+ }
27
23
 
28
- try {
29
- const decoded = jwt.verify(token, JWT_SECRET, {
30
- issuer: "ggcoach-auth-service",
31
- audience: "ggcoach-app",
32
- }) as JWTPayload;
24
+ try {
25
+ const decoded = jwt.verify(token, JWT_SECRET, {
26
+ issuer: "ggcoach-auth-service",
27
+ audience: "ggcoach-app",
28
+ }) as JWTPayload;
33
29
 
34
- const isValid = await validateTokenWithRedis(decoded);
35
- if (!isValid) {
30
+ const isValid = await validateTokenWithRedis(decoded);
31
+ if (!isValid) {
32
+ res.status(403).json({
33
+ success: false,
34
+ message: "Invalid or expired token",
35
+ });
36
+ return;
37
+ }
38
+
39
+ req.user = decoded;
40
+ next();
41
+ } catch (error) {
36
42
  res.status(403).json({
37
43
  success: false,
38
44
  message: "Invalid or expired token",
39
45
  });
40
- return;
41
46
  }
42
-
43
- req.user = decoded;
44
- next();
45
- } catch (error) {
46
- res.status(403).json({
47
- success: false,
48
- message: "Invalid or expired token",
49
- });
50
- }
47
+ };
51
48
  };
52
49
 
53
50
  const validateTokenWithRedis = async (decoded: JWTPayload): Promise<boolean> => {
@@ -70,31 +67,28 @@ const validateTokenWithRedis = async (decoded: JWTPayload): Promise<boolean> =>
70
67
  }
71
68
  };
72
69
 
73
- export const optionalAuth = async (
74
- JWT_SECRET: string,
75
- req: Request,
76
- _res: Response,
77
- next: NextFunction,
78
- ): Promise<void> => {
79
- const authHeader = req.headers["authorization"];
80
- const token = authHeader && authHeader.split(" ")[1];
70
+ export const optionalAuth = (JWT_SECRET: string) => {
71
+ return async (req: Request, _res: Response, next: NextFunction): Promise<void> => {
72
+ const authHeader = req.headers["authorization"];
73
+ const token = authHeader && authHeader.split(" ")[1];
81
74
 
82
- if (token) {
83
- try {
84
- const decoded = jwt.verify(token, JWT_SECRET, {
85
- issuer: "ggcoach-auth-service",
86
- audience: "ggcoach-app",
87
- }) as JWTPayload;
88
- const isValid = await validateTokenWithRedis(decoded);
89
- if (isValid) {
90
- req.user = decoded;
75
+ if (token) {
76
+ try {
77
+ const decoded = jwt.verify(token, JWT_SECRET, {
78
+ issuer: "ggcoach-auth-service",
79
+ audience: "ggcoach-app",
80
+ }) as JWTPayload;
81
+ const isValid = await validateTokenWithRedis(decoded);
82
+ if (isValid) {
83
+ req.user = decoded;
84
+ }
85
+ } catch (error) {
86
+ // Token is invalid, but we continue without user info
87
+ const err = error instanceof Error ? error : new Error(String(error));
88
+ logger.warn(`Invalid token in optional auth: ${err.message}`);
91
89
  }
92
- } catch (error) {
93
- // Token is invalid, but we continue without user info
94
- const err = error instanceof Error ? error : new Error(String(error));
95
- logger.warn(`Invalid token in optional auth: ${err.message}`);
96
90
  }
97
- }
98
91
 
99
- next();
92
+ next();
93
+ };
100
94
  };
@@ -1,7 +1,7 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
2
  import { logger } from '../utils';
3
3
 
4
- export const errorHandler = (isDevelopment: boolean, err: any, req: Request, res: Response, next: NextFunction): void => {
4
+ export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction): void => {
5
5
  logger.error(`Error: ${err}`);
6
6
 
7
7
  // Handle specific error types
@@ -54,7 +54,7 @@ export const errorHandler = (isDevelopment: boolean, err: any, req: Request, res
54
54
  success: false,
55
55
  message: err.message || 'Internal server error',
56
56
  code: err.code || 'INTERNAL_ERROR',
57
- ...(isDevelopment && {
57
+ ...(process.env.NODE_ENV === 'development' && {
58
58
  stack: err.stack,
59
59
  requestId: req.headers['x-request-id']
60
60
  })
@@ -1,25 +1,27 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
2
 
3
- export const requireInternalToken = (ALLOW_DIRECT_ACCESS: boolean, INTERNAL_SERVICE_TOKEN: string, req: Request, res: Response, next: NextFunction): void => {
4
- if (ALLOW_DIRECT_ACCESS) {
5
- next();
6
- return;
7
- }
3
+ export const requireInternalToken = (ALLOW_DIRECT_ACCESS: boolean, INTERNAL_SERVICE_TOKEN: string) => {
4
+ return (req: Request, res: Response, next: NextFunction): void => {
5
+ if (ALLOW_DIRECT_ACCESS) {
6
+ next();
7
+ return;
8
+ }
8
9
 
9
- const token = INTERNAL_SERVICE_TOKEN;
10
- if (!token) {
11
- // If token isn't set, reject to be safe
12
- res.status(403).json({ success: false, message: 'Internal access token not configured' });
13
- return;
14
- }
10
+ const token = INTERNAL_SERVICE_TOKEN;
11
+ if (!token) {
12
+ // If token isn't set, reject to be safe
13
+ res.status(403).json({ success: false, message: 'Internal access token not configured' });
14
+ return;
15
+ }
15
16
 
16
- const incoming = (req.headers['x-internal-token'] as string) || '';
17
- if (incoming !== token) {
18
- res.status(403).json({ success: false, message: 'Forbidden' });
19
- return;
20
- }
17
+ const incoming = (req.headers['x-internal-token'] as string) || '';
18
+ if (incoming !== token) {
19
+ res.status(403).json({ success: false, message: 'Forbidden' });
20
+ return;
21
+ }
21
22
 
22
- next();
23
+ next();
24
+ };
23
25
  };
24
26
 
25
27
  export default requireInternalToken;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shadimakhoul/ggcoach",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Shared utilities and types for GGCoach microservices",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",