Public/cloud-user.ps1

# Define aliases
Set-Alias -Name Remove-CloudGroupUser -value Remove-CloudUserGroupMembership
Set-Alias -Name Add-CloudGroupUser -value New-CloudUserGroupMembership

function Get-CloudUser {
    <#
    .SYNOPSIS
        Gets users from the Cloud Server.
     
    .DESCRIPTION
        Retrieves a list of users. Automatically handles token refresh.
     
    .PARAMETER Name
        Optional. Filter by username.
 
    .PARAMETER ID
        Optional. Filter by ID.
     
    .EXAMPLE
        # Get all users
        Get-CloudUser
         
    .EXAMPLE
        # Get users matching a specific name string
        Get-CloudUser -Name "admin"
 
    .EXAMPLE
        # Get a specific user by ID
        Get-CloudUser -ID 561
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false)]
        [string]$Name,
        
        [Parameter(Mandatory = $false)]
        [int]$ID
    )
    
    # Build the URI - adjust this to match your actual API endpoint
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user"
    
    # Use the helper function which handles token refresh automatically
    $response = Invoke-CloudApiRequest -Uri $uri -Method Get
    
    # Extract instances from the response
    $users = $response.users
    
    # Filter by name if specified
    if ($Name) {
        $users = $users | Where-Object { $_.name -like "*$Name*" }
    }
    
    # Filter by ID if specified - use PSBoundParameters to check if parameter was provided
    elseif ($PSBoundParameters.ContainsKey('ID')) {
            $users = $users | Where-Object { ($_.id -eq $ID) -and ($null -ne $_.id) }
    }
    
    return $users
}

function Get-CloudUserQuota {
    <#
    .SYNOPSIS
        Gets default user quota from the Cloud Server.
     
    .DESCRIPTION
        Retrieves the default user quota. Automatically handles token refresh.
     
    .EXAMPLE
        # Get the default user quota
        Get-CloudUserQuota
         
    #>

        
    # Build the URI - adjust this to match your actual API endpoint
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/quota"
    
    # Use the helper function which handles token refresh automatically
    $response = Invoke-CloudApiRequest -Uri $uri -Method Get
    
    # Extract instances from the response
    $quota = $response
        
    return $quota
}

function New-CloudUser {
    <#
    .SYNOPSIS
        Creates a user on the Cloud Server.
         
    .DESCRIPTION
        Creates a new cloud user. Automatically handles token refresh.
     
    .PARAMETER Username
        Required. Name of the user to be created
         
    .PARAMETER Password
        Required. Password of the user to be created
         
    .PARAMETER AuthDriver
        Optional. Auth source - defaults to core, can specify LDAP
         
    .PARAMETER GroupIDs
        Optional. Group IDs to which this new user will be a member : "-GroupIDs @(2, 3)"
     
    .EXAMPLE
        # Create a basic user with just username and password
        New-CloudUser -Username "jdoe" -Password "SecureP@ssw0rd"
         
    .EXAMPLE
        # Create a user and add them to specific groups
        New-CloudUser -Username "jsmith" -Password "SecureP@ssw0rd" -GroupIDs @(1, 5, 10)
 
    .EXAMPLE
        # Create a user with a specific authentication driver
        New-CloudUser -Username "bjones" -Password "SecureP@ssw0rd" -AuthDriver "ldap"
 
    .EXAMPLE
        # Create a user with all options
        New-CloudUser -Username "asmith" -Password "SecureP@ssw0rd" -AuthDriver "ldap" -GroupIDs @(2, 3)
    #>


    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='Medium')]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Username,
        
        [Parameter(Mandatory = $true)]
        [string]$Password,
        
        [Parameter(Mandatory = $false)]
        [string]$AuthDriver,
        
        [Parameter(Mandatory = $false)]
        [int[]]$GroupIDs
    )
    
    process {
        # Build the user object
        $body = @{
            username = $Username
            password = $Password
        }
        
        # Add optional parameters if provided
        if ($PSBoundParameters.ContainsKey('AuthDriver')) {
            $body['auth'] = $AuthDriver
        }
        
        if ($PSBoundParameters.ContainsKey('GroupIDs')) {
            $body['gids'] = $GroupIDs
        }
        
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user"
        
        if ($PSCmdlet.ShouldProcess("User '$Username'", "Create new user")) {
            try {
                $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $body
                
                Write-Verbose "Successfully created user '$Username' with ID: $($response.id)"
                # Return the newly created user
                Get-CloudUser -ID $response.user
            }
            catch {
                Write-Error "Failed to create user '$Username': $_"
                throw
            }
        }
    }
}

