@xfilecom/core-sdk 1.3.28 → 1.4.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.
- package/dist/filters/i18n-exception.filter.d.ts +18 -0
- package/dist/filters/i18n-exception.filter.js +227 -0
- package/dist/filters/i18n-exception.filter.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/auth-lookup.utils.d.ts +23 -0
- package/dist/utils/auth-lookup.utils.js +61 -0
- package/dist/utils/auth-lookup.utils.js.map +1 -0
- package/dist/utils/config-secret.utils.d.ts +9 -0
- package/dist/utils/config-secret.utils.js +26 -0
- package/dist/utils/config-secret.utils.js.map +1 -0
- package/docs/IMPROVEMENTS_PROPOSAL.md +54 -0
- package/package.json +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ExceptionFilter, ArgumentsHost } from '@nestjs/common';
|
|
2
|
+
import type { ExceptionFilterOptions } from './exception.filter';
|
|
3
|
+
export interface I18nMessageShape {
|
|
4
|
+
ko?: string;
|
|
5
|
+
en?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class I18nExceptionFilter implements ExceptionFilter {
|
|
8
|
+
private readonly logger;
|
|
9
|
+
private readonly errorUtils;
|
|
10
|
+
private readonly options;
|
|
11
|
+
constructor(options?: ExceptionFilterOptions);
|
|
12
|
+
catch(exception: unknown, host: ArgumentsHost): void;
|
|
13
|
+
private handleOptionsRequest;
|
|
14
|
+
private isStaticFile404;
|
|
15
|
+
private buildMeta;
|
|
16
|
+
private extractMessage;
|
|
17
|
+
private logError;
|
|
18
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var I18nExceptionFilter_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.I18nExceptionFilter = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const error_utils_1 = require("../utils/error.utils");
|
|
16
|
+
function tryParseI18nMessage(message) {
|
|
17
|
+
if (typeof message !== 'string' || !message.trim())
|
|
18
|
+
return null;
|
|
19
|
+
const trimmed = message.trim();
|
|
20
|
+
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) === false)
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const parsed = JSON.parse(message);
|
|
24
|
+
if (parsed === null || typeof parsed !== 'object')
|
|
25
|
+
return null;
|
|
26
|
+
const ko = parsed.ko;
|
|
27
|
+
const en = parsed.en;
|
|
28
|
+
if (ko == null && en == null)
|
|
29
|
+
return null;
|
|
30
|
+
return {
|
|
31
|
+
...(typeof ko === 'string' && { ko }),
|
|
32
|
+
...(typeof en === 'string' && { en }),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
let I18nExceptionFilter = I18nExceptionFilter_1 = class I18nExceptionFilter {
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.logger = new common_1.Logger(I18nExceptionFilter_1.name);
|
|
42
|
+
this.errorUtils = new error_utils_1.ErrorUtils();
|
|
43
|
+
this.options = {
|
|
44
|
+
cors: {
|
|
45
|
+
enabled: options.cors?.enabled ?? true,
|
|
46
|
+
allowedOrigins: options.cors?.allowedOrigins || [
|
|
47
|
+
'http://localhost:3001',
|
|
48
|
+
'http://localhost:5173',
|
|
49
|
+
'http://localhost:5174',
|
|
50
|
+
'http://localhost:5175',
|
|
51
|
+
'http://localhost:5176',
|
|
52
|
+
...(process.env.FRONTEND_URL?.split(',') || []),
|
|
53
|
+
],
|
|
54
|
+
allowAllOriginsInDev: options.cors?.allowAllOriginsInDev ?? true,
|
|
55
|
+
},
|
|
56
|
+
meta: {
|
|
57
|
+
enabled: options.meta?.enabled ?? false,
|
|
58
|
+
includeTimestamp: options.meta?.includeTimestamp ?? true,
|
|
59
|
+
includePath: options.meta?.includePath ?? true,
|
|
60
|
+
includeMethod: options.meta?.includeMethod ?? true,
|
|
61
|
+
},
|
|
62
|
+
logging: {
|
|
63
|
+
enabled: options.logging?.enabled ?? true,
|
|
64
|
+
level: options.logging?.level || 'warn',
|
|
65
|
+
includeStack: options.logging?.includeStack ?? true,
|
|
66
|
+
debug: options.logging?.debug ?? false,
|
|
67
|
+
},
|
|
68
|
+
responseFormat: {
|
|
69
|
+
includeDetails: options.responseFormat?.includeDetails ?? false,
|
|
70
|
+
},
|
|
71
|
+
filterStaticFiles: options.filterStaticFiles ?? true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch(exception, host) {
|
|
75
|
+
const ctx = host.switchToHttp();
|
|
76
|
+
const response = ctx.getResponse();
|
|
77
|
+
const request = ctx.getRequest();
|
|
78
|
+
if (this.options.logging.debug) {
|
|
79
|
+
this.logger.debug(`[I18nExceptionFilter] Caught exception for ${request.method} ${request.url}`, {
|
|
80
|
+
exceptionType: exception?.constructor?.name,
|
|
81
|
+
isHttpException: exception instanceof common_1.HttpException,
|
|
82
|
+
isError: exception instanceof Error,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (this.options.cors.enabled && request.method === 'OPTIONS') {
|
|
86
|
+
return this.handleOptionsRequest(request, response);
|
|
87
|
+
}
|
|
88
|
+
const status = exception instanceof common_1.HttpException
|
|
89
|
+
? exception.getStatus()
|
|
90
|
+
: common_1.HttpStatus.INTERNAL_SERVER_ERROR;
|
|
91
|
+
if (this.options.filterStaticFiles && this.isStaticFile404(request, status)) {
|
|
92
|
+
response.status(status).json(this.errorUtils.fromException(exception));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const errorDto = this.errorUtils.fromException(exception);
|
|
96
|
+
if (errorDto.error?.message != null) {
|
|
97
|
+
const i18n = tryParseI18nMessage(errorDto.error.message);
|
|
98
|
+
if (i18n != null && Object.keys(i18n).length > 0) {
|
|
99
|
+
errorDto.error = { ...errorDto.error, message: i18n };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (this.options.meta.enabled) {
|
|
103
|
+
errorDto.meta = this.buildMeta(request);
|
|
104
|
+
}
|
|
105
|
+
if (this.options.responseFormat.includeDetails) {
|
|
106
|
+
const message = this.extractMessage(errorDto);
|
|
107
|
+
errorDto.error = {
|
|
108
|
+
...errorDto.error,
|
|
109
|
+
message,
|
|
110
|
+
details: Array.isArray(message) ? message : [message],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (this.options.logging.enabled) {
|
|
114
|
+
this.logError(exception, request, errorDto, status);
|
|
115
|
+
}
|
|
116
|
+
if (response.headersSent) {
|
|
117
|
+
this.logger.warn(`Response already sent for ${request.method} ${request.url}, cannot send error response`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
if (this.options.logging.debug) {
|
|
122
|
+
this.logger.debug(`[I18nExceptionFilter] Sending error response:`, {
|
|
123
|
+
status: errorDto.code,
|
|
124
|
+
message: this.extractMessage(errorDto),
|
|
125
|
+
path: request.url,
|
|
126
|
+
method: request.method,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
response.status(errorDto.code).json(errorDto);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
this.logger.error(`Failed to send error response for ${request.method} ${request.url}:`, error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
handleOptionsRequest(request, response) {
|
|
136
|
+
const origin = request.headers.origin;
|
|
137
|
+
const allowedOrigin = this.options.cors.allowAllOriginsInDev && process.env.NODE_ENV !== 'production'
|
|
138
|
+
? origin || '*'
|
|
139
|
+
: origin && this.options.cors.allowedOrigins.includes(origin)
|
|
140
|
+
? origin
|
|
141
|
+
: this.options.cors.allowedOrigins[0] || '*';
|
|
142
|
+
response.status(common_1.HttpStatus.OK);
|
|
143
|
+
response.setHeader('Access-Control-Allow-Origin', allowedOrigin);
|
|
144
|
+
response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD');
|
|
145
|
+
response.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin, Access-Control-Request-Method, Access-Control-Request-Headers');
|
|
146
|
+
response.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
147
|
+
response.setHeader('Access-Control-Max-Age', '86400');
|
|
148
|
+
response.end();
|
|
149
|
+
}
|
|
150
|
+
isStaticFile404(request, status) {
|
|
151
|
+
if (status !== common_1.HttpStatus.NOT_FOUND)
|
|
152
|
+
return false;
|
|
153
|
+
const url = request.url;
|
|
154
|
+
return (url === '/favicon.ico' ||
|
|
155
|
+
url.includes('.ico') ||
|
|
156
|
+
url.includes('.png') ||
|
|
157
|
+
url.includes('.jpg') ||
|
|
158
|
+
url.includes('.jpeg') ||
|
|
159
|
+
url.includes('.gif') ||
|
|
160
|
+
url.includes('.svg') ||
|
|
161
|
+
url.includes('.css') ||
|
|
162
|
+
url.includes('.js') ||
|
|
163
|
+
url.includes('.woff') ||
|
|
164
|
+
url.includes('.woff2') ||
|
|
165
|
+
url.includes('.ttf'));
|
|
166
|
+
}
|
|
167
|
+
buildMeta(request) {
|
|
168
|
+
const meta = {};
|
|
169
|
+
if (this.options.meta.includeTimestamp)
|
|
170
|
+
meta.timestamp = new Date().toISOString();
|
|
171
|
+
if (this.options.meta.includePath)
|
|
172
|
+
meta.path = request.url;
|
|
173
|
+
if (this.options.meta.includeMethod)
|
|
174
|
+
meta.method = request.method;
|
|
175
|
+
return meta;
|
|
176
|
+
}
|
|
177
|
+
extractMessage(errorDto) {
|
|
178
|
+
if (!errorDto.error)
|
|
179
|
+
return 'Internal server error';
|
|
180
|
+
const message = errorDto.error.message;
|
|
181
|
+
if (typeof message === 'string')
|
|
182
|
+
return message;
|
|
183
|
+
if (Array.isArray(message))
|
|
184
|
+
return message;
|
|
185
|
+
if (typeof message === 'object' && message !== null && 'message' in message) {
|
|
186
|
+
const inner = message.message;
|
|
187
|
+
if (typeof inner === 'string')
|
|
188
|
+
return inner;
|
|
189
|
+
return JSON.stringify(message);
|
|
190
|
+
}
|
|
191
|
+
if (typeof message === 'object' && message !== null && ('ko' in message || 'en' in message)) {
|
|
192
|
+
return message.ko ?? message.en ?? JSON.stringify(message);
|
|
193
|
+
}
|
|
194
|
+
return String(message);
|
|
195
|
+
}
|
|
196
|
+
logError(exception, request, errorDto, status) {
|
|
197
|
+
const errorLog = {
|
|
198
|
+
status: errorDto.code,
|
|
199
|
+
message: this.extractMessage(errorDto),
|
|
200
|
+
path: request.url,
|
|
201
|
+
method: request.method,
|
|
202
|
+
timestamp: new Date().toISOString(),
|
|
203
|
+
};
|
|
204
|
+
if (status >= common_1.HttpStatus.INTERNAL_SERVER_ERROR) {
|
|
205
|
+
const logData = { ...errorLog };
|
|
206
|
+
if (this.options.logging.includeStack && exception instanceof Error) {
|
|
207
|
+
logData.exception = exception.stack;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
logData.exception = exception;
|
|
211
|
+
}
|
|
212
|
+
this.logger.error(`[${request.method}] ${request.url}`, logData);
|
|
213
|
+
}
|
|
214
|
+
else if (status === common_1.HttpStatus.NOT_FOUND) {
|
|
215
|
+
this.logger.debug(`[${request.method}] ${request.url}`, errorLog);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
this.logger.warn(`[${request.method}] ${request.url}`, errorLog);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
exports.I18nExceptionFilter = I18nExceptionFilter;
|
|
223
|
+
exports.I18nExceptionFilter = I18nExceptionFilter = I18nExceptionFilter_1 = __decorate([
|
|
224
|
+
(0, common_1.Catch)(),
|
|
225
|
+
__metadata("design:paramtypes", [Object])
|
|
226
|
+
], I18nExceptionFilter);
|
|
227
|
+
//# sourceMappingURL=i18n-exception.filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n-exception.filter.js","sourceRoot":"","sources":["../../src/filters/i18n-exception.filter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export * from './interceptors/database-check.interceptor';
|
|
|
17
17
|
export * from './guards/jwt-auth.guard';
|
|
18
18
|
export * from './guards/roles.guard';
|
|
19
19
|
export { AllExceptionsFilter, ExceptionFilterOptions } from './filters/exception.filter';
|
|
20
|
+
export { I18nExceptionFilter, type I18nMessageShape, } from './filters/i18n-exception.filter';
|
|
20
21
|
export * from './decorators/public.decorator';
|
|
21
22
|
export { User, JwtUser } from './decorators/user.decorator';
|
|
22
23
|
export { Roles, ROLES_KEY } from './decorators/roles.decorator';
|
|
@@ -27,3 +28,5 @@ export { loadApplicationYaml, loadApplicationYamlSync, LoadApplicationYamlOption
|
|
|
27
28
|
export { resolveConfigRootDir, createConfigLoader, DEFAULT_CONFIG_ROOT_CANDIDATES, type ResolveConfigRootDirOptions, type CreateConfigLoaderOptions, type GetServiceConfigOverrides, } from './utils/config-loader.utils';
|
|
28
29
|
export { pbkdf2HashPassword, pbkdf2VerifyPassword, deriveKeySha256, PBKDF2_DEFAULT_ITERATIONS, PBKDF2_DEFAULT_KEYLEN, PBKDF2_DEFAULT_DIGEST, PBKDF2_SALT_BYTES, type Pbkdf2Options, } from './utils/crypto.utils';
|
|
29
30
|
export { hashValue, compareValue, hashEmail, compareEmail, emailNormalizer, digitsNormalizer, BUILT_IN_NORMALIZERS, getProfileConfig, hashByKey, compareByKey, lookupHash, compareLookupHash, HashVerificationConfig, HashVerificationConfigMap, type LookupHashOptions, } from './utils/hash-verification.utils';
|
|
31
|
+
export { getOptionalSecret, getEncryptionKey, type ConfigGetter, type GetOptionalSecretOptions, } from './utils/config-secret.utils';
|
|
32
|
+
export { findUserByLookupHash, authenticateWithHashLookup, type DrizzleDb, type FindUserByLookupHashOptions, type AuthenticateWithHashLookupOptions, } from './utils/auth-lookup.utils';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.compareLookupHash = exports.lookupHash = exports.compareByKey = exports.hashByKey = exports.getProfileConfig = exports.BUILT_IN_NORMALIZERS = exports.digitsNormalizer = exports.emailNormalizer = exports.compareEmail = exports.hashEmail = exports.compareValue = exports.hashValue = exports.PBKDF2_SALT_BYTES = exports.PBKDF2_DEFAULT_DIGEST = exports.PBKDF2_DEFAULT_KEYLEN = exports.PBKDF2_DEFAULT_ITERATIONS = exports.deriveKeySha256 = exports.pbkdf2VerifyPassword = exports.pbkdf2HashPassword = exports.DEFAULT_CONFIG_ROOT_CANDIDATES = exports.createConfigLoader = exports.resolveConfigRootDir = exports.CONFIG_SOURCE_ENV_KEY = exports.ENV_CONFIG_FILENAME_PATTERN = exports.DEFAULT_CONFIG_FILENAMES = exports.loadApplicationYamlSync = exports.loadApplicationYaml = exports.getLoggingConfigFromEnv = exports.isProd = exports.isDev = exports.currentAppEnv = exports.isStaging = exports.isProduction = exports.isDevelopment = exports.getAppEnv = exports.ROLES_KEY = exports.Roles = exports.User = exports.AllExceptionsFilter = exports.isLevelEnabled = exports.LOG_LEVEL_ORDER = exports.FileLogWriter = exports.ConsoleLogWriter = exports.CommonErrorDto = exports.CommonResponseDto = void 0;
|
|
17
|
+
exports.authenticateWithHashLookup = exports.findUserByLookupHash = exports.getEncryptionKey = exports.getOptionalSecret = exports.compareLookupHash = exports.lookupHash = exports.compareByKey = exports.hashByKey = exports.getProfileConfig = exports.BUILT_IN_NORMALIZERS = exports.digitsNormalizer = exports.emailNormalizer = exports.compareEmail = exports.hashEmail = exports.compareValue = exports.hashValue = exports.PBKDF2_SALT_BYTES = exports.PBKDF2_DEFAULT_DIGEST = exports.PBKDF2_DEFAULT_KEYLEN = exports.PBKDF2_DEFAULT_ITERATIONS = exports.deriveKeySha256 = exports.pbkdf2VerifyPassword = exports.pbkdf2HashPassword = exports.DEFAULT_CONFIG_ROOT_CANDIDATES = exports.createConfigLoader = exports.resolveConfigRootDir = exports.CONFIG_SOURCE_ENV_KEY = exports.ENV_CONFIG_FILENAME_PATTERN = exports.DEFAULT_CONFIG_FILENAMES = exports.loadApplicationYamlSync = exports.loadApplicationYaml = exports.getLoggingConfigFromEnv = exports.isProd = exports.isDev = exports.currentAppEnv = exports.isStaging = exports.isProduction = exports.isDevelopment = exports.getAppEnv = exports.ROLES_KEY = exports.Roles = exports.User = exports.I18nExceptionFilter = exports.AllExceptionsFilter = exports.isLevelEnabled = exports.LOG_LEVEL_ORDER = exports.FileLogWriter = exports.ConsoleLogWriter = exports.CommonErrorDto = exports.CommonResponseDto = void 0;
|
|
18
18
|
__exportStar(require("./core.module"), exports);
|
|
19
19
|
__exportStar(require("./database/database.module"), exports);
|
|
20
20
|
__exportStar(require("./database/database.service"), exports);
|
|
@@ -40,6 +40,8 @@ __exportStar(require("./guards/jwt-auth.guard"), exports);
|
|
|
40
40
|
__exportStar(require("./guards/roles.guard"), exports);
|
|
41
41
|
var exception_filter_1 = require("./filters/exception.filter");
|
|
42
42
|
Object.defineProperty(exports, "AllExceptionsFilter", { enumerable: true, get: function () { return exception_filter_1.AllExceptionsFilter; } });
|
|
43
|
+
var i18n_exception_filter_1 = require("./filters/i18n-exception.filter");
|
|
44
|
+
Object.defineProperty(exports, "I18nExceptionFilter", { enumerable: true, get: function () { return i18n_exception_filter_1.I18nExceptionFilter; } });
|
|
43
45
|
__exportStar(require("./decorators/public.decorator"), exports);
|
|
44
46
|
var user_decorator_1 = require("./decorators/user.decorator");
|
|
45
47
|
Object.defineProperty(exports, "User", { enumerable: true, get: function () { return user_decorator_1.User; } });
|
|
@@ -88,4 +90,10 @@ Object.defineProperty(exports, "hashByKey", { enumerable: true, get: function ()
|
|
|
88
90
|
Object.defineProperty(exports, "compareByKey", { enumerable: true, get: function () { return hash_verification_utils_1.compareByKey; } });
|
|
89
91
|
Object.defineProperty(exports, "lookupHash", { enumerable: true, get: function () { return hash_verification_utils_1.lookupHash; } });
|
|
90
92
|
Object.defineProperty(exports, "compareLookupHash", { enumerable: true, get: function () { return hash_verification_utils_1.compareLookupHash; } });
|
|
93
|
+
var config_secret_utils_1 = require("./utils/config-secret.utils");
|
|
94
|
+
Object.defineProperty(exports, "getOptionalSecret", { enumerable: true, get: function () { return config_secret_utils_1.getOptionalSecret; } });
|
|
95
|
+
Object.defineProperty(exports, "getEncryptionKey", { enumerable: true, get: function () { return config_secret_utils_1.getEncryptionKey; } });
|
|
96
|
+
var auth_lookup_utils_1 = require("./utils/auth-lookup.utils");
|
|
97
|
+
Object.defineProperty(exports, "findUserByLookupHash", { enumerable: true, get: function () { return auth_lookup_utils_1.findUserByLookupHash; } });
|
|
98
|
+
Object.defineProperty(exports, "authenticateWithHashLookup", { enumerable: true, get: function () { return auth_lookup_utils_1.authenticateWithHashLookup; } });
|
|
91
99
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,gDAA8B;AAG9B,6DAA2C;AAC3C,8DAA4C;AAC5C,4DAA0C;AAG1C,6DAA2C;AAC3C,iEAKoC;AAJlC,uHAAA,iBAAiB,OAAA;AACjB,oHAAA,cAAc,OAAA;AAIhB,0DAAwC;AACxC,sDAAoC;AACpC,uDAAqC;AACrC,yDAAuC;AACvC,yDAQgC;AAN9B,kHAAA,gBAAgB,OAAA;AAChB,+GAAA,aAAa,OAAA;AAGb,iHAAA,eAAe,OAAA;AACf,gHAAA,cAAc,OAAA;AAIhB,qEAAmD;AAEnD,4EAA0D;AAC1D,gFAA8D;AAC9D,4EAA0D;AAG1D,0DAAwC;AACxC,uDAAqC;AAGrC,+DAAyF;AAAhF,uHAAA,mBAAmB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,gDAA8B;AAG9B,6DAA2C;AAC3C,8DAA4C;AAC5C,4DAA0C;AAG1C,6DAA2C;AAC3C,iEAKoC;AAJlC,uHAAA,iBAAiB,OAAA;AACjB,oHAAA,cAAc,OAAA;AAIhB,0DAAwC;AACxC,sDAAoC;AACpC,uDAAqC;AACrC,yDAAuC;AACvC,yDAQgC;AAN9B,kHAAA,gBAAgB,OAAA;AAChB,+GAAA,aAAa,OAAA;AAGb,iHAAA,eAAe,OAAA;AACf,gHAAA,cAAc,OAAA;AAIhB,qEAAmD;AAEnD,4EAA0D;AAC1D,gFAA8D;AAC9D,4EAA0D;AAG1D,0DAAwC;AACxC,uDAAqC;AAGrC,+DAAyF;AAAhF,uHAAA,mBAAmB,OAAA;AAC5B,yEAGyC;AAFvC,4HAAA,mBAAmB,OAAA;AAKrB,gEAA8C;AAC9C,8DAA4D;AAAnD,sGAAA,IAAI,OAAA;AACb,gEAAgE;AAAvD,wGAAA,KAAK,OAAA;AAAE,4GAAA,SAAS,OAAA;AAGzB,2DAAyC;AAGzC,+CAS2B;AARzB,sGAAA,SAAS,OAAA;AACT,0GAAA,aAAa,OAAA;AACb,yGAAA,YAAY,OAAA;AACZ,sGAAA,SAAS,OAAA;AACT,0GAAA,aAAa,OAAA;AACb,kGAAA,KAAK,OAAA;AACL,mGAAA,MAAM,OAAA;AAKR,yDAAiE;AAAxD,yHAAA,uBAAuB,OAAA;AAGhC,iEAQoC;AAPlC,yHAAA,mBAAmB,OAAA;AACnB,6HAAA,uBAAuB,OAAA;AAEvB,8HAAA,wBAAwB,OAAA;AACxB,iIAAA,2BAA2B,OAAA;AAC3B,2HAAA,qBAAqB,OAAA;AAKvB,mEAOqC;AANnC,2HAAA,oBAAoB,OAAA;AACpB,yHAAA,kBAAkB,OAAA;AAClB,qIAAA,8BAA8B,OAAA;AAOhC,qDAS8B;AAR5B,kHAAA,kBAAkB,OAAA;AAClB,oHAAA,oBAAoB,OAAA;AACpB,+GAAA,eAAe,OAAA;AACf,yHAAA,yBAAyB,OAAA;AACzB,qHAAA,qBAAqB,OAAA;AACrB,qHAAA,qBAAqB,OAAA;AACrB,iHAAA,iBAAiB,OAAA;AAKnB,2EAgByC;AAfvC,oHAAA,SAAS,OAAA;AACT,uHAAA,YAAY,OAAA;AACZ,oHAAA,SAAS,OAAA;AACT,uHAAA,YAAY,OAAA;AACZ,0HAAA,eAAe,OAAA;AACf,2HAAA,gBAAgB,OAAA;AAChB,+HAAA,oBAAoB,OAAA;AACpB,2HAAA,gBAAgB,OAAA;AAChB,oHAAA,SAAS,OAAA;AACT,uHAAA,YAAY,OAAA;AACZ,qHAAA,UAAU,OAAA;AACV,4HAAA,iBAAiB,OAAA;AAOnB,mEAKqC;AAJnC,wHAAA,iBAAiB,OAAA;AACjB,uHAAA,gBAAgB,OAAA;AAMlB,+DAMmC;AALjC,yHAAA,oBAAoB,OAAA;AACpB,+HAAA,0BAA0B,OAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type DrizzleDb = {
|
|
2
|
+
select: (cols?: any) => {
|
|
3
|
+
from: (table: any) => {
|
|
4
|
+
where: (cond: any) => {
|
|
5
|
+
limit: (n: number) => Promise<any[]>;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export interface FindUserByLookupHashOptions {
|
|
11
|
+
identifier: string;
|
|
12
|
+
encryptionKey: string;
|
|
13
|
+
lookupFieldMap?: Record<string, string>;
|
|
14
|
+
plainColumn?: string;
|
|
15
|
+
normalizer?: (s: string) => string;
|
|
16
|
+
useSha256Variant?: boolean;
|
|
17
|
+
keyDerivation?: 'none' | 'sha256';
|
|
18
|
+
}
|
|
19
|
+
export declare function findUserByLookupHash(db: DrizzleDb, table: Record<string, any>, options: FindUserByLookupHashOptions): Promise<Record<string, unknown> | null>;
|
|
20
|
+
export interface AuthenticateWithHashLookupOptions extends FindUserByLookupHashOptions {
|
|
21
|
+
passwordColumn?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function authenticateWithHashLookup(db: DrizzleDb, table: Record<string, any>, identifier: string, password: string, options: AuthenticateWithHashLookupOptions): Promise<Record<string, unknown> | null>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findUserByLookupHash = findUserByLookupHash;
|
|
4
|
+
exports.authenticateWithHashLookup = authenticateWithHashLookup;
|
|
5
|
+
const crypto = require("crypto");
|
|
6
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
7
|
+
const hash_verification_utils_1 = require("./hash-verification.utils");
|
|
8
|
+
const crypto_utils_1 = require("./crypto.utils");
|
|
9
|
+
async function findUserByLookupHash(db, table, options) {
|
|
10
|
+
const normalized = options.normalizer ? options.normalizer(options.identifier) : options.identifier;
|
|
11
|
+
if (options.lookupFieldMap && Object.keys(options.lookupFieldMap).length > 0) {
|
|
12
|
+
const plainKey = Object.keys(options.lookupFieldMap)[0];
|
|
13
|
+
const hashColumnName = options.lookupFieldMap[plainKey];
|
|
14
|
+
const hashColumn = table[hashColumnName];
|
|
15
|
+
if (!hashColumn) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const hashes = [
|
|
19
|
+
(0, hash_verification_utils_1.lookupHash)(normalized, options.encryptionKey, {
|
|
20
|
+
keyDerivation: options.keyDerivation ?? 'sha256',
|
|
21
|
+
}),
|
|
22
|
+
];
|
|
23
|
+
if (options.useSha256Variant) {
|
|
24
|
+
hashes.push(crypto.createHash('sha256').update(normalized).digest('hex'));
|
|
25
|
+
}
|
|
26
|
+
const rows = await db
|
|
27
|
+
.select()
|
|
28
|
+
.from(table)
|
|
29
|
+
.where((0, drizzle_orm_1.inArray)(hashColumn, hashes))
|
|
30
|
+
.limit(1);
|
|
31
|
+
const row = rows?.[0];
|
|
32
|
+
return row != null ? row : null;
|
|
33
|
+
}
|
|
34
|
+
if (options.plainColumn) {
|
|
35
|
+
const col = table[options.plainColumn];
|
|
36
|
+
if (!col)
|
|
37
|
+
return null;
|
|
38
|
+
const rows = await db
|
|
39
|
+
.select()
|
|
40
|
+
.from(table)
|
|
41
|
+
.where((0, drizzle_orm_1.eq)(col, normalized))
|
|
42
|
+
.limit(1);
|
|
43
|
+
const row = rows?.[0];
|
|
44
|
+
return row != null ? row : null;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
async function authenticateWithHashLookup(db, table, identifier, password, options) {
|
|
49
|
+
const row = await findUserByLookupHash(db, table, options);
|
|
50
|
+
if (!row)
|
|
51
|
+
return null;
|
|
52
|
+
const passwordColumn = options.passwordColumn ?? 'password';
|
|
53
|
+
const stored = row[passwordColumn];
|
|
54
|
+
if (stored == null || typeof stored !== 'string')
|
|
55
|
+
return null;
|
|
56
|
+
if (!(0, crypto_utils_1.pbkdf2VerifyPassword)(password, stored))
|
|
57
|
+
return null;
|
|
58
|
+
const { [passwordColumn]: _, ...rest } = row;
|
|
59
|
+
return rest;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=auth-lookup.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-lookup.utils.js","sourceRoot":"","sources":["../../src/utils/auth-lookup.utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ConfigGetter {
|
|
2
|
+
get<T = unknown>(key: string): T;
|
|
3
|
+
}
|
|
4
|
+
export interface GetOptionalSecretOptions {
|
|
5
|
+
keys: string[];
|
|
6
|
+
envKey: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function getOptionalSecret(config: ConfigGetter | null | undefined, options: GetOptionalSecretOptions): string | undefined;
|
|
9
|
+
export declare function getEncryptionKey(config: ConfigGetter | null | undefined, serviceKey?: string): string | undefined;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getOptionalSecret = getOptionalSecret;
|
|
4
|
+
exports.getEncryptionKey = getEncryptionKey;
|
|
5
|
+
function getOptionalSecret(config, options) {
|
|
6
|
+
const { keys, envKey } = options;
|
|
7
|
+
for (const key of keys) {
|
|
8
|
+
const value = config?.get?.(key);
|
|
9
|
+
if (value != null && typeof value === 'string' && value.trim() !== '') {
|
|
10
|
+
return value.trim();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const envVal = typeof process !== 'undefined' ? process.env[envKey] : undefined;
|
|
14
|
+
if (envVal != null && typeof envVal === 'string' && envVal.trim() !== '') {
|
|
15
|
+
return envVal.trim();
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
function getEncryptionKey(config, serviceKey) {
|
|
20
|
+
const keys = ['encryptionKey'];
|
|
21
|
+
if (serviceKey) {
|
|
22
|
+
keys.push(`${serviceKey}.encryptionKey`);
|
|
23
|
+
}
|
|
24
|
+
return getOptionalSecret(config, { keys, envKey: 'ENCRYPTION_KEY' });
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=config-secret.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-secret.utils.js","sourceRoot":"","sources":["../../src/utils/config-secret.utils.ts"],"names":[],"mappings":";;AAiCA,8CAgBC;AAgBD,4CASC;AAzCD,SAAgB,iBAAiB,CAC/B,MAAuC,EACvC,OAAiC;IAEjC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACtE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChF,IAAI,MAAM,IAAI,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACzE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAgBD,SAAgB,gBAAgB,CAC9B,MAAuC,EACvC,UAAmB;IAEnB,MAAM,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;IAC/B,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,GAAG,UAAU,gBAAgB,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,iBAAiB,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# core-sdk 개선 제안 (전달용)
|
|
2
|
+
|
|
3
|
+
token-services의 auth-service 정리하면서 **core-sdk로 옮기면 재사용·일관성에 도움이 되는 항목** 정리 문서입니다.
|
|
4
|
+
다른 프로젝트(usdt3 등)에서도 동일 패턴을 쓸 수 있도록 core-sdk에 반영해 주시면 됩니다.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. encryptionKey 읽기 유틸 (반영 완료)
|
|
9
|
+
|
|
10
|
+
- **getOptionalSecret(config, { keys, envKey })**, **getEncryptionKey(config, serviceKey?)**
|
|
11
|
+
- 설정·env에서 시크릿을 일관된 우선순위로 조회.
|
|
12
|
+
- `src/utils/config-secret.utils.ts`에서 export.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 2. 해시 컬럼 기반 사용자 조회 + 비밀번호 검증 (반영 완료)
|
|
17
|
+
|
|
18
|
+
- **findUserByLookupHash(db, table, options)**, **authenticateWithHashLookup(db, table, identifier, password, options)**
|
|
19
|
+
- DB 기반 인증 로직 재사용, auth-service 단순화.
|
|
20
|
+
- `src/utils/auth-lookup.utils.ts`에서 export.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 3. resolveConfigRootDir 후보 확장 (선택, 반영)
|
|
25
|
+
|
|
26
|
+
- token-services는 `options.candidates`로 shared/config 경로 전달 가능.
|
|
27
|
+
- `DEFAULT_CONFIG_ROOT_CANDIDATES` 주석에 안내 추가됨.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 4. I18nExceptionFilter 제안
|
|
32
|
+
|
|
33
|
+
- **에러 응답의 error.message를 { ko, en } 객체로 내리기**
|
|
34
|
+
- **동작**: ErrorUtils.fromException → error.message가 `"{ \"ko\":..., \"en\":... }"` 문자열이면 JSON.parse 해서 객체로 교체 후 응답
|
|
35
|
+
- **기존 기본 필터는 유지**하고, **새 필터는 export만 해 두고**, 쓰는 쪽에서 `filters: { exception: false }` 후 **이 필터만 APP_FILTER로 등록**
|
|
36
|
+
- token-services의 auth-service(및 다른 마이크로서비스), usdt3 등에서 **공통 사용 가능**
|
|
37
|
+
- core-sdk에 이 필터가 들어가면, auth-service에서는 지금 있는 로컬 I18nExceptionFilter를 지우고 core-sdk에서 export한 필터를 쓰면 됩니다.
|
|
38
|
+
(지금은 문서만 수정했고, 코드는 auth-service에 그대로 두었습니다.)
|
|
39
|
+
|
|
40
|
+
**구현 상태**: `I18nExceptionFilter` 및 `I18nMessageShape`를 `src/filters/i18n-exception.filter.ts`에서 구현·export함.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 5. 정리
|
|
45
|
+
|
|
46
|
+
| 항목 | 우선순위 | 요약 |
|
|
47
|
+
|------|----------|------|
|
|
48
|
+
| **getEncryptionKey / getOptionalSecret** | 높음 | 설정·env에서 secret 한 번에 읽기, 서비스 간 일관성 (반영 완료) |
|
|
49
|
+
| **findUserByLookupHash / authenticateWithHashLookup** | 중간 | DB 기반 인증 로직 재사용, auth-service 단순화 (반영 완료) |
|
|
50
|
+
| **resolveConfigRootDir preset/확장** | 낮음 | token-services는 shared/config로 대응 가능 (주석 반영) |
|
|
51
|
+
| **I18nExceptionFilter** | 선택 | error.message를 { ko, en } 객체로 내리기, APP_FILTER로만 사용 (반영 완료) |
|
|
52
|
+
|
|
53
|
+
token-services 쪽에서는 위 1·2·4번이 core-sdk에 반영되면 auth-service를 그에 맞춰 리팩터링할 예정입니다.
|
|
54
|
+
문의나 스펙 조정이 필요하면 알려 주세요.
|