Configuration for CSV integration operations

The base setup of the CSV integration enables successful data import in accordance with the defined integration data schema. The collected and normalized CSV integration data is presented in two perspectives: the account catalogue of the CSV integration and the Analytics warehouse. Both allow users to perform the authoritative source account management and account data analysis.

To support workflow automation, provisioning and reconciliation, additional integration configuration is required, including:

  • Identity attribute model definition
  • Identity lifecycle management
  • Other custom integration operations

Identity attribute model definition

Attributes from CSV records can be used as authoritative ("master") data and mapped to identity properties, such as:

  • Identity identifier
  • Identity name
  • Identity email address
  • Manager
  • Employment start date
  • Employment termination date

The HR Source Attributes Mapping Rule defines the primary attribute authority for each identity property listed above and establishes the inbound update direction, whereby identity attributes are synchronized from CSV (as the HR authoritative source) to ObserveID (as the IGA platform). A code sample for the HR Source Attributes Mapping Rule is provided below.

var accountData = await readOnlyAccess360DbContext.Accounts
.Where(x => x.IntegrationId == integrationId && x.Id == accountId)
.Select(x => new{x.Id,x.Name})
.FirstOrDefaultAsync();
                
var accountEmail = await readOnlyAccess360DbContext.AccountStringAdditionalProperties
.Where(x => x.AccountId == accountData.Id && x.Name == "email")
.OrderByDescending(x => x.LastUpdateTimestamp)
.ThenBy(x => x.Terminated)
.Select(x => x.Value)
.FirstOrDefaultAsync();
                             
var accountName = accountData.Name;
var identityEmail = !string.IsNullOrWhiteSpace(accountEmail) ? accountEmail : accountName;
if (!identityEmail.Contains("@"))
{
identityEmail += "@CSVtest.com.invalid";
}
                            
var accountGivenName = await readOnlyAccess360DbContext.AccountStringAdditionalProperties
.Where(x => x.AccountId == accountData.Id && x.Name == "name")
.OrderByDescending(x => x.LastUpdateTimestamp)
.ThenBy(x => x.Terminated)
.Select(x => x.Value)
.FirstOrDefaultAsync();
                
var accountSurname = await readOnlyAccess360DbContext.AccountStringAdditionalProperties
.Where(x => x.AccountId == accountData.Id && x.Name == "surname")
.OrderByDescending(x => x.LastUpdateTimestamp)
.ThenBy(x => x.Terminated)
.Select(x => x.Value)
.FirstOrDefaultAsync();
                
var identityName = $"{accountGivenName} {accountSurname}";
if (string.IsNullOrWhiteSpace(identityName))
{
identityName = accountName;
}
identityName = identityName.Trim();
                           
var existingIdentityId = await readOnlyAccess360DbContext.Identities
.Where(x => (x.Email == identityEmail))
.Select(x => x.Id)
.FirstOrDefaultAsync();
                
var existingIdentityIdValue = existingIdentityId != Guid.Empty ? existingIdentityId : (Guid?)null;
    
var accountManager = await readOnlyAccess360DbContext.AccountStringAdditionalProperties
.Where(x => x.AccountId == accountData.Id && x.Name == "managerId")
.OrderByDescending(x => x.LastUpdateTimestamp)
.ThenBy(x => x.Terminated)
.Select(x => x.Value)
.FirstOrDefaultAsync();
                
var accountManagerAccountIdValue =(Guid?)null; 
if (accountManager != default)
{
if (Guid.TryParse(accountManager, out var accountManagerId))
{
var accountManagerAccountId = await readOnlyAccess360DbContext.Accounts
.Where(x => x.Id == accountManagerId)
.OrderByDescending(x => x.LastUpdateTimestamp)
.ThenBy(x => x.Terminated)
.Select(x => x.Id)
.SingleOrDefaultAsync();
                
if (accountManagerAccountId != default)
{
accountManagerAccountIdValue = accountManagerAccountId;
}
}
}
var startDateAccount = await readOnlyAccess360DbContext.AccountStringAdditionalProperties
.Where(x => x.AccountId == accountData.Id && x.Name == "startDate" && !x.Terminated)
.OrderByDescending(x => x.LastUpdateTimestamp)
.Select(x => x.Value)
.FirstOrDefaultAsync();
DateTime? startDateAccountValue = null;
if (DateTime.TryParse(startDateAccount , out var startDateAccountValue1))
{
startDateAccountValue = startDateAccountValue1;
}
return new
    (
    existingIdentityIdValue, 
    identityName, 
    identityEmail, 
    "Gopi-Test-Role-QA", 
    accountManagerAccountIdValue, 
    startDateAccountValue, 
    null
    );

Identity lifecycle management

Identity lifecycle events, such as Joiner or Termination Event are triggered by detected changes in identity attributes. The inbound update flow of authoritative data from CSV to ObserveID plays a key role in initiating the corresponding lifecycle processing. HR Source Rules define the relationship between lifecycle events and changes in identity attributes and must be configured to enable identity lifecycle management when CSV is used as the authoritative source.

HR Source Joiner Rule detects a new account record in the CSV integration and may optionally evaluate additional attributes. A code sample for the HR Source Joiner Rule is provided below.

return readOnlyAccess360DbContext.Accounts.Any(x => !x.Terminated && x.Id == accountId);

HR Source Leaver Rule detects the disablement or inactivation of an existing account record in the CSV integration and may optionally evaluate additional attributes. A code sample for the HR Source Leaver Rule is provided below.

return readOnlyAccess360DbContext.Accounts.Any(x => x.IsLocked && x.Id == accountId)
? true
: false;

HR Source Reinstatement Rule detects the reactivation of a previously inactive account record in the CSV integration and may optionally evaluate additional attributes. A code sample for the HR Source Reinstatement Rule is provided below.

return readOnlyAccess360DbContext.Accounts.Any(x => x.IsLocked && x.Id == accountId)
? false
: true;

Custom Integration Operations

Upon request, the CSV integration can be extended with custom operations implemented on an ad hoc basis and tailored to the specific needs of an organization. This enables the creation of customized functional capabilities designed to meet unique business requirements.