function Remove-CloudUser {
    <#
    .SYNOPSIS
        Removes a user from the Cloud Server.
     
    .DESCRIPTION
        Removes a user. Automatically handles token refresh.
     
    .PARAMETER ID
        Required. User ID.
     
    .EXAMPLE
        # Remove user with confirmation prompt (default behavior):
        Remove-CloudUser -ID 3
        Confirm
        Are you sure you want to perform this action?
        Performing the operation "Remove User" on target "User ID 3 (MyUser)".
        [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y
 
    .EXAMPLE
        # Remove user without confirmation prompt:
        Remove-CloudUser -ID 3 -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$ID
    )
    
    process {
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}"
        
        Invoke-CloudResourceRemoval `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "User" `
            -ID $ID `
            -Uri $uri `
            -GetResourceScript { Get-CloudUser -ID $ID }
    }
}

function New-CloudUserLoginToken {
    <#
    .SYNOPSIS
        Creates a new user login token on the Cloud Server.
         
    .DESCRIPTION
        Creates a new login token for a user. Automatically handles token refresh.
     
    .PARAMETER Username
        Required. Name of the user
         
    .PARAMETER Token
        Optional. Token to be set for the user. If blank, will generate a token.
         
    .PARAMETER Duration
        Required. Duration in seconds of the validity for the token
         
    .PARAMETER GroupID
        Required. ID of the group
     
    .EXAMPLE
        # Generate a new token for jsmith valid for 5 minutes
         New-CloudUserLoginToken -username jsmith -duration 300 -GroupID 1
         
    .EXAMPLE
        # Create a specific token for jsmith, valid for 24 hours
         New-CloudUserLoginToken -username jsmith -duration 86400 -GroupID 1 -token ff1c8f3753d842c8355f3f1672ae7720804585a73c537745a92b7c7ce9772f12
    #>


    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='Medium')]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Username,
        
        [Parameter(Mandatory = $false)]
        [string]$Token,
        
        [Parameter(Mandatory = $True)]
        [int]$Duration,
        
        [Parameter(Mandatory = $True)]
        [int]$GroupID
    )
    
    process {
        # Build the user object

if ($token) {
$body = @{
  duration = $Duration
  group = $GroupID
  token = $Token
  username = $Username
  }
}
else {
$body = @{
  duration = $Duration
  group = $GroupID
  username = $Username
}
}
        
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/login"
        
        if ($PSCmdlet.ShouldProcess("User '$Username'", "Create login token")) {
            try {
                $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $body
                
                Write-Verbose "Successfully created user token for '$Username': $($response.id)"
                Write-Host "Successfully created user token for $Username" -ForegroundColor Cyan
                Write-Host $response.token -ForegroundColor Cyan
            }
            catch {
                Write-Error "Failed to create user '$Username': $_"
                throw
            }
        }
    }
}

