source/Public/New-RJTenant.ps1

function New-RJTenant {
    <#
    .SYNOPSIS
    Creates a new RealmJoin tenant by creating the necessary service principals and assigning mandatory Microsoft Graph permissions.
 
    .DESCRIPTION
    This cmdlet creates or updates service principals for the RealmJoin application and assigns the mandatory
    Microsoft Graph permissions based on selected features. Mandatory features are always enabled.
 
    .PARAMETER Features
    Optional array of feature names to enable. Available features can be viewed using Show-RJFeatureInfo.
    Mandatory features are automatically included and don't need to be specified.
    Default: @('IntuneLAPS', 'ShowSignin', 'Autopilot', 'DeviceIntuneActions', 'DeviceHealthScript')
    Use @() to enable only mandatory features.
    Cannot be used together with the -All parameter.
 
    .PARAMETER All
    When specified, enables all available features (both mandatory and optional).
    Cannot be used together with the -Features parameter.
 
    .PARAMETER ReadOnly
    When specified, assigns read-only permissions instead of full permissions where available.
    For example, Group.ReadWrite.All becomes Group.Read.All.
 
    .PARAMETER Token
    Optional token for RealmJoin customer API integration. When provided, sends the configured
    optional features to the RealmJoin customer API after successful tenant configuration.
 
    .PARAMETER WhatIf
    Shows what would be done without actually performing the tenant creation.
 
    .EXAMPLE
    New-RJTenant
    Creates the tenant with mandatory features plus default optional features (all features except Client).
 
    .EXAMPLE
    New-RJTenant -Features @()
    Creates the tenant with only mandatory features.
 
    .EXAMPLE
    New-RJTenant -Features @('DeviceHealthScript')
    Creates the tenant with mandatory features plus only DeviceHealthScript.
 
    .EXAMPLE
    New-RJTenant -All
    Creates the tenant with all available features enabled.
 
    .EXAMPLE
    Show-RJFeatureInfo; New-RJTenant -Features @('DeviceHealthScript')
    Shows available features first, then creates tenant with selected features.
 
    .EXAMPLE
    New-RJTenant -ReadOnly
    Creates the tenant with default features but using read-only permissions where possible.
 
    .EXAMPLE
    New-RJTenant -All -ReadOnly
    Creates the tenant with all available features enabled using read-only permissions.
 
    .EXAMPLE
    New-RJTenant -WhatIf
    Shows what permissions would be assigned without actually doing it.
 
    .EXAMPLE
    New-RJTenant -Features @('DeviceHealthScript') -Verbose
    Creates tenant with detailed verbose output showing the creation process.
 
    .EXAMPLE
    New-RJTenant -Token "abc123"
    Creates the tenant with default features and sends configuration to RealmJoin customer API.
 
    .NOTES
    This cmdlet requires appropriate Azure AD permissions to create service principals and assign app roles.
    Mandatory features are always enabled regardless of the Features parameter.
    Use either -Features or -All, but not both.
    The -ReadOnly switch applies to all selected features and uses ReadOnlyPermissions where available.
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [string[]]$Features = $DefaultSelectedFeatures,
        [switch]$All,
        [switch]$ReadOnly,
        [string]$Token
    )

    begin {
        Write-Verbose "Configuring new RealmJoin tenant"
    }

    process {
        Write-Information "Initializing required modules"
        if (-not (Initialize-RequiredModule)) {
            # Modules are not ready - exit gracefully without throwing
            Write-Verbose "Module initialization failed - function cannot proceed"
            return
        }
        Write-Information "All required modules are initialized"

        Write-Information "Logging in"
        $null = Invoke-GraphLogin

        Write-Information "Getting tenant information"
        $tenantInfo = Get-TenantInfo
        Write-Information "Tenant: $($tenantInfo.DisplayName) ($($tenantInfo.TenantId))"

        # Determine which features to enable
        if ($All) {
            $selectedFeatures = (Get-RJFeatureDefinitionList).Name
            Write-Verbose "Using -All switch: enabling all available features"
        }
        else {
            $selectedFeatures = $Features
            Write-Verbose "Using specified features: $($Features -join ', ')"
        }

        $featureResolution = Resolve-RJFeature -SelectedFeatures $selectedFeatures -ReadOnly:$ReadOnly
        $permissionMode = if ($ReadOnly) { "read-only" } else { "full" }
        Write-Information "Selected features: $($featureResolution.FeatureNames -join ', ') with $permissionMode permissions"

        if ($PSCmdlet.ShouldProcess("Tenant: $($tenantInfo.DisplayName) ($($tenantInfo.TenantId))")) {
            $results = Set-RJTenantServicePrincipal -FeatureResolution $featureResolution

            if (-not $results.Success) {
                throw "Failed to configure RealmJoin tenant"
            }

            # Send token to customer API if provided
            if ($Token) {
                $optionalFeatures = $featureResolution.FeatureNames | Where-Object { $_ -notin (Get-RJMandatoryFeatureList).Name }
                Invoke-RJTenantRefresh -Token $Token -OptionalFeatures $optionalFeatures
            }

            # Open RealmJoin Portal if new service principal was created
            Open-RJPortalIfNewServicePrincipal -ProcessedApps $results.ProcessedApps

            # Final summary
            Write-Information ""
            Write-Information "=== Summary ==="
            Write-Information "Successfully configured RealmJoin tenant with $($results.FeatureResolution.FeatureNames.Count) features using $permissionMode permissions"
            Write-Information "Enabled features: $($results.FeatureResolution.FeatureNames -join ', ')"
        }
        else {
            Write-Verbose "Getting analysis for all service principals"
            $analysis = Get-RJTenantPermissionAnalysis -FeatureResolution $featureResolution
            Show-RJFeatureAnalysis -FeatureAnalysis $analysis.FeatureAnalysis -OrphanedServicePrincipals $analysis.OrphanedServicePrincipals
        }
    }

    end {
        Write-Verbose "RealmJoin tenant configuration completed"
    }
}