Functions/New.ps1

function New-LinaAgent {
    <#
.SYNOPSIS
Creates a new agent.
.DESCRIPTION
Creates a new agent with the provided name.
.INPUTS
None
.OUTPUTS
LinaAgent Object
.PARAMETER Name
Name of the agent to create
.PARAMETER Tenant
Optional : Name of the tenant where the agent should be created.
If not provided, agent will be created in the current tenant.
In global view (no tenant selected), agent will be created in the default tenant.
.PARAMETER NodeName
Optional : Name of the Lina server node where the agent should be created.
If not provided when in Multi-server mode, the node with least agents will be selected
.EXAMPLE
New-LinaAgent -Name "TEST-CREATE"
Creates a new agent in current tenant.
.EXAMPLE
New-LinaAgent -Name "TEST-CREATE2" -Tenant "MyTenant"
Creates a new agent in tenant MyTenant
#>

    [cmdletbinding()]
    Param(
        [Parameter(Mandatory = $true, ParameterSetName = "Name", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $false, ParameterSetName = "Name", Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]$Tenant,
        [Parameter(Mandatory = $false, ParameterSetName = "Name", Position = 2)]
        [ValidateNotNullOrEmpty()]
        [string]$NodeName           
    )
    Write-Host2 "Creating a Lina agent named $Name"
    if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
        Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
        return
    }

    $current_tenant_id = Get-LinaCurrentTenantID 6>$null
    if (!$Tenant) {
        if ($current_tenant_id -le 1) {
            # No current tenant (global view) => using default tenant
            $domain = LinaTenantShort 6>$null | Where-Object { $_.IsDefault } 
            if ($domain.ID -le 1) {
                # No default Tenant ....
                Write-Host2 "ERROR : There is no default tenant. Please select a tenant."
                return 
            }
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name
            Write-Host2 "No tenant selected, agent will be created in default tenant $domain_name (ID $domain_id)"
        }
        else {
            # Using Current tenant
            $domain = Get-LinaTenant -ID (Get-LinaCurrentTenantID) 6>$null
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name            
            Write-Host2 "No tenant selected, agent will be created in current tenant $domain_name (ID $domain_id)"
        }
    }
    else {
        $domain = LinaTenantShort 6>$null | Where-Object { $_.Name -eq $Tenant }
        $domain_id = [int]$domain.ID
        $domain_name = [string]$domain.Name
        if ( !($domain_id -gt 0) ) {
            Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant"
            Return
        }
    }

    $void = Set-LinaCurrentTenant -ID $domain_id 6>$null
    
    if ($GLOBAL_LINA_SERVERTYPE -eq "master") {
        # Selecting node when in Multi-server
        if ($NodeName) {  
            $node_id = (Get-LinaNode -Name $NodeName | Select-Object -last 1).ID 6>$null
        } else {
            # Automatic selection
            Write-Host2 "No node provided, Server node with least agents will be automatically selected"
            $node_id = (Get-LinaNode | Sort-Object -Property NbAgents -Descending | Select-Object -last 1).ID 6>$null
        }

    }
    if ($node_id) { $server_id="<ServerID>$node_id</ServerID>" } else { $server_id="" }
    
    $body = 'data=<?xml version="1.0" encoding="UTF-8"?><HNConfig><Func>ADD</Func><Client><Name>' + $Name + '</Name>'+$server_id+'</Client></HNConfig>'

    if ($global:INT_LINA_API_VERSION -lt 60) {
        # Lina < 6.0
        $request = CallAPI -Path "/mng_client.html" -ContentType "application/xml" -Body $body
    } else {
        # Lina > 6.0
        $request = CallAPI -Path "/mng_client.json" -ContentType "application/xml" -Body $body
    }
   
    
    # Setting back the current tenant to what it was before the New-LinaAgent command
    #Write-Host "Current tenant ID is : "
    $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null
    if ([string]$request -like "*[0]*") {
        Write-Host2 "Agent $Name successfully created in Tenant $domain_name"
        $agent_created = Get-LinaAgent -Name $Name
        Return $agent_created
    }
    else {
        TranslateErrorCode -LinaError $request -FailedAction "create agent $Name"
        Return $null
    }    
}

