Fix API authentication and identity service updates

This commit is contained in:
2026-09-02 18:19:34 +05:30
parent 54cd2a1e5f
commit a579da0f70
8 changed files with 1244 additions and 6 deletions
+25
View File
@@ -0,0 +1,25 @@
$content = Get-Content -Raw "c:\Users\Lenovo\Desktop\ai_pharma_frontend\src\services\api.ts"
$target = "}, (error) => {`r`n return Promise.reject(error);`r`n});"
$replacement = @"
}, (error) => {
return Promise.reject(error);
});
// Response interceptor to handle global errors like 401 Unauthorized
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && error.response.status === 401) {
// Token is invalid or expired
localStorage.removeItem('auth_token');
localStorage.removeItem('user');
localStorage.removeItem('actor_id');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
"@
$content = $content.Replace($target, $replacement)
Set-Content -Path "c:\Users\Lenovo\Desktop\ai_pharma_frontend\src\services\api.ts" -Value $content -NoNewline
+176
View File
@@ -0,0 +1,176 @@
const fs = require('fs');
const collection = {
info: {
name: "Pharmacy Core API",
description: "API collection for Pharmacy Core API",
schema: "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
variable: [
{
key: "baseUrl",
value: "http://localhost:8080",
type: "string"
},
{
key: "token",
value: "",
type: "string"
}
],
auth: {
type: "bearer",
bearer: [
{
key: "token",
value: "{{token}}",
type: "string"
}
]
},
item: []
};
function createFolder(name, endpoints, prefix) {
const items = endpoints.map(ep => {
const method = ep.method.toUpperCase();
const fullPath = (prefix + ep.path).replace(/\/$/, "");
const urlParts = fullPath.split('/').filter(p => p !== '');
const request = {
method: method,
header: [],
url: {
raw: `{{baseUrl}}${fullPath}`,
host: ["{{baseUrl}}"],
path: urlParts
}
};
if (['POST', 'PUT', 'PATCH'].includes(method)) {
request.body = {
mode: "raw",
raw: "{}",
options: {
raw: {
language: "json"
}
}
};
}
return {
name: ep.name || `${method} ${ep.path}`,
request: request
};
});
return {
name: name,
item: items
};
}
const modules = [
{
name: "Auth / Identity",
prefix: "/v1/auth",
endpoints: [
{ method: "GET", path: "/me", name: "Get Current User" },
{ method: "PUT", path: "/me", name: "Update Current User" },
{ method: "POST", path: "/register", name: "Register" },
{ method: "POST", path: "/login", name: "Login" },
{ method: "POST", path: "/logout", name: "Logout" },
{ method: "POST", path: "/token", name: "Refresh Token" }
]
},
{
name: "Catalogue",
prefix: "/v1",
endpoints: [
{ method: "GET", path: "/drugs", name: "Get Drugs" },
{ method: "POST", path: "/drugs", name: "Create Drug" },
{ method: "GET", path: "/drugs/search", name: "Search Drugs" },
{ method: "GET", path: "/products/:product_id/batches", name: "Get Product Batches" }
]
},
{
name: "Inventory",
prefix: "/v1/inventory",
endpoints: [
{ method: "POST", path: "/grn", name: "Create GRN" },
{ method: "GET", path: "/expiring", name: "Get Expiring Stock" },
{ method: "GET", path: "/low-stock", name: "Get Low Stock" },
{ method: "POST", path: "/adjustments", name: "Stock Adjustment" },
{ method: "GET", path: "/recall/:batch_no", name: "Recall Batch" }
]
},
{
name: "Dispensing (Orders)",
prefix: "/v1/orders",
endpoints: [
{ method: "GET", path: "/history", name: "Get Order History" },
{ method: "GET", path: "/h1-register", name: "Get H1 Register" },
{ method: "GET", path: "/:id/invoice/pdf", name: "Get Invoice PDF" },
{ method: "POST", path: "/", name: "Create Order" },
{ method: "PATCH", path: "/:id/items", name: "Update Order Items" },
{ method: "POST", path: "/:id/precheck", name: "Precheck Order" },
{ method: "POST", path: "/:id/dispense", name: "Dispense Order" }
]
},
{
name: "Audit",
prefix: "/v1/audit",
endpoints: [
{ method: "GET", path: "/ai-calls", name: "Get AI Calls" },
{ method: "GET", path: "/overrides", name: "Get Overrides" },
{ method: "GET", path: "/h1-register", name: "Get H1 Register Audit" },
{ method: "GET", path: "/sales-register", name: "Get Sales Register" },
{ method: "GET", path: "/dashboard-metrics", name: "Get Dashboard Metrics" }
]
},
{
name: "Prescription",
prefix: "/v1/rx",
endpoints: [
{ method: "POST", path: "/", name: "Upload Prescription" },
{ method: "GET", path: "/", name: "Get Prescriptions" },
{ method: "GET", path: "/:id", name: "Get Prescription by ID" },
{ method: "POST", path: "/:id/confirm", name: "Confirm Prescription" }
]
},
{
name: "AI",
prefix: "/v1/ai",
endpoints: [
{ method: "POST", path: "/voice", name: "Voice AI" }
]
},
{
name: "Integration",
prefix: "/v1/integration",
endpoints: [
{ method: "POST", path: "/hospital/patient-sync", name: "Sync Hospital Patient" },
{ method: "GET", path: "/hospital/patients", name: "Get Hospital Patients" },
{ method: "POST", path: "/telegaruda/prescription", name: "Receive Telegaruda Rx" },
{ method: "GET", path: "/telegaruda/patient/:patientId", name: "Fetch Telegaruda Patient" },
{ method: "GET", path: "/hospital/prescriptions", name: "Get Hospital Prescriptions" }
]
},
{
name: "Upload",
prefix: "/v1/upload",
endpoints: [
{ method: "POST", path: "/", name: "Upload File" },
{ method: "GET", path: "/presigned", name: "Get Presigned URL" }
]
}
];
modules.forEach(mod => {
collection.item.push(createFolder(mod.name, mod.endpoints, mod.prefix));
});
// Write to file
fs.writeFileSync('postman_collection.json', JSON.stringify(collection, null, 2));
console.log('Collection generated at postman_collection.json');
+948
View File
@@ -0,0 +1,948 @@
{
"info": {
"name": "Pharmacy Core API",
"description": "API collection for Pharmacy Core API",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
{
"key": "baseUrl",
"value": "http://localhost:8080",
"type": "string"
},
{
"key": "token",
"value": "",
"type": "string"
}
],
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{token}}",
"type": "string"
}
]
},
"item": [
{
"name": "Auth / Identity",
"item": [
{
"name": "Get Current User",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/auth/me",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"auth",
"me"
]
}
}
},
{
"name": "Update Current User",
"request": {
"method": "PUT",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/auth/me",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"auth",
"me"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Register",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/auth/register",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"auth",
"register"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Login",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/auth/login",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"auth",
"login"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Logout",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/auth/logout",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"auth",
"logout"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Refresh Token",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/auth/token",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"auth",
"token"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
}
]
},
{
"name": "Catalogue",
"item": [
{
"name": "Get Drugs",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/drugs",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"drugs"
]
}
}
},
{
"name": "Create Drug",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/drugs",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"drugs"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Search Drugs",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/drugs/search",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"drugs",
"search"
]
}
}
},
{
"name": "Get Product Batches",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/products/:product_id/batches",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"products",
":product_id",
"batches"
]
}
}
}
]
},
{
"name": "Inventory",
"item": [
{
"name": "Create GRN",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/inventory/grn",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"inventory",
"grn"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Get Expiring Stock",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/inventory/expiring",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"inventory",
"expiring"
]
}
}
},
{
"name": "Get Low Stock",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/inventory/low-stock",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"inventory",
"low-stock"
]
}
}
},
{
"name": "Stock Adjustment",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/inventory/adjustments",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"inventory",
"adjustments"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Recall Batch",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/inventory/recall/:batch_no",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"inventory",
"recall",
":batch_no"
]
}
}
}
]
},
{
"name": "Dispensing (Orders)",
"item": [
{
"name": "Get Order History",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/orders/history",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"orders",
"history"
]
}
}
},
{
"name": "Get H1 Register",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/orders/h1-register",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"orders",
"h1-register"
]
}
}
},
{
"name": "Get Invoice PDF",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/orders/:id/invoice/pdf",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"orders",
":id",
"invoice",
"pdf"
]
}
}
},
{
"name": "Create Order",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/orders",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"orders"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Update Order Items",
"request": {
"method": "PATCH",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/orders/:id/items",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"orders",
":id",
"items"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Precheck Order",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/orders/:id/precheck",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"orders",
":id",
"precheck"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Dispense Order",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/orders/:id/dispense",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"orders",
":id",
"dispense"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
}
]
},
{
"name": "Audit",
"item": [
{
"name": "Get AI Calls",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/audit/ai-calls",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"audit",
"ai-calls"
]
}
}
},
{
"name": "Get Overrides",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/audit/overrides",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"audit",
"overrides"
]
}
}
},
{
"name": "Get H1 Register Audit",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/audit/h1-register",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"audit",
"h1-register"
]
}
}
},
{
"name": "Get Sales Register",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/audit/sales-register",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"audit",
"sales-register"
]
}
}
},
{
"name": "Get Dashboard Metrics",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/audit/dashboard-metrics",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"audit",
"dashboard-metrics"
]
}
}
}
]
},
{
"name": "Prescription",
"item": [
{
"name": "Upload Prescription",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/rx",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"rx"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Get Prescriptions",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/rx",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"rx"
]
}
}
},
{
"name": "Get Prescription by ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/rx/:id",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"rx",
":id"
]
}
}
},
{
"name": "Confirm Prescription",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/rx/:id/confirm",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"rx",
":id",
"confirm"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
}
]
},
{
"name": "AI",
"item": [
{
"name": "Voice AI",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/ai/voice",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"ai",
"voice"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
}
]
},
{
"name": "Integration",
"item": [
{
"name": "Sync Hospital Patient",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/integration/hospital/patient-sync",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"integration",
"hospital",
"patient-sync"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Get Hospital Patients",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/integration/hospital/patients",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"integration",
"hospital",
"patients"
]
}
}
},
{
"name": "Receive Telegaruda Rx",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/integration/telegaruda/prescription",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"integration",
"telegaruda",
"prescription"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Fetch Telegaruda Patient",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/integration/telegaruda/patient/:patientId",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"integration",
"telegaruda",
"patient",
":patientId"
]
}
}
},
{
"name": "Get Hospital Prescriptions",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/integration/hospital/prescriptions",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"integration",
"hospital",
"prescriptions"
]
}
}
}
]
},
{
"name": "Upload",
"item": [
{
"name": "Upload File",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/upload",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"upload"
]
},
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
}
}
},
{
"name": "Get Presigned URL",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/v1/upload/presigned",
"host": [
"{{baseUrl}}"
],
"path": [
"v1",
"upload",
"presigned"
]
}
}
}
]
}
]
}
+5
View File
@@ -2,6 +2,7 @@ import express from 'express';
import cors from 'cors'; import cors from 'cors';
import helmet from 'helmet'; import helmet from 'helmet';
import { errorHandler } from './middleware/error'; import { errorHandler } from './middleware/error';
import { requireApiKey } from './middleware/auth';
// Import routers // Import routers
import identityRouter from './modules/identity/router'; import identityRouter from './modules/identity/router';
@@ -39,6 +40,9 @@ app.use((req, res, next) => {
next(); next();
}); });
// Global API Key Check
app.use(requireApiKey);
// API Routes // API Routes
app.use('/v1/auth', identityRouter); app.use('/v1/auth', identityRouter);
app.use('/v1', catalogueRouter); app.use('/v1', catalogueRouter);
@@ -61,3 +65,4 @@ app.use(errorHandler);
app.listen(PORT, () => { app.listen(PORT, () => {
console.log(`Pharmacy Core API listening on port ${PORT}`); console.log(`Pharmacy Core API listening on port ${PORT}`);
}); });
+23 -2
View File
@@ -1,7 +1,8 @@
import { Request, Response, NextFunction, RequestHandler } from 'express'; import { Request, Response, NextFunction, RequestHandler } from 'express';
import jwt from 'jsonwebtoken'; import jwt from 'jsonwebtoken';
const JWT_SECRET = process.env.JWT_SECRET || 'super_secret_pharmacy_key_2026'; // JWT_SECRET will be evaluated at runtime to avoid loading order issues
const API_KEY = process.env.API_KEY;
declare global { declare global {
namespace Express { namespace Express {
@@ -12,7 +13,26 @@ declare global {
} }
} }
export const requireApiKey: RequestHandler = (req: Request, res: Response, next: NextFunction): void => {
const apiKey = req.headers['x-api-key'];
const expectedApiKey = process.env.API_KEY;
// If API_KEY is set in .env, enforce it
if (expectedApiKey && apiKey !== expectedApiKey) {
res.status(401).json({
error: 'UNAUTHORIZED',
message: 'Missing or invalid API Key.',
details: {},
retryable: false
});
return;
}
next();
};
export const requireAuth: RequestHandler = (req: Request, res: Response, next: NextFunction): void => { export const requireAuth: RequestHandler = (req: Request, res: Response, next: NextFunction): void => {
const authHeader = req.headers.authorization; const authHeader = req.headers.authorization;
const actorId = req.headers['x-actor-id'] as string; const actorId = req.headers['x-actor-id'] as string;
@@ -29,8 +49,9 @@ export const requireAuth: RequestHandler = (req: Request, res: Response, next: N
const token = authHeader.split(' ')[1]; const token = authHeader.split(' ')[1];
try { try {
const secret = process.env.JWT_SECRET || 'super_secret_pharmacy_key_2026';
// Cryptographically verify the token using our secret key // Cryptographically verify the token using our secret key
const payload = jwt.verify(token, JWT_SECRET) as any; const payload = jwt.verify(token, secret) as any;
if (payload.userId) { if (payload.userId) {
// User JWT Token // User JWT Token
+2 -2
View File
@@ -9,7 +9,7 @@ const router = Router();
const upload = multer({ storage: multer.memoryStorage() }); const upload = multer({ storage: multer.memoryStorage() });
const s3Service = new S3Service(); const s3Service = new S3Service();
const identityService = new IdentityService(); const identityService = new IdentityService();
const JWT_SECRET = process.env.JWT_SECRET || 'super_secret_pharmacy_key_2026'; // JWT_SECRET evaluated at runtime
// GET /v1/auth/me (Get Profile) // GET /v1/auth/me (Get Profile)
router.get('/me', requireAuth, async (req, res) => { router.get('/me', requireAuth, async (req, res) => {
@@ -123,7 +123,7 @@ router.post('/token', (req, res) => {
tenantId: client_id, tenantId: client_id,
scopes: ['rx:read', 'rx:write', 'dispense:human', 'catalogue:read'] scopes: ['rx:read', 'rx:write', 'dispense:human', 'catalogue:read']
}, },
JWT_SECRET, process.env.JWT_SECRET || 'super_secret_pharmacy_key_2026',
{ expiresIn: '8h' } { expiresIn: '8h' }
); );
+2 -2
View File
@@ -2,7 +2,7 @@ import { pool } from '../../db/pool';
import bcrypt from 'bcrypt'; import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken'; import jwt from 'jsonwebtoken';
const JWT_SECRET = process.env.JWT_SECRET || 'super_secret_pharmacy_key_2026'; // JWT_SECRET evaluated at runtime
export class IdentityService { export class IdentityService {
async registerUser(payload: { async registerUser(payload: {
@@ -63,7 +63,7 @@ export class IdentityService {
role: user.role, role: user.role,
tenant_id: user.tenant_id tenant_id: user.tenant_id
}, },
JWT_SECRET, process.env.JWT_SECRET || 'super_secret_pharmacy_key_2026',
{ expiresIn: '12h' } // Usually 8-12 hours for a shift { expiresIn: '12h' } // Usually 8-12 hours for a shift
); );
+63
View File
@@ -0,0 +1,63 @@
import os
filepath = r"c:\Users\Lenovo\Desktop\ai_pharma_frontend\src\services\api.ts"
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
# Replacement 1: Add API_KEY to axios.create
old_axios_create = """export const api = axios.create({
baseURL: API_BASE_URL,
headers: {
'Content-Type': 'application/json',
},
});"""
new_axios_create = """export const api = axios.create({
baseURL: API_BASE_URL,
headers: {
'Content-Type': 'application/json',
'x-api-key': import.meta.env.VITE_API_KEY || '',
},
});"""
content = content.replace(old_axios_create, new_axios_create)
# Replacement 2: update authenticate
old_auth = """ const response = await axios.post(`${API_BASE_URL}/auth/token`, {
grant_type: 'client_credentials',
client_id: 'jayam_web_ai',
client_secret: 'my_secret_key'
});"""
new_auth = """ const response = await axios.post(`${API_BASE_URL}/auth/token`, {
grant_type: 'client_credentials',
client_id: 'jayam_web_ai',
client_secret: 'my_secret_key'
}, {
headers: { 'x-api-key': import.meta.env.VITE_API_KEY || '' }
});"""
content = content.replace(old_auth, new_auth)
# Replacement 3: update loginPharmacist
old_login = """ const response = await axios.post(`${API_BASE_URL}/auth/login`, credentials);"""
new_login = """ const response = await axios.post(`${API_BASE_URL}/auth/login`, credentials, {
headers: { 'x-api-key': import.meta.env.VITE_API_KEY || '' }
});"""
content = content.replace(old_login, new_login)
# Replacement 4: update logoutPharmacist
old_logout = """ const response = await axios.post(`${API_BASE_URL}/auth/logout`);"""
new_logout = """ const response = await axios.post(`${API_BASE_URL}/auth/logout`, {}, {
headers: { 'x-api-key': import.meta.env.VITE_API_KEY || '' }
});"""
content = content.replace(old_logout, new_logout)
with open(filepath, "w", encoding="utf-8") as f:
f.write(content)
print("Updated api.ts")