function Disable-CloudUser {
    <#
    .SYNOPSIS
        Disables a user from the Cloud Server.
     
    .DESCRIPTION
        Disables a user. Automatically handles token refresh.
     
    .PARAMETER Name
        Required. User ID.
     
    .EXAMPLE
        # Disable user with confirmation prompt (default behavior):
        Disable-CloudUser -ID 3
        Confirm
        Are you sure you want to perform this action?
        Performing the operation "Disable User" on target "User ID 3 (MyUser)".
        [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y
 
    .EXAMPLE
        # Disable user without confirmation prompt:
        Disable-CloudUser -ID 3 -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$ID
    )
    
    process {
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}/enable"
$body = @{
  enable = $false
}
          $actionParts = @("Disable user $UserID")
        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "User" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action "Disable" `
            -GetResourceScript { Get-CloudUser -ID $ID } `
            -SuccessMessage "User $ID disabled successfully."
    }
}

function Enable-CloudUser {
    <#
    .SYNOPSIS
        Enables a user from the Cloud Server.
     
    .DESCRIPTION
        Enables a user. Automatically handles token refresh.
     
    .PARAMETER Name
        Required. User ID.
     
    .EXAMPLE
        # Enable user with confirmation prompt (default behavior):
        Enable-CloudUser -ID 3
        Confirm
        Are you sure you want to perform this action?
        Performing the operation "Enable User" on target "User ID 3 (MyUser)".
        [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y
 
    .EXAMPLE
        # Enable user without confirmation prompt:
        Enable-CloudUser -ID 3 -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$ID
    )
    
    process {
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}/enable"
$body = @{
  enable = $true
}
        $Action = "update"
        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "User" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action "Ensable" `
            -GetResourceScript { Get-CloudUser -ID $ID } `
            -SuccessMessage "User $ID enabled successfully."
    }
}

function Add-CloudUserGroupMembership {
    <#
    .SYNOPSIS
        Adds a user to a secondary group on the Cloud Server.
     
    .DESCRIPTION
        Adds a user to a secondary group. Automatically handles token refresh.
     
    .PARAMETER User
        ID of the user
         
    .PARAMETER ID
        ID of the group
             
    .EXAMPLE
        # Adds user 12 to group 104
        Add-CloudUserGroupMembership -id 104 -user 12
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [int]$User,
        
        [Parameter(Mandatory = $true)]
        [int]$ID
    )
        
    $newgroup= @{
        user = $User
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${User}/group/${ID}"
       
    $response = Invoke-CloudApiRequest -Uri $uri -Method POST -Body $newgroup
    
    return $response
}