function New-LinaStrategy {
    <#
    .SYNOPSIS
    Creates a new strategy from scratch or from another one (cloning).
    .DESCRIPTION
    Creates a new strategy with the provided name and configuration.
    Current limitations : two parameters (gateways where encryption is disabled or WAN mode disabled) are not kept when cloning/creating
    .INPUTS
    Single LinaStrategy Object or Array of parameters
    .OUTPUTS
    LinaStrategy Object
    .PARAMETER Name
    Name of the strategy to create
    .PARAMETER Tenant
    Optional : Name of the tenant where the new strategy should be created.
    If not provided, strategy will be created in the same tenant as the original (global if not provided)
    .EXAMPLE
    Get-LinaStrategy -Name "MyStrat" | New-LinaStrategy -Name "Strat2"
    Clone the strategy MyStrat to Strat2 in same tenant and keep all settings
    .EXAMPLE
    Get-LinaStrategy -Name "MyStrat" | New-LinaStrategy -Name "Strat2" -Tenant "Customer2"
    Clone the strategy MyStrat to Strat2 in tenant Customer2 and keep all settings
   .EXAMPLE
    @{ RPOInMinutes = 1 } | New-LinaStrategy -Name "Strat4"
    Creates a new strategy with default parameters except for RPO.
    #>

    [cmdletbinding()]
    Param(
        [Parameter(ValueFromPipeline = $True, ParameterSetName = "ByObject")]
        [pscustomobject]$lina_strategy,
        [Parameter(Mandatory = $true, ParameterSetName = "ByObject", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $false, ParameterSetName = "ByObject", Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]$Tenant
    )
    BEGIN {    
        if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
            Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
            return
        } 
    }
    PROCESS {
        $current_tenant_id = Get-LinaCurrentTenantID 6>$null
            
        if ($Tenant) {
                
            $domain = LinaTenantShort -Name $Tenant 6>$null
            $domain_id = [int]$domain.ID
            if ( !($domain_id -gt 0) ) {
                Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant"
                Return
            }
            Write-Host2 "Creating strategy $Name in Tenant $Tenant"
        }
        elseif ($current_tenant_id -gt 1 ) {
            $tenant_name = (LinaTenantShort -ID $current_tenant_id 6>$null).Name
            Write-Host2 "Creating strategy $Name in current Tenant $tenant_name (ID = $current_tenant_id)"
        }
        elseif ($current_tenant_id -le 1) {
            # No current tenant (global view) => using default tenant instead
            $domain = LinaTenantShort 6>$null | Where-Object { $_.IsDefault } 
            if ($domain.ID -le 1) {
                # No default Tenant ....
                Write-Host2 "ERROR : There is no default tenant. Please select a tenant to create this strategy."
                return 
            }
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name
            Write-Host2 "No tenant selected, strategy will be created in default tenant $domain_name (ID $domain_id)"
        } 
           
        $xml = '<?xml version="1.0" encoding="UTF-8"?><HNConfig><Func>ADD</Func><ServiceProfile><Name>' + $Name + '</Name>'
        if ($lina_strategy) {
            if ([string]$lina_strategy.GetType() -like "*PSCustomObject*") {
                $items = $lina_strategy.PSObject.Properties
            }
            else {
                $items = $lina_strategy.GetEnumerator()
            }
        }
        foreach ($param in $items) {
            if ([string]$lina_strategy.GetType() -like "*PSCustomObject*") {
                $current_key = $($param.Name)
                $current_value = $($param.Value)
            }
            else {
                $current_key = $param.Key
                $current_value = $param.Value
            }                
            switch ($current_key) {
                RPOInMinutes { $current_value = $current_value * 60 }
                AlwaysEncrypt { $current_value = !$current_value }
                AlertAfterDays { $current_value = $current_value * 24 * 3600 }
                QuotaMaxProtSizeMB { $current_value = $current_value * 1024 * 1024 }
                QuotaMaxHistSizeMB { $current_value = $current_value * 1024 * 1024 }
                TenantID { 
                    # Replacing the Tenant with the one provided
                    if ($domain_id -ge 0) { $current_value = $domain_id } 
                }                        
            }
            # Convert Boolean to 0 or 1
            If ($current_value -eq $True -OR $current_value -eq $false) { $current_value = [int]$current_value }
                    
            # Translate Powershell names to XML tags
            $int_trans = $INT_STRATEGIES_MAPPINGS[$current_key]

            if ($current_key -notin "Name", "ID", "InternalName", "ReplicationTarget", "Tenant" ) {
                # Filter out some parameters for creation
                $xml += "<$int_trans>$current_value</$int_trans>"
            }
        }
        $xml += "</ServiceProfile></HNConfig>"
        $body = "data=$xml"
        $request = CallAPI -Path "/mng_serviceprofile.html" -ContentType "application/xml" -Body $body
        if ([string]$request -like "*[0]*") {
            Write-Host2 "Strategy $Name successfully created."
            $strategy_created = Get-LinaStrategy -Name $Name
                
            # Setting back the current tenant to what it was before the New-LinaStrategy command
            if ($Tenant) { Set-LinaCurrentTenant -ID $current_tenant_id 6>$null }
                
            Return $strategy_created
        }
        else {
            TranslateErrorCode -LinaError $request -FailedAction "create strategy $Name"
            Return $null
        }
    }
    END { }
}

