file copyright author Vivek M. Chawla <@VivekMChawla>
 *  summary description version license import { Connection } from '@salesforce/core' ; import { JsonMap } from '@salesforce/ts-types' ; import { AnyJson } from '@salesforce/ts-types' ; import { RecordResult } from 'jsforce' ; import { updateObserver } from '../../sfdx-falcon-notifications' ; import { FalconProgressNotifications } from '../../sfdx-falcon-notifications' ; import { SfdxFalconResult } from '../../sfdx-falcon-result' ; import { SfdxFalconResultType } from '../../sfdx-falcon-result' ; import { waitASecond } from '../../sfdx-falcon-util/async' ; import { TargetOrg } from '../types' ; import { ExecutorMessages } from '../types' ; import { RestApiRequestDefinition } from '../../sfdx-falcon-types' ; import { User } from '../../sfdx-falcon-types' ; import { SObjectFindResult } from '../../sfdx-falcon-types' ; import { PermissionSetAssignment } from '../../sfdx-falcon-types' ; import { Subscriber } from '../../sfdx-falcon-types' ; import { changePassword } from '../../sfdx-falcon-util/jsforce' ; import { getAssignedPermsets } from '../../sfdx-falcon-util/jsforce' ; import { getProfileId } from '../../sfdx-falcon-util/jsforce' ; import { getUserId } from '../../sfdx-falcon-util/jsforce' ; import { restApiRequest } from '../../sfdx-falcon-util/jsforce' ; import { getConnection } from '../../sfdx-falcon-util/sfdx' ; import { resolveConnection } from '../../sfdx-falcon-util/sfdx' ; const dbgNs = 'EXECUTOR:hybrid:' ; interface description interface AssignPermsetsResultDetail { userId : string ; permsets : string [ ] ; connection : Connection ; permsetList : string ; qrPermsets : SObjectFindResult ; permsetIds : string [ ] ; permsetsFound : string [ ] ; assignedPermsets : string [ ] ; unassignedPermsets : string [ ] ; permsetAssignmentRecs : PermissionSetAssignment [ ] ; assignmentResults : RecordResult ; } interface description interface ConfigureUserResultDetail { username : string ; userDefinition : JsonMap ; targetOrg : TargetOrg ; connection : Connection ; profileId : string ; userId : string ; cleanUserDefinition : JsonMap ; updateUserRequest : RestApiRequestDefinition ; updateUserResponse : AnyJson ; } interface description interface CreateUserResultDetail { uniqueUsername : string ; password : string ; userDefinition : JsonMap ; targetOrg : TargetOrg ; connection : Connection ; profileId : string ; userId : string ; cleanUserDefinition : JsonMap ; createUserRequest : RestApiRequestDefinition ; createUserResponse : AnyJson ; } function param { string | Connection } aliasOrConnection param { string } userId param { string [ ] } permsets returns { Promise < SfdxFalconResult > } description public async export async function assignPermsets ( aliasOrConnection , userId , permsets ) { const executorResult = new SfdxFalconResult ( `hybrid:assignPermsets` , SfdxFalconResultType . EXECUTOR ) ; const executorResultDetail = { userId : userId , permsets : permsets , connection : null , permsetList : null , qrPermsets : null , permsetIds : null , permsetsFound : null , assignedPermsets : null , unassignedPermsets : null , permsetAssignmentRecs : null , assignmentResults : null } as AssignPermsetsResultDetail ; executorResult . detail = executorResultDetail ; executorResult . debugResult ( `Initialized` , `${ dbgNs }assignPermsets:` ) ; if ( typeof userId !== 'string' ) { executorResult . throw ( new TypeError ( `ERROR_INVALID_PARAMETER: Missing userId [assignPermsets()]` ) ) ; } if ( Array . isArray ( permsets ) === false ) { executorResult . throw ( new TypeError ( `ERROR_INVALID_PARAMETER: Permsets must be provided as an array of strings` ) ) ; } if ( permsets . length < 1 ) { return executorResult . success ( ) ; } const rc = await resolveConnection ( aliasOrConnection ) ; const permsetList = permsets . map ( item => `'${ item }'` ) . join ( ',' ) ; executorResultDetail . permsetList = permsetList ; const permSet = rc . connection . sobject ( 'PermissionSet' ) ; const qrPermsets = await permSet . find ( `Name IN (${ permsetList })` , `Name, Id` ) as SObjectFindResult ; executorResultDetail . qrPermsets = qrPermsets ; const permsetIds = qrPermsets . map ( record => record . Id ) as [ string ] ; executorResultDetail . permsetIds = permsetIds ; executorResult . debugResult ( `Got the IDs for all requested Permsets` , `${ dbgNs }assignPermsets:` ) ; if ( permsets . length !== permsetIds . length ) { const permsetsRequested = permsets . join ( '\n' ) ; const permsetsFound = qrPermsets . map ( record => `${ record . Name } (${ record . Id })` ) ; const listOfPermsetsFound = ( permsetsFound ) ? permsetsFound . join ( '\n' ) : 'NONE' ; executorResultDetail . permsetsFound = permsetsFound ; executorResult . debugResult ( `One or more requested Permsets not found` , `${ dbgNs }assignPermsets:` ) ; executorResult . throw ( new Error ( `ERROR_MISSING_PERMSET: One or more of the specified permsets do not ` + `exist in the target org (${ rc . orgIdentifier }).\n\n` + `Permsets Requested:\n${ permsetsRequested }\n\n` + `Permsets Found:\n${ listOfPermsetsFound }\n\n` ) ) ; } const assignedPermsets = await getAssignedPermsets ( rc . connection , userId ) . catch ( error => { executorResult . throw ( error ) ; } ) as string [ ] ; executorResultDetail . assignedPermsets = assignedPermsets ; const unassignedPermsets = permsetIds . filter ( permsetId => ! assignedPermsets . includes ( permsetId ) ) ; executorResultDetail . unassignedPermsets = unassignedPermsets ; const permsetAssignmentRecs = new Array < PermissionSetAssignment > ( ) ; for ( const permsetId of unassignedPermsets ) { permsetAssignmentRecs . push ( { AssigneeId : userId , PermissionSetId : permsetId } ) ; } executorResultDetail . permsetAssignmentRecs = permsetAssignmentRecs ; const permSetAssignment = rc . connection . sobject ( 'PermissionSetAssignment' ) ; const assignmentResults = await permSetAssignment . insert ( permsetAssignmentRecs ) . catch ( error => { executorResult . throw ( error ) ; } ) as RecordResult ; executorResultDetail . assignmentResults = assignmentResults ; if ( Array . isArray ( assignmentResults ) ) { for ( const assignmentResult of assignmentResults ) { if ( assignmentResult . success === false ) { executorResult . throw ( new Error ( `One or more Permission Sets could not be assigned.\n\n${ JSON . stringify ( assignmentResults ) }` ) ) ; } } } else { if ( assignmentResults . success === false ) { executorResult . throw ( new Error ( `One or more Permission Sets could not be assigned.\n\n${ JSON . stringify ( assignmentResults ) }` ) ) ; } } executorResult . debugResult ( `Permset Assignment Successful` , `${ dbgNs }assignPermsets:` ) ; return executorResult . success ( ) ; } function param { string } username param { JsonMap } userDefinition param { TargetOrg } targetOrg param { ExecutorMessages } executorMessages param { Subscriber } observer returns { Promise < SfdxFalconResult > } description public async export async function configureUser ( username , userDefinition , targetOrg , executorMessages , observer ? ) { const executorResult = new SfdxFalconResult ( `hybrid:configureUser` , SfdxFalconResultType . EXECUTOR ) ; const executorResultDetail = { username : username , userDefinition : userDefinition , targetOrg : targetOrg , connection : null , profileId : null , userId : null , cleanUserDefinition : null , updateUserRequest : null , updateUserResponse : null } as ConfigureUserResultDetail ; executorResult . detail = executorResultDetail ; executorResult . debugResult ( `Initialized` , `${ dbgNs }configureUser:` ) ; updateObserver ( observer , `[0s] ${ executorMessages . progressMsg }` ) ; const progressNotifications = FalconProgressNotifications . start ( executorMessages . progressMsg , 1000 , executorResult , observer ) ; const connection = await getConnection ( targetOrg . alias ) . catch ( error => { executorResult . throw ( error ) ; } ) as Connection ; executorResultDetail . connection = connection ; const profileId = await getProfileId ( connection , userDefinition . profileName as string ) . catch ( error => { executorResult . throw ( error ) ; } ) as string ; executorResultDetail . profileId = profileId ; const userId = await getUserId ( connection , username ) . catch ( error => { executorResult . throw ( error ) ; } ) as string ; executorResultDetail . userId = userId ; const cleanUserDefinition = { ... userDefinition } ; delete cleanUserDefinition . permsets ; delete cleanUserDefinition . generatePassword ; delete cleanUserDefinition . profileName ; delete cleanUserDefinition . password ; delete cleanUserDefinition . Username ; delete cleanUserDefinition . Email ; executorResultDetail . cleanUserDefinition = cleanUserDefinition ; const updateUserRequest = { aliasOrConnection : connection , request : { method : 'patch' , url : `/sobjects/User/${ userId }` , body : JSON . stringify ( { ... cleanUserDefinition } ) } } ; executorResultDetail . updateUserRequest = updateUserRequest ; executorResult . debugResult ( `Created REST API Request Object` , `${ dbgNs }configureUser:` ) ; const updateUserResponse = await restApiRequest ( updateUserRequest ) . catch ( error => { executorResult . throw ( error ) ; } ) ; executorResultDetail . updateUserResponse = updateUserResponse as AnyJson ; if ( typeof userDefinition . permsets !== 'undefined' ) { await assignPermsets ( connection , userId , userDefinition . permsets as string [ ] ) . then ( successResult => { executorResult . addChild ( successResult ) ; } ) . catch ( error => { executorResult . throw ( error ) ; } ) ; } executorResult . debugResult ( `Assigned Permission Sets` , `${ dbgNs }configureUser:` ) ; FalconProgressNotifications . finish ( progressNotifications ) ; updateObserver ( observer , `[${ executorResult . durationString }] SUCCESS: ${ executorMessages . successMsg }` ) ; await waitASecond ( 3 ) ; return executorResult . success ( ) ; } function param { string } uniqueUsername param { string } password param { JsonMap } userDefinition param { TargetOrg } targetOrg param { ExecutorMessages } executorMessages param { Subscriber } observer returns { Promise < SfdxFalconResult > } description public async export async function createUser ( uniqueUsername , password , userDefinition , targetOrg , executorMessages , observer ? ) { const executorResult = new SfdxFalconResult ( `hybrid:createUser` , SfdxFalconResultType . EXECUTOR ) ; const executorResultDetail = { uniqueUsername : uniqueUsername , password : password , userDefinition : userDefinition , targetOrg : targetOrg , connection : null , profileId : null , userId : null , cleanUserDefinition : null , createUserRequest : null , createUserResponse : null } as CreateUserResultDetail ; executorResult . detail = executorResultDetail ; executorResult . debugResult ( `Initialized` , `${ dbgNs }createUser:` ) ; updateObserver ( observer , `[0s] ${ executorMessages . progressMsg }` ) ; const progressNotifications = FalconProgressNotifications . start ( executorMessages . progressMsg , 1000 , executorResult , observer ) ; const connection = await getConnection ( targetOrg . alias ) . catch ( error => { executorResult . throw ( error ) ; } ) as Connection ; executorResultDetail . connection = connection ; const profileId = await getProfileId ( targetOrg . alias , userDefinition . profileName as string ) . catch ( error => { executorResult . throw ( error ) ; } ) as string ; executorResultDetail . profileId = profileId ; const cleanUserDefinition = { ... userDefinition } ; delete cleanUserDefinition . permsets ; delete cleanUserDefinition . generatePassword ; delete cleanUserDefinition . profileName ; delete cleanUserDefinition . password ; delete cleanUserDefinition . Username ; executorResultDetail . cleanUserDefinition = cleanUserDefinition ; const createUserRequest = { aliasOrConnection : connection , request : { method : 'post' , url : '/sobjects/User/' , body : JSON . stringify ( { ... cleanUserDefinition , username : uniqueUsername , profileId : profileId } ) } } ; executorResultDetail . createUserRequest = createUserRequest ; executorResult . debugResult ( `Created REST API Request Object` , `${ dbgNs }createUser:` ) ; const createUserResponse = await restApiRequest ( createUserRequest ) . catch ( error => { executorResult . throw ( error ) ; } ) as User ; executorResultDetail . createUserResponse = createUserResponse as AnyJson ; executorResult . debugResult ( `Created a new Salesforce User` , `${ dbgNs }createUser:` ) ; const userId = createUserResponse . id ; await changePassword ( connection , userId , password ) . catch ( error => { executorResult . throw ( error ) ; } ) ; if ( typeof userDefinition . permsets !== 'undefined' ) { await assignPermsets ( connection , userId , userDefinition . permsets as string [ ] ) . then ( successResult => { executorResult . addChild ( successResult ) ; } ) . catch ( error => { executorResult . throw ( error ) ; } ) ; } executorResult . debugResult ( `Assigned Permission Sets` , `${ dbgNs }createUser:` ) ; FalconProgressNotifications . finish ( progressNotifications ) ; updateObserver ( observer , `[${ executorResult . durationString }] SUCCESS: ${ executorMessages . successMsg }` ) ; await waitASecond ( 3 ) ; return executorResult . success ( ) ; }