function Remove-CloudUserGroupMembership {
    <#
    .SYNOPSIS
        Removes a user from a group on the Cloud Server.
     
    .DESCRIPTION
        Removes a user from a group. Automatically handles token refresh.
     
    .PARAMETER ID
        Required. User ID.
     
    .EXAMPLE
        # Remove user from group with confirmation prompt (default behavior):
        Remove-CloudUserGroupMembership -ID 102 -User 12
        Confirm
        Are you sure you want to perform this action?
        Performing the operation "Remove User" on target "User ID 3 (MyUser)".
        [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y
 
    .EXAMPLE
        # Remove user without confirmation prompt:
        Remove-CloudUserGroupMembership -ID 102 -User 12 -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$ID,
        
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$User
    )
    
    process {
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${User}/group/${ID}"
        
        Invoke-CloudResourceRemoval `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "Membership of user" `
            -ID $User `
            -Uri $uri 
# -GetResourceScript { Get-Clouduser -ID $User }
    }
}

function Update-CloudUserQuota {
    <#
    .SYNOPSIS
        Updates the user quota limits on the Cloud Server.
     
    .DESCRIPTION
        Updates quota limits for the specified user. You can update instance quotas,
        datastore quotas, and network quotas. Automatically handles token refresh.
         
    .PARAMETER InstanceQuota
        Optional. Hashtable containing instance quota limits (cpu, memory, running_cpu, running_memory,
        running_instances, system_disk_size, instances).
         
    .PARAMETER DatastoreQuota
        Optional. Hashtable containing datastore quota limits.
         
    .PARAMETER NetworkQuota
        Optional. Hashtable containing network quota limits.
     
    .PARAMETER ID
        Required. ID of the user
         
    .EXAMPLE
        # Update the instance quota of a user
        Update-CloudUserQuota -id 12 -InstanceQuota @{
            cpu = 100
            memory = 204800
            running_cpu = 50
            running_memory = 102400
            running_instances = 10
            system_disk_size = 1000000
            instances = 20
        }
    #>

    
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)]
        [int]$ID,
    
        [Parameter()]
        [hashtable]$InstanceQuota,
        
        [Parameter()]
        [hashtable]$DatastoreQuota,
        
        [Parameter()]
        [hashtable]$NetworkQuota
    )
    
    # Build the template string in OpenNebula format
    $templateLines = @()
    
    if ($InstanceQuota) {
        $quotaItems = $InstanceQuota.GetEnumerator() | ForEach-Object { 
            " $($_.Key.ToUpper()) = `"$($_.Value)`"" 
        }
        $templateLines += "INSTANCE_QUOTA = ["
        $templateLines += $quotaItems -join ",`n"
        $templateLines += "]"
    }
    
    if ($DatastoreQuota) {
        $quotaItems = $DatastoreQuota.GetEnumerator() | ForEach-Object { 
            " $($_.Key.ToUpper()) = `"$($_.Value)`"" 
        }
        $templateLines += "DATASTORE_QUOTA = ["
        $templateLines += $quotaItems -join ",`n"
        $templateLines += "]"
    }
    
    if ($NetworkQuota) {
        $quotaItems = $NetworkQuota.GetEnumerator() | ForEach-Object { 
            " $($_.Key.ToUpper()) = `"$($_.Value)`"" 
        }
        $templateLines += "NETWORK_QUOTA = ["
        $templateLines += $quotaItems -join ",`n"
        $templateLines += "]"
    }
    
    if ($templateLines.Count -eq 0) {
        Write-Error "At least one quota type must be specified (InstanceQuota, DatastoreQuota, or NetworkQuota)"
        return
    }
    
    $templateString = $templateLines -join "`n"
    
    # Create body hashtable
    $body = @{
        template = $templateString
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}/quota"
    
    if ($PSCmdlet.ShouldProcess("Default user quota", "Update")) {
        $response = Invoke-CloudApiRequest -Uri $uri -Method POST -Body $body
        return $response.quota
    }
}

function Update-CloudUserGroupMembership {
    <#
    .SYNOPSIS
        Changes the user's default group on the Cloud Server.
     
    .DESCRIPTION
        Changes the user's default group. Automatically handles token refresh.
     
    .PARAMETER User
        Required. ID of the user
         
    .PARAMETER ID
        Required. ID of the group
             
    .EXAMPLE
        # Updates the primary group of user 12 to group 104
        Update-CloudUserGroupMembership -id 104 -user 12
         
    .EXAMPLE
        # Updates the primary group of user 12 to group 104 without confirmation
        Update-CloudUserGroupMembership -id 104 -user 12 -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true)]
        [int]$User,
        
        [Parameter(Mandatory = $true)]
        [int]$ID
    )
    
    $body= @{
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${User}/group/${ID}"

    Invoke-CloudResourceUpdate `
        -CallerPSCmdlet $PSCmdlet `
        -ResourceType "User Group" `
        -ID $ID `
        -Uri $uri `
        -Body $body `
        -Action "Update" `
        -GetResourceScript { Get-CloudUser -ID $User }
}

function Update-CloudUserPassword {
    <#
    .SYNOPSIS
        Changes the user's authentication driver and password on the Cloud Server.
 
    .DESCRIPTION
        Changes the user's authentication driver and password. Automatically handles token refresh, clears value of $Password after running.
     
    .PARAMETER ID
        Required. ID of the user
         
    .PARAMETER Password
        Required. The new password
             
    .EXAMPLE
        # Updates the auth driver of user 12 to ldap
        Update-CloudUserPassword -id 12 -Password $Password -Driver ldap
         
    .EXAMPLE
        # Updates the password of user 12 without confirmation
        Update-CloudUserPassword -id 12 -Password $Password -Confirm:$false
 
    .EXAMPLE
        # Pipe SecureString password through directly without storing in variable and update user's password
        Read-Host -AsSecureString -Prompt "Enter password" | Update-CloudUserPassword -ID 12 -Driver ldap -Confirm:$false
         
    .EXAMPLE
        # Prompt for the new user password for user 12 and change it without confirmation
        $Password = Read-Host -AsSecureString -Prompt "Enter password"
        Update-CloudUserPassword -id 12 -Password $Password -Confirm:$false
 
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
        [object]$Password,
        
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)]
        [int]$ID
    )
    
    if ($Password -is [SecureString]) {
    write-verbose "Using Secure Password"
    # Convert SecureString to plain text only when needed
    $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
        [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
    )

    }
    else {
    write-verbose "Using Plaintext Password"
    }
    
    $body= @{
        password=$password
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}/password"
           
    Invoke-CloudResourceUpdate `
        -CallerPSCmdlet $PSCmdlet `
        -ResourceType "User Password" `
        -ID $ID `
        -Uri $uri `
        -Body $body `
        -Action "Update" `
        -GetResourceScript { Get-CloudUser -ID $ID }
        
    $global:password = $null
}

