@hiliosai/sdk 0.1.15 → 0.1.16
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/index.d.ts +4 -8
- package/dist/index.js +246 -246
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, ServiceBroker, ServiceSchema as ServiceSchema$1, ServiceSettingSchema, Service, BrokerOptions, ActionSchema, ServiceEvents, ServiceMethods, ServiceHooks } from 'moleculer';
|
|
1
|
+
import { Context, ServiceBroker, ServiceSchema as ServiceSchema$1, ServiceSettingSchema, Service, BrokerOptions, ActionSchema, ServiceEvents, ServiceMethods, ServiceHooks, Middleware } from 'moleculer';
|
|
2
2
|
import env from '@ltv/env';
|
|
3
3
|
export { default as env } from '@ltv/env';
|
|
4
4
|
|
|
@@ -57,7 +57,7 @@ interface PermissionHelpers {
|
|
|
57
57
|
auditLog(action: string, resource?: unknown, metadata?: Record<string, unknown>): void;
|
|
58
58
|
createError(message: string, code: string, statusCode?: number): Error;
|
|
59
59
|
}
|
|
60
|
-
type AppContext<TDatasources = unknown, TParams = unknown, TMeta extends AppMeta = AppMeta, TLocals = unknown
|
|
60
|
+
type AppContext<TDatasources = unknown, TParams = unknown, TMeta extends AppMeta = AppMeta, TLocals = Record<string, unknown>> = Context<TParams, TMeta, TLocals> & PermissionHelpers & {
|
|
61
61
|
datasources: TDatasources;
|
|
62
62
|
broker: Context['broker'] & {
|
|
63
63
|
sendToChannel: SendToChannelMethod;
|
|
@@ -823,13 +823,9 @@ type Permission = keyof typeof PERMISSIONS | string | ((ctx: AppContext, action:
|
|
|
823
823
|
interface ActionWithPermissions extends ActionSchema {
|
|
824
824
|
permissions?: Permission | Permission[];
|
|
825
825
|
}
|
|
826
|
-
declare const PermissionsMiddleware:
|
|
827
|
-
localAction(handler: (...args: unknown[]) => unknown, action: ActionWithPermissions): ((...args: unknown[]) => unknown) | ((this: Service, ctx: AppContext) => Promise<unknown>);
|
|
828
|
-
};
|
|
826
|
+
declare const PermissionsMiddleware: Middleware;
|
|
829
827
|
|
|
830
|
-
declare const ContextHelpersMiddleware:
|
|
831
|
-
localAction(handler: (...args: unknown[]) => unknown): (this: unknown, ctx: AppContext) => unknown;
|
|
832
|
-
};
|
|
828
|
+
declare const ContextHelpersMiddleware: Middleware;
|
|
833
829
|
|
|
834
830
|
/**
|
|
835
831
|
* Define a service
|
package/dist/index.js
CHANGED
|
@@ -245,6 +245,250 @@ var ROLE_PERMISSIONS = {
|
|
|
245
245
|
]
|
|
246
246
|
};
|
|
247
247
|
|
|
248
|
+
// src/errors/permission.error.ts
|
|
249
|
+
var PermissionError = class _PermissionError extends Error {
|
|
250
|
+
constructor(message, data) {
|
|
251
|
+
super(message);
|
|
252
|
+
this.code = "PERMISSION_DENIED";
|
|
253
|
+
this.statusCode = 403;
|
|
254
|
+
this.name = "PermissionError";
|
|
255
|
+
this.data = data;
|
|
256
|
+
if (Error.captureStackTrace) {
|
|
257
|
+
Error.captureStackTrace(this, _PermissionError);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// src/errors/auth.error.ts
|
|
263
|
+
var AuthenticationError = class _AuthenticationError extends Error {
|
|
264
|
+
constructor(message, data) {
|
|
265
|
+
super(message);
|
|
266
|
+
this.code = "AUTH_REQUIRED";
|
|
267
|
+
this.statusCode = 401;
|
|
268
|
+
this.name = "AuthenticationError";
|
|
269
|
+
this.data = data;
|
|
270
|
+
if (Error.captureStackTrace) {
|
|
271
|
+
Error.captureStackTrace(this, _AuthenticationError);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
var TenantError = class _TenantError extends Error {
|
|
276
|
+
constructor(message, data) {
|
|
277
|
+
super(message);
|
|
278
|
+
this.code = "TENANT_REQUIRED";
|
|
279
|
+
this.statusCode = 401;
|
|
280
|
+
this.name = "TenantError";
|
|
281
|
+
this.data = data;
|
|
282
|
+
if (Error.captureStackTrace) {
|
|
283
|
+
Error.captureStackTrace(this, _TenantError);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// src/utils/context-cache.ts
|
|
289
|
+
var ContextCache = class _ContextCache {
|
|
290
|
+
constructor() {
|
|
291
|
+
this.memoryCache = /* @__PURE__ */ new Map();
|
|
292
|
+
this.TTL = 5 * 60 * 1e3;
|
|
293
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), 60 * 1e3);
|
|
294
|
+
}
|
|
295
|
+
static getInstance() {
|
|
296
|
+
if (!_ContextCache.instance) {
|
|
297
|
+
_ContextCache.instance = new _ContextCache();
|
|
298
|
+
}
|
|
299
|
+
return _ContextCache.instance;
|
|
300
|
+
}
|
|
301
|
+
async get(key, factory) {
|
|
302
|
+
const cached = this.memoryCache.get(key);
|
|
303
|
+
if (cached && Date.now() - cached.timestamp < this.TTL) {
|
|
304
|
+
return cached.value;
|
|
305
|
+
}
|
|
306
|
+
const value = await factory();
|
|
307
|
+
this.memoryCache.set(key, { value, timestamp: Date.now() });
|
|
308
|
+
return value;
|
|
309
|
+
}
|
|
310
|
+
set(key, value) {
|
|
311
|
+
this.memoryCache.set(key, { value, timestamp: Date.now() });
|
|
312
|
+
}
|
|
313
|
+
delete(key) {
|
|
314
|
+
return this.memoryCache.delete(key);
|
|
315
|
+
}
|
|
316
|
+
clear() {
|
|
317
|
+
this.memoryCache.clear();
|
|
318
|
+
}
|
|
319
|
+
cleanup() {
|
|
320
|
+
const now = Date.now();
|
|
321
|
+
const keysToDelete = [];
|
|
322
|
+
this.memoryCache.forEach((entry, key) => {
|
|
323
|
+
if (now - entry.timestamp > this.TTL) {
|
|
324
|
+
keysToDelete.push(key);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
keysToDelete.forEach((key) => this.memoryCache.delete(key));
|
|
328
|
+
}
|
|
329
|
+
destroy() {
|
|
330
|
+
if (this.cleanupInterval) {
|
|
331
|
+
clearInterval(this.cleanupInterval);
|
|
332
|
+
}
|
|
333
|
+
this.clear();
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// src/utils/permission-calculator.ts
|
|
338
|
+
var PermissionCalculator = class {
|
|
339
|
+
static calculateUserPermissions(user) {
|
|
340
|
+
if (!user || !Array.isArray(user.roles)) {
|
|
341
|
+
return [];
|
|
342
|
+
}
|
|
343
|
+
const explicitPermissions = Array.isArray(user.permissions) ? user.permissions : [];
|
|
344
|
+
const rolePermissions = user.roles.flatMap((role) => {
|
|
345
|
+
return ROLE_PERMISSIONS[role] ?? [];
|
|
346
|
+
});
|
|
347
|
+
const allPermissions = [...explicitPermissions, ...rolePermissions];
|
|
348
|
+
const uniquePermissions = [];
|
|
349
|
+
allPermissions.forEach((permission) => {
|
|
350
|
+
if (!uniquePermissions.includes(permission)) {
|
|
351
|
+
uniquePermissions.push(permission);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
return uniquePermissions;
|
|
355
|
+
}
|
|
356
|
+
static hasPermission(user, permission) {
|
|
357
|
+
if (typeof permission !== "string" || !permission.trim()) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
if (!user || typeof user !== "object") {
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
if (!Array.isArray(user.roles)) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
if (Array.isArray(user.permissions) && user.permissions.includes(permission)) {
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
return user.roles.some((role) => {
|
|
370
|
+
const rolePermissions = ROLE_PERMISSIONS[role] ?? [];
|
|
371
|
+
return rolePermissions.includes(permission);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// src/middlewares/context-helpers.middleware.ts
|
|
377
|
+
var ContextHelpersMiddleware = {
|
|
378
|
+
// Add helper functions to context before action handlers
|
|
379
|
+
localAction(handler) {
|
|
380
|
+
return function ContextHelpersWrapper(ctx) {
|
|
381
|
+
const cache = ContextCache.getInstance();
|
|
382
|
+
const memoizedPermissions = /* @__PURE__ */ new Map();
|
|
383
|
+
ctx.hasPermission = function(permission) {
|
|
384
|
+
if (memoizedPermissions.has(permission)) {
|
|
385
|
+
const cachedResult = memoizedPermissions.get(permission);
|
|
386
|
+
return cachedResult === true;
|
|
387
|
+
}
|
|
388
|
+
const user = ctx.meta.user;
|
|
389
|
+
if (!user) {
|
|
390
|
+
memoizedPermissions.set(permission, false);
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
const result = PermissionCalculator.hasPermission(user, permission);
|
|
394
|
+
memoizedPermissions.set(permission, result);
|
|
395
|
+
return result;
|
|
396
|
+
};
|
|
397
|
+
ctx.getUserPermissions = async function() {
|
|
398
|
+
const user = ctx.meta.user;
|
|
399
|
+
if (!user) return [];
|
|
400
|
+
const cacheKey = `permissions:${user.id}:${JSON.stringify(user.roles)}`;
|
|
401
|
+
return cache.get(cacheKey, () => {
|
|
402
|
+
return PermissionCalculator.calculateUserPermissions(user);
|
|
403
|
+
});
|
|
404
|
+
};
|
|
405
|
+
ctx.hasRole = function(role) {
|
|
406
|
+
const user = ctx.ensureUser();
|
|
407
|
+
return Array.isArray(user.roles) && user.roles.includes(role);
|
|
408
|
+
};
|
|
409
|
+
ctx.isTenantMember = function() {
|
|
410
|
+
const user = ctx.ensureUser();
|
|
411
|
+
return !!(user.tenantId && ctx.meta.tenantId && user.tenantId === ctx.meta.tenantId);
|
|
412
|
+
};
|
|
413
|
+
ctx.isTenantOwner = function() {
|
|
414
|
+
return ctx.isTenantMember() && ctx.hasRole("OWNER");
|
|
415
|
+
};
|
|
416
|
+
ctx.ensureUser = () => {
|
|
417
|
+
if (!ctx.meta.user) {
|
|
418
|
+
ctx.broker.logger.error("Authentication required", {
|
|
419
|
+
action: ctx.action?.name,
|
|
420
|
+
requestId: ctx.meta.requestId,
|
|
421
|
+
userAgent: ctx.meta.userAgent,
|
|
422
|
+
ip: ctx.meta.clientIP
|
|
423
|
+
});
|
|
424
|
+
throw new AuthenticationError("Authentication required", {
|
|
425
|
+
code: "AUTH_REQUIRED",
|
|
426
|
+
statusCode: 401,
|
|
427
|
+
requestId: ctx.meta.requestId
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
return ctx.meta.user;
|
|
431
|
+
};
|
|
432
|
+
ctx.ensureTenant = () => {
|
|
433
|
+
if (!ctx.meta.tenantId) {
|
|
434
|
+
ctx.broker.logger.error("Tenant required", {
|
|
435
|
+
action: ctx.action?.name,
|
|
436
|
+
userId: ctx.meta.user?.id,
|
|
437
|
+
requestId: ctx.meta.requestId
|
|
438
|
+
});
|
|
439
|
+
throw new TenantError("Tenant required", {
|
|
440
|
+
code: "TENANT_REQUIRED",
|
|
441
|
+
statusCode: 401,
|
|
442
|
+
tenantId: ctx.meta.tenantId,
|
|
443
|
+
requestId: ctx.meta.requestId
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
id: ctx.meta.tenantId,
|
|
448
|
+
name: ctx.meta.tenantName ?? ""
|
|
449
|
+
};
|
|
450
|
+
};
|
|
451
|
+
ctx.auditLog = function(action, resource, metadata) {
|
|
452
|
+
ctx.broker.logger.info("Audit log", {
|
|
453
|
+
action,
|
|
454
|
+
resource: resource ? {
|
|
455
|
+
type: typeof resource,
|
|
456
|
+
id: resource.id
|
|
457
|
+
} : void 0,
|
|
458
|
+
userId: ctx.meta.user?.id,
|
|
459
|
+
tenantId: ctx.meta.tenantId,
|
|
460
|
+
requestId: ctx.meta.requestId,
|
|
461
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
462
|
+
...metadata
|
|
463
|
+
});
|
|
464
|
+
};
|
|
465
|
+
ctx.createError = function(message, code, statusCode = 400) {
|
|
466
|
+
const errorData = {
|
|
467
|
+
code,
|
|
468
|
+
statusCode,
|
|
469
|
+
userId: ctx.meta.user?.id,
|
|
470
|
+
tenantId: ctx.meta.tenantId,
|
|
471
|
+
requestId: ctx.meta.requestId,
|
|
472
|
+
action: ctx.action?.name,
|
|
473
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
474
|
+
};
|
|
475
|
+
ctx.broker.logger.warn("Context error created", {
|
|
476
|
+
message,
|
|
477
|
+
...errorData
|
|
478
|
+
});
|
|
479
|
+
if (code === "AUTH_REQUIRED") {
|
|
480
|
+
return new AuthenticationError(message, errorData);
|
|
481
|
+
}
|
|
482
|
+
if (code === "TENANT_REQUIRED") {
|
|
483
|
+
return new TenantError(message, errorData);
|
|
484
|
+
}
|
|
485
|
+
return new Error(message);
|
|
486
|
+
};
|
|
487
|
+
return handler.call(this, ctx);
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
248
492
|
// src/configs/moleculer/bulkhead.ts
|
|
249
493
|
var bulkheadConfig = {
|
|
250
494
|
// Enable feature.
|
|
@@ -600,46 +844,6 @@ var isProd = nodeEnv === "production";
|
|
|
600
844
|
var REDIS_URL = env3.string("REDIS_URL");
|
|
601
845
|
var env_default = env3;
|
|
602
846
|
|
|
603
|
-
// src/errors/permission.error.ts
|
|
604
|
-
var PermissionError = class _PermissionError extends Error {
|
|
605
|
-
constructor(message, data) {
|
|
606
|
-
super(message);
|
|
607
|
-
this.code = "PERMISSION_DENIED";
|
|
608
|
-
this.statusCode = 403;
|
|
609
|
-
this.name = "PermissionError";
|
|
610
|
-
this.data = data;
|
|
611
|
-
if (Error.captureStackTrace) {
|
|
612
|
-
Error.captureStackTrace(this, _PermissionError);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
// src/errors/auth.error.ts
|
|
618
|
-
var AuthenticationError = class _AuthenticationError extends Error {
|
|
619
|
-
constructor(message, data) {
|
|
620
|
-
super(message);
|
|
621
|
-
this.code = "AUTH_REQUIRED";
|
|
622
|
-
this.statusCode = 401;
|
|
623
|
-
this.name = "AuthenticationError";
|
|
624
|
-
this.data = data;
|
|
625
|
-
if (Error.captureStackTrace) {
|
|
626
|
-
Error.captureStackTrace(this, _AuthenticationError);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
};
|
|
630
|
-
var TenantError = class _TenantError extends Error {
|
|
631
|
-
constructor(message, data) {
|
|
632
|
-
super(message);
|
|
633
|
-
this.code = "TENANT_REQUIRED";
|
|
634
|
-
this.statusCode = 401;
|
|
635
|
-
this.name = "TenantError";
|
|
636
|
-
this.data = data;
|
|
637
|
-
if (Error.captureStackTrace) {
|
|
638
|
-
Error.captureStackTrace(this, _TenantError);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
};
|
|
642
|
-
|
|
643
847
|
// src/middlewares/permissions.middleware.ts
|
|
644
848
|
var permissionHandlers = {
|
|
645
849
|
[PERMISSIONS.AUTHENTICATED]: async (ctx) => !!ctx.meta.user?.id,
|
|
@@ -732,210 +936,6 @@ var PermissionsMiddleware = {
|
|
|
732
936
|
}
|
|
733
937
|
};
|
|
734
938
|
|
|
735
|
-
// src/utils/context-cache.ts
|
|
736
|
-
var ContextCache = class _ContextCache {
|
|
737
|
-
constructor() {
|
|
738
|
-
this.memoryCache = /* @__PURE__ */ new Map();
|
|
739
|
-
this.TTL = 5 * 60 * 1e3;
|
|
740
|
-
this.cleanupInterval = setInterval(() => this.cleanup(), 60 * 1e3);
|
|
741
|
-
}
|
|
742
|
-
static getInstance() {
|
|
743
|
-
if (!_ContextCache.instance) {
|
|
744
|
-
_ContextCache.instance = new _ContextCache();
|
|
745
|
-
}
|
|
746
|
-
return _ContextCache.instance;
|
|
747
|
-
}
|
|
748
|
-
async get(key, factory) {
|
|
749
|
-
const cached = this.memoryCache.get(key);
|
|
750
|
-
if (cached && Date.now() - cached.timestamp < this.TTL) {
|
|
751
|
-
return cached.value;
|
|
752
|
-
}
|
|
753
|
-
const value = await factory();
|
|
754
|
-
this.memoryCache.set(key, { value, timestamp: Date.now() });
|
|
755
|
-
return value;
|
|
756
|
-
}
|
|
757
|
-
set(key, value) {
|
|
758
|
-
this.memoryCache.set(key, { value, timestamp: Date.now() });
|
|
759
|
-
}
|
|
760
|
-
delete(key) {
|
|
761
|
-
return this.memoryCache.delete(key);
|
|
762
|
-
}
|
|
763
|
-
clear() {
|
|
764
|
-
this.memoryCache.clear();
|
|
765
|
-
}
|
|
766
|
-
cleanup() {
|
|
767
|
-
const now = Date.now();
|
|
768
|
-
const keysToDelete = [];
|
|
769
|
-
this.memoryCache.forEach((entry, key) => {
|
|
770
|
-
if (now - entry.timestamp > this.TTL) {
|
|
771
|
-
keysToDelete.push(key);
|
|
772
|
-
}
|
|
773
|
-
});
|
|
774
|
-
keysToDelete.forEach((key) => this.memoryCache.delete(key));
|
|
775
|
-
}
|
|
776
|
-
destroy() {
|
|
777
|
-
if (this.cleanupInterval) {
|
|
778
|
-
clearInterval(this.cleanupInterval);
|
|
779
|
-
}
|
|
780
|
-
this.clear();
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
|
|
784
|
-
// src/utils/permission-calculator.ts
|
|
785
|
-
var PermissionCalculator = class {
|
|
786
|
-
static calculateUserPermissions(user) {
|
|
787
|
-
if (!user || !Array.isArray(user.roles)) {
|
|
788
|
-
return [];
|
|
789
|
-
}
|
|
790
|
-
const explicitPermissions = Array.isArray(user.permissions) ? user.permissions : [];
|
|
791
|
-
const rolePermissions = user.roles.flatMap((role) => {
|
|
792
|
-
return ROLE_PERMISSIONS[role] ?? [];
|
|
793
|
-
});
|
|
794
|
-
const allPermissions = [...explicitPermissions, ...rolePermissions];
|
|
795
|
-
const uniquePermissions = [];
|
|
796
|
-
allPermissions.forEach((permission) => {
|
|
797
|
-
if (!uniquePermissions.includes(permission)) {
|
|
798
|
-
uniquePermissions.push(permission);
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
return uniquePermissions;
|
|
802
|
-
}
|
|
803
|
-
static hasPermission(user, permission) {
|
|
804
|
-
if (typeof permission !== "string" || !permission.trim()) {
|
|
805
|
-
return false;
|
|
806
|
-
}
|
|
807
|
-
if (!user || typeof user !== "object") {
|
|
808
|
-
return false;
|
|
809
|
-
}
|
|
810
|
-
if (!Array.isArray(user.roles)) {
|
|
811
|
-
return false;
|
|
812
|
-
}
|
|
813
|
-
if (Array.isArray(user.permissions) && user.permissions.includes(permission)) {
|
|
814
|
-
return true;
|
|
815
|
-
}
|
|
816
|
-
return user.roles.some((role) => {
|
|
817
|
-
const rolePermissions = ROLE_PERMISSIONS[role] ?? [];
|
|
818
|
-
return rolePermissions.includes(permission);
|
|
819
|
-
});
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
|
-
|
|
823
|
-
// src/middlewares/context-helpers.middleware.ts
|
|
824
|
-
var ContextHelpersMiddleware = {
|
|
825
|
-
// Add helper functions to context before action handlers
|
|
826
|
-
localAction(handler) {
|
|
827
|
-
return function ContextHelpersWrapper(ctx) {
|
|
828
|
-
const cache = ContextCache.getInstance();
|
|
829
|
-
const memoizedPermissions = /* @__PURE__ */ new Map();
|
|
830
|
-
ctx.hasPermission = function(permission) {
|
|
831
|
-
if (memoizedPermissions.has(permission)) {
|
|
832
|
-
const cachedResult = memoizedPermissions.get(permission);
|
|
833
|
-
return cachedResult === true;
|
|
834
|
-
}
|
|
835
|
-
const user = ctx.meta.user;
|
|
836
|
-
if (!user) {
|
|
837
|
-
memoizedPermissions.set(permission, false);
|
|
838
|
-
return false;
|
|
839
|
-
}
|
|
840
|
-
const result = PermissionCalculator.hasPermission(user, permission);
|
|
841
|
-
memoizedPermissions.set(permission, result);
|
|
842
|
-
return result;
|
|
843
|
-
};
|
|
844
|
-
ctx.getUserPermissions = async function() {
|
|
845
|
-
const user = ctx.meta.user;
|
|
846
|
-
if (!user) return [];
|
|
847
|
-
const cacheKey = `permissions:${user.id}:${JSON.stringify(user.roles)}`;
|
|
848
|
-
return cache.get(cacheKey, () => {
|
|
849
|
-
return PermissionCalculator.calculateUserPermissions(user);
|
|
850
|
-
});
|
|
851
|
-
};
|
|
852
|
-
ctx.hasRole = function(role) {
|
|
853
|
-
const user = ctx.ensureUser();
|
|
854
|
-
return Array.isArray(user.roles) && user.roles.includes(role);
|
|
855
|
-
};
|
|
856
|
-
ctx.isTenantMember = function() {
|
|
857
|
-
const user = ctx.ensureUser();
|
|
858
|
-
return !!(user.tenantId && ctx.meta.tenantId && user.tenantId === ctx.meta.tenantId);
|
|
859
|
-
};
|
|
860
|
-
ctx.isTenantOwner = function() {
|
|
861
|
-
return ctx.isTenantMember() && ctx.hasRole("OWNER");
|
|
862
|
-
};
|
|
863
|
-
ctx.ensureUser = () => {
|
|
864
|
-
if (!ctx.meta.user) {
|
|
865
|
-
ctx.broker.logger.error("Authentication required", {
|
|
866
|
-
action: ctx.action?.name,
|
|
867
|
-
requestId: ctx.meta.requestId,
|
|
868
|
-
userAgent: ctx.meta.userAgent,
|
|
869
|
-
ip: ctx.meta.clientIP
|
|
870
|
-
});
|
|
871
|
-
throw new AuthenticationError("Authentication required", {
|
|
872
|
-
code: "AUTH_REQUIRED",
|
|
873
|
-
statusCode: 401,
|
|
874
|
-
requestId: ctx.meta.requestId
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
|
-
return ctx.meta.user;
|
|
878
|
-
};
|
|
879
|
-
ctx.ensureTenant = () => {
|
|
880
|
-
if (!ctx.meta.tenantId) {
|
|
881
|
-
ctx.broker.logger.error("Tenant required", {
|
|
882
|
-
action: ctx.action?.name,
|
|
883
|
-
userId: ctx.meta.user?.id,
|
|
884
|
-
requestId: ctx.meta.requestId
|
|
885
|
-
});
|
|
886
|
-
throw new TenantError("Tenant required", {
|
|
887
|
-
code: "TENANT_REQUIRED",
|
|
888
|
-
statusCode: 401,
|
|
889
|
-
tenantId: ctx.meta.tenantId,
|
|
890
|
-
requestId: ctx.meta.requestId
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
return {
|
|
894
|
-
id: ctx.meta.tenantId,
|
|
895
|
-
name: ctx.meta.tenantName ?? ""
|
|
896
|
-
};
|
|
897
|
-
};
|
|
898
|
-
ctx.auditLog = function(action, resource, metadata) {
|
|
899
|
-
ctx.broker.logger.info("Audit log", {
|
|
900
|
-
action,
|
|
901
|
-
resource: resource ? {
|
|
902
|
-
type: typeof resource,
|
|
903
|
-
id: resource.id
|
|
904
|
-
} : void 0,
|
|
905
|
-
userId: ctx.meta.user?.id,
|
|
906
|
-
tenantId: ctx.meta.tenantId,
|
|
907
|
-
requestId: ctx.meta.requestId,
|
|
908
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
909
|
-
...metadata
|
|
910
|
-
});
|
|
911
|
-
};
|
|
912
|
-
ctx.createError = function(message, code, statusCode = 400) {
|
|
913
|
-
const errorData = {
|
|
914
|
-
code,
|
|
915
|
-
statusCode,
|
|
916
|
-
userId: ctx.meta.user?.id,
|
|
917
|
-
tenantId: ctx.meta.tenantId,
|
|
918
|
-
requestId: ctx.meta.requestId,
|
|
919
|
-
action: ctx.action?.name,
|
|
920
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
921
|
-
};
|
|
922
|
-
ctx.broker.logger.warn("Context error created", {
|
|
923
|
-
message,
|
|
924
|
-
...errorData
|
|
925
|
-
});
|
|
926
|
-
if (code === "AUTH_REQUIRED") {
|
|
927
|
-
return new AuthenticationError(message, errorData);
|
|
928
|
-
}
|
|
929
|
-
if (code === "TENANT_REQUIRED") {
|
|
930
|
-
return new TenantError(message, errorData);
|
|
931
|
-
}
|
|
932
|
-
return new Error(message);
|
|
933
|
-
};
|
|
934
|
-
return handler.call(this, ctx);
|
|
935
|
-
};
|
|
936
|
-
}
|
|
937
|
-
};
|
|
938
|
-
|
|
939
939
|
// src/mixins/datasource.mixin.ts
|
|
940
940
|
function DatasourceMixin(datasourceConstructors = {}) {
|
|
941
941
|
const datasourceInstances = {};
|
|
@@ -1236,10 +1236,10 @@ function defineIntegration(config) {
|
|
|
1236
1236
|
i_verifyWebhook: {
|
|
1237
1237
|
rest: {
|
|
1238
1238
|
method: "GET",
|
|
1239
|
-
path: "/:
|
|
1239
|
+
path: "/:channelId"
|
|
1240
1240
|
},
|
|
1241
1241
|
params: {
|
|
1242
|
-
|
|
1242
|
+
channelId: "string",
|
|
1243
1243
|
mode: "string",
|
|
1244
1244
|
token: "string",
|
|
1245
1245
|
challenge: "string"
|