UNPKG

appstore-cli

Version:

A command-line interface (CLI) to interact with the Apple App Store Connect API.

271 lines (246 loc) 9.85 kB
import fs from 'fs'; import * as path from 'path'; import { safeLogger } from '../security/dataHandler.js'; import { ProvisioningProfileValidator } from './provisioningProfile.js'; import { CertificateValidator } from './certificate.js'; import { FastlaneTokenValidator } from './fastlaneToken.js'; /** * Comprehensive credential validator that validates all credential types */ export class CredentialValidator { /** * Validates all provided credentials * @param credentials Object containing all credential information * @returns True if all credentials are valid, false otherwise */ static validateAllCredentials(credentials: { provisioningProfilePath?: string; certificatePath?: string; certificatePassword?: string; fastlaneToken?: string | null; }): boolean { try { let isValid = true; // Validate provisioning profile if provided if (credentials.provisioningProfilePath) { const provisioningProfileInfo = ProvisioningProfileValidator.parseAndValidate(credentials.provisioningProfilePath); if (!provisioningProfileInfo) { safeLogger.error('Provisioning profile validation failed. See troubleshooting tips for help', { filePath: credentials.provisioningProfilePath }); isValid = false; } } // Validate certificate if provided if (credentials.certificatePath) { const certificateInfo = CertificateValidator.parseAndValidate( credentials.certificatePath, credentials.certificatePassword ); if (!certificateInfo) { safeLogger.error('Certificate validation failed. See troubleshooting tips for help', { filePath: credentials.certificatePath }); isValid = false; } // Validate certificate password for .p12 files if (credentials.certificatePassword && path.extname(credentials.certificatePath).toLowerCase() === '.p12') { const isPasswordValid = CertificateValidator.validateP12Password( credentials.certificatePath, credentials.certificatePassword ); if (!isPasswordValid) { safeLogger.error('Certificate password validation failed. Check that the password is correct', { filePath: credentials.certificatePath }); isValid = false; } } } // Validate Fastlane token if provided if (credentials.fastlaneToken) { const isTokenValid = FastlaneTokenValidator.validateToken(credentials.fastlaneToken); if (!isTokenValid) { safeLogger.error('Fastlane token validation failed. See troubleshooting tips for help'); isValid = false; } } if (isValid) { safeLogger.debug('All credentials validated successfully'); } else { safeLogger.error('One or more credentials failed validation. Please check the errors above and see troubleshooting tips'); } return isValid; } catch (error) { safeLogger.error('Error validating credentials. This may indicate an issue with one or more credential files', { error: (error as Error).message }); return false; } } /** * Performs format validation on credential files without parsing content * @param credentials Object containing all credential file paths * @returns True if all credential formats are valid, false otherwise */ static validateCredentialFormats(credentials: { provisioningProfilePath?: string; certificatePath?: string; fastlaneToken?: string | null; }): boolean { try { let isValid = true; // Validate provisioning profile format if provided if (credentials.provisioningProfilePath) { const isFormatValid = ProvisioningProfileValidator.validateFilePath(credentials.provisioningProfilePath); if (!isFormatValid) { safeLogger.error('Provisioning profile format validation failed. Check the file path and extension', { filePath: credentials.provisioningProfilePath }); isValid = false; } } // Validate certificate format if provided if (credentials.certificatePath) { const isFormatValid = CertificateValidator.validateFilePath(credentials.certificatePath); if (!isFormatValid) { safeLogger.error('Certificate format validation failed. Check the file path and extension', { filePath: credentials.certificatePath }); isValid = false; } } // Validate Fastlane token format if provided if (credentials.fastlaneToken) { const isFormatValid = FastlaneTokenValidator.isValidFormat(credentials.fastlaneToken); if (!isFormatValid) { safeLogger.error('Fastlane token format validation failed. Check that the token is correctly formatted', { tokenLength: credentials.fastlaneToken.length }); isValid = false; } } if (isValid) { safeLogger.debug('All credential formats validated successfully'); } else { safeLogger.error('One or more credential formats failed validation. Please check the errors above'); } return isValid; } catch (error) { safeLogger.error('Error validating credential formats', { error: (error as Error).message }); return false; } } /** * Checks if credential files are readable * @param credentials Object containing all credential file paths * @returns True if all credential files are readable, false otherwise */ static areCredentialsReadable(credentials: { provisioningProfilePath?: string; certificatePath?: string; }): boolean { try { let isValid = true; // Check provisioning profile readability if provided if (credentials.provisioningProfilePath) { const isReadable = ProvisioningProfileValidator.isReadable(credentials.provisioningProfilePath); if (!isReadable) { safeLogger.error('Provisioning profile is not readable. Check file permissions', { filePath: credentials.provisioningProfilePath }); isValid = false; } } // Check certificate readability if provided if (credentials.certificatePath) { const isReadable = CertificateValidator.isReadable(credentials.certificatePath); if (!isReadable) { safeLogger.error('Certificate is not readable. Check file permissions', { filePath: credentials.certificatePath }); isValid = false; } } if (isValid) { safeLogger.debug('All credential files are readable'); } else { safeLogger.error('One or more credential files are not readable. Please check the errors above'); } return isValid; } catch (error) { safeLogger.error('Error checking credential readability', { error: (error as Error).message }); return false; } } /** * Gets detailed information about all provided credentials * @param credentials Object containing all credential information * @returns Object with detailed information about each credential */ static getCredentialInfo(credentials: { provisioningProfilePath?: string; certificatePath?: string; certificatePassword?: string; fastlaneToken?: string | null; }): any { const info: any = {}; try { // Get provisioning profile info if provided if (credentials.provisioningProfilePath) { const profileInfo = ProvisioningProfileValidator.parseAndValidate(credentials.provisioningProfilePath); if (profileInfo) { info.provisioningProfile = ProvisioningProfileValidator.getBasicInfo(profileInfo); } } // Get certificate info if provided if (credentials.certificatePath) { const certInfo = CertificateValidator.parseAndValidate( credentials.certificatePath, credentials.certificatePassword ); if (certInfo) { info.certificate = CertificateValidator.getBasicInfo(certInfo); } } // Get Fastlane token info if provided if (credentials.fastlaneToken) { info.fastlaneToken = { length: credentials.fastlaneToken.length, formatValid: FastlaneTokenValidator.isValidFormat(credentials.fastlaneToken) }; } return info; } catch (error) { safeLogger.error('Error getting credential information', { error: (error as Error).message }); return info; } } /** * Provides comprehensive troubleshooting guidance for all credential types * @returns Object with troubleshooting tips for each credential type */ static getTroubleshootingGuidance(): any { return { provisioningProfile: ProvisioningProfileValidator.getTroubleshootingTips(), certificate: CertificateValidator.getTroubleshootingTips(), fastlaneToken: FastlaneTokenValidator.getTroubleshootingTips(), general: [ "Ensure all credential files are in the correct format and not corrupted", "Check that file paths are correct and files exist at the specified locations", "Verify that you have read permissions for all credential files", "Make sure credentials haven't expired (especially provisioning profiles and certificates)", "Confirm that all credentials match your app's bundle identifier and intended distribution method", "For CI/CD environments, ensure credentials are properly secured and accessible" ] }; } } export default CredentialValidator;