Skip to content

Commit ef6af16

Browse files
committed
feat: added protection in the metrics routes
1 parent 1c80b96 commit ef6af16

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

.env.example

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ INDEXER_URL=https://grants-stack-indexer-v2.gitcoin.co/
66
NODE_ENV=development
77

88
NEW_RELIC_APP_NAME=retrofunding-api
9-
NEW_RELIC_LICENSE_KEY=XXXXXXXXXXXXX
9+
NEW_RELIC_LICENSE_KEY=XXXXXXXXXXXXX
10+
ADMIN_API_KEY=XXXXXXXXXXXXX
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { env } from '@/env';
2+
import { UnauthorizedError } from '@/errors';
3+
import { type Request, type Response } from 'express';
4+
5+
export const adminAuthMiddleware = (req: Request, res: Response): void => {
6+
const adminApiKey = req.headers['x-admin-api-key'];
7+
8+
if (adminApiKey !== env.ADMIN_API_KEY) {
9+
res.status(401).json({ message: 'Unauthorized' });
10+
throw new UnauthorizedError('Unauthorized');
11+
}
12+
};

src/controllers/metricController.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import metricService from '@/service/MetricService';
33
import { catchError, validateRequest } from '@/utils';
44
import { type Metric, MetricOrientation } from '@/entity/Metric';
55
import { BadRequestError, IsNullError } from '@/errors';
6+
import { adminAuthMiddleware } from '@/controllers/adminAuthMiddleware';
67
import { createLogger } from '@/logger';
78

89
const logger = createLogger();
@@ -31,8 +32,7 @@ export const addMetrics = async (
3132
// Validate the incoming request
3233
validateRequest(req, res);
3334

34-
// TODO: ensure caller is admin
35-
35+
adminAuthMiddleware(req, res);
3636
const data = req.body as Metric[];
3737

3838
// Combined validation to check if req.body is Metric[]
@@ -66,6 +66,8 @@ export const updateMetric = async (
6666
const identifier = req.params.identifier;
6767
const metric = req.body as Partial<Metric>;
6868

69+
adminAuthMiddleware(req, res);
70+
6971
const [error, metrics] = await catchError(
7072
metricService.updateMetric(identifier, metric)
7173
);

src/routes/metricRoutes.ts

+21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ const router = Router();
1010
* tags:
1111
* - metrics
1212
* summary: Adds an array of metrics to the database
13+
* security:
14+
* - AdminApiKey: []
15+
* parameters:
16+
* - in: header
17+
* name: X-Admin-API-Key
18+
* schema:
19+
* type: string
20+
* required: true
21+
* description: Admin API key for authentication
1322
* requestBody:
1423
* required: true
1524
* content:
@@ -70,6 +79,8 @@ const router = Router();
7079
* description: Metrics added successfully
7180
* 400:
7281
* description: Invalid input
82+
* 401:
83+
* description: Unauthorized - Invalid or missing admin API key
7384
* 500:
7485
* description: Internal server error
7586
*/
@@ -82,6 +93,8 @@ router.post('/', addMetrics);
8293
* tags:
8394
* - metrics
8495
* summary: Updates a metric
96+
* security:
97+
* - AdminApiKey: []
8598
* parameters:
8699
* - in: path
87100
* name: identifier
@@ -90,6 +103,12 @@ router.post('/', addMetrics);
90103
* schema:
91104
* type: string
92105
* example: "userEngagement"
106+
* - in: header
107+
* name: X-Admin-API-Key
108+
* schema:
109+
* type: string
110+
* required: true
111+
* description: Admin API key for authentication
93112
* requestBody:
94113
* required: true
95114
* content:
@@ -106,6 +125,8 @@ router.post('/', addMetrics);
106125
* description: Metric updated successfully
107126
* 400:
108127
* description: Invalid input
128+
* 401:
129+
* description: Unauthorized - Invalid or missing admin API key
109130
* 500:
110131
* description: Internal server error
111132
*/

0 commit comments

Comments
 (0)