@contiva/sap-integration-suite-client
Version:
SAP Cloud Platform Integration API Client
1,009 lines (1,008 loc) • 53.9 kB
JavaScript
"use strict";
/**
* SAP Security Content Client
*
* This file contains a client class for interacting with the
* Security Content API of SAP Cloud Integration. This API allows management of
* security artifacts like User Credentials, OAuth2 Credentials, Keystores
* (Certificates, Key Pairs), Secure Parameters, Certificate-to-User Mappings,
* and Access Policies.
*
* @module sap-integration-suite-client/security-content
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SecurityContentClient = void 0;
const response_normalizer_1 = require("../utils/response-normalizer");
const cache_key_generator_1 = require("../utils/cache-key-generator");
const cache_config_1 = require("../core/cache-config");
/**
* SAP Security Content Client
*
* Provides simplified access to the Security Content API.
*/
class SecurityContentClient {
/**
* Creates a new SecurityContentClient
*
* @param {SecurityContentApi<unknown>} api - The underlying API instance
* @param {CacheManager} [cacheManager] - Optional: CacheManager for cache operations
* @param {string} [hostname] - Optional: Hostname for cache key generation
*/
constructor(api, cacheManager, hostname) {
this.cacheManager = null;
this.hostname = '';
this.api = api;
this.normalizer = new response_normalizer_1.ResponseNormalizer();
this.cacheManager = cacheManager || null;
this.hostname = hostname || '';
}
// --- User Credential Methods ---
/**
* Retrieves all deployed user credentials.
*
* @returns {Promise<ComSapHciApiUserCredential[]>} Promise resolving to a list of user credentials.
*
* @example
* const credentials = await client.getUserCredentials();
*/
async getUserCredentials() {
const response = await this.api.userCredentials.userCredentialsList();
return this.normalizer.normalizeArrayResponse(response.data, 'getUserCredentials');
}
/**
* Adds new user credentials.
*
* @param {ComSapHciApiUserCredentialCreate} credentialData Data for the new user credential.
* @returns {Promise<void>} Promise resolving when the credential is created.
*
* @example
* await client.createUserCredential({
* Name: 'MySFTPCreds',
* Kind: 'default', // or 'successfactors', 'openconnectors'
* User: 'sftpUser',
* Password: 'sftpPassword'
* });
*/
async createUserCredential(credentialData) {
await this.api.userCredentials.userCredentialsCreate(credentialData);
}
/**
* Retrieves a specific user credential by its name.
*
* @param {string} name The name of the user credential.
* @returns {Promise<ComSapHciApiUserCredential | undefined>} Promise resolving to the credential or undefined.
*
* @example
* const cred = await client.getUserCredentialByName('MySFTPCreds');
*/
async getUserCredentialByName(name) {
const response = await this.api.userCredentialsName.userCredentialsList(name);
return this.normalizer.normalizeEntityResponse(response.data, 'getUserCredentialByName');
}
/**
* Updates an existing user credential.
*
* @param {string} name The name of the credential to update.
* @param {ComSapHciApiUserCredentialUpdate} credentialData Updated data for the credential.
* @returns {Promise<void>} Promise resolving when the credential is updated.
*
* @example
* await client.updateUserCredential('MySFTPCreds', { Password: 'newPassword' });
*/
async updateUserCredential(name, credentialData) {
await this.api.userCredentialsName.userCredentialsUpdate(name, credentialData);
}
/**
* Deletes a user credential.
*
* @param {string} name The name of the credential to delete.
* @returns {Promise<void>} Promise resolving when the credential is deleted.
*
* @example
* await client.deleteUserCredential('OldCreds');
*/
async deleteUserCredential(name) {
await this.api.userCredentialsName.userCredentialsDelete(name);
}
// --- Secure Parameter Methods (Neo only) ---
/**
* Retrieves all deployed secure parameters (values are not returned).
* Note: This resource is only available in the Neo environment.
*
* @returns {Promise<ComSapHciApiSecureParameter[]>} Promise resolving to a list of secure parameters.
*
* @example
* const params = await client.getSecureParameters();
*/
async getSecureParameters() {
try {
const response = await this.api.secureParameters.secureParametersList();
return this.normalizer.normalizeArrayResponse(response.data, 'getSecureParameters');
}
catch (error) {
// Handle potential 404 if API doesn't exist in CF
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 404) {
console.warn('SecureParameters API might not be available in this environment (Cloud Foundry?). Returning empty array.');
return [];
}
throw error; // Re-throw other errors
}
}
/**
* Adds a new secure parameter.
* Note: This resource is only available in the Neo environment.
*
* @param {ComSapHciApiSecureParameterCreate} parameterData Data for the new secure parameter.
* @returns {Promise<void>} Promise resolving when the parameter is created.
*
* @example
* await client.createSecureParameter({ Name: 'MyApiKey', SecureParam: 'secretValue' });
*/
async createSecureParameter(parameterData) {
await this.api.secureParameters.secureParametersCreate(parameterData);
}
/**
* Retrieves a specific secure parameter by its name (value is not returned).
* Note: This resource is only available in the Neo environment.
*
* @param {string} name The name of the secure parameter.
* @returns {Promise<ComSapHciApiSecureParameter | undefined>} Promise resolving to the parameter or undefined.
*
* @example
* const param = await client.getSecureParameterByName('MyApiKey');
*/
async getSecureParameterByName(name) {
try {
const response = await this.api.secureParametersName.secureParametersList(name);
return this.normalizer.normalizeEntityResponse(response.data, 'getSecureParameterByName');
}
catch (error) {
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 404) {
return undefined; // Not found is a valid case
}
throw error;
}
}
/**
* Updates an existing secure parameter.
* Note: This resource is only available in the Neo environment.
*
* @param {string} name The name of the parameter to update.
* @param {ComSapHciApiSecureParameterUpdate} parameterData Updated data (can include Name, Description, SecureParam).
* @returns {Promise<void>} Promise resolving when the parameter is updated.
*
* @example
* await client.updateSecureParameter('MyApiKey', { SecureParam: 'newSecretValue' });
*/
async updateSecureParameter(name, parameterData) {
await this.api.secureParametersName.secureParametersUpdate(name, parameterData);
}
/**
* Deletes a secure parameter.
* Note: This resource is only available in the Neo environment.
*
* @param {string} name The name of the parameter to delete.
* @returns {Promise<void>} Promise resolving when the parameter is deleted.
*
* @example
* await client.deleteSecureParameter('OldApiKey');
*/
async deleteSecureParameter(name) {
await this.api.secureParametersName.secureParametersDelete(name);
}
// --- OAuth2 Client Credential Methods ---
/**
* Retrieves all OAuth2 client credentials.
*
* @param {boolean} [expandCustomParameters=false] If true, expands custom parameters associated with the credentials.
* @returns {Promise<ComSapHciApiOAuth2ClientCredential[]>} Promise resolving to a list of OAuth2 credentials.
*
* @example
* const oauthCreds = await client.getOAuth2ClientCredentials();
* const oauthCredsWithParams = await client.getOAuth2ClientCredentials(true);
*/
async getOAuth2ClientCredentials(expandCustomParameters = false) {
const response = await this.api.oAuth2ClientCredentials.oAuth2ClientCredentialsList({
$expand: expandCustomParameters ? ['CustomParameters'] : undefined,
});
return this.normalizer.normalizeArrayResponse(response.data, 'getOAuth2ClientCredentials');
}
/**
* Adds new OAuth2 client credentials.
*
* @param {ComSapHciApiOAuth2ClientCredentialCreate} credentialData Data for the new OAuth2 credential.
* @returns {Promise<void>} Promise resolving when the credential is created.
*
* @example
* await client.createOAuth2ClientCredential({
* Name: 'MyOAuthApp',
* TokenServiceUrl: 'https://example.com/oauth/token',
* ClientId: 'client-id',
* ClientSecret: 'client-secret'
* });
*/
async createOAuth2ClientCredential(credentialData) {
await this.api.oAuth2ClientCredentials.oAuth2ClientCredentialsCreate(credentialData);
}
/**
* Retrieves a specific OAuth2 client credential by its name.
*
* @param {string} name The name of the OAuth2 credential.
* @param {boolean} [expandCustomParameters=false] If true, expands custom parameters.
* @returns {Promise<ComSapHciApiOAuth2ClientCredential | undefined>} Promise resolving to the credential or undefined.
*
* @example
* const cred = await client.getOAuth2ClientCredentialByName('MyOAuthApp');
*/
async getOAuth2ClientCredentialByName(name, expandCustomParameters = false) {
const response = await this.api.oAuth2ClientCredentialsName.oAuth2ClientCredentialsList(name, {
$expand: expandCustomParameters ? ['CustomParameters'] : undefined,
});
return this.normalizer.normalizeEntityResponse(response.data, 'getOAuth2ClientCredentialByName');
}
/**
* Updates an existing OAuth2 client credential.
*
* @param {string} name The name of the credential to update.
* @param {ComSapHciApiOAuth2ClientCredentialUpdate} credentialData Updated data.
* @returns {Promise<void>} Promise resolving when the credential is updated.
*
* @example
* await client.updateOAuth2ClientCredential('MyOAuthApp', { ClientSecret: 'new-secret' });
*/
async updateOAuth2ClientCredential(name, credentialData) {
await this.api.oAuth2ClientCredentialsName.oAuth2ClientCredentialsUpdate(name, credentialData);
}
/**
* Deletes an OAuth2 client credential.
*
* @param {string} name The name of the credential to delete.
* @returns {Promise<void>} Promise resolving when the credential is deleted.
*
* @example
* await client.deleteOAuth2ClientCredential('OldOAuthApp');
*/
async deleteOAuth2ClientCredential(name) {
await this.api.oAuth2ClientCredentialsName.oAuth2ClientCredentialsDelete(name);
}
// --- Keystore Management Methods ---
/**
* Retrieves properties (like size) and optionally entries for a specified keystore.
*
* @param {('system' | 'backup_admin_system')} keystoreName Name of the keystore.
* @param {boolean} [expandEntries=false] If true, includes the list of entries in the response.
* @param {('Entries' | 'LastModifiedBy' | 'LastModifiedTime' | 'Size')[]} [select] Properties to select.
* @returns {Promise<any>} Promise resolving to the keystore properties (structure varies based on select/expand).
*
* @example
* const systemKeystoreInfo = await client.getKeystoreProperties('system');
* console.log('System Keystore Size:', systemKeystoreInfo?.Size);
*
* @example
* // Get keystore with entries expanded
* const systemKeystoreWithEntries = await client.getKeystoreProperties('system', true);
*/
async getKeystoreProperties(keystoreName, expandEntries = false, select) {
var _a;
const response = await this.api.keystoresKeystoreName.keystoresList([keystoreName], {
$expand: expandEntries ? ['Entries'] : undefined,
$select: select
});
// Response structure can vary based on expand/select, return the 'd' object.
return (_a = response.data) === null || _a === void 0 ? void 0 : _a.d;
}
/**
* Retrieves the number of entries in a specified keystore.
*
* @param {('system' | 'KeyRenewal')} keystoreName Name of the keystore.
* @returns {Promise<number>} Promise resolving to the number of entries.
*
* @example
* const systemSize = await client.getKeystoreSize('system');
*/
async getKeystoreSize(keystoreName) {
const response = await this.api.keystoresKeystoreName.sizeValueList([keystoreName]);
// API returns count as plain string
const countString = response.data;
return parseInt(countString || '0', 10);
}
/**
* Imports entries from a JKS or JCEKS keystore file into the system keystore.
*
* @param {File} keystoreFile Keystore file (JKS/JCEKS format).
* @param {string} password Password for the keystore file.
* @param {('replace' | 'merge' | 'overwrite')} [importOption='overwrite'] How to handle existing entries.
* @param {boolean} [returnKeystoreEntries=true] If true, returns the import status for each entry.
* @returns {Promise<ComSapHciApiKeystoreEntryImported[] | undefined>} Promise resolving to the list of imported entries with status, if requested.
*
* @example
* // Assuming 'file' is a File object from an input element
* // const file = document.getElementById('keystoreInput').files[0];
* // await client.importKeystore(file, 'keystorePassword', 'merge');
*/
async importKeystore(keystoreFile, password, importOption = 'overwrite', returnKeystoreEntries = true) {
var _a, _b;
const keystoreData = {
Name: 'system', // Target keystore is always 'system' for import
Resource: keystoreFile,
Password: password
};
const response = await this.api.keystoreResources.keystoreResourcesCreate(keystoreData, {
importOption: [importOption],
returnKeystoreEntries: [returnKeystoreEntries]
});
return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d) === null || _b === void 0 ? void 0 : _b.results;
}
/**
* Backs up tenant administrator-owned entries from the system keystore to the backup keystore.
* This overwrites the previous backup.
*
* @returns {Promise<void>} Promise resolving when the backup is complete.
*
* @example
* await client.backupKeystore();
*/
async backupKeystore() {
// API uses POST with Name='backup_admin_system', no body/options needed for backup itself.
const backupData = { Name: 'backup_admin_system' };
await this.api.keystoreResources.keystoreResourcesCreate(backupData, {
// Ensure no import options are sent for backup
returnKeystoreEntries: [false] // Don't need entries returned for backup
});
}
/**
* Exports the public content of a keystore (system or backup).
*
* Note: API returns `void`, the content is in the response body (JKS format).
*
* @param {('system' | 'backup_admin_system')} keystoreName Name of the keystore to export.
* @returns {Promise<any>} Promise resolving to the exported keystore content (JKS).
*
* @example
* const exportedKeystore = await client.exportKeystore('system');
* // Process exportedKeystore (e.g., save as file)
*/
async exportKeystore(_keystoreName) {
// This endpoint is GET /KeystoreResources('{KeystoreName}')/$value
// Need to manually construct the path as the generated client doesn't expose $value directly here.
// This is a limitation of the current generator setup.
// A workaround would involve using the base HTTP client directly.
// For now, this method cannot be implemented correctly with the generated client.
console.error('exportKeystore cannot be reliably implemented with the current generated client due to missing $value endpoint access for KeystoreResources.');
throw new Error('Export Keystore functionality not available via generated client.');
// Potential workaround (untested, requires direct HTTP access):
// const response = await (this.api as any).httpClient.request({
// path: `/KeystoreResources('${keystoreName}')/$value`,
// method: 'GET',
// secure: true,
// format: 'blob' // Or appropriate format for binary data
// });
// return response.data;
}
/**
* Restores tenant administrator-owned entries from the backup keystore to the system keystore.
*
* @param {('replace' | 'overwrite')} [importOption='overwrite'] How to handle existing entries in the system keystore.
* @param {boolean} [returnKeystoreEntries=true] If true, returns the restore status for each entry.
* @returns {Promise<ComSapHciApiKeystoreEntryImported[] | undefined>} Promise resolving to the list of restored entries with status, if requested.
*
* @example
* await client.restoreKeystoreBackup('overwrite');
*/
async restoreKeystoreBackup(importOption = 'overwrite', returnKeystoreEntries = true) {
var _a, _b;
// API uses PUT on /KeystoreResources('system') with query param retrieveBackup=backup_admin_system
const dummyBody = {}; // Body seems required but not used for restore
const response = await this.api.keystoreResourcesSystem.keystoreResourcesSystemUpdate(dummyBody, // Cast needed as type expects KeystoreEntryAliasMassdelete
{
retrieveBackup: ['backup_admin_system'], // Pass as array to match type "backup_admin_system"[]
importOption: [importOption],
returnKeystoreEntries: [returnKeystoreEntries]
});
return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d) === null || _b === void 0 ? void 0 : _b.results;
}
/**
* Deletes multiple specified entries (owned by tenant administrator) from the system keystore.
*
* @param {string[]} aliasesToDelete List of aliases to delete.
* @param {boolean} [returnKeystoreEntries=false] If true, returns the deletion status for each entry.
* @returns {Promise<ComSapHciApiKeystoreEntryImported[] | undefined>} Promise resolving to the list of entries with status, if requested.
*
* @example
* await client.deleteKeystoreEntries(['alias1', 'alias2']);
*/
async deleteKeystoreEntries(aliasesToDelete, returnKeystoreEntries = false) {
var _a, _b;
// API uses PUT on /KeystoreResources('system') with query param deleteEntries=true and body containing aliases
const deleteBody = { Aliases: aliasesToDelete.join(';') };
const response = await this.api.keystoreResourcesSystem.keystoreResourcesSystemUpdate(deleteBody, {
deleteEntries: ['true'],
returnKeystoreEntries: [returnKeystoreEntries]
});
return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d) === null || _b === void 0 ? void 0 : _b.results;
}
// --- Keystore History Methods ---
/**
* Retrieves entries from the history keystore.
*
* @param {('Alias' | 'Hexalias' | 'KeyType' | 'LastModifiedBy' | 'LastModifiedTime' | 'Owner' | 'Validity')[]} [select] Properties to select.
* @returns {Promise<ComSapHciApiHistoryKeystoreEntry[]>} Promise resolving to a list of history entries.
*
* @example
* const history = await client.getKeystoreHistoryEntries();
*/
async getKeystoreHistoryEntries(select) {
const response = await this.api.historyKeystoreEntries.historyKeystoreEntriesList({ $select: select });
return this.normalizer.normalizeArrayResponse(response.data, 'getKeystoreHistoryEntries');
}
/**
* Retrieves a specific entry from the history keystore by its hex-encoded alias.
*
* @param {string} hexAlias Hex-encoded alias of the history entry.
* @param {('Alias' | 'KeyType' | 'LastModifiedBy' | 'LastModifiedTime' | 'Owner' | 'Validity')[]} [select] Properties to select.
* @returns {Promise<ComSapHciApiHistoryKeystoreEntry | undefined>} Promise resolving to the history entry or undefined.
*
* @example
* const historyEntry = await client.getKeystoreHistoryEntry('historyHexAlias');
*/
async getKeystoreHistoryEntry(hexAlias, select) {
const response = await this.api.historyKeystoreEntriesHexalias.historyKeystoreEntriesList(hexAlias, { $select: select });
return this.normalizer.normalizeEntityResponse(response.data, 'getKeystoreHistoryEntry');
}
/**
* Restores an entry from the history keystore to the renewal keystore.
*
* @param {string} hexAlias Hex-encoded alias of the history entry to restore.
* @param {string} [destinationAlias] Optional new alias for the entry in the renewal keystore. If empty, defaults to '[number]_original_alias'.
* @returns {Promise<void>} Promise resolving when the entry is restored.
*
* @example
* await client.restoreHistoryKeystoreEntry('historyHexAlias', 'restoredAlias');
*/
async restoreHistoryKeystoreEntry(hexAlias, destinationAlias) {
// API uses PUT with copy=true query param
const dummyBody = { Status: 'Restoring' };
await this.api.historyKeystoreEntriesHexalias.historyKeystoreEntriesUpdate(hexAlias, {
destinationAlias: destinationAlias,
copy: [true] // Must be true for restore
}, dummyBody);
}
// --- Certificate-to-User Mapping Methods (Neo only) ---
/**
* Retrieves all certificate-to-user mappings.
* Note: This resource is only available in the Neo environment.
*
* @param {object} [options] Optional parameters for filtering, sorting, and selection.
* @param {string} [options.filter] OData filter string (only `User eq 'username'` supported).
* @param {('Id' | 'Id desc' | 'User' | 'User desc' | 'Certificate' | 'Certificate desc' | 'CreatedBy' | 'CreatedBy desc' | 'CreatedTime' | 'CreatedTime desc' | 'LastModifiedBy' | 'LastModifiedBy desc' | 'LastModifiedTime' | 'LastModifiedTime desc' | 'ValidUntil')[]} [options.orderby] Sorting order.
* @param {('Id' | 'User' | 'Certificate' | 'LastModifiedBy' | 'LastModifiedTime' | 'CreatedBy' | 'CreatedTime' | 'ValidUntil')[]} [options.select] Properties to select.
* @returns {Promise<ComSapHciApiCertificateUserMapping[]>} Promise resolving to a list of mappings.
*
* @example
* const allMappings = await client.getCertificateUserMappings();
* const userMappings = await client.getCertificateUserMappings({ filter: "User eq 'myuser'" });
*/
async getCertificateUserMappings(options = {}) {
try {
const response = await this.api.certificateUserMappings.certificateUserMappingsList({
$filter: options.filter,
$orderby: options.orderby,
$select: options.select,
});
return this.normalizer.normalizeArrayResponse(response.data, 'getCertificateUserMappings');
}
catch (error) {
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 404) {
console.warn('CertificateUserMappings API might not be available in this environment (Cloud Foundry?). Returning empty array.');
return [];
}
throw error;
}
}
/**
* Adds a new certificate-to-user mapping.
* Note: This resource is only available in the Neo environment.
*
* @param {ComSapHciApiCertificateUserMappingCreate} mappingData Data for the new mapping (User, Certificate content).
* @returns {Promise<ComSapHciApiCertificateUserMapping | undefined>} Promise resolving to the created mapping.
*
* @example
* // Assuming 'certFile' is a File object
* // const newMapping = await client.createCertificateUserMapping({ User: 'newUser', Certificate: certFile });
*/
async createCertificateUserMapping(mappingData) {
const response = await this.api.certificateUserMappings.certificateUserMappingsCreate(mappingData);
return this.normalizer.normalizeEntityResponse(response.data, 'createCertificateUserMapping');
}
/**
* Retrieves a specific certificate-to-user mapping by its ID.
* Note: This resource is only available in the Neo environment.
*
* @param {string} id The ID of the mapping.
* @param {('User' | 'Certificate' | 'LastModifiedBy' | 'LastModifiedTime' | 'CreatedBy' | 'CreatedTime')[]} [select] Properties to select.
* @returns {Promise<ComSapHciApiCertificateUserMapping | undefined>} Promise resolving to the mapping or undefined.
*
* @example
* const mapping = await client.getCertificateUserMappingById('mapping-id...');
*/
async getCertificateUserMappingById(id, select) {
try {
const response = await this.api.certificateUserMappingsId.certificateUserMappingsList(id, { $select: select });
return this.normalizer.normalizeEntityResponse(response.data, 'getCertificateUserMappingById');
}
catch (error) {
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 404) {
return undefined;
}
throw error;
}
}
/**
* Deletes a certificate-to-user mapping.
* Note: This resource is only available in the Neo environment.
*
* @param {string} id The ID of the mapping to delete.
* @returns {Promise<void>} Promise resolving when the mapping is deleted.
*
* @example
* await client.deleteCertificateUserMapping('mapping-id-to-delete');
*/
async deleteCertificateUserMapping(id) {
await this.api.certificateUserMappingsId.certificateUserMappingsDelete(id);
}
// --- Access Policy & Artifact Reference Methods ---
/**
* Retrieves all Access Policies.
*
* @param {object} [options] Optional parameters for filtering, pagination, sorting, selection, and expansion.
* @param {number} [options.top] Maximum number of policies to retrieve.
* @param {number} [options.skip] Number of policies to skip.
* @param {string} [options.filter] OData filter string (e.g., "RoleName eq 'Policy1'").
* @param {('Id' | 'Id desc' | 'RoleName' | 'RoleName desc')[]} [options.orderby] Sorting order.
* @param {('Id' | 'RoleName' | 'Description')[]} [options.select] Properties to select.
* @param {boolean} [options.expandArtifactReferences=false] If true, expands the associated ArtifactReferences.
* @param {boolean} [options.inlinecount=false] If true, includes the total count.
* @returns {Promise<{ policies: ComSapHciApiAccessPolicy[], count?: number }>} Promise resolving to the policies and optional count.
*
* @example
* const { policies } = await client.getAccessPolicies({ expandArtifactReferences: true });
*/
async getAccessPolicies(options = {}) {
var _a, _b;
const response = await this.api.accessPolicies.accessPoliciesList({
$top: options.top,
$skip: options.skip,
$filter: options.filter,
$orderby: options.orderby,
$select: options.select,
$expand: options.expandArtifactReferences ? ['ArtifactReferences'] : undefined,
$inlinecount: options.inlinecount ? ['allpages'] : undefined,
});
const policies = this.normalizer.normalizeArrayResponse(response.data, 'getAccessPolicies');
const countString = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d) === null || _b === void 0 ? void 0 : _b.__count;
const count = countString ? parseInt(countString, 10) : undefined;
return { policies, count };
}
/**
* Adds a new Access Policy, optionally with initial Artifact References.
*
* @param {ComSapHciApiAccessPolicyCreate} policyData Data for the new policy, including RoleName and optionally ArtifactReferences.
* @returns {Promise<void>} Promise resolving when the policy is created.
*
* @example
* await client.createAccessPolicy({
* RoleName: 'FlowExecutors',
* Description: 'Can execute specific flows',
* ArtifactReferences: [
* { Name: 'AllowFlow1', Type: 'INTEGRATION_FLOW', ConditionAttribute: 'Name', ConditionValue: 'Flow1', ConditionType: 'exactString' }
* ]
* });
*/
async createAccessPolicy(policyData) {
await this.api.accessPolicies.accessPoliciesCreate(policyData);
}
/**
* Deletes an Access Policy by its ID.
*
* @param {string} policyId The ID of the policy to delete.
* @returns {Promise<void>} Promise resolving when the policy is deleted.
*
* @example
* await client.deleteAccessPolicy('policy-id-123');
*/
async deleteAccessPolicy(policyId) {
await this.api.accessPoliciesId.accessPoliciesDelete(policyId);
}
/**
* Updates an Access Policy (only PATCH is supported by the API).
* Note: This method currently only triggers the PATCH request without specific update data,
* as the generated client doesn't directly support PATCH bodies.
* A custom request might be needed for actual updates.
*
* @param {string} policyId The ID of the policy to update.
* @returns {Promise<void>}
*
* @example
* // Note: Actual update might require custom implementation
* await client.updateAccessPolicy('policy-id-123');
*/
async updateAccessPolicy(policyId) {
// Generated client uses PATCH but doesn't accept a body easily.
// For actual updates (e.g., changing Description), a custom request might be needed.
console.warn('updateAccessPolicy currently performs a PATCH request without data. Actual updates may require custom implementation.');
await this.api.accessPoliciesId.accessPoliciesPartialUpdate(policyId);
}
/**
* Retrieves all Artifact References.
*
* @param {object} [options] Optional parameters for filtering, pagination, sorting, and selection.
* @param {number} [options.top] Maximum number of references to retrieve.
* @param {number} [options.skip] Number of references to skip.
* @param {string} [options.filter] OData filter string (e.g., "Id eq 'ref1'").
* @param {('Id' | 'Id desc' | 'Name' | 'Name desc')[]} [options.orderby] Sorting order.
* @param {('Id' | 'Name' | 'Description' | 'Type' | 'ConditionAttribute' | 'ConditionValue' | 'ConditionType')[]} [options.select] Properties to select.
* @param {boolean} [options.inlinecount=false] If true, includes the total count.
* @returns {Promise<{ references: ComSapHciApiArtifactReference[], count?: number }>} Promise resolving to the references and optional count.
*
* @example
* const { references } = await client.getArtifactReferences();
*/
async getArtifactReferences(options = {}) {
var _a, _b;
const response = await this.api.artifactReferences.artifactReferencesList({
$top: options.top,
$skip: options.skip,
$filter: options.filter,
$orderby: options.orderby,
$select: options.select,
$inlinecount: options.inlinecount ? ['allpages'] : undefined,
});
const references = this.normalizer.normalizeArrayResponse(response.data, 'getArtifactReferences');
const countString = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d) === null || _b === void 0 ? void 0 : _b.__count;
const count = countString ? parseInt(countString, 10) : undefined;
return { references, count };
}
/**
* Adds a new Artifact Reference to an existing Access Policy.
*
* @param {string} policyId The ID of the Access Policy to add the reference to.
* @param {Omit<ComSapHciApiArtifactReferenceCreatesep, 'AcessPolicy'>} referenceData Data for the new artifact reference.
* @returns {Promise<void>} Promise resolving when the reference is created.
*
* @example
* await client.createArtifactReference('policy-id-123', {
* Name: 'AllowFlow2', Type: 'INTEGRATION_FLOW', ConditionAttribute: 'Name', ConditionValue: 'Flow2', ConditionType: 'exactString'
* });
*/
async createArtifactReference(policyId, referenceData) {
// The API uses a specific type `ComSapHciApiArtifactReferenceCreatesep` which includes
// an `AcessPolicy` property (note the typo). We need to construct this.
const apiData = {
...referenceData,
AcessPolicy: { Id: policyId } // Link to the policy using the typo 'AcessPolicy'
};
await this.api.artifactReferences.artifactReferencesCreate(apiData);
}
/**
* Deletes an Artifact Reference by its ID.
*
* @param {string} referenceId The ID of the artifact reference to delete.
* @returns {Promise<void>} Promise resolving when the reference is deleted.
*
* @example
* await client.deleteArtifactReference('ref-id-456');
*/
async deleteArtifactReference(referenceId) {
await this.api.artifactReferencesId.artifactReferencesDelete(referenceId);
}
/**
* Retrieves entries from a specified keystore.
*
* @param {('system' | 'backup_admin_system' | 'KeyRenewal')} keystoreName Name of the keystore.
* @param {('Alias' | 'Hexalias' | 'KeyType' | 'LastModifiedBy' | 'LastModifiedTime' | 'Owner' | 'Status' | 'Type' | 'Validity')[]} [select] Properties to select.
* @returns {Promise<ComSapHciApiKeystoreEntry[]>} Promise resolving to a list of keystore entries.
*
* @example
* const entries = await client.getKeystoreEntries('system');
*/
async getKeystoreEntries(keystoreName, select) {
const response = await this.api.keystoreEntries.keystoreEntriesList({
keystoreName: [keystoreName],
$select: select
});
return this.normalizer.normalizeArrayResponse(response.data, 'getKeystoreEntries');
}
/**
* Retrieves a specific keystore entry by its hex-encoded alias.
*
* @param {string} hexAlias Hex-encoded alias of the entry.
* @param {('system' | 'backup_admin_system' | 'KeyRenewal')} [keystoreName='system'] The name of the keystore.
* @param {('Alias' | 'KeyType' | 'LastModifiedBy' | 'LastModifiedTime' | 'Owner' | 'Status' | 'Type' | 'Validity')[]} [select] Properties to select.
* @returns {Promise<ComSapHciApiKeystoreEntry | undefined>} Promise resolving to the entry or undefined.
*
* @example
* const entry = await client.getKeystoreEntry('hex...');
*/
async getKeystoreEntry(hexAlias, keystoreName = 'system', select) {
const response = await this.api.keystoreEntriesHexalias.keystoreEntriesList(hexAlias, {
keystoreName: [keystoreName],
$select: select
});
return this.normalizer.normalizeEntityResponse(response.data, 'getKeystoreEntry');
}
// --- Key Pair Generation Methods ---
/**
* Generates a new key pair (RSA or ECC).
*
* @param {ComSapHciApiKeyPairGenerationRequestCreate} keyPairData Details for key pair generation.
* @param {boolean} [returnKeystoreEntries=false] Return updated keystore entries in response.
* @returns {Promise<{ keyPairInfo?: any, entries?: ComSapHciApiKeystoreEntry[] }>} Promise with generated key pair info and optionally the entry list.
*
* @example
* const { keyPairInfo } = await client.generateKeyPair({
* Alias: 'myNewKeyPair',
* KeyType: 'RSA',
* KeySize: 2048,
* SignatureAlgorithm: 'SHA256/RSA',
* CommonName: 'My Common Name'
* // ... other DN components
* });
*/
async generateKeyPair(keyPairData, returnKeystoreEntries = false) {
var _a, _b, _c, _d;
const response = await this.api.keyPairGenerationRequests.keyPairGenerationRequestsCreate({ returnKeystoreEntries: [returnKeystoreEntries] }, keyPairData);
// Add explicit type annotation, noting the base type might differ from create type
// Using 'any' as the exact response structure for KeyPairGenerationRequest isn't explicitly defined.
const keyPairInfo = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d;
// Actual entries might be nested differently or require re-fetching.
const entries = (_d = (_c = (_b = response.data) === null || _b === void 0 ? void 0 : _b.d) === null || _c === void 0 ? void 0 : _c.Entries) === null || _d === void 0 ? void 0 : _d.results;
return { keyPairInfo, entries };
}
/**
* Generates an RSA key pair from an existing private key file (PKCS#1 PEM format).
*
* @param {ComSapHciApiRSAKeyGenerationRequestCreate} rsaData Details including Alias, RSAFile (base64 encoded private key), SignatureAlgorithm, and DN components.
* @param {boolean} [returnKeystoreEntries=false] Return updated keystore entries in response.
* @returns {Promise<{ keyPairInfo?: any, entries?: ComSapHciApiKeystoreEntry[] }>} Promise with generated key pair info and optionally the entry list.
*
* @example
* const { keyPairInfo } = await client.generateRsaKeyPair({
* Alias: 'myImportedRsaKey',
* RSAFile: 'base64PrivateKeyContent',
* SignatureAlgorithm: 'SHA256/RSA',
* CommonName: 'Imported Key'
* });
*/
async generateRsaKeyPair(rsaData, returnKeystoreEntries = false) {
var _a, _b, _c, _d;
const response = await this.api.rsaKeyGenerationRequests.rsaKeyGenerationRequestsCreate({ returnKeystoreEntries: [returnKeystoreEntries] }, rsaData);
// Using 'any' as the exact response structure for KeyPairGenerationRequest isn't explicitly defined.
const keyPairInfo = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d; // Explicit annotation
const entries = (_d = (_c = (_b = response.data) === null || _b === void 0 ? void 0 : _b.d) === null || _c === void 0 ? void 0 : _c.Entries) === null || _d === void 0 ? void 0 : _d.results;
return { keyPairInfo, entries };
}
/**
* Generates an SSH private key pair from an OpenSSH (RSA, DSA, EC) or PuTTY (RSA, DSA) file.
* Alias will be id_rsa, id_dsa, or id_ec based on algorithm.
*
* @param {ComSapHciApiSSHKeyGenerationRequestCreate} sshData Details including SSHFile (key content), optional Password, and DN components.
* @param {boolean} [update=false] Update existing SSH key pair.
* @param {boolean} [returnKeystoreEntries=false] Return updated keystore entries in response.
* @returns {Promise<{ responseInfo?: ComSapHciApiSSHKeyGenerationRequestCreateResponse, entries?: ComSapHciApiKeystoreEntry[] }>} Promise with response info (containing Alias) and optionally the entry list.
*
* @example
* const { responseInfo } = await client.generateSshKeyPair({
* SSHFile: 'ssh-rsa AAAAB3NzaC1yc2.... user@host',
* CommonName: 'My SSH Key'
* }, false);
* console.log('Generated SSH Key Alias:', responseInfo?.Alias);
*/
async generateSshKeyPair(sshData, update = false, returnKeystoreEntries = false) {
var _a, _b, _c, _d;
const response = await this.api.sshKeyGenerationRequests.sshKeyGenerationRequestsCreate({
update: [update],
returnKeystoreEntries: [returnKeystoreEntries]
}, sshData);
// const responseInfo = response.data?.d;
const responseInfo = (_a = response.data) === null || _a === void 0 ? void 0 : _a.d; // Explicit annotation
const entries = (_d = (_c = (_b = response.data) === null || _b === void 0 ? void 0 : _b.d) === null || _c === void 0 ? void 0 : _c.Entries) === null || _d === void 0 ? void 0 : _d.results; // Adjust if structure differs
return { responseInfo, entries };
}
/**
* Retrieves a certificate chain.
*
* @param {string} hexAlias Hex-encoded alias of the key pair.
* @param {('system' | 'backup_admin_system' | 'KeyRenewal' | 'KeyHistory')} [keystoreName='system'] Keystore name.
* @param {('Alias' | 'KeyType' | 'LastModifiedBy' | 'LastModifiedTime' | 'Owner' | 'Validity')[]} [select] Properties to select.
* @returns {Promise<ComSapHciApiChainCertificate[]>} Promise resolving to the list of chain certificates.
*
* @example
* const chainCertificates = await client.getCertificateChain('hex...');
*/
async getCertificateChain(hexAlias, keystoreName = 'system', select) {
const response = await this.api.keystoreEntriesHexalias.chainCertificatesList(hexAlias, {
keystoreName: [keystoreName],
$select: select
});
return this.normalizer.normalizeArrayResponse(response.data, 'getCertificateChain');
}
// --- Cached Methods (Stale-While-Revalidate Pattern) ---
/**
* Retrieves all keystore entries (with Caching)
* Implements Stale-While-Revalidate Pattern
*
* @param {('system' | 'backup_admin_system' | 'KeyRenewal')} keystoreName Name of the keystore.
* @param {boolean} [forceRefresh=false] Forces fetching fresh data from SAP.
* @param {('Alias' | 'Hexalias' | 'KeyType' | 'LastModifiedBy' | 'LastModifiedTime' | 'Owner' | 'Status' | 'Type' | 'Validity')[]} [select] Properties to select.
* @returns {Promise<{ data: ComSapHciApiKeystoreEntry[]; cacheInfo: CacheInfo }>} Keystore entries with cache information.
*
* @example
* const { data, cacheInfo } = await client.getKeystoreEntriesWithCache('system');
* console.log(cacheInfo.status); // 'HIT', 'HIT-STALE', 'MISS', or 'DISABLED'
*/
async getKeystoreEntriesWithCache(keystoreName, forceRefresh = false, select) {
const endpoint = '/KeystoreEntries';
const queryParams = { keystoreName, select };
// Fallback if no cacheManager
if (!this.cacheManager || !this.hostname) {
const data = await this.getKeystoreEntries(keystoreName, select);
return {
data,
cacheInfo: {
hit: false,
age: null,
status: 'DISABLED',
source: 'sap-api-direct',
},
};
}
const cacheKey = (0, cache_key_generator_1.generateCacheKey)(this.hostname, 'GET', endpoint, queryParams);
const cacheOptions = { ttl: cache_config_1.CACHE_TTL.STANDARD, revalidateAfter: cache_config_1.REVALIDATE_AFTER.STANDARD };
const fetchFn = async () => {
return this.getKeystoreEntries(keystoreName, select);
};
const result = await this.cacheManager.getOrFetch(cacheKey, fetchFn, cacheOptions, forceRefresh);
return {
data: result.data,
cacheInfo: {
...result.cacheInfo,
key: cacheKey,
source: 'npm-package-cache',
},
};
}
/**
* Retrieves all deployed user credentials (with Caching)
* Implements Stale-While-Revalidate Pattern
*
* @param {boolean} [forceRefresh=false] Forces fetching fresh data from SAP.
* @returns {Promise<{ data: ComSapHciApiUserCredential[]; cacheInfo: CacheInfo }>} User credentials with cache information.
*
* @example
* const { data, cacheInfo } = await client.getUserCredentialsWithCache();
* console.log(cacheInfo.status); // 'HIT', 'HIT-STALE', 'MISS', or 'DISABLED'
*/
async getUserCredentialsWithCache(forceRefresh = false) {
const endpoint = '/UserCredentials';
// Fallback if no cacheManager
if (!this.cacheManager || !this.hostname) {
const data = await this.getUserCredentials();
return {
data,
cacheInfo: {
hit: false,
age: null,
status: 'DISABLED',
source: 'sap-api-direct',
},
};
}
const cacheKey = (0, cache_key_generator_1.generateCacheKey)(this.hostname, 'GET', endpoint);
const cacheOptions = { ttl: cache_config_1.CACHE_TTL.STANDARD, revalidateAfter: cache_config_1.REVALIDATE_AFTER.STANDARD };
const fetchFn = async () => {
return this.getUserCredentials();
};
const result = await this.cacheManager.getOrFetch(cacheKey, fetchFn, cacheOptions, forceRefresh);
return {
data: result.data,
cacheInfo: {
...result.cacheInfo,
key: cacheKey,
source: 'npm-package-cache',
},
};
}
/**
* Retrieves all OAuth2 client credentials (with Caching)
* Implements Stale-While-Revalidate Pattern
*
* @param {boolean} [expandCustomParameters=false] If true, expands custom parameters.
* @param {boolean} [forceRefresh=false] Forces fetching fresh data from SAP.
* @returns {Promise<{ data: ComSapHciApiOAuth2ClientCredential[]; cacheInfo: CacheInfo }>} OAuth2 credentials with cache information.
*
* @example
* const { data, cacheInfo } = await client.getOAuth2ClientCredentialsWithCache();
* console.log(cacheInfo.status); // 'HIT', 'HIT-STALE', 'MISS', or 'DISABLED'
*/
async getOAuth2ClientCredentialsWithCache(expandCustomParameters = false, forceRefresh = false) {
const endpoint = '/OAuth2ClientCredentials';
const queryParams = { expandCustomParameters };
// Fallback if no cacheManager
if (!this.cacheManager || !this.hostname) {
const data = await this.getOAuth2ClientCredentials(expandCustomParameters);
return {
data,
cacheInfo: {
hit: false,
age: null,
status: 'DISABLED',
source: 'sap-api-direct',
},
};
}
const cacheKey = (0, cache_key_generator_1.generateCacheKey)(this.hostname, 'GET', endpoint, queryParams);
const cacheOptions = { ttl: cache_config_1.CACHE_TTL.STANDARD, revalidateAfter: cache_config_1.REVALIDATE_AFTER.STANDARD };
const fetchFn = async () => {
return this.getOAuth2ClientCredentials(expandCustomParameters);
};
const result = await this.cacheManager.getOrFetch(cacheKey, fetchFn, cacheOptions, forceRefresh);
return {
data: result.data,
cacheInfo: {
...result.cacheInfo,
key: cacheKey,
source: 'npm-package-cache',
},
};
}
/**
* Retrieves all Access Policies (with Caching)
* Implements Stale-While-Revalidate Pattern
*
* @param {object} [options] Optional parameters for filtering, pagination, sorting, selection, and expansion.
* @param {boolean} [forceRefresh=false] Forces fetching fresh data from SAP.
* @returns {Promise<{ data: { policies: ComSapHciApiAccessPolicy[], count?: number }; cacheInfo: CacheInfo }>} Access policies with cache information.
*
* @example
* const { data, cacheInfo } = await client.getAccessPoliciesWithCache({ expandArtifactReferences: true });
* console.log(data.policies);
* console.log(cacheInfo.status); // 'HIT', 'HIT-STALE', 'MISS', or 'DISABLED'
*/
async getAccessPoliciesWithCache(options = {}, forceRefresh = false) {
const endpoint = '/AccessPolicies';
const queryParams = { ...options };
// Fallback if no cacheManager
if (!this.cacheManager || !this.hostname) {
const data = await this.getAccessPolicies(options);
return {
data,
cacheInfo: {
hit: false,
age: null,
status: 'DISABLED',
source: 'sap-api-direct',
},
};
}
const cacheKey = (0, cache_key_generator_1.generateCacheKey)(this.hostname, 'GET', endpoint, queryParams);
const cacheOptions = { ttl: cache_config_1.CACHE_TTL.STANDARD, revalidateAfter: cache_config_1.REVALIDATE_AFTER.STANDARD };
const fetchFn = async () => {
return this.getAccessPolicies(options);
};
const result = await this.cacheManager.getOrFetch(cacheKey, fetchFn, cacheOptions, forceRefresh);
return {
data: result.data,
cacheInfo: {
...result.cacheInfo,
key: cacheKey,
source: 'npm-package-cache',
},
};
}
/**
* Retrieves a certificate chain (with Caching)
* Implements Stale-While-Revalidate Pattern
*
* @param {string} hexAlias Hex-encoded alias of the key pair.
* @param {('system' | 'backup_admin_system' | 'KeyRenewal' | 'KeyHistory')} [keystoreName='system'] Keystore name.
* @param {boolean} [forceRefresh=false] Forces fetching fresh data from SAP.