function New-LinaAgentGroup {
    <#
    .SYNOPSIS
    Creates a new agent group
    .DESCRIPTION
    Creates a new agent group with the provided name.
    .INPUTS
    None
    .OUTPUTS
    LinaAgentGroup Object
    .PARAMETER Name
    Name of the agent group to create
    .PARAMETER Tenant
    Optional : Name of the tenant where the agent group should be created.
    If not provided, agent group will be created in the current tenant.
    In global view (no tenant selected), agent group will be created in the default tenant.
    .EXAMPLE
    New-LinaAgentGroup -Name "Test-Group"
    Creates a new agent group in current tenant.
    .EXAMPLE
    New-LinaAgent -Name "Test-Group" -Tenant "MyTenant"
    Creates a new agent group in tenant MyTenant
    #>

    [cmdletbinding()]
    Param(
        [Parameter(Mandatory = $true, ParameterSetName = "Name", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $false, ParameterSetName = "Name", Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]$Tenant      
    )
    Write-Host2 "Creating a Lina agent group named $Name"
    if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
        Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
        return
    }
    $current_tenant_id = Get-LinaCurrentTenantID 6>$null
    if (!$Tenant) {
        if ($current_tenant_id -le 1) {
            # No current tenant (global view) => using default tenant
            $domain = LinaTenantShort 6>$null | Where-Object { $_.IsDefault } 
            if ($domain.ID -le 1) {
                # No default Tenant ....
                Write-Host2 "ERROR : There is no default tenant. Please select a tenant."
                return 
            }
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name
            Write-Host2 "No tenant selected, agent group will be created in default tenant $domain_name (ID $domain_id)"
        }
        else {
            # Using Current tenant
            $domain = LinaTenantShort -ID (Get-LinaCurrentTenantID) 6>$null
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name            
            Write-Host2 "No tenant selected, agent group will be created in current tenant $domain_name (ID $domain_id)"
        }
    }
    else {
        $domain = LinaTenantShort 6>$null | Where-Object { $_.Name -eq $Tenant }
        $domain_id = [int]$domain.ID
        $domain_name = [string]$domain.Name
        if ( !($domain_id -gt 0) ) {
            Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant"
            Return
        }
    }
        
    $void = Set-LinaCurrentTenant -ID $domain_id 6>$null
    # Hierarchy ID 1 = legacy groups with Lina < 6.0
    # Hierarchy ID 2 = new agent groups with inheritance

    if ($global:INT_LINA_API_VERSION -lt 60 ) {
        # Legacy mode
        $hierarchy_id=1 
    }else {
        # New agents groups
        $hierarchy_id=2
    }
    $body = 'data=<?xml version="1.0" encoding="UTF-8"?><HNConfig><Func>ADDG</Func><Hierarchy><ID>'+$hierarchy_id+'</ID><Group><Name>' + $Name + '</Name></Group></Hierarchy></HNConfig>'
    $request = CallAPI -Path "/mng_hierarchy.html" -ContentType "application/xml" -Body $body
        
        
    # Setting back the current tenant to what it was before the New-LinaAgentGroup command
    $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null
    if ([string]$request -like "*[0]*") {
        Write-Host2 "Agent group $Name successfully created in Tenant $domain_name (ID $domain_id)"
        $agent_created = Get-LinaAgentGroup -Name $Name -Tenant $domain_name
        Return $agent_created
    }
    else {
        TranslateErrorCode -LinaError $request -FailedAction "create agent group $Name"
        Return $null
    }    
}

function New-LinaTenant {
    <#
        .SYNOPSIS
        Creates a new tenant
        .DESCRIPTION
        Creates a new tenant with the provided name. Needs to be logged as superadmin in order to work.
        .INPUTS
        None
        .OUTPUTS
        LinaTenant Object
        .PARAMETER Name
        Name of the tenant to create
        .PARAMETER Comments
        Name of the tenant to create
        .PARAMETER Default
        Optional : If set to true, the new tenant will be the default tenant.
        .EXAMPLE
        New-LinaTenant -Name "MyTenant"
        Creates a new tenant named "Mytenant"
        #>

    [cmdletbinding()]
    Param(
        [Parameter(Mandatory = $true, ParameterSetName = "Name", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $false, ParameterSetName = "Name", Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]$Comments
    )

    if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
        Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
        return
    }

    if ($global:INT_LINA_API_VERSION -le 60) {
        $request = CallAPI -Path "/ADE/check_session.xml"
        $current_tenant_id = [int](([xml]$request).session.effective_domain_id)
    }else {
        $request = CallAPI -Path "/ADE/check_session.json"
        $current_tenant_id = $request.effective_domain_id
    }
        
    if ($current_tenant_id -gt 1) {
        Write-Host2 "WARNING : to create a tenant you should be logged as superadmin and be in the global view (using Set-LinaCurrentTenant -All). Current tenant ID is : $current_tenant_id"
        return ""
    }
        
    Write-Host2 "Creating a new Lina Tenant"

    $name_enc = [System.Web.HttpUtility]::UrlEncode($Name)
    $comment_enc = [System.Web.HttpUtility]::UrlEncode($Comments)
    $request = CallAPI -Path "/ADM/add_domain.json?name=$name_enc&comment=$comment_enc" -ContentType "application/json"

    if ([string]$request -like "*[0]*") {
        $tenant_id = $request.id 
        Write-Host2 "Tenant $Name successfully created (ID $tenant_id)"
        # Going back to global view to be able to list tenants
        Set-LinaCurrentTenant -All 6>$null
        $tenant_created = Get-LinaTenant -ID $tenant_id
        Return $tenant_created
    }
    else {
        TranslateErrorCode -LinaError $request -FailedAction "create tenant $Name"
        Set-LinaCurrentTenant -All 6>$null
        Return $null
    }    
}

