@resolveio/server-lib 22.2.21 → 22.2.22

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/util/customer-portal-password.ts"],"names":[],"mappings":"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","file":"customer-portal-password.js","sourcesContent":["import { CustomerPortalPasswords } from '../collections/customer-portal-password.collection';\nimport { UserModel } from '../models/user.model';\nimport { ResolveIOServer } from '../resolveio-server-app';\nconst crypto = require('crypto');\n\nconst ALGORITHM = 'aes-256-gcm';\nconst ENCRYPTION_KEY_VERSION = 1;\nconst IV_LENGTH_BYTES = 12;\n\ninterface PasswordCipherPayload {\n\tcipherText: string;\n\tiv: string;\n\tauthTag: string;\n\tkeyVersion: number;\n}\n\ninterface PasswordRecordMeta {\n\tupdatedByUserId?: string;\n\tupdatedByUser?: string;\n}\n\nexport function isCustomerPortalUser(user: UserModel | any): boolean {\n\tif (!user || typeof user !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst other = user.other || {};\n\tif (other.id_customer) {\n\t\treturn true;\n\t}\n\n\tif (Array.isArray(other.customers) && other.customers.length > 0) {\n\t\treturn true;\n\t}\n\n\tconst groups = Array.isArray(user?.roles?.groups) ? user.roles.groups : [];\n\tif (groups.some(group => {\n\t\tif (!group || typeof group.name !== 'string') {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst normalized = group.name.trim().toLowerCase();\n\t\treturn normalized === 'customer portal' || normalized === 'customer-portal';\n\t})) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nexport async function saveCustomerPortalPassword(user: UserModel | any, password: string, meta?: PasswordRecordMeta): Promise<void> {\n\tif (!user?._id) {\n\t\treturn;\n\t}\n\n\tif (!CustomerPortalPasswords) {\n\t\treturn;\n\t}\n\n\tif (!isCustomerPortalUser(user)) {\n\t\tawait clearCustomerPortalPassword(user._id);\n\t\treturn;\n\t}\n\n\tif (!password || typeof password !== 'string') {\n\t\tawait clearCustomerPortalPassword(user._id);\n\t\treturn;\n\t}\n\n\tconst payload = encryptPassword(password);\n\tconst setData: any = {\n\t\tid_user: user._id,\n\t\tcipher_text: payload.cipherText,\n\t\tiv: payload.iv,\n\t\tauth_tag: payload.authTag,\n\t\tkey_version: payload.keyVersion,\n\t\tlast_set_at: new Date()\n\t};\n\n\tif (meta?.updatedByUserId) {\n\t\tsetData.updated_by_user_id = meta.updatedByUserId;\n\t}\n\n\tif (meta?.updatedByUser) {\n\t\tsetData.updated_by_user = meta.updatedByUser;\n\t}\n\n\tawait CustomerPortalPasswords.updateOne(\n\t\t{id_user: user._id},\n\t\t{\n\t\t\t$set: setData\n\t\t},\n\t\t{upsert: true}\n\t);\n}\n\nexport async function clearCustomerPortalPassword(userId: string): Promise<void> {\n\tif (!userId || !CustomerPortalPasswords) {\n\t\treturn;\n\t}\n\n\tawait CustomerPortalPasswords.deleteOne({id_user: userId});\n}\n\nexport async function getDecryptedCustomerPortalPassword(userId: string): Promise<{password: string; lastSetAt?: Date}> {\n\tif (!userId) {\n\t\tthrow new Error('Customer portal user id is required.');\n\t}\n\n\tif (!CustomerPortalPasswords) {\n\t\tthrow new Error('Customer portal password store is not available.');\n\t}\n\n\tconst record = await CustomerPortalPasswords.findOne({id_user: userId});\n\tif (!record) {\n\t\tthrow new Error('No stored customer portal password is available for this user.');\n\t}\n\n\tconst password = decryptPassword({\n\t\tcipherText: record.cipher_text,\n\t\tiv: record.iv,\n\t\tauthTag: record.auth_tag,\n\t\tkeyVersion: record.key_version\n\t});\n\n\treturn {\n\t\tpassword,\n\t\tlastSetAt: record.last_set_at\n\t};\n}\n\nfunction encryptPassword(plainText: string): PasswordCipherPayload {\n\tconst key = resolveEncryptionKey();\n\tconst ivBuffer = crypto.randomBytes(IV_LENGTH_BYTES);\n\tconst cipher = crypto.createCipheriv(ALGORITHM, key, ivBuffer);\n\tconst encrypted = Buffer.concat([cipher.update(plainText, 'utf8'), cipher.final()]);\n\tconst authTag = cipher.getAuthTag();\n\n\treturn {\n\t\tcipherText: encrypted.toString('base64'),\n\t\tiv: ivBuffer.toString('base64'),\n\t\tauthTag: authTag.toString('base64'),\n\t\tkeyVersion: ENCRYPTION_KEY_VERSION\n\t};\n}\n\nfunction decryptPassword(payload: PasswordCipherPayload): string {\n\tif (!payload || payload.keyVersion !== ENCRYPTION_KEY_VERSION) {\n\t\tthrow new Error('Unsupported customer portal password encryption version.');\n\t}\n\n\tconst key = resolveEncryptionKey();\n\tconst decipher = crypto.createDecipheriv(\n\t\tALGORITHM,\n\t\tkey,\n\t\tBuffer.from(payload.iv, 'base64')\n\t);\n\tdecipher.setAuthTag(Buffer.from(payload.authTag, 'base64'));\n\n\tconst decrypted = Buffer.concat([\n\t\tdecipher.update(Buffer.from(payload.cipherText, 'base64')),\n\t\tdecipher.final()\n\t]);\n\n\treturn decrypted.toString('utf8');\n}\n\nfunction resolveEncryptionKey(): Buffer {\n\tconst config = ResolveIOServer.getServerConfig ? ResolveIOServer.getServerConfig() : {};\n\tconst secret = String(\n\t\t(config && config['CUSTOMER_PORTAL_PASSWORD_SECRET'])\n\t\t|| process.env.CUSTOMER_PORTAL_PASSWORD_SECRET\n\t\t|| (config && config['JWT_SECRET'])\n\t\t|| process.env.JWT_SECRET\n\t\t|| ''\n\t).trim();\n\n\tif (!secret) {\n\t\tthrow new Error('Missing CUSTOMER_PORTAL_PASSWORD_SECRET (or JWT_SECRET) for customer portal password encryption.');\n\t}\n\n\treturn crypto.createHash('sha256').update(secret, 'utf8').digest();\n}\n"]}