Function Find-CoreContact { <# .SYNOPSIS Function for searching for contacts in CORE via CTKAPI .DESCRIPTION Function for doing a contact based search via the Core API (CTKAPI) You can specify multiple search criteria to focus your search for various criteria You essentially need to choose your search terms and our output. Output is set by the params Attributes and CustomAttributes. You can ignore these and a default set of contact attributes will be returned If you need more information from your search, add attribute groups with the attribute param. You can also add custom attributes if you want to get even more granular See the help for the attribute param for this function for more information Input is set by the other params, simply select them and fill in the criteria In the background this function is using the where statement on the ticket class against the CTKAPI and parsing the output. It will also: - Manage your token, prompting for new one if it expires - Parse output into a Powershell friendly output - If the query is too large it will automatically start breaking it out into smaller ones - Has throttling protection to stop CTKAPI Make your search as specific as possible, so use as many function parameters as you can to limit your search. It will be faster and you will get far more useful data back. Dont just search for all contacts on an account and filter in powershell, its SLOW! There are many, many variations of search, returning lots of data. Check examples section for some inspiration as well as the param help for details on the search types Input for a single search criteria is limited to 249. This is a CTKAPI limitation. If you want to search for more then 249 of a single thing, say, 500 SSOs, you will need to split the input up before you pass it to this function as any input will not accept more then 249 Try to limit the number of attributes you return. It is best practice to limit the attribute groups you use as well. While pretty small, all of these will have an effect on the time a query takes See the help for Get-CoreContactAttributes and the attribute param for this function for more information. Make sure you check the CustomAttribute help as well, as this may be useful for limiting your querys Throttling will stop you performing too many queries in a time frame, so if you see a pause during a query, this is to stop the CTKAPI rejecting your query .PARAMETER Id Optional Core ID for users to search for (you can specify up to 249) If you want a single user, just pass a single ID Validated against regex Example: 1293362 Example: 1057184 Example: @(1057184,1293362) .PARAMETER Ssos Optional SSOs for users to search for (you can specify up to 249) If you do not know SSOs you can use Get-Racker in the DevelopmentTools module If you want a single user, just pass the single username Validated against regex Example: mart6771 Example: george.smith Example: @("mart6771","george.smith") .PARAMETER FirstNames Optional First names for users to search for (you can specify up to 249) Returns all matching users Validated against regex Example: taylor Example: graham Example: @("Taylor","Graham") .PARAMETER LastNames Optional Last names for users to search for (you can specify up to 249) Returns all matching users If you want a single user, just pass the single username Validated against regex Example: rhodes Example: weston Example: @("Rhodes","Weston") .PARAMETER IsEmployee Optional Filter search to return only rackers Switch .PARAMETER Attributes Specify groups of ticket attributes to return with your search There is a default list of attributes that will always be returned, but you can specify additional groups Use the following command to return all contact attributes and their group names Get-CoreContactAttributes -PrintAttributes You can also use the CustomAttributes param to return individual attributes See the help for Get-CoreContactAttributes for more information .PARAMETER CustomAttributes Hashtable of additional attributes to return with your search There is a default list of ticket attributes that will always be returned You can specify additional groups using the Attribute parameter (see Attribute param help) You can also get more attributes here: https://ws.core.rackspace.com/ctkapi/browse/Contact/Contact If you want to just return 1 or 2 additional params, use this parameter. You will need to provide a hashtable of attributes, where the friendly name is the key and the value is the Core API search For example, $Result = Find-CoreContact -Ssos "mart6141" -CustomAttribute @{"reverse_name"="reverse_name"} $result.reverse_name You can use the command Get-CoreContactAttributes -PrintAttributes to get a list of attributes and their CustomAttribute syntax .PARAMETER FullObject Optional Switch Retuns the full object from core (.result) plus the time taken by the query,load args,limit,offset,count of objects retruned,etc If switch is not specified the .result content are only returned i.e. the data from core which is the default. Example of retruning Full object count : 1 load_arg : @{limit=100; values=System.Object[]; class=Contact.ContactWhere; offset=0} limit : 100 result : {@{is_employee=True; employee_userid=mart6141; last_name=Howlett; name=Martin Howlett;....}} offset : 0 class : Contact.Contact QueryTime : 0.5068027 .EXAMPLE Returns contact information for user $Result = Find-CoreContact -Ssos "mart6141" .EXAMPLE Returns contact information for user and customattribute reverse_name $Result = Find-CoreContact -Ssos "mart6141" -CustomAttribute @{"reverse_name"="reverse_name"} $result.reverse_name .OUTPUTS The result object from Core .NOTES Written by Martin Howlett / Mark Wichall #> [CmdletBinding()] Param ( [Parameter()] [ValidatePattern("^\d{4,10}$")] [ValidateCount(1,249)] [String[]]$Id, [Parameter()] [ValidatePattern("^[!\#\$%&'-\.0-9@A-Z\^_``a-z\{\}~\u00C0-\u024F]{1,64}$")] #https://stackoverflow.com/questions/20690499/concrete-javascript-regex-for-accented-characters-diacritics [ValidateCount(1,249)] [String[]]$Ssos, [Parameter()] [ValidatePattern("^[!\#\$%&'-\.0-9@A-Z\^_``a-z\{\}~\u00C0-\u024F]{1,64}$")] [ValidateCount(1,249)] [String[]]$FirstNames, [Parameter()] [ValidatePattern("^[!\#\$%&'-\.0-9@A-Z\^_``a-z\{\}~\u00C0-\u024F]{1,64}$")] [ValidateCount(1,249)] [String[]]$LastNames, [Parameter()] [ValidateNotNullOrEmpty()] [Switch]$IsEmployee, [ValidateRange(1,249)] [Parameter()] [int]$QueryLimit = 100, [Parameter()] [Validateset("Default","Is")] [ValidateNotNullOrEmpty()] [String[]]$Attributes, [Parameter()] [ValidateNotNullOrEmpty()] [Hashtable]$CustomAttributes, [ValidateNotNullOrEmpty()] [Switch]$FullObject ) Begin { Write-Verbose "Start of $($MyInvocation.MyCommand)" } Process { Write-Verbose "Verbose switch used!" Write-Verbose "Start of $($MyInvocation.MyCommand)" #Create the dictionary that will hold our query arguments [Hashtable]$SearchTerms = @{} Write-Verbose $SearchTerms.GetType() #Add query attributes if($Id) { #Make array unique $Id = Get-UniqueArray -InputArray $Id $SearchTerms.Add("Id",[Array]("id","in", [System.Collections.ArrayList]$Id)) Write-Verbose "Added IDs: $($Id -join ",")" } if($Ssos) { #Make array unique $Ssos = Get-UniqueArray -InputArray $Ssos $SearchTerms.Add("SSOs",[Array]("employee_userid","in", [System.Collections.ArrayList]$Ssos)) Write-Verbose "Added SSOs: $($Ssos -join ",")" } if($FirstNames) { #Make array unique $FirstNames = Get-UniqueArray -InputArray $FirstNames $SearchTerms.Add("FirstNames",[Array]("first_name","in", [System.Collections.ArrayList]$FirstNames)) Write-Verbose "Added first names: $($FirstNames -join ",")" } if($LastNames) { #Make array unique $LastNames = Get-UniqueArray -InputArray $LastNames $SearchTerms.Add("LastNames",[Array]("last_name","in", [System.Collections.ArrayList]$LastNames)) Write-Verbose "Added last names: $($LastNames -join ",")" } if($IsEmployee) { $SearchTerms.Add("IsEmployee",[Array]("is_employee","=", $True)) Write-Verbose "Added IsEmployee" } #if we dont have any search terms, throw an error if($SearchTerms.keys.count -eq 0) { Throw "No criteria selected for contact search" } #Add our list of user selected attributes [Hashtable]$CoreContactAttributes = @{} if($Attributes) { $CoreContactAttributes.Add("Attributes",$Attributes) } $QueryAttributes = Get-CoreContactAttributes @CoreContactAttributes #Build our variables for the Core where statement handler [Hashtable]$WrapperParams = @{ SearchTerms = $SearchTerms Attributes = $QueryAttributes Class = "Contact" QueryLimit = $QueryLimit } #if the user has supplied a custom attribute hashtable, we pass this to our where wrapper if($CustomAttributes) { $WrapperParams.Add("CustomAttributes",$CustomAttributes) } $result = Invoke-CoreWhereWrapper @WrapperParams #Retruns the .result value as default, full object retruned if $FullObject switch used. If (-not $FullObject) { $result = $result.result } return $result } End { #Log to appstats Set-LogtoAppstats -FunctionID "Find-CoreContact" -AppID "PoshCore" Write-Verbose "End of $($MyInvocation.MyCommand)" } } Function Get-CoreContactAttributes { <# .SYNOPSIS Returns attributes for Contactwhere queries .DESCRIPTION Creates a hashtable of attributes used with Contactwhere statements in Core Using the attribute switch you can build up set of attributes by specify the groups you want included To get an idea of what attributes are in what group, run the command: Get-CoreContactAttributes -PrintAttributes This will print all the groups to the screen to find the one you need The default group of attributes will always be returned and cannot be changed You can specify additional attributes using the custom attribute param. Use the printattribute command to see the syntax The reason we return a hash table is so we can get the Core API to return friendly names so we do not have to process stuff For example this entry: @{"segment"="segment.name"} Typically the Core API would return a Segment Class, so by using dot notation we have Core expand it to return the name. By using a hashtable in this fashion, the "friendly" name is the key and the actual Core query is the value ------------ DEV NOTES: ------------- If you are adding or removing an attribute group, you must make sure you: - Update the ValidateSet for attributes on Find-CoreContact - Update the ValidateSet for attributes on this function - Update the array for attributes in the $PrintAttributes if statement at the bottom of this function If you are adding an attribute group, you MUST make sure the hashtable variable you create matches this naming convention: $ContactAttributes .PARAMETER Attributes Optional Array of additional groups of attribute to return This would typically be passed from Find-CoreContact You can specify any combination of attribute groups you want, depending on your requirements Returning every group is obviously going to slow down a core query, so try to keep the groups to a minimum To see a list of what attributes are in what group, use Get-CoreContactAttributes -PrintAttributes .PARAMETER PrintAttributes Can only be used by itself Run to get a print out of all the attribute groups and their PoshCore name, Core API value and the Custom attribute syntax Example output of default values for Contact (note, values subject to change) Attribute group name: Default ------------------------------------------------------------------------------ | PoshCore name: | Core API value: | Custom attribute syntax: | ------------------------------------------------------------------------------ | is_employee | is_employee | @{"is_employee"="is_employee"} | | employee_number | employee_number | @{"employee_number"="employee_number"} | | id | id | @{"id"="id"} | | imaway | imaway | @{"imaway"="imaway"} | | login_time | login_time | @{"login_time"="login_time"} | | name | name | @{"name"="name"} | | last_active | last_active | @{"last_active"="last_active"} | | employee_userid | employee_userid | @{"employee_userid"="employee_userid"} | | first_name | first_name | @{"first_name"="first_name"} | | last_name | last_name | @{"last_name"="last_name"} | ------------------------------------------------------------------------------ .EXAMPLE Prints out of all the attribute groups and their PoshCore name, Core API value and the Custom attribute syntax Get-CoreContactAttributes -PrintAttributes .EXAMPLE Get a hashtable of the default Contact attributes. This should then be passed to Get-CoreWhereWrapper attribute param $Attributes = Get-CoreContactAttributes .OUTPUTS Hashtable of attributes to use with Invoke-CoreQueryWrapper .NOTES Written by Martin Howlett #> [CmdletBinding(DefaultParameterSetName='Attributes')] Param ( [Parameter(ParameterSetName="Attributes")] [Validateset("Default","Is")] [AllowEmptyString()] [String[]]$Attributes = "Default", [Parameter(ParameterSetName="PrintAttributes")] [Switch]$PrintAttributes ) Begin { Write-Verbose "Start of $($MyInvocation.MyCommand)" } Process { #The default list of params we will always return [Hashtable]$DefaultContactAttributes = @{ "employee_userid" = "employee_userid" "id" = "id" "is_employee" = "is_employee" "login_time" = "login_time" "name" = "name" "first_name" = "first_name" "last_name" = "last_name" "employee_number" = "employee_number" "last_active" = "last_active" "imaway" = "imaway" "primary_email" = "primary_email.address" } [Hashtable]$IsContactAttributes = @{ "is_core" = "is_core" "is_customer" = "is_customer" "is_idle" = "is_idle" "is_online" = "is_online" "is_suspended" = "is_suspended" "is_system_user" = "is_system_user" "is_team_lead" = "is_team_lead" "is_team_tech_lead" = "is_team_tech_lead" } #Create output object [Hashtable]$ContactAttributes = @{} #Add our top level attributes switch ($Attributes) { {$_ -contains 'Default'}{$ContactAttributes += $DefaultContactAttributes ; Write-Verbose 'adding Default attributes'} {$_ -contains 'Is'}{$ContactAttributes += $IsContactAttributes ; Write-Verbose 'adding Is attributes'} } #if user selected the print attribute switch we just print them to screen and dont return anything if($PrintAttributes) { Write-Verbose "PrintAttributes selected" #set variables to generate our hash table for Write-AttributesToHost #$AllGroups should match the ValidateSet on the Attributes param on this function $AttributeClass = "Contact" $AllGroups = @("Default","Is") #create the hashtable of all attribute hashtable groups we pass to Write-Attributes $AttributeHashtable = @{} ForEach ($Group in $AllGroups) { $AttributeHashtable.Add($Group,$((Get-Variable -Name "$Group$AttributeClass`Attributes").Value)) } Write-AttributesToHost -AttributeHashtable $AttributeHashtable } else { Return $ContactAttributes } } End { #Log to appstats Set-LogtoAppstats -FunctionID "Get-CoreContactAttributes" -AppID "PoshCore" Write-Verbose "End of $($MyInvocation.MyCommand)" } }