function New-LinaUserProfile {
    <#
            .SYNOPSIS
            (Deprecated in Lina 6.1+, use Copy-LinaUserGroup instead) Creates a new user profile
            .DESCRIPTION
            Creates a new user profile with the provided name or using its original name.
            Note : Requires PowerShell 5.0 or greater.
            .INPUTS
            Single LinaUserProfile Object or Array of parameters
            .OUTPUTS
            LinaUserProfile Object
            .PARAMETER Name
            Optional : Name of the User Profile to create. DO NOT pass the name if you pipe multiple User Profiles to the command as only the first one will be created.
            .PARAMETER Tenant
            Optional : Name of the tenant where the user profile should be created.
            If not provided, user profile will be created in the current tenant.
            In global view (no tenant selected), user profile will be created in the default tenant.
            .EXAMPLE
            Get-LinaUserProfile -Name "TemplateProfile" | New-LinaUserProfile -Name "MyUserProfile"
            Creates a new user profile in current tenant with same config as TemplateProfile
            .EXAMPLE
            Get-LinaUserProfile -Tenant "MyTenant" | Where { $_.BuiltIn -ne $True -AND $_.InternalName -ne "Default" } | New-LinaUserProfile -Tenant 'MyTenant2'
            Clone all custom user profiles from Tenant MyTenant to MyTenant2
            #>

    [cmdletbinding()]
    Param(
        [Parameter(ValueFromPipeline = $True, ParameterSetName = "ByObject")]
        [pscustomobject[]]$LinaUserProfiles,

        [Parameter(Mandatory = $false, ParameterSetName = "ByObject", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $false, ParameterSetName = "ByObject", Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]$Tenant      
    )
    BEGIN {
        $nb_of_userprofiles_to_create = 0
        if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
            Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
            return
        }

        if ($global:INT_LINA_API_VERSION -ge 61) {
            Write-Warning "UserProfiles are deprecated and have been merged with User Groups. Use Copy-LinaUserGroup instead." 
            return
        }
    }
    PROCESS {

        foreach ($LinaUserProfile in $LinaUserProfiles) {
            $nb_of_userprofiles_to_create += 1
            # Should be useless now
            If (!$LinaUserProfile.ID) { return }
                    
            if (!$Name) {
                $Name = $LinaUserProfile.Name 
            }
            elseif ($nb_of_userprofiles_to_create -gt 1) {
                Write-Host2 "ERROR : You cannot use -Name if you pipe multiple user profiles. Remove the -Name option, Original Names will be kept"
                Return
            }

            Write-Host2 "Creating a Lina user profile named $Name"
            if ($PSVersionTable.PSVersion.Major -lt 5) {
                Write-Host2 "ERROR : This cmdlet requires PowerShell 5.0 or greater in order to work"
                Return 
            }

            $current_tenant_id = Get-LinaCurrentTenantID 6>$null
            if (!$Tenant) {
                if ($current_tenant_id -le 1) {
                    # No current tenant (global view) => using default tenant
                    $domain = LinaTenantShort 6>$null | Where-Object { $_.IsDefault } 
                    if ($domain.ID -le 1) {
                        # No default Tenant ....
                        Write-Host2 "ERROR : There is no default tenant. Please select a tenant."
                        return 
                    }
                    $domain_id = [int]$domain.ID
                    $domain_name = [string]$domain.Name
                    Write-Host2 "No tenant selected, user profile will be created in default tenant $domain_name (ID $domain_id)"
                }
                else {
                    # Using Current tenant
                    $domain = LinaTenantShort -ID (Get-LinaCurrentTenantID) 6>$null
                    $domain_id = [int]$domain.ID
                    $domain_name = [string]$domain.Name            
                    Write-Host2 "No tenant selected, user profile will be created in current tenant $domain_name (ID $domain_id)"
                }
            }
            else {
                $domain = LinaTenantShort 6>$null | Where-Object { $_.Name -eq $Tenant }
                $domain_id = [int]$domain.ID
                $domain_name = [string]$domain.Name
                if ( !($domain_id -gt 0) ) {
                    Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant"
                    Return
                }
            }
                    
            $void = Set-LinaCurrentTenant -ID $domain_id 6>$null
            # Needs to clarify if ID of hierarchy can be anything else than 1 or not (<ID>1</ID>)

            $profilename_exists = Get-LinaUserProfile -Name $Name 6>$null
            if ($Null -ne $profilename_exists) {
                Write-Host2 "ERROR : A user profile already exists with this name ($Name) in this Tenant"
                Return
            }


            if ($LinaUserProfile) {
                $ObjectType = [string]$LinaUserProfile.GetType()
                if ($ObjectType -like "*PSCustomObject*") {
                    $item = $LinaUserProfile.PSObject.Properties
                    $role1 = 0
                    $role2 = 0
                    $role3 = 0
                    $role4 = 0
                    foreach ($param in $item) {
                        if ($ObjectType -like "*PSCustomObject*") {
                            $current_key = $($param.Name)
                            $current_value = $($param.Value)
                        }
                        else {
                            $current_key = $param.Key
                            $current_value = $param.Value
                        }
                        switch ($current_key) {
                            InternalRoles1 { $role1 = $current_value }
                            InternalRoles2 { $role2 = $current_value }
                            InternalRoles3 { $role3 = $current_value }
                            InternalRoles4 { $role4 = $current_value }
                        }
                    }
                    $name_enc = [System.Web.HttpUtility]::UrlEncode($Name)

                    $request = CallAPI -Path "/ADM/add_profile.json?name=$name_enc&roles1=$role1&roles2=$role2&roles3=$role3&roles4=$role4" -ContentType "application/json"
                    if ([string]$request -like "*[0]*") {
                        $userprofile_id = $request.id 
                        Write-Host2 "User Profile $Name successfully created (ID $userprofile_id)"
                                
                        $userprofile_created = Get-LinaUserProfile -ID $userprofile_id
                        # Setting back the current tenant to what it was before the New-LinaAgentGroup command
                        $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null
                        Return $userprofile_created
                    }
                    else {
                        TranslateErrorCode -LinaError $request -FailedAction "create user profile $Name"
                        # Setting back the current tenant to what it was before the New-LinaAgentGroup command
                        $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null
                        Return $null
                    } 
                }
                else {
                    Write-Host2 "ERROR : This method is not supported yet. Please provide an existing UserProfile as input : Get-LinaUserProfile | New-LinaUserProfile"
                    Return $null
                    #$item = $LinaUserProfile.GetEnumerator()
                }
            }
        }
    }
    END { }   
}


