diff --git a/module/Entra/Microsoft.Entra/Users/Get-EntraInactiveSignInUser.ps1 b/module/Entra/Microsoft.Entra/Users/Get-EntraInactiveSignInUser.ps1 new file mode 100644 index 000000000..53d72f909 --- /dev/null +++ b/module/Entra/Microsoft.Entra/Users/Get-EntraInactiveSignInUser.ps1 @@ -0,0 +1,78 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +# ------------------------------------------------------------------------------ + +function Get-EntraInactiveSignInUser { + [CmdletBinding()] + [OutputType([string])] + param ( + # User Last Sign In Activity is before Days ago + [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 1)] + [Alias("BeforeDaysAgo")] + [int] $LastSignInBeforeDaysAgo = 30, + # Return results for All, Member, or Guest userTypes + [ValidateSet("All", "Member", "Guest")] + [string] + $UserType = "All" + ) + + process { + $customHeaders = New-EntraCustomHeaders -Command $MyInvocation.MyCommand + $queryDate = (Get-Date).AddDays(-$LastSignInBeforeDaysAgo).ToString("yyyy-MM-ddTHH:mm:ssZ") + $inactiveFilter = "(signInActivity/lastSignInDateTime le $queryDate)" + + $uri = "/v1.0/users?`$filter=$inactiveFilter&`$select=signInActivity,UserPrincipalName,Id,DisplayName,mail,userType,createdDateTime,accountEnabled" + + Write-Debug ("Retrieving Users with Filter {0}" -f $inactiveFilter) + $queryUsers = (Invoke-GraphRequest -Method GET -Uri $uri -Headers $customHeaders).value + + switch ($UserType) { + "Member" { $users = $queryUsers | Where-Object { $_.userType -eq 'Member' } } + "Guest" { $users = $queryUsers | Where-Object { $_.userType -eq 'Guest' } } + "All" { $users = $queryUsers } + } + + foreach ($userObject in $users) { + $checkedUser = [ordered] @{ + UserID = $userObject.Id + DisplayName = $userObject.DisplayName + UserPrincipalName = $userObject.UserPrincipalName + Mail = $userObject.Mail + UserType = $userObject.UserType + AccountEnabled = $userObject.AccountEnabled + } + + If ($null -eq $userObject.signInActivity.LastSignInDateTime) { + $checkedUser["LastSignInDateTime"] = "Unknown" + $checkedUser["LastSigninDaysAgo"] = "Unknown" + $checkedUser["lastNonInteractiveSignInDateTime"] = "Unknown" + } + else { + $checkedUser["LastSignInDateTime"] = $userObject.signInActivity.LastSignInDateTime + $checkedUser["LastSigninDaysAgo"] = (New-TimeSpan -Start $checkedUser.LastSignInDateTime -End (Get-Date)).Days + $checkedUser["lastSignInRequestId"] = $userObject.signInActivity.lastSignInRequestId + + If ($null -eq $userObject.signInActivity.lastNonInteractiveSignInDateTime) { + $checkedUser["lastNonInteractiveSignInDateTime"] = "Unknown" + $checkedUser["LastNonInteractiveSigninDaysAgo"] = "Unknown" + } else { + $checkedUser["lastNonInteractiveSignInDateTime"] = $userObject.signInActivity.lastNonInteractiveSignInDateTime + $checkedUser["LastNonInteractiveSigninDaysAgo"] = (New-TimeSpan -Start $checkedUser.lastNonInteractiveSignInDateTime -End (Get-Date)).Days + $checkedUser["lastNonInteractiveSignInRequestId"] = $userObject.signInActivity.lastNonInteractiveSignInRequestId + } + } + + If ($null -eq $userObject.CreatedDateTime) { + $checkedUser["CreatedDateTime"] = "Unknown" + $checkedUser["CreatedDaysAgo"] = "Unknown" + } + else { + $checkedUser["CreatedDateTime"] = $userObject.CreatedDateTime + $checkedUser["CreatedDaysAgo"] = (New-TimeSpan -Start $userObject.CreatedDateTime -End (Get-Date)).Days + } + + Write-Output ([PSCustomObject]$checkedUser) + } + } +} + diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Users/Get-EntraBetaInactiveSignInUser.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Users/Get-EntraBetaInactiveSignInUser.ps1 new file mode 100644 index 000000000..50149b5a8 --- /dev/null +++ b/module/EntraBeta/Microsoft.Entra.Beta/Users/Get-EntraBetaInactiveSignInUser.ps1 @@ -0,0 +1,79 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +# ------------------------------------------------------------------------------ + +function Get-EntraBetaInactiveSignInUser { + [CmdletBinding()] + [OutputType([string])] + param ( + # User Last Sign In Activity is before Days ago + [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 1)] + [Alias("BeforeDaysAgo")] + [int] $LastSignInBeforeDaysAgo = 30, + # Return results for All, Member, or Guest userTypes + [ValidateSet("All", "Member", "Guest")] + [string] + $UserType = "All" + ) + + process { + $customHeaders = New-EntraBetaCustomHeaders -Command $MyInvocation.MyCommand + $queryDate = (Get-Date).AddDays(-$LastSignInBeforeDaysAgo).ToString("yyyy-MM-ddTHH:mm:ssZ") + $inactiveFilter = "(signInActivity/lastSignInDateTime le $queryDate)" + + $uri = "/beta/users?`$filter=$inactiveFilter&`$select=signInActivity,UserPrincipalName,Id,DisplayName,mail,userType,createdDateTime,accountEnabled" + + Write-Debug ("Retrieving Users with Filter {0}" -f $inactiveFilter) + $queryUsers = (Invoke-GraphRequest -Method GET -Uri $uri -Headers $customHeaders).value + + switch ($UserType) { + "Member" { $users = $queryUsers | Where-Object { $_.userType -eq 'Member' } } + "Guest" { $users = $queryUsers | Where-Object { $_.userType -eq 'Guest' } } + "All" { $users = $queryUsers } + } + + foreach ($userObject in $users) { + $checkedUser = [ordered] @{ + UserID = $userObject.Id + DisplayName = $userObject.DisplayName + UserPrincipalName = $userObject.UserPrincipalName + Mail = $userObject.Mail + UserType = $userObject.UserType + AccountEnabled = $userObject.AccountEnabled + } + + If ($null -eq $userObject.signInActivity.LastSignInDateTime) { + $checkedUser["LastSignInDateTime"] = "Unknown" + $checkedUser["LastSigninDaysAgo"] = "Unknown" + $checkedUser["lastNonInteractiveSignInDateTime"] = "Unknown" + } + else { + $checkedUser["LastSignInDateTime"] = $userObject.signInActivity.LastSignInDateTime + $checkedUser["LastSigninDaysAgo"] = (New-TimeSpan -Start $checkedUser.LastSignInDateTime -End (Get-Date)).Days + $checkedUser["lastSignInRequestId"] = $userObject.signInActivity.lastSignInRequestId + + If ($null -eq $userObject.signInActivity.lastNonInteractiveSignInDateTime) { + $checkedUser["lastNonInteractiveSignInDateTime"] = "Unknown" + $checkedUser["LastNonInteractiveSigninDaysAgo"] = "Unknown" + } else { + $checkedUser["lastNonInteractiveSignInDateTime"] = $userObject.signInActivity.lastNonInteractiveSignInDateTime + $checkedUser["LastNonInteractiveSigninDaysAgo"] = (New-TimeSpan -Start $checkedUser.lastNonInteractiveSignInDateTime -End (Get-Date)).Days + $checkedUser["lastNonInteractiveSignInRequestId"] = $userObject.signInActivity.lastNonInteractiveSignInRequestId + } + } + + If ($null -eq $userObject.CreatedDateTime) { + $checkedUser["CreatedDateTime"] = "Unknown" + $checkedUser["CreatedDaysAgo"] = "Unknown" + } + else { + $checkedUser["CreatedDateTime"] = $userObject.CreatedDateTime + $checkedUser["CreatedDaysAgo"] = (New-TimeSpan -Start $userObject.CreatedDateTime -End (Get-Date)).Days + } + + Write-Output ([PSCustomObject]$checkedUser) + } + } +} + + diff --git a/module/docs/entra-powershell-beta/Users/Get-EntraBetaInactiveSignInUser.md b/module/docs/entra-powershell-beta/Users/Get-EntraBetaInactiveSignInUser.md new file mode 100644 index 000000000..4b4f72417 --- /dev/null +++ b/module/docs/entra-powershell-beta/Users/Get-EntraBetaInactiveSignInUser.md @@ -0,0 +1,154 @@ +--- +title: Get-EntraBetaInactiveSignInUser +description: This article provides details on the Get-EntraBetaInactiveSignInUser command. + +ms.topic: reference +ms.date: 04/02/2025 +ms.author: eunicewaweru +ms.reviewer: stevemutungi +manager: CelesteDG +author: msewaweru + +external help file: Microsoft.Entra.Beta.Users-Help.xml +Module Name: Microsoft.Entra.Beta +online version: https://learn.microsoft.com/powershell/module/Microsoft.Entra.Beta/Get-EntraBetaInactiveSignInUser + +schema: 2.0.0 +--- + +# Get-EntraBetaInactiveSignInUser + +## Synopsis + +Retrieve users who have not had interactive sign-ins since a specified number of days ago. + +## Syntax + +```powershell +Get-EntraBetaInactiveSignInUser +[-LastSignInBeforeDaysAgo ] +[-UserType ] +[] +``` + +## Description + +The `Get-EntraBetaInactiveSignInUser` cmdlet retrieves users who have not signed in interactively within a specified number of days. This can be useful for identifying inactive accounts in your Microsoft Entra ID environment. + +## Examples + +### Example 1: Retrieve users who have not signed in for 30 days + +```powershell +Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 30 +``` + +```Output +UserID : dddddddd-3333-4444-5555-eeeeeeeeeeee +DisplayName : John Doe +UserPrincipalName : example@contoso.onmicrosoft.com +Mail : example@contoso.onmicrosoft.com +UserType : Member +AccountEnabled : True +LastSignInDateTime : 03/02/2025 5:59:28 AM +LastSigninDaysAgo : 30 +lastSignInRequestId : cccccccc-2222-3333-4444-dddddddddddd +lastNonInteractiveSignInDateTime : Unknown +LastNonInteractiveSigninDaysAgo : Unknown +CreatedDateTime : 01/04/2025 5:55:34 AM +CreatedDaysAgo : 30 + +UserID : aaaaaaaaa-3333-4444-5555-eeeeeeeeeeee +DisplayName : Example User +UserPrincipalName : example@contoso.onmicrosoft.com +Mail : example@contoso.onmicrosoft.com +UserType : Guest +AccountEnabled : True +LastSignInDateTime : 03/02/2025 5:59:28 AM +LastSigninDaysAgo : 30 +lastSignInRequestId : ddddddddd-2222-3333-4444-dddddddddddd +lastNonInteractiveSignInDateTime : Unknown +LastNonInteractiveSigninDaysAgo : Unknown +CreatedDateTime : 01/04/2025 5:00:34 AM +CreatedDaysAgo : 30 +``` + +This command retrieves users who have not had an interactive sign-in within the last 30 days. + +### Example 2: Retrieve inactive guest users + +```powershell +Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 90 -UserType "Guest" +``` + +```Output +UserID : dddddddd-3333-4444-5555-eeeeeeeeeeee +DisplayName : John Doe +UserPrincipalName : example@contoso.onmicrosoft.com +Mail : example@contoso.onmicrosoft.com +UserType : Guest +AccountEnabled : True +LastSignInDateTime : 03/02/2025 5:59:28 AM +LastSigninDaysAgo : 30 +lastSignInRequestId : cccccccc-2222-3333-4444-dddddddddddd +lastNonInteractiveSignInDateTime : Unknown +LastNonInteractiveSigninDaysAgo : Unknown +CreatedDateTime : 01/04/2025 5:55:34 AM +CreatedDaysAgo : 30 +``` + +This command retrieves guest users who have not had an interactive sign-in within the last 90 days. + +## Parameters + +### -LastSignInBeforeDaysAgo + +Specifies the number of days since the last interactive sign-in. Users who have not signed in within this period will be returned. + +```yaml +Type: System.Int32 +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -UserType + +Filters users based on their type (e.g., "Member" or "Guest"). + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: "All" +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: `-Debug`, `-ErrorAction`, `-ErrorVariable`, `-InformationAction`, `-InformationVariable`, `-OutVariable`, `-OutBuffer`, `-PipelineVariable`, `-Verbose`, `-WarningAction`, and `-WarningVariable`. For more information, see [about_CommonParameters](https://go.microsoft.com/fwlink/?LinkID=113216). + +## Inputs + +### System.Int32 + +You can pipe an integer value to the `-LastSignInBeforeDaysAgo` parameter. + +## Outputs + +### System.Object + +Returns a list of users who have not signed in within the specified period. + +## Notes + +## Related Links diff --git a/module/docs/entra-powershell-v1.0/Users/Get-EntraInactiveSignInUser.md b/module/docs/entra-powershell-v1.0/Users/Get-EntraInactiveSignInUser.md new file mode 100644 index 000000000..0cb21fcdc --- /dev/null +++ b/module/docs/entra-powershell-v1.0/Users/Get-EntraInactiveSignInUser.md @@ -0,0 +1,154 @@ +--- +title: Get-EntraInactiveSignInUser +description: This article provides details on the Get-EntraInactiveSignInUser command. + +ms.topic: reference +ms.date: 04/02/2025 +ms.author: eunicewaweru +ms.reviewer: stevemutungi +manager: CelesteDG +author: msewaweru + +external help file: Microsoft.Entra.Users-Help.xml +Module Name: Microsoft.Entra +online version: https://learn.microsoft.com/powershell/module/Microsoft.Entra/Get-EntraInactiveSignInUser + +schema: 2.0.0 +--- + +# Get-EntraInactiveSignInUser + +## Synopsis + +Retrieve users who have not had interactive sign-ins since a specified number of days ago. + +## Syntax + +```powershell +Get-EntraInactiveSignInUser +[-LastSignInBeforeDaysAgo ] +[-UserType ] +[] +``` + +## Description + +The `Get-EntraInactiveSignInUser` cmdlet retrieves users who have not signed in interactively within a specified number of days. This can be useful for identifying inactive accounts in your Microsoft Entra ID environment. + +## Examples + +### Example 1: Retrieve users who have not signed in for 30 days + +```powershell +Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 30 -All +``` + +```Output +UserID : dddddddd-3333-4444-5555-eeeeeeeeeeee +DisplayName : John Doe +UserPrincipalName : johndoe@contoso.onmicrosoft.com +Mail : johndoe@contoso.onmicrosoft.com +UserType : Member +AccountEnabled : True +LastSignInDateTime : 03/02/2025 5:59:28 AM +LastSigninDaysAgo : 30 +lastSignInRequestId : cccccccc-2222-3333-4444-dddddddddddd +lastNonInteractiveSignInDateTime : Unknown +LastNonInteractiveSigninDaysAgo : Unknown +CreatedDateTime : 01/04/2025 5:55:34 AM +CreatedDaysAgo : 30 + +UserID : aaaaaaaaa-3333-4444-5555-eeeeeeeeeeee +DisplayName : Example User +UserPrincipalName : example@contoso.onmicrosoft.com +Mail : example@contoso.onmicrosoft.com +UserType : Guest +AccountEnabled : True +LastSignInDateTime : 03/02/2025 5:59:28 AM +LastSigninDaysAgo : 30 +lastSignInRequestId : ddddddddd-2222-3333-4444-dddddddddddd +lastNonInteractiveSignInDateTime : Unknown +LastNonInteractiveSigninDaysAgo : Unknown +CreatedDateTime : 01/04/2025 5:00:34 AM +CreatedDaysAgo : 30 +``` + +This command retrieves users who have not had an interactive sign-in within the last 30 days. + +### Example 2: Retrieve inactive guest users + +```powershell +Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 90 -UserType "Guest" +``` + +```Output +UserID : dddddddd-3333-4444-5555-eeeeeeeeeeee +DisplayName : John Doe +UserPrincipalName : example@contoso.onmicrosoft.com +Mail : example@contoso.onmicrosoft.com +UserType : Guest +AccountEnabled : True +LastSignInDateTime : 03/02/2025 5:59:28 AM +LastSigninDaysAgo : 30 +lastSignInRequestId : cccccccc-2222-3333-4444-dddddddddddd +lastNonInteractiveSignInDateTime : Unknown +LastNonInteractiveSigninDaysAgo : Unknown +CreatedDateTime : 01/04/2025 5:55:34 AM +CreatedDaysAgo : 30 +``` + +This command retrieves guest users who have not had an interactive sign-in within the last 90 days. + +## Parameters + +### -LastSignInBeforeDaysAgo + +Specifies the number of days since the last interactive sign-in. Users who have not signed in within this period will be returned. + +```yaml +Type: System.Int32 +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -UserType + +Filters users based on their type (e.g., "Member" or "Guest"). + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: "All" +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: `-Debug`, `-ErrorAction`, `-ErrorVariable`, `-InformationAction`, `-InformationVariable`, `-OutVariable`, `-OutBuffer`, `-PipelineVariable`, `-Verbose`, `-WarningAction`, and `-WarningVariable`. For more information, see [about_CommonParameters](https://go.microsoft.com/fwlink/?LinkID=113216). + +## Inputs + +### System.Int32 + +You can pipe an integer value to the `-LastSignInBeforeDaysAgo` parameter. + +## Outputs + +### System.Object + +Returns a list of users who have not signed in within the specified period. + +## Notes + +## Related Links diff --git a/test/Entra/Users/Get-EntraInactiveSignInUser.Tests.ps1 b/test/Entra/Users/Get-EntraInactiveSignInUser.Tests.ps1 new file mode 100644 index 000000000..7658d44a9 --- /dev/null +++ b/test/Entra/Users/Get-EntraInactiveSignInUser.Tests.ps1 @@ -0,0 +1,130 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +# ------------------------------------------------------------------------------ + +BeforeAll { + if ((Get-Module -Name Microsoft.Entra.Users) -eq $null) { + Import-Module Microsoft.Entra.Users + } + Import-Module (Join-Path $PSScriptRoot "..\..\Common-Functions.ps1") -Force + + Mock -CommandName Get-Date -MockWith { [datetime]"2024-03-21T00:00:00Z" } + + Mock -CommandName Invoke-GraphRequest -MockWith { + return @{ + value = @( + @{ + Id = "user1" + DisplayName = "John Doe" + UserPrincipalName = "johndoe@example.com" + Mail = "johndoe@example.com" + UserType = "Member" + AccountEnabled = $true + signInActivity = @{ + lastSignInDateTime = (Get-Date).AddDays(-40).ToString("yyyy-MM-ddTHH:mm:ssZ") + lastSignInRequestId = "12345" + lastNonInteractiveSignInDateTime = (Get-Date).AddDays(-100).ToString("yyyy-MM-ddTHH:mm:ssZ") + lastNonInteractiveSignInRequestId = "67890" + } + CreatedDateTime = (Get-Date).AddDays(-365).ToString("yyyy-MM-ddTHH:mm:ssZ") + }, + @{ + Id = "user2" + DisplayName = "Jane Guest" + UserPrincipalName = "janeguest@example.com" + Mail = "janeguest@example.com" + UserType = "Guest" + AccountEnabled = $true + signInActivity = @{ + lastSignInDateTime = (Get-Date).AddDays(-50).ToString("yyyy-MM-ddTHH:mm:ssZ") + lastSignInRequestId = "12345" + lastNonInteractiveSignInDateTime = $null + lastNonInteractiveSignInRequestId = $null + } + CreatedDateTime = (Get-Date).AddDays(-400).ToString("yyyy-MM-ddTHH:mm:ssZ") + }, + @{ + Id = "user3" + DisplayName = "Unknown Sign In" + UserPrincipalName = "unknownsign@example.com" + Mail = "unknownsign@example.com" + UserType = "Member" + AccountEnabled = $true + signInActivity = @{ + lastSignInDateTime = $null + lastSignInRequestId = $null + lastNonInteractiveSignInDateTime = $null + lastNonInteractiveSignInRequestId = $null + } + CreatedDateTime = (Get-Date).AddDays(-100).ToString("yyyy-MM-ddTHH:mm:ssZ") + } + ) + } + } -ModuleName Microsoft.Entra.Users +} + +Describe 'Get-EntraInactiveSignInUser' { + + Context "Get-EntraInactiveSignInUser Tests" { + + It "Should return all inactive users" { + $result = Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "All" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 3 + $result[0].UserID | Should -Be "user1" + $result[1].UserID | Should -Be "user2" + $result[2].UserID | Should -Be "user3" + } + + It "Should return only inactive Member users" { + $result = Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "Member" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 2 + $result[0].UserID | Should -Be "user1" + $result[1].UserID | Should -Be "user3" + } + + It "Should return only inactive Guest users" { + $result = Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "Guest" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 1 + $result[0].UserID | Should -Be "user2" + } + + It "Should handle users with null lastSignInDateTime" { + $result = Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "All" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 3 + $result[2].UserID | Should -Be "user3" + $result[2].LastSignInDateTime | Should -Be "Unknown" + } + + It "Should return users based on specific date ranges" { + # Test with a smaller date range, expecting only user2 to be returned + $result = Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 45 -UserType "All" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 3 + $result[0].UserID | Should -Be "user1" + $result[1].UserID | Should -Be "user2" + } + + It "Should contain 'User-Agent' header" { + $userAgentHeaderValue = "PowerShell/$psVersion EntraPowershell/$entraVersion Get-EntraInactiveSignInUser" + $result = Get-EntraInactiveSignInUser -LastSignInBeforeDaysAgo 45 -UserType "All" + $result | Should -Not -BeNullOrEmpty + $userAgentHeaderValue = "PowerShell/$psVersion EntraPowershell/$entraVersion Get-EntraInactiveSignInUser" + Should -Invoke -CommandName Invoke-GraphRequest -ModuleName Microsoft.Entra.Users -Times 1 -ParameterFilter { + $Headers.'User-Agent' | Should -Be $userAgentHeaderValue + $true + } + } + + + } + +} diff --git a/test/EntraBeta/Users/Get-EntraBetaInactiveSignInUser.Tests.ps1 b/test/EntraBeta/Users/Get-EntraBetaInactiveSignInUser.Tests.ps1 new file mode 100644 index 000000000..5286fdea8 --- /dev/null +++ b/test/EntraBeta/Users/Get-EntraBetaInactiveSignInUser.Tests.ps1 @@ -0,0 +1,130 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +# ------------------------------------------------------------------------------ + +BeforeAll { + if ((Get-Module -Name Microsoft.Entra.Beta.Users) -eq $null) { + Import-Module Microsoft.Entra.Beta.Users + } + Import-Module (Join-Path $PSScriptRoot "..\..\Common-Functions.ps1") -Force + + Mock -CommandName Get-Date -MockWith { [datetime]"2024-03-21T00:00:00Z" } + + Mock -CommandName Invoke-GraphRequest -MockWith { + return @{ + value = @( + @{ + Id = "user1" + DisplayName = "John Doe" + UserPrincipalName = "johndoe@example.com" + Mail = "johndoe@example.com" + UserType = "Member" + AccountEnabled = $true + signInActivity = @{ + lastSignInDateTime = (Get-Date).AddDays(-40).ToString("yyyy-MM-ddTHH:mm:ssZ") + lastSignInRequestId = "12345" + lastNonInteractiveSignInDateTime = (Get-Date).AddDays(-100).ToString("yyyy-MM-ddTHH:mm:ssZ") + lastNonInteractiveSignInRequestId = "67890" + } + CreatedDateTime = (Get-Date).AddDays(-365).ToString("yyyy-MM-ddTHH:mm:ssZ") + }, + @{ + Id = "user2" + DisplayName = "Jane Guest" + UserPrincipalName = "janeguest@example.com" + Mail = "janeguest@example.com" + UserType = "Guest" + AccountEnabled = $true + signInActivity = @{ + lastSignInDateTime = (Get-Date).AddDays(-50).ToString("yyyy-MM-ddTHH:mm:ssZ") + lastSignInRequestId = "12345" + lastNonInteractiveSignInDateTime = $null + lastNonInteractiveSignInRequestId = $null + } + CreatedDateTime = (Get-Date).AddDays(-400).ToString("yyyy-MM-ddTHH:mm:ssZ") + }, + @{ + Id = "user3" + DisplayName = "Unknown Sign In" + UserPrincipalName = "unknownsign@example.com" + Mail = "unknownsign@example.com" + UserType = "Member" + AccountEnabled = $true + signInActivity = @{ + lastSignInDateTime = $null + lastSignInRequestId = $null + lastNonInteractiveSignInDateTime = $null + lastNonInteractiveSignInRequestId = $null + } + CreatedDateTime = (Get-Date).AddDays(-100).ToString("yyyy-MM-ddTHH:mm:ssZ") + } + ) + } + } -ModuleName Microsoft.Entra.Beta.Users +} + +Describe 'Get-EntraBetaInactiveSignInUser' { + + Context "Get-EntraBetaInactiveSignInUser Tests" { + + It "Should return all inactive users" { + $result = Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "All" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 3 + $result[0].UserID | Should -Be "user1" + $result[1].UserID | Should -Be "user2" + $result[2].UserID | Should -Be "user3" + } + + It "Should return only inactive Member users" { + $result = Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "Member" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 2 + $result[0].UserID | Should -Be "user1" + $result[1].UserID | Should -Be "user3" + } + + It "Should return only inactive Guest users" { + $result = Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "Guest" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 1 + $result[0].UserID | Should -Be "user2" + } + + It "Should handle users with null lastSignInDateTime" { + $result = Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 30 -UserType "All" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 3 + $result[2].UserID | Should -Be "user3" + $result[2].LastSignInDateTime | Should -Be "Unknown" + } + + It "Should return users based on specific date ranges" { + # Test with a smaller date range, expecting only user2 to be returned + $result = Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 45 -UserType "All" + + $result | Should -Not -BeNullOrEmpty + $result.Count | Should -Be 3 + $result[0].UserID | Should -Be "user1" + $result[1].UserID | Should -Be "user2" + } + + It "Should contain 'User-Agent' header" { + $userAgentHeaderValue = "PowerShell/$psVersion EntraPowershell/$entraVersion Get-EntraBetaInactiveSignInUser" + $result = Get-EntraBetaInactiveSignInUser -LastSignInBeforeDaysAgo 45 -UserType "All" + $result | Should -Not -BeNullOrEmpty + $userAgentHeaderValue = "PowerShell/$psVersion EntraPowershell/$entraVersion Get-EntraBetaInactiveSignInUser" + Should -Invoke -CommandName Invoke-GraphRequest -ModuleName Microsoft.Entra.Beta.Users -Times 1 -ParameterFilter { + $Headers.'User-Agent' | Should -Be $userAgentHeaderValue + $true + } + } + + + } + +}