function Update-CloudUserAuth {
    <#
    .SYNOPSIS
        Changes the user's authentication driver and password on the Cloud Server.
 
    .DESCRIPTION
        Changes the user's authentication driver and password. Automatically handles token refresh.
     
    .PARAMETER ID
        Required. ID of the user
         
    .PARAMETER Driver
        Required. The desired authentication driver (typically core or ldap)
 
    .PARAMETER Password
        Required. The new password
             
    .EXAMPLE
        # Updates the auth driver of user 12 to ldap and uses a previously defined variable to set the password
        Update-CloudUserAuth -id 12 -Password $Password -Driver ldap
         
    .EXAMPLE
        # Updates the auth driver of 12 to core and sets the password to "Password123!", without confirmation
        Update-CloudUserAuth -id 12 -Password "Password123!" -Driver core -Confirm:$false
         
    .EXAMPLE
        # Pipe SecureString password through directly without storing in variable and update user's password and auth driver to ldap
        Read-Host -AsSecureString -Prompt "Enter password" | Update-CloudUserAuth -ID 12 -Driver ldap -Confirm:$false
         
    .EXAMPLE
        # Prompt for the new user password for user 12, and set the password and driver to core without confirmation
        $Password = Read-Host -AsSecureString -Prompt "Enter password"
        Update-CloudUserAuth -id 12 -Password $Password -Driver core -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
        [object]$Password,
        
        [Parameter(Mandatory = $true)]
        [string]$driver,
        
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)]
        [int]$ID
    )
    
    if ($Password -is [SecureString]) {
    write-verbose "Using Secure Password"
    # Convert SecureString to plain text only when needed
    $Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
        [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
    )

    }
    else {
    write-verbose "Using Plaintext Password"
    }
    $body= @{
        password=$Password
        driver=$Driver
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}/auth"
           
        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "User Auth Source" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action "Update" `
            -GetResourceScript { Get-CloudUser -ID $ID }
            
    $global:password = $null
}

function Update-CloudUser {
    <#
    .SYNOPSIS
        Updates a user on the Cloud Server.
     
    .DESCRIPTION
        Updates a user's template. You can choose to merge with the existing template
        or replace it entirely. Merge is enabled by default. Automatically handles token refresh.
         
    .PARAMETER ID
        Required. ID of the user to update.
         
    .PARAMETER Template
        Required. Template content for the user in OpenNebula format.
         
    .PARAMETER Merge
        Optional. If true (default), merges with existing template. If false, replaces the template entirely.
        Use -Merge:$false to completely replace the user configuration.
         
    .EXAMPLE
        # Update user's SSH public key (merge with existing)
        $template = 'SSH_PUBLIC_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB... user@host"'
        Update-CloudUser -ID 5 -Template $template
         
    .EXAMPLE
        # Update user's language preference
        $template = 'LANG="es"'
        Update-CloudUser -ID 5 -Template $template
         
    .EXAMPLE
        # Update multiple user preferences
        $template = @"
LANG="en"
SCHEME="light"
DISABLE_ANIMATIONS="true"
"@
        Update-CloudUser -ID 5 -Template $template
         
    .EXAMPLE
        # Replace entire user template
        $template = @"
LANG="en"
SCHEME="dark"
DISABLE_ANIMATIONS="false"
SSH_PUBLIC_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB... user@host"
"@
        Update-CloudUser -ID 5 -Template $template -Merge:$false
         
    .EXAMPLE
        # Add custom user attributes
        $template = @"
DEPARTMENT="IT"
COST_CENTER="12345"
MANAGER="John Doe"
"@
        Update-CloudUser -ID 10 -Template $template
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)]
        [int]$ID,
        
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$Template,
        
        [Parameter()]
        [bool]$Merge = $true
    )
    
    process {

        $body = @{
            merge = $Merge
            template = $Template
        }
        
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}"
            Write-Verbose "Request URI: $uri"
            Write-Verbose "Merge: $Merge"
            Write-Verbose "Template:`n$Template"
            

        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "User" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action "Update" `
            -GetResourceScript { Get-CloudUser -ID $ID }
        Write-Verbose "Successfully updated user ID: $ID"
    }
}

function Enable-CloudUserRGW {
    <#
    .SYNOPSIS
        Enables RGW access for a user on the Cloud Server.
     
    .DESCRIPTION
        Enables RGW access for a user. Automatically handles token refresh.
         
    .PARAMETER ID
        Required. ID of the user to update.
         
    .PARAMETER Confirm
        Optional. Defaults to requiring confirmation. Use -Confirm:$false to skip prompt
         
    .EXAMPLE
        # Enable RGW attributes for user 30
        Enable-CloudUserRGW -ID 30
         
    .EXAMPLE
        # Enable RGW attributes for user 30 without confirmation
        Enable-CloudUserRGW -ID 30 -confirm:$false
         
    .EXAMPLE
        # Enable RGW attributes for a piped-through user without confirmation
        Get-CloudUser -Name "New-Tenant-admin" | Enable-CloudUserRGW -confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)]
        [int]$ID

    )
    
    process {
        $rgwtemplate = "RADOSGW = true"
        $body = @{
            merge = $true
            template = $rgwtemplate
        }
        
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}"

        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "User" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action "Enable RGW" `
            -GetResourceScript { Get-CloudUser -ID $ID }
        Write-Verbose "Successfully updated user ID: $ID"
    }
}

function Disable-CloudUserRGW {
    <#
    .SYNOPSIS
        Disables RGW access for a user on the Cloud Server.
     
    .DESCRIPTION
        Disables RGW access for a user. Automatically handles token refresh.
         
    .PARAMETER ID
        Required. ID of the user to update.
         
    .PARAMETER Confirm
        Optional. Defaults to requiring confirmation. Use -Confirm:$false to skip prompt
         
    .EXAMPLE
        # Disable RGW attributes for user 30
        Disable-CloudUserRGW -ID 30
         
    .EXAMPLE
        # Disable RGW attributes for user 30 without confirmation
        Disable-CloudUserRGW -ID 30 -confirm:$false
         
    .EXAMPLE
        # Disable RGW attributes for a piped-through user without confirmation
        Get-CloudUser -Name "New-Tenant-admin" | Disable-CloudUserRGW -confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)]
        [int]$ID

    )
    
    process {
        $rgwtemplate = "RADOSGW = false"
        $body = @{
            merge = $true
            template = $rgwtemplate
        }
        
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/user/${ID}"

        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "User" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action "Disable RGW" `
            -GetResourceScript { Get-CloudUser -ID $ID }
        Write-Verbose "Successfully updated user ID: $ID"
    }
}