function New-LinaUser {
    <#
.SYNOPSIS
Creates a new user.
.DESCRIPTION
Creates a new user.
.INPUTS
None
.OUTPUTS
The new LinaUser Object
.PARAMETER Tenant
Optional : Name of the tenant where the user should be created.
If not provided, agent will be created in the current tenant.
In global view (no tenant selected), agent will be created in the default tena
.PARAMETER Name
Mandatory : Name for the user
.PARAMETER Password
Mandatory : Password for the user
.PARAMETER Disabled
Mandatory : Status of the user. Can be $True (Disabled) or $False (Enabled)
.PARAMETER UserGroup
Mandatory : User group (and user profile) for the user
Note : User group has to be in the same tenant as the user
.EXAMPLE
New-LinaUser -Name "MyUser" -Tenant "MyTenant" -Password "V3ryS3CuRe$" -UserGroup "Groupe d'utilisateurs administrateurs"
Creates a new user MyUser in Tenant MyTenant. By default, newly created users are enabled and can log in.
#>

    [cmdletbinding()]
    Param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [string]$Tenant, 
        [Parameter(Mandatory = $True)]
        [ValidateNotNullOrEmpty()]
        [string]$Password,
        [Parameter(Mandatory = $True)]
        [ValidateNotNullOrEmpty()]
        [string]$UserGroup
    )

        Write-Host2 "Creating a user $Name"
        if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
            Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
            return
        }

        $current_tenant_id = Get-LinaCurrentTenantID 6>$null
        if (!$Tenant) {
            if ($current_tenant_id -le 1) {
                # No current tenant (global view) => using default tenant
                $domain = LinaTenantShort 6>$null | Where-Object { $_.IsDefault } 
                if ($domain.ID -le 1) {
                    # No default Tenant ....
                    Write-Host2 "ERROR : There is no default tenant. Please select a tenant."
                    return 
                }
                $domain_id = [int]$domain.ID
                $domain_name = [string]$domain.Name
                Write-Host2 "No tenant selected, user will be created in default tenant $domain_name (ID $domain_id)"
            }
            else {
                # Using Current tenant
                $domain = Get-LinaTenant -ID (Get-LinaCurrentTenantID) 6>$null
                $domain_id = [int]$domain.ID
                $domain_name = [string]$domain.Name            
                Write-Host2 "No tenant selected, user will be created in current tenant $domain_name (ID $domain_id)"
            }
        }
        else {
            $domain = LinaTenantShort 6>$null | Where-Object { $_.Name -eq $Tenant }
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name
            if ( !($domain_id -gt 0) ) {
                Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant"
                Return
            }
        }
        $void = Set-LinaCurrentTenant -ID $domain_id 6>$null
        
        $user_group = Get-LinaUserGroup -Name $UserGroup
        if ($user_group) {
            $user_group_id = $user_group.ID
        }else {
            Write-Host2 "ERROR : No user group found with name ($UserGroup) in Tenant $domain_name. Please input the exact name of the user group"
            Return
        }

        $name_enc=[System.Web.HttpUtility]::UrlEncode($Name)
        $pass_enc=[System.Web.HttpUtility]::UrlEncode($Password)
        $request = CallAPI -Path "/ADM/add_user.json?user=$name_enc&pass=$pass_enc&type=1&ug_id=$user_group_id" -ContentType "application/json"
        
        # Setting back the current tenant to what it was before the New-LinaUser command
        
        if ($request.status -eq 0) {
            Write-Host2 "User $Name successfully created in Tenant $domain_name"
            $user_created = Get-LinaUser -ID $request.ID
            $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null
            Return $user_created
        }
        else {
            TranslateErrorCode -LinaError $request -FailedAction "create user $Name in Tenant $domain_name"
            Return $null
        }  
}

