@adaptic/backend-legacy 0.0.70 → 0.0.72
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/client.cjs +1 -1
- package/config/jwtConfig.cjs +52 -0
- package/config/jwtConfig.d.ts +16 -0
- package/config/jwtConfig.d.ts.map +1 -0
- package/config/jwtConfig.js.map +1 -0
- package/config/metrics.cjs +261 -0
- package/config/metrics.d.ts +88 -0
- package/config/metrics.d.ts.map +1 -0
- package/config/metrics.js.map +1 -0
- package/config/persisted-queries.cjs +122 -0
- package/config/persisted-queries.d.ts +40 -0
- package/config/persisted-queries.d.ts.map +1 -0
- package/config/persisted-queries.js.map +1 -0
- package/config/tracing.cjs +128 -0
- package/config/tracing.d.ts +24 -0
- package/config/tracing.d.ts.map +1 -0
- package/config/tracing.js.map +1 -0
- package/middleware/audit-logger.cjs +223 -0
- package/middleware/audit-logger.d.ts +85 -0
- package/middleware/audit-logger.d.ts.map +1 -0
- package/middleware/audit-logger.js.map +1 -0
- package/middleware/auth.cjs +44 -0
- package/middleware/auth.d.ts +6 -0
- package/middleware/auth.d.ts.map +1 -0
- package/middleware/auth.js.map +1 -0
- package/middleware/graphql-validation-plugin.cjs +164 -0
- package/middleware/graphql-validation-plugin.d.ts +37 -0
- package/middleware/graphql-validation-plugin.d.ts.map +1 -0
- package/middleware/graphql-validation-plugin.js.map +1 -0
- package/middleware/index.cjs +46 -0
- package/middleware/index.d.ts +13 -0
- package/middleware/index.d.ts.map +1 -0
- package/middleware/index.js.map +1 -0
- package/middleware/input-validator.cjs +220 -0
- package/middleware/input-validator.d.ts +63 -0
- package/middleware/input-validator.d.ts.map +1 -0
- package/middleware/input-validator.js.map +1 -0
- package/middleware/query-complexity.cjs +182 -0
- package/middleware/query-complexity.d.ts +56 -0
- package/middleware/query-complexity.d.ts.map +1 -0
- package/middleware/query-complexity.js.map +1 -0
- package/middleware/rate-limiter.cjs +112 -0
- package/middleware/rate-limiter.d.ts +16 -0
- package/middleware/rate-limiter.d.ts.map +1 -0
- package/middleware/rate-limiter.js.map +1 -0
- package/middleware/soft-delete.cjs +175 -0
- package/middleware/soft-delete.d.ts +146 -0
- package/middleware/soft-delete.d.ts.map +1 -0
- package/middleware/soft-delete.js.map +1 -0
- package/middleware/types.cjs +17 -0
- package/middleware/types.d.ts +87 -0
- package/middleware/types.d.ts.map +1 -0
- package/middleware/types.js.map +1 -0
- package/middleware/validation-examples.cjs +403 -0
- package/middleware/validation-examples.d.ts +76 -0
- package/middleware/validation-examples.d.ts.map +1 -0
- package/middleware/validation-examples.js.map +1 -0
- package/package.json +5 -1
- package/utils/index.cjs +75 -0
- package/utils/index.d.ts +20 -0
- package/utils/index.d.ts.map +1 -0
- package/utils/index.js.map +1 -0
- package/utils/logger.cjs +31 -0
- package/utils/logger.d.ts +9 -0
- package/utils/logger.d.ts.map +1 -0
- package/utils/logger.js.map +1 -0
- package/validators/allocation-validator.cjs +85 -0
- package/validators/allocation-validator.d.ts +32 -0
- package/validators/allocation-validator.d.ts.map +1 -0
- package/validators/allocation-validator.js.map +1 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initTracing = initTracing;
|
|
4
|
+
exports.shutdownTracing = shutdownTracing;
|
|
5
|
+
const sdk_node_1 = require("@opentelemetry/sdk-node");
|
|
6
|
+
const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
|
|
7
|
+
const instrumentation_http_1 = require("@opentelemetry/instrumentation-http");
|
|
8
|
+
const instrumentation_express_1 = require("@opentelemetry/instrumentation-express");
|
|
9
|
+
const instrumentation_graphql_1 = require("@opentelemetry/instrumentation-graphql");
|
|
10
|
+
const resources_1 = require("@opentelemetry/resources");
|
|
11
|
+
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
|
|
12
|
+
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
|
|
13
|
+
const logger_1 = require("../utils/logger.cjs");
|
|
14
|
+
const SERVICE_NAME = 'backend-legacy';
|
|
15
|
+
/**
|
|
16
|
+
* Reads the package version for trace resource attributes.
|
|
17
|
+
* Falls back to 'unknown' if the version cannot be determined.
|
|
18
|
+
*/
|
|
19
|
+
function getPackageVersion() {
|
|
20
|
+
try {
|
|
21
|
+
const pkg = require('../../package.json.cjs');
|
|
22
|
+
return pkg.version || 'unknown';
|
|
23
|
+
}
|
|
24
|
+
catch (_a) {
|
|
25
|
+
return 'unknown';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the OTLP endpoint from environment variables.
|
|
30
|
+
* Defaults to http://localhost:4318/v1/traces (standard OTLP HTTP endpoint).
|
|
31
|
+
*/
|
|
32
|
+
function getOtlpEndpoint() {
|
|
33
|
+
return (process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/traces');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Determines if tracing is enabled.
|
|
37
|
+
* Disabled by default in development; enabled in production and staging.
|
|
38
|
+
* Can be explicitly controlled via OTEL_TRACING_ENABLED env var.
|
|
39
|
+
*/
|
|
40
|
+
function isTracingEnabled() {
|
|
41
|
+
const explicitSetting = process.env.OTEL_TRACING_ENABLED;
|
|
42
|
+
if (explicitSetting !== undefined) {
|
|
43
|
+
return explicitSetting === 'true' || explicitSetting === '1';
|
|
44
|
+
}
|
|
45
|
+
const env = process.env.NODE_ENV || 'development';
|
|
46
|
+
return env === 'production' || env === 'staging';
|
|
47
|
+
}
|
|
48
|
+
let sdk = null;
|
|
49
|
+
/**
|
|
50
|
+
* Initializes OpenTelemetry tracing for the backend-legacy service.
|
|
51
|
+
*
|
|
52
|
+
* Configures:
|
|
53
|
+
* - HTTP instrumentation for incoming/outgoing HTTP requests
|
|
54
|
+
* - Express instrumentation for route-level spans
|
|
55
|
+
* - GraphQL instrumentation for resolver-level spans
|
|
56
|
+
* - OTLP HTTP exporter for sending traces to a collector (e.g., Jaeger, Grafana Tempo)
|
|
57
|
+
*
|
|
58
|
+
* Environment variables:
|
|
59
|
+
* - OTEL_TRACING_ENABLED: Explicit on/off ('true'/'false'). Defaults to on in production/staging.
|
|
60
|
+
* - OTEL_EXPORTER_OTLP_ENDPOINT: Collector endpoint (default: http://localhost:4318/v1/traces)
|
|
61
|
+
* - OTEL_SERVICE_NAME: Override service name (default: 'backend-legacy')
|
|
62
|
+
*
|
|
63
|
+
* Call this function before any other imports that need instrumentation (e.g., before Express/Apollo setup).
|
|
64
|
+
*/
|
|
65
|
+
function initTracing() {
|
|
66
|
+
if (!isTracingEnabled()) {
|
|
67
|
+
logger_1.logger.info('OpenTelemetry tracing is disabled', {
|
|
68
|
+
reason: 'OTEL_TRACING_ENABLED not set or environment is development',
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const endpoint = getOtlpEndpoint();
|
|
73
|
+
const serviceName = process.env.OTEL_SERVICE_NAME || SERVICE_NAME;
|
|
74
|
+
const serviceVersion = getPackageVersion();
|
|
75
|
+
const traceExporter = new exporter_trace_otlp_http_1.OTLPTraceExporter({
|
|
76
|
+
url: endpoint,
|
|
77
|
+
});
|
|
78
|
+
const resource = (0, resources_1.resourceFromAttributes)({
|
|
79
|
+
[semantic_conventions_1.ATTR_SERVICE_NAME]: serviceName,
|
|
80
|
+
[semantic_conventions_1.ATTR_SERVICE_VERSION]: serviceVersion,
|
|
81
|
+
'deployment.environment': process.env.NODE_ENV || 'development',
|
|
82
|
+
});
|
|
83
|
+
sdk = new sdk_node_1.NodeSDK({
|
|
84
|
+
resource,
|
|
85
|
+
spanProcessors: [new sdk_trace_node_1.BatchSpanProcessor(traceExporter)],
|
|
86
|
+
instrumentations: [
|
|
87
|
+
new instrumentation_http_1.HttpInstrumentation({
|
|
88
|
+
ignoreIncomingRequestHook: (req) => {
|
|
89
|
+
// Skip health check endpoints to reduce trace noise
|
|
90
|
+
return req.url === '/health' || req.url === '/metrics';
|
|
91
|
+
},
|
|
92
|
+
}),
|
|
93
|
+
new instrumentation_express_1.ExpressInstrumentation(),
|
|
94
|
+
new instrumentation_graphql_1.GraphQLInstrumentation({
|
|
95
|
+
mergeItems: true,
|
|
96
|
+
allowValues: true,
|
|
97
|
+
depth: 5,
|
|
98
|
+
}),
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
sdk.start();
|
|
102
|
+
logger_1.logger.info('OpenTelemetry tracing initialized', {
|
|
103
|
+
endpoint,
|
|
104
|
+
serviceName,
|
|
105
|
+
serviceVersion,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Gracefully shuts down the OpenTelemetry SDK.
|
|
110
|
+
* Should be called during application shutdown (SIGTERM/SIGINT handlers).
|
|
111
|
+
* Flushes any pending spans before shutting down.
|
|
112
|
+
*/
|
|
113
|
+
async function shutdownTracing() {
|
|
114
|
+
if (sdk) {
|
|
115
|
+
try {
|
|
116
|
+
await sdk.shutdown();
|
|
117
|
+
logger_1.logger.info('OpenTelemetry tracing shut down successfully');
|
|
118
|
+
}
|
|
119
|
+
catch (shutdownError) {
|
|
120
|
+
logger_1.logger.error('Error shutting down OpenTelemetry tracing', {
|
|
121
|
+
error: shutdownError instanceof Error
|
|
122
|
+
? shutdownError.message
|
|
123
|
+
: String(shutdownError),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=tracing.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initializes OpenTelemetry tracing for the backend-legacy service.
|
|
3
|
+
*
|
|
4
|
+
* Configures:
|
|
5
|
+
* - HTTP instrumentation for incoming/outgoing HTTP requests
|
|
6
|
+
* - Express instrumentation for route-level spans
|
|
7
|
+
* - GraphQL instrumentation for resolver-level spans
|
|
8
|
+
* - OTLP HTTP exporter for sending traces to a collector (e.g., Jaeger, Grafana Tempo)
|
|
9
|
+
*
|
|
10
|
+
* Environment variables:
|
|
11
|
+
* - OTEL_TRACING_ENABLED: Explicit on/off ('true'/'false'). Defaults to on in production/staging.
|
|
12
|
+
* - OTEL_EXPORTER_OTLP_ENDPOINT: Collector endpoint (default: http://localhost:4318/v1/traces)
|
|
13
|
+
* - OTEL_SERVICE_NAME: Override service name (default: 'backend-legacy')
|
|
14
|
+
*
|
|
15
|
+
* Call this function before any other imports that need instrumentation (e.g., before Express/Apollo setup).
|
|
16
|
+
*/
|
|
17
|
+
export declare function initTracing(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Gracefully shuts down the OpenTelemetry SDK.
|
|
20
|
+
* Should be called during application shutdown (SIGTERM/SIGINT handlers).
|
|
21
|
+
* Flushes any pending spans before shutting down.
|
|
22
|
+
*/
|
|
23
|
+
export declare function shutdownTracing(): Promise<void>;
|
|
24
|
+
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/config/tracing.ts"],"names":[],"mappings":"AAsDA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAgDlC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAcrD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../src/config/tracing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Audit Logging Middleware
|
|
4
|
+
*
|
|
5
|
+
* Captures all GraphQL mutations and records an append-only audit trail.
|
|
6
|
+
* Each audit log entry includes: user ID (from JWT context), timestamp,
|
|
7
|
+
* operation type, model name, record ID, and changed fields.
|
|
8
|
+
*
|
|
9
|
+
* This middleware is implemented as an Apollo Server plugin that intercepts
|
|
10
|
+
* mutation operations and logs them to the AuditLog table.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.createAuditLogPlugin = createAuditLogPlugin;
|
|
14
|
+
exports.parseMutationOperation = parseMutationOperation;
|
|
15
|
+
exports.extractUserId = extractUserId;
|
|
16
|
+
exports.extractRecordId = extractRecordId;
|
|
17
|
+
exports.extractChangedFields = extractChangedFields;
|
|
18
|
+
const logger_1 = require("../utils/logger.cjs");
|
|
19
|
+
/** List of models that are excluded from audit logging (e.g., the audit log itself) */
|
|
20
|
+
const EXCLUDED_MODELS = new Set([
|
|
21
|
+
'AuditLog',
|
|
22
|
+
'Session',
|
|
23
|
+
'VerificationToken',
|
|
24
|
+
'Authenticator',
|
|
25
|
+
]);
|
|
26
|
+
/**
|
|
27
|
+
* Extracts the model name and operation type from a GraphQL mutation operation name.
|
|
28
|
+
* TypeGraphQL-Prisma generates mutations with names like:
|
|
29
|
+
* createOneUser, updateOneUser, deleteOneUser,
|
|
30
|
+
* createManyUser, updateManyUser, deleteManyUser,
|
|
31
|
+
* upsertOneUser
|
|
32
|
+
*
|
|
33
|
+
* @param operationName - The name of the GraphQL field being executed
|
|
34
|
+
* @returns Parsed mutation data or null if not a recognized mutation pattern
|
|
35
|
+
*/
|
|
36
|
+
function parseMutationOperation(operationName) {
|
|
37
|
+
const createPattern = /^(createOne|createMany|upsertOne)(\w+)$/;
|
|
38
|
+
const updatePattern = /^(updateOne|updateMany|upsertOne)(\w+)$/;
|
|
39
|
+
const deletePattern = /^(deleteOne|deleteMany)(\w+)$/;
|
|
40
|
+
let match = createPattern.exec(operationName);
|
|
41
|
+
if (match) {
|
|
42
|
+
return {
|
|
43
|
+
operationType: 'CREATE',
|
|
44
|
+
modelName: match[2],
|
|
45
|
+
operationName,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
match = updatePattern.exec(operationName);
|
|
49
|
+
if (match) {
|
|
50
|
+
return {
|
|
51
|
+
operationType: 'UPDATE',
|
|
52
|
+
modelName: match[2],
|
|
53
|
+
operationName,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
match = deletePattern.exec(operationName);
|
|
57
|
+
if (match) {
|
|
58
|
+
return {
|
|
59
|
+
operationType: 'DELETE',
|
|
60
|
+
modelName: match[2],
|
|
61
|
+
operationName,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Extracts the user ID from the context user object.
|
|
68
|
+
* Handles both JWT-decoded objects and raw string tokens.
|
|
69
|
+
*
|
|
70
|
+
* @param user - The user object from GraphQL context
|
|
71
|
+
* @returns The user ID string or null
|
|
72
|
+
*/
|
|
73
|
+
function extractUserId(user) {
|
|
74
|
+
if (!user)
|
|
75
|
+
return null;
|
|
76
|
+
if (typeof user === 'string')
|
|
77
|
+
return user;
|
|
78
|
+
return user.sub || user.id || null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Extracts the record ID from the mutation result data.
|
|
82
|
+
* Looks for 'id' field in the top-level result object.
|
|
83
|
+
*
|
|
84
|
+
* @param data - The result data from the mutation
|
|
85
|
+
* @returns The record ID as a string, or 'unknown'
|
|
86
|
+
*/
|
|
87
|
+
function extractRecordId(data) {
|
|
88
|
+
if (!data)
|
|
89
|
+
return 'unknown';
|
|
90
|
+
// The result is typically nested under the mutation name
|
|
91
|
+
const values = Object.values(data);
|
|
92
|
+
if (values.length === 0)
|
|
93
|
+
return 'unknown';
|
|
94
|
+
const result = values[0];
|
|
95
|
+
if (result &&
|
|
96
|
+
typeof result === 'object' &&
|
|
97
|
+
'id' in result) {
|
|
98
|
+
return String(result.id);
|
|
99
|
+
}
|
|
100
|
+
return 'unknown';
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Extracts changed fields from the mutation variables.
|
|
104
|
+
* For create operations, captures all input data.
|
|
105
|
+
* For update operations, captures the data being set.
|
|
106
|
+
* For delete operations, captures the where clause.
|
|
107
|
+
*
|
|
108
|
+
* @param operationType - The type of mutation operation
|
|
109
|
+
* @param variables - The GraphQL variables passed to the mutation
|
|
110
|
+
* @returns A JSON-serializable object representing the changed fields
|
|
111
|
+
*/
|
|
112
|
+
function extractChangedFields(operationType, variables) {
|
|
113
|
+
if (!variables)
|
|
114
|
+
return {};
|
|
115
|
+
switch (operationType) {
|
|
116
|
+
case 'CREATE':
|
|
117
|
+
return { input: variables.data || variables };
|
|
118
|
+
case 'UPDATE':
|
|
119
|
+
return {
|
|
120
|
+
where: variables.where || {},
|
|
121
|
+
data: variables.data || {},
|
|
122
|
+
};
|
|
123
|
+
case 'DELETE':
|
|
124
|
+
return { where: variables.where || {} };
|
|
125
|
+
default:
|
|
126
|
+
return variables;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Creates an Apollo Server plugin that logs all mutations to the AuditLog table.
|
|
131
|
+
*
|
|
132
|
+
* The plugin intercepts the willSendResponse lifecycle event to capture
|
|
133
|
+
* mutation results after they have been processed by the resolvers.
|
|
134
|
+
* Only successful mutations are logged (errors are not audited here).
|
|
135
|
+
*
|
|
136
|
+
* @returns An Apollo Server plugin instance
|
|
137
|
+
*/
|
|
138
|
+
function createAuditLogPlugin() {
|
|
139
|
+
return {
|
|
140
|
+
async requestDidStart(_requestContext) {
|
|
141
|
+
return {
|
|
142
|
+
async willSendResponse(requestContext) {
|
|
143
|
+
var _a, _b, _c, _d;
|
|
144
|
+
const { contextValue, response, request, document } = requestContext;
|
|
145
|
+
// Only audit mutations
|
|
146
|
+
if (!document)
|
|
147
|
+
return;
|
|
148
|
+
const definitions = document.definitions;
|
|
149
|
+
const operationDef = definitions.find((def) => def.kind === 'OperationDefinition' && def.operation === 'mutation');
|
|
150
|
+
if (!operationDef || operationDef.kind !== 'OperationDefinition')
|
|
151
|
+
return;
|
|
152
|
+
// Skip if there were errors (we only audit successful mutations)
|
|
153
|
+
if (response.body.kind === 'single' &&
|
|
154
|
+
((_a = response.body.singleResult.errors) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const prisma = contextValue.prisma;
|
|
158
|
+
if (!prisma) {
|
|
159
|
+
logger_1.logger.warn('Audit logger: Prisma client not available in context');
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Extract mutation field names from the selection set
|
|
163
|
+
const selections = operationDef.selectionSet.selections;
|
|
164
|
+
for (const selection of selections) {
|
|
165
|
+
if (selection.kind !== 'Field')
|
|
166
|
+
continue;
|
|
167
|
+
const fieldName = selection.name.value;
|
|
168
|
+
const auditData = parseMutationOperation(fieldName);
|
|
169
|
+
if (!auditData)
|
|
170
|
+
continue;
|
|
171
|
+
if (EXCLUDED_MODELS.has(auditData.modelName))
|
|
172
|
+
continue;
|
|
173
|
+
const userId = extractUserId(contextValue.user);
|
|
174
|
+
const variables = request.variables;
|
|
175
|
+
const changedFields = extractChangedFields(auditData.operationType, variables);
|
|
176
|
+
// Extract record ID from response data
|
|
177
|
+
let recordId = 'unknown';
|
|
178
|
+
if (response.body.kind === 'single' &&
|
|
179
|
+
response.body.singleResult.data) {
|
|
180
|
+
recordId = extractRecordId(response.body.singleResult.data);
|
|
181
|
+
}
|
|
182
|
+
// Extract IP address from request context
|
|
183
|
+
const ipAddress = ((_b = contextValue.req) === null || _b === void 0 ? void 0 : _b.ip) ||
|
|
184
|
+
((_d = (_c = contextValue.req) === null || _c === void 0 ? void 0 : _c.headers) === null || _d === void 0 ? void 0 : _d['x-forwarded-for']) ||
|
|
185
|
+
null;
|
|
186
|
+
try {
|
|
187
|
+
const prismaRecord = prisma;
|
|
188
|
+
if (prismaRecord.auditLog) {
|
|
189
|
+
const auditLogDelegate = prismaRecord.auditLog;
|
|
190
|
+
await auditLogDelegate.create({
|
|
191
|
+
data: {
|
|
192
|
+
userId,
|
|
193
|
+
operationType: auditData.operationType,
|
|
194
|
+
modelName: auditData.modelName,
|
|
195
|
+
recordId,
|
|
196
|
+
changedFields,
|
|
197
|
+
operationName: auditData.operationName,
|
|
198
|
+
ipAddress,
|
|
199
|
+
metadata: {
|
|
200
|
+
graphqlOperationName: request.operationName || null,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
logger_1.logger.warn('Audit logger: AuditLog model not available on Prisma client');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
// Audit logging failures should never break the main request
|
|
211
|
+
logger_1.logger.error('Audit logger: Failed to write audit log entry', {
|
|
212
|
+
error: error instanceof Error ? error.message : String(error),
|
|
213
|
+
modelName: auditData.modelName,
|
|
214
|
+
operationType: auditData.operationType,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=audit-logger.js.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit Logging Middleware
|
|
3
|
+
*
|
|
4
|
+
* Captures all GraphQL mutations and records an append-only audit trail.
|
|
5
|
+
* Each audit log entry includes: user ID (from JWT context), timestamp,
|
|
6
|
+
* operation type, model name, record ID, and changed fields.
|
|
7
|
+
*
|
|
8
|
+
* This middleware is implemented as an Apollo Server plugin that intercepts
|
|
9
|
+
* mutation operations and logs them to the AuditLog table.
|
|
10
|
+
*/
|
|
11
|
+
import type { ApolloServerPlugin } from '@apollo/server';
|
|
12
|
+
import type { PrismaClient } from '@prisma/client';
|
|
13
|
+
/** Represents the user object decoded from JWT context */
|
|
14
|
+
interface AuditUser {
|
|
15
|
+
sub?: string;
|
|
16
|
+
id?: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
role?: string;
|
|
19
|
+
provider?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Context shape expected by the audit logger plugin */
|
|
22
|
+
interface AuditContext {
|
|
23
|
+
prisma: PrismaClient;
|
|
24
|
+
user?: AuditUser | string | null;
|
|
25
|
+
req?: {
|
|
26
|
+
ip?: string;
|
|
27
|
+
headers?: Record<string, string | string[] | undefined>;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Fields extracted from a GraphQL mutation for audit logging */
|
|
31
|
+
interface MutationAuditData {
|
|
32
|
+
operationType: 'CREATE' | 'UPDATE' | 'DELETE';
|
|
33
|
+
modelName: string;
|
|
34
|
+
operationName: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extracts the model name and operation type from a GraphQL mutation operation name.
|
|
38
|
+
* TypeGraphQL-Prisma generates mutations with names like:
|
|
39
|
+
* createOneUser, updateOneUser, deleteOneUser,
|
|
40
|
+
* createManyUser, updateManyUser, deleteManyUser,
|
|
41
|
+
* upsertOneUser
|
|
42
|
+
*
|
|
43
|
+
* @param operationName - The name of the GraphQL field being executed
|
|
44
|
+
* @returns Parsed mutation data or null if not a recognized mutation pattern
|
|
45
|
+
*/
|
|
46
|
+
declare function parseMutationOperation(operationName: string): MutationAuditData | null;
|
|
47
|
+
/**
|
|
48
|
+
* Extracts the user ID from the context user object.
|
|
49
|
+
* Handles both JWT-decoded objects and raw string tokens.
|
|
50
|
+
*
|
|
51
|
+
* @param user - The user object from GraphQL context
|
|
52
|
+
* @returns The user ID string or null
|
|
53
|
+
*/
|
|
54
|
+
declare function extractUserId(user: AuditUser | string | null | undefined): string | null;
|
|
55
|
+
/**
|
|
56
|
+
* Extracts the record ID from the mutation result data.
|
|
57
|
+
* Looks for 'id' field in the top-level result object.
|
|
58
|
+
*
|
|
59
|
+
* @param data - The result data from the mutation
|
|
60
|
+
* @returns The record ID as a string, or 'unknown'
|
|
61
|
+
*/
|
|
62
|
+
declare function extractRecordId(data: Record<string, unknown> | null | undefined): string;
|
|
63
|
+
/**
|
|
64
|
+
* Extracts changed fields from the mutation variables.
|
|
65
|
+
* For create operations, captures all input data.
|
|
66
|
+
* For update operations, captures the data being set.
|
|
67
|
+
* For delete operations, captures the where clause.
|
|
68
|
+
*
|
|
69
|
+
* @param operationType - The type of mutation operation
|
|
70
|
+
* @param variables - The GraphQL variables passed to the mutation
|
|
71
|
+
* @returns A JSON-serializable object representing the changed fields
|
|
72
|
+
*/
|
|
73
|
+
declare function extractChangedFields(operationType: 'CREATE' | 'UPDATE' | 'DELETE', variables: Record<string, unknown> | null | undefined): Record<string, unknown>;
|
|
74
|
+
/**
|
|
75
|
+
* Creates an Apollo Server plugin that logs all mutations to the AuditLog table.
|
|
76
|
+
*
|
|
77
|
+
* The plugin intercepts the willSendResponse lifecycle event to capture
|
|
78
|
+
* mutation results after they have been processed by the resolvers.
|
|
79
|
+
* Only successful mutations are logged (errors are not audited here).
|
|
80
|
+
*
|
|
81
|
+
* @returns An Apollo Server plugin instance
|
|
82
|
+
*/
|
|
83
|
+
export declare function createAuditLogPlugin(): ApolloServerPlugin<AuditContext>;
|
|
84
|
+
export { parseMutationOperation, extractUserId, extractRecordId, extractChangedFields, };
|
|
85
|
+
//# sourceMappingURL=audit-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-logger.d.ts","sourceRoot":"","sources":["../../src/middleware/audit-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,0DAA0D;AAC1D,UAAU,SAAS;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wDAAwD;AACxD,UAAU,YAAY;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,GAAG,CAAC,EAAE;QACJ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;KACzD,CAAC;CACH;AAED,iEAAiE;AACjE,UAAU,iBAAiB;IACzB,aAAa,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAUD;;;;;;;;;GASG;AACH,iBAAS,sBAAsB,CAC7B,aAAa,EAAE,MAAM,GACpB,iBAAiB,GAAG,IAAI,CAiC1B;AAED;;;;;;GAMG;AACH,iBAAS,aAAa,CACpB,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,MAAM,GAAG,IAAI,CAIf;AAED;;;;;;GAMG;AACH,iBAAS,eAAe,CACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAC/C,MAAM,CAiBR;AAED;;;;;;;;;GASG;AACH,iBAAS,oBAAoB,CAC3B,aAAa,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EAC7C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACpD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,kBAAkB,CAAC,YAAY,CAAC,CAoHvE;AAED,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,oBAAoB,GACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../../src/middleware/audit-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
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 jwtConfig_1 = require("../config/jwtConfig.cjs");
|
|
9
|
+
const logger_1 = require("../utils/logger.cjs");
|
|
10
|
+
const authMiddleware = (req, res, next) => {
|
|
11
|
+
const authHeader = req.header('Authorization') || '';
|
|
12
|
+
const token = authHeader.startsWith('Bearer ')
|
|
13
|
+
? authHeader.replace('Bearer ', '')
|
|
14
|
+
: '';
|
|
15
|
+
if (!token) {
|
|
16
|
+
return res.status(401).send({ error: 'Unauthorized' });
|
|
17
|
+
}
|
|
18
|
+
// Handle Google OAuth tokens
|
|
19
|
+
if (token.startsWith('ya29.')) {
|
|
20
|
+
logger_1.logger.info('Detected Google OAuth token in middleware, skipping JWT verification');
|
|
21
|
+
req.user = { provider: 'google', token };
|
|
22
|
+
return next();
|
|
23
|
+
}
|
|
24
|
+
// Handle regular JWT tokens
|
|
25
|
+
try {
|
|
26
|
+
// Check for server-to-server auth token from environment
|
|
27
|
+
const serverAuthToken = process.env.SERVER_AUTH_TOKEN;
|
|
28
|
+
if (serverAuthToken && token === serverAuthToken) {
|
|
29
|
+
req.user = { sub: 'server', name: 'Server Auth', role: 'server' };
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const decoded = jsonwebtoken_1.default.verify(token, jwtConfig_1.jwtSecret);
|
|
33
|
+
req.user = decoded;
|
|
34
|
+
}
|
|
35
|
+
next();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
39
|
+
logger_1.logger.warn(`[Auth] Middleware JWT verification failed: ${errorMessage}`);
|
|
40
|
+
res.status(401).send({ error: 'Unauthorized' });
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.authMiddleware = authMiddleware;
|
|
44
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
export interface AuthenticatedRequest extends Request {
|
|
3
|
+
user?: any;
|
|
4
|
+
}
|
|
5
|
+
export declare const authMiddleware: (req: AuthenticatedRequest, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
6
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK1D,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,eAAO,MAAM,cAAc,GACzB,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,MAAM,YAAY,8CAqCnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":";;;;;;AACA,gEAA+B;AAC/B,mDAAgD;AAChD,4CAAyC;AAMlC,MAAM,cAAc,GAAG,CAC5B,GAAyB,EACzB,GAAa,EACb,IAAkB,EAClB,EAAE;IACF,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IACrD,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC;QAC5C,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;QACnC,CAAC,CAAC,EAAE,CAAC;IAEP,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,6BAA6B;IAC7B,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,eAAM,CAAC,IAAI,CACT,sEAAsE,CACvE,CAAC;QACF,GAAG,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QACzC,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAED,4BAA4B;IAC5B,IAAI,CAAC;QACH,yDAAyD;QACzD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACtD,IAAI,eAAe,IAAI,KAAK,KAAK,eAAe,EAAE,CAAC;YACjD,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,qBAAS,CAAC,CAAC;YAC7C,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC;QACrB,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QAC3D,eAAM,CAAC,IAAI,CAAC,8CAA8C,YAAY,EAAE,CAAC,CAAC;QAC1E,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC,CAAC;AAxCW,QAAA,cAAc,kBAwCzB"}
|