@twin.org/api-auth-entity-storage-service 0.0.3-next.40 → 0.0.3-next.41
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.
|
@@ -164,6 +164,7 @@ export class EntityStorageAuthenticationAuditService {
|
|
|
164
164
|
* Hash a list of IP addresses using SHA-256.
|
|
165
165
|
* @param ipAddresses The IP addresses to hash.
|
|
166
166
|
* @returns The hexadecimal hashes of the salted IPs.
|
|
167
|
+
* @internal
|
|
167
168
|
*/
|
|
168
169
|
hashIpAddresses(ipAddresses) {
|
|
169
170
|
if (!Is.stringValue(this._ipHashSalt) || !Is.array(ipAddresses)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityStorageAuthenticationAuditService.js","sourceRoot":"","sources":["../../../src/services/entityStorageAuthenticationAuditService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tAuthAuditEvent,\n\tIAuthenticationAuditComponent,\n\tIAuthenticationAuditEntry\n} from \"@twin.org/api-auth-entity-storage-models\";\nimport { HttpContextIdKeys } from \"@twin.org/api-models\";\nimport { ContextIdStore, ContextIdKeys } from \"@twin.org/context\";\nimport {\n\tConverter,\n\tGuards,\n\tIs,\n\tRandomHelper,\n\tValidation,\n\ttype IValidationFailure\n} from \"@twin.org/core\";\nimport { Sha256 } from \"@twin.org/crypto\";\nimport { ComparisonOperator } from \"@twin.org/entity\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { AuthenticationAuditEntry } from \"../entities/authenticationAuditEntry.js\";\nimport type { IEntityStorageAuthenticationAuditServiceConstructorOptions } from \"../models/IEntityStorageAuthenticationAuditServiceConstructorOptions.js\";\n\n/**\n * Implementation of the authentication audit component using entity storage.\n */\nexport class EntityStorageAuthenticationAuditService implements IAuthenticationAuditComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<EntityStorageAuthenticationAuditService>();\n\n\t/**\n\t * The entity storage for authentication audit entries.\n\t * @internal\n\t */\n\tprivate readonly _authenticationAuditEntryEntityStorage: IEntityStorageConnector<AuthenticationAuditEntry>;\n\n\t/**\n\t * The server-side salt for hashing IP addresses in audit logs, if configured.\n\t * @internal\n\t */\n\tprivate readonly _ipHashSalt?: string;\n\n\t/**\n\t * Create a new instance of EntityStorageAuthenticationAuditService.\n\t * @param options The dependencies for the identity connector.\n\t */\n\tconstructor(options?: IEntityStorageAuthenticationAuditServiceConstructorOptions) {\n\t\tthis._authenticationAuditEntryEntityStorage = EntityStorageConnectorFactory.get(\n\t\t\toptions?.authenticationAuditEntryStorageType ?? \"authentication-audit-entry\"\n\t\t);\n\t\tconst salt = options?.config?.ipHashSalt?.trim();\n\t\tif (Is.stringValue(salt)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.stringValue(\n\t\t\t\tnameof(options?.config?.ipHashSalt),\n\t\t\t\tsalt,\n\t\t\t\tvalidationFailures,\n\t\t\t\tundefined,\n\t\t\t\t{ minLength: 32 }\n\t\t\t);\n\t\t\tconst entropy = new Set(salt).size;\n\t\t\tif (entropy < 8) {\n\t\t\t\tvalidationFailures.push({\n\t\t\t\t\tproperty: nameof(options?.config?.ipHashSalt),\n\t\t\t\t\treason: \"validation.saltEntropyTooLow\"\n\t\t\t\t});\n\t\t\t}\n\t\t\tValidation.asValidationError(\n\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\tnameof(options?.config?.ipHashSalt),\n\t\t\t\tvalidationFailures\n\t\t\t);\n\n\t\t\tthis._ipHashSalt = salt;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn EntityStorageAuthenticationAuditService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Create a new audit entry.\n\t * @param entry The audit entry to be logged.\n\t * @returns The unique identifier of the created audit entry.\n\t */\n\tpublic async create(\n\t\tentry: Omit<IAuthenticationAuditEntry, \"id\" | \"dateCreated\">\n\t): Promise<string> {\n\t\tGuards.object<IAuthenticationAuditEntry>(\n\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\tnameof(entry),\n\t\t\tentry\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\tnameof(entry.event),\n\t\t\tentry.event\n\t\t);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\n\t\tconst newAuditEntry: AuthenticationAuditEntry = {\n\t\t\tid: RandomHelper.generateUuidV7(\"compact\"),\n\t\t\tdateCreated: new Date().toISOString(),\n\t\t\tevent: entry.event,\n\t\t\tactorId: entry.actorId ?? contextIds?.[ContextIdKeys.User],\n\t\t\tnodeId: entry.nodeId ?? contextIds?.[ContextIdKeys.Node],\n\t\t\torganizationId: entry.organizationId ?? contextIds?.[ContextIdKeys.Organization],\n\t\t\ttenantId: entry.tenantId ?? contextIds?.[ContextIdKeys.Tenant],\n\t\t\tdata: entry.data,\n\t\t\tipAddressHashes: this.hashIpAddresses(contextIds?.[HttpContextIdKeys.IpAddress]?.split(\"|\")),\n\t\t\tuserAgent: contextIds?.[HttpContextIdKeys.UserAgent],\n\t\t\tcorrelationId: contextIds?.[HttpContextIdKeys.CorrelationId]\n\t\t};\n\n\t\ttry {\n\t\t\tawait this._authenticationAuditEntryEntityStorage.set(newAuditEntry);\n\t\t} catch {\n\t\t\t// Best-effort audit logging: do not interrupt auth/admin flows if persistence fails.\n\t\t}\n\n\t\treturn newAuditEntry.id;\n\t}\n\n\t/**\n\t * Query the audit entries.\n\t * @param options The query options.\n\t * @param options.actorId The actor identifier to filter the audit entries, optional.\n\t * @param options.organizationId The organization identifier to filter the audit entries, optional.\n\t * @param options.tenantId The tenant identifier to filter the audit entries, optional.\n\t * @param options.nodeId The node identifier to filter the audit entries, optional.\n\t * @param options.event The audit event to filter the audit entries, optional.\n\t * @param options.startDate The start date to filter the audit entries, optional.\n\t * @param options.endDate The end date to filter the audit entries, optional.\n\t * @param cursor The cursor for pagination.\n\t * @param limit The maximum number of entries to return.\n\t * @returns The audit entries.\n\t */\n\tpublic async query(\n\t\toptions?: {\n\t\t\tactorId?: string;\n\t\t\torganizationId?: string;\n\t\t\ttenantId?: string;\n\t\t\tnodeId?: string;\n\t\t\tevent?: AuthAuditEvent | string;\n\t\t\tstartDate?: string;\n\t\t\tendDate?: string;\n\t\t},\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\tentries: IAuthenticationAuditEntry[];\n\t\tcursor?: string;\n\t}> {\n\t\tconst conditions: {\n\t\t\tproperty: string;\n\t\t\tvalue: string;\n\t\t\tcomparison: (typeof ComparisonOperator)[keyof typeof ComparisonOperator];\n\t\t}[] = [];\n\n\t\tif (Is.object(options)) {\n\t\t\tif (!Is.empty(options.actorId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.actorId),\n\t\t\t\t\toptions.actorId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"actorId\",\n\t\t\t\t\tvalue: options.actorId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.organizationId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.organizationId),\n\t\t\t\t\toptions.organizationId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"organizationId\",\n\t\t\t\t\tvalue: options.organizationId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.tenantId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.tenantId),\n\t\t\t\t\toptions.tenantId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"tenantId\",\n\t\t\t\t\tvalue: options.tenantId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.nodeId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.nodeId),\n\t\t\t\t\toptions.nodeId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"nodeId\",\n\t\t\t\t\tvalue: options.nodeId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.event)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.event),\n\t\t\t\t\toptions.event\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"event\",\n\t\t\t\t\tvalue: options.event,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.startDate)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.startDate),\n\t\t\t\t\toptions.startDate\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"dateCreated\",\n\t\t\t\t\tvalue: options.startDate,\n\t\t\t\t\tcomparison: ComparisonOperator.GreaterThanOrEqual\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.endDate)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.endDate),\n\t\t\t\t\toptions.endDate\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"dateCreated\",\n\t\t\t\t\tvalue: options.endDate,\n\t\t\t\t\tcomparison: ComparisonOperator.LessThanOrEqual\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst result = await this._authenticationAuditEntryEntityStorage.query(\n\t\t\tconditions.length > 0 ? { conditions } : undefined,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tcursor,\n\t\t\tlimit\n\t\t);\n\n\t\treturn {\n\t\t\tentries: result.entities as IAuthenticationAuditEntry[],\n\t\t\tcursor: result.cursor\n\t\t};\n\t}\n\n\t/**\n\t * Hash a list of IP addresses using SHA-256.\n\t * @param ipAddresses The IP addresses to hash.\n\t * @returns The hexadecimal hashes of the salted IPs.\n\t */\n\tprivate hashIpAddresses(ipAddresses: string[] | undefined): string[] | undefined {\n\t\tif (!Is.stringValue(this._ipHashSalt) || !Is.array(ipAddresses)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn ipAddresses.map(ip => {\n\t\t\tconst hash = Sha256.sum256(Converter.utf8ToBytes(`${this._ipHashSalt}:${ip}`));\n\t\t\treturn Converter.bytesToHex(hash);\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"entityStorageAuthenticationAuditService.js","sourceRoot":"","sources":["../../../src/services/entityStorageAuthenticationAuditService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tAuthAuditEvent,\n\tIAuthenticationAuditComponent,\n\tIAuthenticationAuditEntry\n} from \"@twin.org/api-auth-entity-storage-models\";\nimport { HttpContextIdKeys } from \"@twin.org/api-models\";\nimport { ContextIdStore, ContextIdKeys } from \"@twin.org/context\";\nimport {\n\tConverter,\n\tGuards,\n\tIs,\n\tRandomHelper,\n\tValidation,\n\ttype IValidationFailure\n} from \"@twin.org/core\";\nimport { Sha256 } from \"@twin.org/crypto\";\nimport { ComparisonOperator } from \"@twin.org/entity\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { AuthenticationAuditEntry } from \"../entities/authenticationAuditEntry.js\";\nimport type { IEntityStorageAuthenticationAuditServiceConstructorOptions } from \"../models/IEntityStorageAuthenticationAuditServiceConstructorOptions.js\";\n\n/**\n * Implementation of the authentication audit component using entity storage.\n */\nexport class EntityStorageAuthenticationAuditService implements IAuthenticationAuditComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<EntityStorageAuthenticationAuditService>();\n\n\t/**\n\t * The entity storage for authentication audit entries.\n\t * @internal\n\t */\n\tprivate readonly _authenticationAuditEntryEntityStorage: IEntityStorageConnector<AuthenticationAuditEntry>;\n\n\t/**\n\t * The server-side salt for hashing IP addresses in audit logs, if configured.\n\t * @internal\n\t */\n\tprivate readonly _ipHashSalt?: string;\n\n\t/**\n\t * Create a new instance of EntityStorageAuthenticationAuditService.\n\t * @param options The dependencies for the identity connector.\n\t */\n\tconstructor(options?: IEntityStorageAuthenticationAuditServiceConstructorOptions) {\n\t\tthis._authenticationAuditEntryEntityStorage = EntityStorageConnectorFactory.get(\n\t\t\toptions?.authenticationAuditEntryStorageType ?? \"authentication-audit-entry\"\n\t\t);\n\t\tconst salt = options?.config?.ipHashSalt?.trim();\n\t\tif (Is.stringValue(salt)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.stringValue(\n\t\t\t\tnameof(options?.config?.ipHashSalt),\n\t\t\t\tsalt,\n\t\t\t\tvalidationFailures,\n\t\t\t\tundefined,\n\t\t\t\t{ minLength: 32 }\n\t\t\t);\n\t\t\tconst entropy = new Set(salt).size;\n\t\t\tif (entropy < 8) {\n\t\t\t\tvalidationFailures.push({\n\t\t\t\t\tproperty: nameof(options?.config?.ipHashSalt),\n\t\t\t\t\treason: \"validation.saltEntropyTooLow\"\n\t\t\t\t});\n\t\t\t}\n\t\t\tValidation.asValidationError(\n\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\tnameof(options?.config?.ipHashSalt),\n\t\t\t\tvalidationFailures\n\t\t\t);\n\n\t\t\tthis._ipHashSalt = salt;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn EntityStorageAuthenticationAuditService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Create a new audit entry.\n\t * @param entry The audit entry to be logged.\n\t * @returns The unique identifier of the created audit entry.\n\t */\n\tpublic async create(\n\t\tentry: Omit<IAuthenticationAuditEntry, \"id\" | \"dateCreated\">\n\t): Promise<string> {\n\t\tGuards.object<IAuthenticationAuditEntry>(\n\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\tnameof(entry),\n\t\t\tentry\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\tnameof(entry.event),\n\t\t\tentry.event\n\t\t);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\n\t\tconst newAuditEntry: AuthenticationAuditEntry = {\n\t\t\tid: RandomHelper.generateUuidV7(\"compact\"),\n\t\t\tdateCreated: new Date().toISOString(),\n\t\t\tevent: entry.event,\n\t\t\tactorId: entry.actorId ?? contextIds?.[ContextIdKeys.User],\n\t\t\tnodeId: entry.nodeId ?? contextIds?.[ContextIdKeys.Node],\n\t\t\torganizationId: entry.organizationId ?? contextIds?.[ContextIdKeys.Organization],\n\t\t\ttenantId: entry.tenantId ?? contextIds?.[ContextIdKeys.Tenant],\n\t\t\tdata: entry.data,\n\t\t\tipAddressHashes: this.hashIpAddresses(contextIds?.[HttpContextIdKeys.IpAddress]?.split(\"|\")),\n\t\t\tuserAgent: contextIds?.[HttpContextIdKeys.UserAgent],\n\t\t\tcorrelationId: contextIds?.[HttpContextIdKeys.CorrelationId]\n\t\t};\n\n\t\ttry {\n\t\t\tawait this._authenticationAuditEntryEntityStorage.set(newAuditEntry);\n\t\t} catch {\n\t\t\t// Best-effort audit logging: do not interrupt auth/admin flows if persistence fails.\n\t\t}\n\n\t\treturn newAuditEntry.id;\n\t}\n\n\t/**\n\t * Query the audit entries.\n\t * @param options The query options.\n\t * @param options.actorId The actor identifier to filter the audit entries, optional.\n\t * @param options.organizationId The organization identifier to filter the audit entries, optional.\n\t * @param options.tenantId The tenant identifier to filter the audit entries, optional.\n\t * @param options.nodeId The node identifier to filter the audit entries, optional.\n\t * @param options.event The audit event to filter the audit entries, optional.\n\t * @param options.startDate The start date to filter the audit entries, optional.\n\t * @param options.endDate The end date to filter the audit entries, optional.\n\t * @param cursor The cursor for pagination.\n\t * @param limit The maximum number of entries to return.\n\t * @returns The audit entries.\n\t */\n\tpublic async query(\n\t\toptions?: {\n\t\t\tactorId?: string;\n\t\t\torganizationId?: string;\n\t\t\ttenantId?: string;\n\t\t\tnodeId?: string;\n\t\t\tevent?: AuthAuditEvent | string;\n\t\t\tstartDate?: string;\n\t\t\tendDate?: string;\n\t\t},\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\tentries: IAuthenticationAuditEntry[];\n\t\tcursor?: string;\n\t}> {\n\t\tconst conditions: {\n\t\t\tproperty: string;\n\t\t\tvalue: string;\n\t\t\tcomparison: (typeof ComparisonOperator)[keyof typeof ComparisonOperator];\n\t\t}[] = [];\n\n\t\tif (Is.object(options)) {\n\t\t\tif (!Is.empty(options.actorId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.actorId),\n\t\t\t\t\toptions.actorId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"actorId\",\n\t\t\t\t\tvalue: options.actorId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.organizationId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.organizationId),\n\t\t\t\t\toptions.organizationId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"organizationId\",\n\t\t\t\t\tvalue: options.organizationId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.tenantId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.tenantId),\n\t\t\t\t\toptions.tenantId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"tenantId\",\n\t\t\t\t\tvalue: options.tenantId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.nodeId)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.nodeId),\n\t\t\t\t\toptions.nodeId\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"nodeId\",\n\t\t\t\t\tvalue: options.nodeId,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.event)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.event),\n\t\t\t\t\toptions.event\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"event\",\n\t\t\t\t\tvalue: options.event,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.startDate)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.startDate),\n\t\t\t\t\toptions.startDate\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"dateCreated\",\n\t\t\t\t\tvalue: options.startDate,\n\t\t\t\t\tcomparison: ComparisonOperator.GreaterThanOrEqual\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(options.endDate)) {\n\t\t\t\tGuards.stringValue(\n\t\t\t\t\tEntityStorageAuthenticationAuditService.CLASS_NAME,\n\t\t\t\t\tnameof(options.endDate),\n\t\t\t\t\toptions.endDate\n\t\t\t\t);\n\t\t\t\tconditions.push({\n\t\t\t\t\tproperty: \"dateCreated\",\n\t\t\t\t\tvalue: options.endDate,\n\t\t\t\t\tcomparison: ComparisonOperator.LessThanOrEqual\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst result = await this._authenticationAuditEntryEntityStorage.query(\n\t\t\tconditions.length > 0 ? { conditions } : undefined,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tcursor,\n\t\t\tlimit\n\t\t);\n\n\t\treturn {\n\t\t\tentries: result.entities as IAuthenticationAuditEntry[],\n\t\t\tcursor: result.cursor\n\t\t};\n\t}\n\n\t/**\n\t * Hash a list of IP addresses using SHA-256.\n\t * @param ipAddresses The IP addresses to hash.\n\t * @returns The hexadecimal hashes of the salted IPs.\n\t * @internal\n\t */\n\tprivate hashIpAddresses(ipAddresses: string[] | undefined): string[] | undefined {\n\t\tif (!Is.stringValue(this._ipHashSalt) || !Is.array(ipAddresses)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn ipAddresses.map(ip => {\n\t\t\tconst hash = Sha256.sum256(Converter.utf8ToBytes(`${this._ipHashSalt}:${ip}`));\n\t\t\treturn Converter.bytesToHex(hash);\n\t\t});\n\t}\n}\n"]}
|
|
@@ -50,10 +50,4 @@ export declare class EntityStorageAuthenticationAuditService implements IAuthent
|
|
|
50
50
|
entries: IAuthenticationAuditEntry[];
|
|
51
51
|
cursor?: string;
|
|
52
52
|
}>;
|
|
53
|
-
/**
|
|
54
|
-
* Hash a list of IP addresses using SHA-256.
|
|
55
|
-
* @param ipAddresses The IP addresses to hash.
|
|
56
|
-
* @returns The hexadecimal hashes of the salted IPs.
|
|
57
|
-
*/
|
|
58
|
-
private hashIpAddresses;
|
|
59
53
|
}
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.41](https://github.com/iotaledger/twin-api/compare/api-auth-entity-storage-service-v0.0.3-next.40...api-auth-entity-storage-service-v0.0.3-next.41) (2026-06-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Miscellaneous Chores
|
|
7
|
+
|
|
8
|
+
* **api-auth-entity-storage-service:** Synchronize repo versions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/api-auth-entity-storage-models bumped from 0.0.3-next.40 to 0.0.3-next.41
|
|
16
|
+
* @twin.org/api-core bumped from 0.0.3-next.40 to 0.0.3-next.41
|
|
17
|
+
* @twin.org/api-models bumped from 0.0.3-next.40 to 0.0.3-next.41
|
|
18
|
+
|
|
3
19
|
## [0.0.3-next.40](https://github.com/iotaledger/twin-api/compare/api-auth-entity-storage-service-v0.0.3-next.39...api-auth-entity-storage-service-v0.0.3-next.40) (2026-06-04)
|
|
4
20
|
|
|
5
21
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/api-auth-entity-storage-service",
|
|
3
|
-
"version": "0.0.3-next.
|
|
3
|
+
"version": "0.0.3-next.41",
|
|
4
4
|
"description": "Authentication service implementation and REST routes backed by entity storage.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twin.org/api-auth-entity-storage-models": "0.0.3-next.
|
|
18
|
-
"@twin.org/api-core": "0.0.3-next.
|
|
19
|
-
"@twin.org/api-models": "0.0.3-next.
|
|
17
|
+
"@twin.org/api-auth-entity-storage-models": "0.0.3-next.41",
|
|
18
|
+
"@twin.org/api-core": "0.0.3-next.41",
|
|
19
|
+
"@twin.org/api-models": "0.0.3-next.41",
|
|
20
20
|
"@twin.org/background-task-models": "next",
|
|
21
21
|
"@twin.org/context": "next",
|
|
22
22
|
"@twin.org/core": "next",
|