function New-LinaUserGroup {
    <#
.SYNOPSIS
Creates a new user group.
.DESCRIPTION
Creates a new user group.
.INPUTS
None
.OUTPUTS
The new LinaUserGroup Object
.PARAMETER Tenant
Optional : Name of the tenant where the user group should be created.
If not provided, user group will be created in the current tenant.
In global view (no tenant selected), agent will be created in the default tena
.PARAMETER Name
Mandatory : Name for the User Group
.PARAMETER UserProfile
Mandatory : User profile for the user
Note : User profile has to be in the same tenant as the user group
.EXAMPLE
New-LinaUserGroup -Name "MyUserGroup" -Tenant "MyTenant" -UserProfile "Profil administrateur"
Creates a new user groupe MyUserGroup in Tenant MyTenant using User Profile "Profil administrateur"
#>

    [cmdletbinding()]
    Param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $False)]
        [ValidateNotNullOrEmpty()]
        [string]$Tenant, 
        [Parameter(Mandatory = $True)]
        [ValidateNotNullOrEmpty()]
        [string]$UserProfile
    )

    Write-Host2 "Creating a user group $Name"
    if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
        Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
        return
    }

    if ($global:INT_LINA_API_VERSION -ge 61) {
        Write-Warning "This cmdlet is not yet supported in Lina 6.1+. Use Copy-LinaUserGroup instead." 
        return
    }
        $current_tenant_id = Get-LinaCurrentTenantID 6>$null
        if (!$Tenant) {
            if ($current_tenant_id -le 1) {
                # No current tenant (global view) => using default tenant
                $domain = LinaTenantShort 6>$null | Where-Object { $_.IsDefault } 
                if ($domain.ID -le 1) {
                    # No default Tenant ....
                    Write-Host2 "ERROR : There is no default tenant. Please select a tenant."
                    return 
                }
                $domain_id = [int]$domain.ID
                $domain_name = [string]$domain.Name
                Write-Host2 "No tenant selected, user group will be created in default tenant $domain_name (ID $domain_id)"
            }
            else {
                # Using Current tenant
                $domain = Get-LinaTenant -ID (Get-LinaCurrentTenantID) 6>$null
                $domain_id = [int]$domain.ID
                $domain_name = [string]$domain.Name            
                Write-Host2 "No tenant selected, user group will be created in current tenant $domain_name (ID $domain_id)"
            }
        }
        else {
            $domain = LinaTenantShort 6>$null | Where-Object { $_.Name -eq $Tenant }
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name
            if ( !($domain_id -gt 0) ) {
                Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant"
                Return
            }
        }
        $void = Set-LinaCurrentTenant -ID $domain_id 6>$null
        
        $user_profile = Get-LinaUserProfile -Name $UserProfile
        if ($user_profile) {
            $user_profile_id = $user_profile.ID
        }else {
            Write-Host2 "ERROR : No user profile found with name ($UserGroup) in Tenant $domain_name. Please input the exact name of the user profile"
            Return
        }

        $name_enc=[System.Web.HttpUtility]::UrlEncode($Name)
        $request = CallAPI -Path "/ADM/add_user_group.json?name=$name_enc" -ContentType "application/json"
        
        if ($request.status -eq 0) {
            $usergroup_id=$request.ID
            $request = CallAPI -Path "/ADM/attach_prof_to_ug.json?prof_id=$user_profile_id&ug_id=$usergroup_id" -ContentType "application/json"
            if ($request.status -eq 0) {
                Write-Host2 "User group $Name successfully created in Tenant $domain_name"
                $usergroup_created = Get-LinaUserGroup -ID $usergroup_id
                # Setting back the current tenant to what it was before the New- command
                $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null
                Return $usergroup_created
            }
            else {
                TranslateErrorCode -LinaError $request -FailedAction "attaching user group $Name to user profile $UserProfile in Tenant $domain_name"
                Return $null
            }  
        }
        else {
            TranslateErrorCode -LinaError $request -FailedAction "create user group $Name in Tenant $domain_name"
            Return $null
        }  
}

