{"version":3,"file":"generateCrossAccountApiKeys-D2v1Q25y.mjs","names":[],"sources":["../src/lib/api-keys/generateCrossAccountApiKeys.ts"],"sourcesContent":["import { ScopeName } from '@transcend-io/privacy-types';\nimport {\n  buildTranscendGraphQLClientGeneric,\n  loginUser,\n  createApiKey,\n  fetchAllApiKeys,\n  deleteApiKey,\n  assumeRole,\n} from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { StoredApiKey } from '../../codecs.js';\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\n\nexport interface ApiKeyGenerateError {\n  /** Name of instance */\n  organizationName: string;\n  /** Error */\n  error: string;\n  /** Organization ID API key is for */\n  organizationId: string;\n}\n\n/**\n * Generate API keys across multiple transcend accounts\n *\n * @param options - Options\n * @returns Number of API keys created\n */\nexport async function generateCrossAccountApiKeys({\n  email,\n  password,\n  scopes,\n  apiKeyTitle,\n  parentOrganizationId,\n  deleteExistingApiKey = true,\n  createNewApiKey = true,\n  transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n  /** Email address of user generating API keys */\n  email: string;\n  /** Password of user generating API keys */\n  password: string;\n  /** Filter for organizations that match this parent organization ID */\n  parentOrganizationId?: string;\n  /** Title of the API create to create */\n  apiKeyTitle: string;\n  /** Title of the API create to create */\n  scopes: ScopeName[];\n  /** API URL for Transcend backend */\n  transcendUrl?: string;\n  /** When true delete existing API keys with that title, if set to false an API key exists with that title, an error is thrown */\n  deleteExistingApiKey?: boolean;\n  /** When true, generate new API keys, otherwise only will delete past API keys */\n  createNewApiKey?: boolean;\n}): Promise<{\n  /** Successfully generated */\n  apiKeys: StoredApiKey[];\n  /** Error results */\n  errors: ApiKeyGenerateError[];\n}> {\n  // Create GraphQL client\n  const client = await buildTranscendGraphQLClientGeneric(transcendUrl, {});\n\n  // Login the user\n  logger.info(colors.magenta('Logging in using email and password.'));\n  const { roles, loginCookie } = await loginUser(client, { email, password, logger });\n  logger.info(\n    colors.green(\n      `Successfully logged in and found ${roles.length} role${roles.length === 1 ? '' : 's'}!`,\n    ),\n  );\n\n  // Filter down by parentOrganizationId\n  const filteredRoles = parentOrganizationId\n    ? roles.filter(\n        (role) =>\n          role.organization.id === parentOrganizationId ||\n          role.organization.parentOrganizationId === parentOrganizationId,\n      )\n    : roles;\n\n  // Save cookie to call route subsequent times\n  client.setHeaders({\n    Cookie: loginCookie,\n  });\n\n  // Save the resulting API keys\n  const results: StoredApiKey[] = [];\n  const errors: ApiKeyGenerateError[] = [];\n\n  // Generate API keys\n  logger.info(\n    colors.magenta(`Generating API keys with title: ${apiKeyTitle}, scopes: ${scopes.join(',')}.`),\n  );\n\n  // Map over each role\n  await mapSeries(filteredRoles, async (role) => {\n    try {\n      // Log into the other instance\n      await assumeRole(client, { roleId: role.id, email, logger });\n\n      // Grab API keys with that title\n      logger.info(\n        colors.magenta(\n          `Checking if API key already exists in organization \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n        ),\n      );\n\n      // Delete existing API key\n      const [apiKeyWithTitle] = await fetchAllApiKeys(client, {\n        logger,\n        filterBy: { titles: [apiKeyTitle] },\n      });\n      if (apiKeyWithTitle && deleteExistingApiKey) {\n        logger.info(\n          colors.yellow(\n            `Deleting existing API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n          ),\n        );\n        await deleteApiKey(client, { id: apiKeyWithTitle.id, logger });\n        logger.info(\n          colors.green(\n            `Successfully deleted API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n          ),\n        );\n      } else if (apiKeyWithTitle) {\n        // throw error if one exists but not configured to delete\n        throw new Error(`API key already exists with title: \"${apiKeyTitle}\"`);\n      }\n\n      // Create the API key\n      if (createNewApiKey) {\n        logger.info(\n          colors.magenta(\n            `Creating API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n          ),\n        );\n        const { apiKey } = await createApiKey(client, {\n          input: { title: apiKeyTitle, scopes },\n          logger,\n        });\n        results.push({\n          organizationName: role.organization.name,\n          organizationId: role.organization.id,\n          apiKey,\n        });\n        logger.info(\n          colors.green(\n            `Successfully created API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n          ),\n        );\n      } else {\n        // Delete only\n        results.push({\n          organizationName: role.organization.name,\n          organizationId: role.organization.id,\n          apiKey: '',\n        });\n      }\n    } catch (err) {\n      logger.error(\n        colors.red(\n          `Failed to create API key in organization \"${role.organization.name}\"! - ${err.message}`,\n        ),\n      );\n      errors.push({\n        organizationName: role.organization.name,\n        organizationId: role.organization.id,\n        error: err.message,\n      });\n    }\n  });\n  logger.info(\n    colors.green(\n      `Successfully created ${results.length} API key${results.length === 1 ? '' : 's'}`,\n    ),\n  );\n\n  if (errors.length > 0) {\n    logger.error(\n      colors.red(`Failed to create ${errors.length} API key${errors.length === 1 ? '' : 's'}!`),\n    );\n  }\n\n  return { errors, apiKeys: results };\n}\n"],"mappings":"uTA+BA,eAAsB,EAA4B,CAChD,QACA,WACA,SACA,cACA,uBACA,uBAAuB,GACvB,kBAAkB,GAClB,eAAe,GAuBd,CAED,IAAM,EAAS,MAAM,EAAmC,EAAc,EAAE,CAAC,CAGzE,EAAO,KAAK,EAAO,QAAQ,uCAAuC,CAAC,CACnE,GAAM,CAAE,QAAO,eAAgB,MAAM,EAAU,EAAQ,CAAE,QAAO,WAAU,SAAQ,CAAC,CACnF,EAAO,KACL,EAAO,MACL,oCAAoC,EAAM,OAAO,OAAO,EAAM,SAAW,EAAI,GAAK,IAAI,GACvF,CACF,CAGD,IAAM,EAAgB,EAClB,EAAM,OACH,GACC,EAAK,aAAa,KAAO,GACzB,EAAK,aAAa,uBAAyB,EAC9C,CACD,EAGJ,EAAO,WAAW,CAChB,OAAQ,EACT,CAAC,CAGF,IAAM,EAA0B,EAAE,CAC5B,EAAgC,EAAE,CAgGxC,OA7FA,EAAO,KACL,EAAO,QAAQ,mCAAmC,EAAY,YAAY,EAAO,KAAK,IAAI,CAAC,GAAG,CAC/F,CAGD,MAAM,EAAU,EAAe,KAAO,IAAS,CAC7C,GAAI,CAEF,MAAM,EAAW,EAAQ,CAAE,OAAQ,EAAK,GAAI,QAAO,SAAQ,CAAC,CAG5D,EAAO,KACL,EAAO,QACL,uDAAuD,EAAK,aAAa,KAAK,iBAAiB,EAAY,IAC5G,CACF,CAGD,GAAM,CAAC,GAAmB,MAAM,EAAgB,EAAQ,CACtD,SACA,SAAU,CAAE,OAAQ,CAAC,EAAY,CAAE,CACpC,CAAC,CACF,GAAI,GAAmB,EACrB,EAAO,KACL,EAAO,OACL,iCAAiC,EAAK,aAAa,KAAK,iBAAiB,EAAY,IACtF,CACF,CACD,MAAM,EAAa,EAAQ,CAAE,GAAI,EAAgB,GAAI,SAAQ,CAAC,CAC9D,EAAO,KACL,EAAO,MACL,oCAAoC,EAAK,aAAa,KAAK,iBAAiB,EAAY,IACzF,CACF,SACQ,EAET,MAAU,MAAM,uCAAuC,EAAY,GAAG,CAIxE,GAAI,EAAiB,CACnB,EAAO,KACL,EAAO,QACL,wBAAwB,EAAK,aAAa,KAAK,iBAAiB,EAAY,IAC7E,CACF,CACD,GAAM,CAAE,UAAW,MAAM,EAAa,EAAQ,CAC5C,MAAO,CAAE,MAAO,EAAa,SAAQ,CACrC,SACD,CAAC,CACF,EAAQ,KAAK,CACX,iBAAkB,EAAK,aAAa,KACpC,eAAgB,EAAK,aAAa,GAClC,SACD,CAAC,CACF,EAAO,KACL,EAAO,MACL,oCAAoC,EAAK,aAAa,KAAK,iBAAiB,EAAY,IACzF,CACF,MAGD,EAAQ,KAAK,CACX,iBAAkB,EAAK,aAAa,KACpC,eAAgB,EAAK,aAAa,GAClC,OAAQ,GACT,CAAC,OAEG,EAAK,CACZ,EAAO,MACL,EAAO,IACL,6CAA6C,EAAK,aAAa,KAAK,OAAO,EAAI,UAChF,CACF,CACD,EAAO,KAAK,CACV,iBAAkB,EAAK,aAAa,KACpC,eAAgB,EAAK,aAAa,GAClC,MAAO,EAAI,QACZ,CAAC,GAEJ,CACF,EAAO,KACL,EAAO,MACL,wBAAwB,EAAQ,OAAO,UAAU,EAAQ,SAAW,EAAI,GAAK,MAC9E,CACF,CAEG,EAAO,OAAS,GAClB,EAAO,MACL,EAAO,IAAI,oBAAoB,EAAO,OAAO,UAAU,EAAO,SAAW,EAAI,GAAK,IAAI,GAAG,CAC1F,CAGI,CAAE,SAAQ,QAAS,EAAS"}