{"version":3,"file":"verify-api-key.mjs","names":["formatter","constants"],"sources":["../../../src/services/client-integrations/verify-api-key.ts"],"sourcesContent":["import { timingSafeEqual } from \"node:crypto\";\nimport { scrypt } from \"@noble/hashes/scrypt.js\";\nimport constants from \"../../constants/constants.js\";\nimport formatter from \"../../libs/formatters/index.js\";\nimport { copy } from \"../../libs/i18n/index.js\";\nimport { ClientIntegrationsRepository } from \"../../libs/repositories/index.js\";\nimport type { LucidClientIntegrationAuth } from \"../../types/hono.js\";\nimport { decodeApiKey } from \"../../utils/client-integrations/encode-api-key.js\";\nimport { decrypt } from \"../../utils/helpers/encrypt-decrypt.js\";\nimport type { ServiceFn } from \"../../utils/services/types.js\";\n\nconst verifyApiKey: ServiceFn<\n\t[\n\t\t{\n\t\t\tapiKey: string;\n\t\t},\n\t],\n\tLucidClientIntegrationAuth\n> = async (context, data) => {\n\tconst ClientIntegrations = new ClientIntegrationsRepository(\n\t\tcontext.db.client,\n\t\tcontext.config.db,\n\t);\n\n\tconst { key: decodedKey, apiKey: decodedApiKey } = decodeApiKey(data.apiKey);\n\tif (!decodedApiKey) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\tmessage: copy(\"server:core.client.integrations.api.key.missing\"),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\tif (!decodedKey) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\tmessage: copy(\"server:core.client.integrations.key.missing\"),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tconst clientIntegrationRes =\n\t\tawait ClientIntegrations.selectSingleByKeyWithScopes({\n\t\t\tkey: decodedKey,\n\t\t\tvalidation: {\n\t\t\t\tenabled: true,\n\t\t\t\tdefaultError: {\n\t\t\t\t\tmessage: copy(\"server:core.client.integrations.not.found\"),\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\tif (clientIntegrationRes.error) return clientIntegrationRes;\n\n\tif (!formatter.formatBoolean(clientIntegrationRes.data.enabled)) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\tmessage: copy(\"server:core.client.integrations.disabled\"),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tconst secret = decrypt(\n\t\tclientIntegrationRes.data.secret,\n\t\tcontext.config.secrets.encryption,\n\t);\n\n\tconst inputApiKeyHash = Buffer.from(\n\t\tscrypt(decodedApiKey, secret, constants.scrypt),\n\t).toString(\"base64\");\n\n\tconst inputHashBuffer = Buffer.from(inputApiKeyHash, \"utf8\");\n\tconst storedHashBuffer = Buffer.from(\n\t\tclientIntegrationRes.data.api_key,\n\t\t\"utf8\",\n\t);\n\tconst verifyApiKey =\n\t\tinputHashBuffer.length === storedHashBuffer.length &&\n\t\ttimingSafeEqual(inputHashBuffer, storedHashBuffer);\n\n\tif (verifyApiKey === false) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\tmessage: copy(\"server:core.client.integrations.api.key.invalid\"),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: {\n\t\t\tid: clientIntegrationRes.data.id,\n\t\t\tkey: clientIntegrationRes.data.key,\n\t\t\tscopes: (clientIntegrationRes.data.scopes || []).map((s) => s.scope),\n\t\t\ttenantKey: clientIntegrationRes.data.tenant_key ?? null,\n\t\t},\n\t};\n};\n\nexport default verifyApiKey;\n"],"mappings":"8bAWA,MAAM,EAOF,MAAO,EAAS,IAAS,CAC5B,IAAM,EAAqB,IAAI,EAC9B,EAAQ,GAAG,OACX,EAAQ,OAAO,EAChB,EAEM,CAAE,IAAK,EAAY,OAAQ,GAAkB,EAAa,EAAK,MAAM,EAC3E,GAAI,CAAC,EACJ,MAAO,CACN,MAAO,CACN,QAAS,EAAK,iDAAiD,CAChE,EACA,KAAM,IAAA,EACP,EAED,GAAI,CAAC,EACJ,MAAO,CACN,MAAO,CACN,QAAS,EAAK,6CAA6C,CAC5D,EACA,KAAM,IAAA,EACP,EAGD,IAAM,EACL,MAAM,EAAmB,4BAA4B,CACpD,IAAK,EACL,WAAY,CACX,QAAS,GACT,aAAc,CACb,QAAS,EAAK,2CAA2C,CAC1D,CACD,CACD,CAAC,EACF,GAAI,EAAqB,MAAO,OAAO,EAEvC,GAAI,CAACA,EAAU,cAAc,EAAqB,KAAK,OAAO,EAC7D,MAAO,CACN,MAAO,CACN,QAAS,EAAK,0CAA0C,CACzD,EACA,KAAM,IAAA,EACP,EAGD,IAAM,EAAS,EACd,EAAqB,KAAK,OAC1B,EAAQ,OAAO,QAAQ,UACxB,EAEM,EAAkB,OAAO,KAC9B,EAAO,EAAe,EAAQC,EAAU,MAAM,CAC/C,CAAC,CAAC,SAAS,QAAQ,EAEb,EAAkB,OAAO,KAAK,EAAiB,MAAM,EACrD,EAAmB,OAAO,KAC/B,EAAqB,KAAK,QAC1B,MACD,EAcA,OAZC,EAAgB,SAAW,EAAiB,QAC5C,EAAgB,EAAiB,CAAgB,KAE7B,GACb,CACN,MAAO,CACN,QAAS,EAAK,iDAAiD,CAChE,EACA,KAAM,IAAA,EACP,EAGM,CACN,MAAO,IAAA,GACP,KAAM,CACL,GAAI,EAAqB,KAAK,GAC9B,IAAK,EAAqB,KAAK,IAC/B,QAAS,EAAqB,KAAK,QAAU,CAAC,EAAA,CAAG,IAAK,GAAM,EAAE,KAAK,EACnE,UAAW,EAAqB,KAAK,YAAc,IACpD,CACD,CACD"}