function New-LinaCrossRestoreToken {
<#
.SYNOPSIS
Creates a new cross restore token.
.DESCRIPTION
Creates a cross restore token code to access backups of an agent for define period.
.INPUTS
None
.OUTPUTS
The new LinaCrossRestoreToken Object
.PARAMETER AgentName
Mandatory : Name of the agent.
Note : this command currently supports only one agent at a time.
.PARAMETER ExpiresIn
Optional : Period of validity (provided as a valid TimeSpan).
Note : It must be less or equal to 1 year. If not provided, token will be valid forever.
.PARAMETER ExpirationDate
Optional : Expiration date for the token (provided as a valid Date).
Note : It must be a date no further than 1 year. If not provided, token will be valid forever.
.EXAMPLE
New-LinaCrossRestoreToken -AgentName "MyAgent"
Creates a new cross restore token valid forever for agent MyAgent
.EXAMPLE
$expire_in = New-TimeSpan -Hours 10
New-LinaCrossRestoreToken -AgentName "MyAgent" -ExpiresIn $expire_in
Creates a new cross restore token valid 10 hours for agent MyAgent
.EXAMPLE
$expdate = Get-Date -Year 2022 -Month 5 -Day 10
New-LinaCrossRestoreToken -AgentName "MyAgent" -ExpirationDate $expdate
Creates a new cross restore token valid until 2022/05/10 for agent MyAgent
#>
    
    [cmdletbinding()]
    Param(
        [Parameter(ParameterSetName = "NoExpiration",Mandatory = $true)]
        [Parameter(ParameterSetName = "ByExpiresIn",Mandatory = $true)]
        [Parameter(ParameterSetName = "ByExpirationDate",Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$AgentName,
        [Parameter(ParameterSetName = "ByExpiresIn",Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [timespan]$ExpiresIn,
        [Parameter(ParameterSetName = "ByExpirationDate",Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [datetime]$ExpirationDate
    )

        Write-Host2 "Creating a new cross restore tokens for Agent $AgentName"
        if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
            Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
            return
        }
        
        if ($global:INT_LINA_API_VERSION -lt 52 ) {
            Write-Host2 "ERROR : This feature is only available on Lina 5.2+"
            Return $Null
        }

        $current_tenant_id = Get-LinaCurrentTenantID 6>$null

        # Supports only one agent. AgentName is also unique across tenants
        $lina_agent = Get-LinaAgent -Name "$AgentName"
        if ($lina_agent.Count -gt 1 ) {
            # More than 1 agent
            Write-Host2 "ERROR : Multiple agents are not supported. Please provide a single agent name."
            Return
        }

        if ( !$lina_agent) {
            Write-Host2 "ERROR : No agent found with name $AgentName. Please input the exact name of the Agent"
            Return
        }
        
        # Validity should be provided as number of milliseconds from now
        if ($ExpiresIn) {
            # Validity is a period of time
            $validity_time = [math]::Truncate($ExpiresIn.TotalMilliseconds)
        }elseif ($ExpirationDate) {
             # Validity is a date
            $validity_time = [math]::Truncate((New-TimeSpan -End $ExpirationDate).TotalMilliseconds)
        }else {
            # No parameter = Valid forever
            $validity_time = 0
        }

        if ($validity_time -gt ((New-TimeSpan -Days 365).TotalMilliseconds)) {
            Write-Host2 "ERROR : Token validity cannot exceed one year."
            Return
        }

        if ($lina_agent.TenantID -ne $current_tenant_id) {
            # Need to switch to same tenant to be able to create the token
            $void = Set-LinaCurrentTenant -ID $lina_agent.TenantID 6>$null
        }

        $body = 'data=<?xml version="1.0" encoding="UTF-8"?><Params><ValidityTime>' + $validity_time + '</ValidityTime><AgentArray><Agent><ID>' + $lina_agent.ID + '</ID><Name>' + $lina_agent.Name + '</Name></Agent></AgentArray></Params>'
        $request = CallAPI -Path "/security_cross_newtoken.json" -ContentType "application/json" -Body $body

        if ($request.status -eq 0) {
            $token = Get-LinaCrossRestoreToken -ID $request.token.id
            $token
            Write-Host2 "SUCCESS : Cross Restore token $($token.Code) (ID $($token.ID)) created for agent $AgentName, Exp. Date : $($token.ExpirationDate) (in approx $($token.ExpiresIn))"
        }else {
            TranslateErrorCode -LinaError $request -FailedAction "create cross restore token for agent $AgentName with validity time = $validity_time"
        }
        $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null
}


function New-LinaTag {
<#
.SYNOPSIS
Creates a new tag
.DESCRIPTION
Creates a new tag with the provided name.
.INPUTS
None
.OUTPUTS
LinaTag Object
.PARAMETER Name
Name of the Tag to create
.PARAMETER Tenant
Optional : Name of the tenant where the tag should be created.
If not provided, tag will be created in the current tenant.
In global view (no tenant selected), tag will be created in the default tenant.
.PARAMETER Colors
Optional : Colors of the tag. First color is for text, second color is for background
Default value is #4c4c4c/#CDCDCD (dark grey on light grey)
.EXAMPLE
New-LinaTag -Name "MyTag" -Colors "#FFFFFF/#000000"
Creates a new tag named "MyTag" with white text and black background in default tenant
#>


    [cmdletbinding()]
    Param(
        [Parameter(Mandatory = $true, ParameterSetName = "Name", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory = $false, ParameterSetName = "Name", Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]$Tenant,        
        [Parameter(Mandatory = $false, ParameterSetName = "Name", Position = 1)]
        [ValidateNotNullOrEmpty()]
        [string]$Colors
    )

    if ($global:GLOBAL_LINA_CONNECTED -eq $False) { 
        Write-Error "$($global:GLOBAL_DISCONNNECTED_MESSAGE)" 
        return
    }

    if ($global:INT_LINA_API_VERSION -lt 60) {
        Write-Host2 "WARNING : Tags are not available in Lina versions below 6.0."
        Return
    }

    $current_tenant_id = Get-LinaCurrentTenantID 6>$null
    if (!$Tenant) {
        if ($current_tenant_id -le 1) {
            # No current tenant (global view) => using default tenant
            $domain = LinaTenantShort 6>$null | Where-Object { $_.IsDefault } 
            if ($domain.ID -le 1) {
                # No default Tenant ....
                Write-Host2 "ERROR : There is no default tenant. Please select a tenant."
                return 
            }
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name
            Write-Host2 "No tenant selected, agent will be created in default tenant $domain_name (ID $domain_id)"
        }
        else {
            # Using Current tenant
            $domain = Get-LinaTenant -ID (Get-LinaCurrentTenantID) 6>$null
            $domain_id = [int]$domain.ID
            $domain_name = [string]$domain.Name            
            Write-Host2 "No tenant selected, agent will be created in current tenant $domain_name (ID $domain_id)"
        }
    }
    else {
        $domain = LinaTenantShort 6>$null | Where-Object { $_.Name -eq $Tenant }
        $domain_id = [int]$domain.ID
        $domain_name = [string]$domain.Name
        if ( !($domain_id -gt 0) ) {
            Write-Host2 "ERROR : No tenant found with name $Tenant. Please input the exact name of the Tenant"
            Return
        }
    }

    $void = Set-LinaCurrentTenant -ID $domain_id 6>$null

    if ($Colors) {
        $tag_colors=$Colors
        Write-Host2 "Creating a new Lina Tag with name $Name and colors $tag_colors"
    }else {
        $tag_colors="#4c4c4c/#CDCDCD"
        Write-Host2 "Creating a new Lina Tag with name $Name and default colors ($tag_colors)"
    }

    $name_enc = [System.Web.HttpUtility]::UrlEncode($Name)
    $colors_enc = [System.Web.HttpUtility]::UrlEncode($tag_colors)
    $request = CallAPI -Path "/ADE/tag/add.json?name=$name_enc&color=$colors_enc" -Method Get

    # Setting back the current tenant to what it was before the New-LinaTag command
    $void = Set-LinaCurrentTenant -ID $current_tenant_id 6>$null

    if ([string]$request -like "*[0]*") {
        $tag_id=$request.id
        Write-Host2 "Tag $Name successfully created (ID $tag_id)"
        $tag_created = Get-LinaTag -ID $tag_id
        Return $tag_created
    }else {
        TranslateErrorCode -LinaError $request -FailedAction "create tag $Name"
        Return $null
    }    
}