Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated Pester test guidance in AI instructions in community style guidelines.
- Added SChannelDsc as a required module for integration tests and enabled the
prerequisites tests `Ensure TLS 1.2 is enabled` ([issue #2441](https://github.com/dsccommunity/SqlServerDsc/issues/2441)).
- `SqlLogin`
- Added parameter `Language` to allow setting the default language used by the login.
Comment thread
johlju marked this conversation as resolved.

## [17.5.0] - 2026-01-30

Expand Down
57 changes: 50 additions & 7 deletions source/DSCResources/DSC_SqlLogin/DSC_SqlLogin.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ function Get-TargetResource
InstanceName = $InstanceName
Disabled = $login.IsDisabled
DefaultDatabase = $login.DefaultDatabase
Language = $login.Language
}

if ($login.LoginType -eq 'SqlLogin')
Expand Down Expand Up @@ -120,6 +121,9 @@ function Get-TargetResource

.PARAMETER DefaultDatabase
Specifies the default database for the login.

.PARAMETER Language
Specifies the default language for the login.
#>
function Set-TargetResource
{
Expand Down Expand Up @@ -179,7 +183,11 @@ function Set-TargetResource

[Parameter()]
[System.String]
$DefaultDatabase
$DefaultDatabase,

[Parameter()]
[System.String]
$Language
)

$serverObject = Connect-SQL -ServerName $ServerName -InstanceName $InstanceName -ErrorAction 'Stop'
Expand Down Expand Up @@ -263,9 +271,18 @@ function Set-TargetResource
}
}

if ( $PSBoundParameters.ContainsKey('DefaultDatabase') -and ($login.DefaultDatabase -ne $DefaultDatabase) )
if ( ( $PSBoundParameters.ContainsKey('DefaultDatabase') -and ($login.DefaultDatabase -ne $DefaultDatabase) ) -or
( $PSBoundParameters.ContainsKey('Language') -and $login.Language -ne $Language ) )
{
$login.DefaultDatabase = $DefaultDatabase
if ( $PSBoundParameters.ContainsKey('DefaultDatabase') )
{
$login.DefaultDatabase = $DefaultDatabase
}

if ( $PSBoundParameters.ContainsKey('Language') )
{
$login.Language = $Language
}
Update-SQLServerLogin -Login $login
}
}
Expand Down Expand Up @@ -338,10 +355,20 @@ function Set-TargetResource
$login.Disable()
}

# Set the default database if specified
if ( $PSBoundParameters.ContainsKey('DefaultDatabase') )
if ( ( $PSBoundParameters.ContainsKey('DefaultDatabase') -and ($login.DefaultDatabase -ne $DefaultDatabase) ) -or
( $PSBoundParameters.ContainsKey('Language') -and $login.Language -ne $Language ) )
{
$login.DefaultDatabase = $DefaultDatabase
# Set the default database if specified
if ( $PSBoundParameters.ContainsKey('DefaultDatabase') )
{
$login.DefaultDatabase = $DefaultDatabase
}

# Set the language if specified
if ( $PSBoundParameters.ContainsKey('Language') )
{
$login.Language = $Language
}
Update-SQLServerLogin -Login $login
}
}
Expand Down Expand Up @@ -398,6 +425,9 @@ function Set-TargetResource

.PARAMETER DefaultDatabase
Specifies the default database for the login.

.PARAMETER Language
Specifies the default language for the login.
#>
function Test-TargetResource
{
Expand Down Expand Up @@ -457,7 +487,11 @@ function Test-TargetResource

[Parameter()]
[System.String]
$DefaultDatabase
$DefaultDatabase,

[Parameter()]
[System.String]
$Language
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)

Write-Verbose -Message (
Expand Down Expand Up @@ -522,6 +556,15 @@ function Test-TargetResource
$testPassed = $false
}

if ( $PSBoundParameters.ContainsKey('Language') -and ($loginInfo.Language -ne $Language) )
{
Write-Verbose -Message (
$script:localizedData.WrongLanguage -f $Name, $loginInfo.Language, $Language
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

$testPassed = $false
}

if ( $LoginType -eq 'SqlLogin' )
{
if ( $PSBoundParameters.ContainsKey('LoginPasswordExpirationEnabled') -and $LoginPasswordExpirationEnabled -ne $loginInfo.LoginPasswordExpirationEnabled )
Expand Down
1 change: 1 addition & 0 deletions source/DSCResources/DSC_SqlLogin/DSC_SqlLogin.schema.mof
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ class DSC_SqlLogin : OMI_BaseResource
[Write, Description("Specifies if the login password is required to conform to the password policy specified in the system security policy. Only applies to _SQL Logins_.")] Boolean LoginPasswordPolicyEnforced;
[Write, Description("Specifies if the login is disabled. Default value is `$false`.")] Boolean Disabled;
[Write, Description("Specifies the default database name.")] String DefaultDatabase;
[Write, Description("Specifies the default language.")] String Language;
};
85 changes: 85 additions & 0 deletions tests/Unit/DSC_SqlLogin.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ Describe 'SqlLogin\Get-TargetResource' -Tag 'Get' {
Add-Member -MemberType NoteProperty -Name 'Name' -Value $MockLoginName -PassThru |
Add-Member -MemberType NoteProperty -Name 'LoginType' -Value $MockLoginType -PassThru |
Add-Member -MemberType NoteProperty -Name 'DefaultDatabase' -Value 'master' -PassThru |
Add-Member -MemberType NoteProperty -Name 'Language' -Value 'us_english' -PassThru |
Add-Member -MemberType NoteProperty -Name 'IsDisabled' -Value $true -PassThru |
Add-Member -MemberType NoteProperty -Name 'MustChangePassword' -Value $true -PassThru |
Add-Member -MemberType NoteProperty -Name 'PasswordExpirationEnabled' -Value $true -PassThru |
Expand Down Expand Up @@ -145,6 +146,7 @@ Describe 'SqlLogin\Get-TargetResource' -Tag 'Get' {
$result.LoginType | Should -Be $MockLoginType
$result.Disabled | Should -BeTrue
$result.DefaultDatabase | Should -Be 'master'
$result.Language | Should -Be 'us_english'

if ($MockLoginType -eq 'SqlLogin')
{
Expand Down Expand Up @@ -197,6 +199,7 @@ Describe 'SqlLogin\Get-TargetResource' -Tag 'Get' {
Add-Member -MemberType NoteProperty -Name 'Name' -Value 'Login1' -PassThru |
Add-Member -MemberType NoteProperty -Name 'LoginType' -Value 'SqlLogin' -PassThru |
Add-Member -MemberType NoteProperty -Name 'DefaultDatabase' -Value 'master' -PassThru |
Add-Member -MemberType NoteProperty -Name 'Language' -Value 'us_english' -PassThru |
Add-Member -MemberType NoteProperty -Name 'IsDisabled' -Value $true -PassThru |
Add-Member -MemberType NoteProperty -Name 'MustChangePassword' -Value $true -PassThru |
Add-Member -MemberType NoteProperty -Name 'PasswordExpirationEnabled' -Value $true -PassThru |
Expand Down Expand Up @@ -226,6 +229,7 @@ Describe 'SqlLogin\Get-TargetResource' -Tag 'Get' {
$result.LoginType | Should -BeNullOrEmpty
$result.Disabled | Should -BeFalse
$result.DefaultDatabase | Should -BeNullOrEmpty
$result.Language | Should -BeNullOrEmpty

if ($MockLoginType -eq 'SqlLogin')
{
Expand Down Expand Up @@ -456,12 +460,17 @@ Describe 'SqlLogin\Test-TargetResource' -Tag 'Test' {
MockPropertyName = 'DefaultDatabase'
MockPropertyValue = 'database1'
}
@{
MockPropertyName = 'Language'
MockPropertyValue = 'Français'
}
) {
BeforeAll {
Mock -CommandName Get-TargetResource -MockWith {
return @{
Ensure = 'Present'
DefaultDatabase = 'master'
Language = 'us_english'
<#
Switch the value of the property to the opposite of what
will be specified in the call to Test-TargetResource.
Expand Down Expand Up @@ -756,6 +765,39 @@ Describe 'SqlLogin\Set-TargetResource' -Tag 'Set' {
}
}

Context 'When creating a new login of type WindowsUser and specifying a language' {
BeforeAll {
$mockConnectSQL = {
return New-Object -TypeName Object |
Add-Member -MemberType 'NoteProperty' -Name 'LoginMode' -Value 'Integrated' -PassThru |
Add-Member -MemberType 'ScriptProperty' -Name 'Logins' -Value {
# Mocks no existing logins.
return @{}
} -PassThru -Force
}

Mock -CommandName Connect-SQL -MockWith $mockConnectSQL
Mock -CommandName New-SQLServerLogin
}

It 'Should not throw and call the correct mocks' {
InModuleScope -ScriptBlock {
Set-StrictMode -Version 1.0

$mockSetTargetResourceParameters.Name = 'Windows\Login1'
$mockSetTargetResourceParameters.LoginType = 'WindowsUser'
$mockSetTargetResourceParameters.Language = 'Français'

$null = Set-TargetResource @mockSetTargetResourceParameters -ErrorAction 'Stop'
}

Should -Invoke -CommandName Connect-SQL -Exactly -Times 1 -Scope It
Should -Invoke -CommandName New-SQLServerLogin -ParameterFilter {
$Login.Name -eq 'Windows\Login1' -and $Login.Language -eq 'Français'
} -Exactly -Times 1 -Scope It
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Context 'When creating a new login of type WindowsUser and specifying that it should be disabled' {
BeforeAll {
$mockConnectSQL = {
Expand Down Expand Up @@ -941,6 +983,42 @@ Describe 'SqlLogin\Set-TargetResource' -Tag 'Set' {
}
}

Context 'When creating a new login of type SqlLogin and specifying a language' {
BeforeAll {
$mockConnectSQL = {
return New-Object -TypeName Object |
Add-Member -MemberType 'NoteProperty' -Name 'LoginMode' -Value 'Mixed' -PassThru |
Add-Member -MemberType 'ScriptProperty' -Name 'Logins' -Value {
# Mocks no existing logins.
return @{}
} -PassThru -Force
}

Mock -CommandName Connect-SQL -MockWith $mockConnectSQL
Mock -CommandName New-SQLServerLogin
}

It 'Should not throw and call the correct mocks' {
InModuleScope -ScriptBlock {
Set-StrictMode -Version 1.0

$mockPassword = ConvertTo-SecureString -String 'P@ssw0rd-12P@ssw0rd-12' -AsPlainText -Force

$mockSetTargetResourceParameters.Name = 'SqlLogin1'
$mockSetTargetResourceParameters.LoginType = 'SqlLogin'
$mockSetTargetResourceParameters.Language = 'Français'
$mockSetTargetResourceParameters.LoginCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList @($mockTestTargetResourceParameters.Name, $mockPassword)

$null = Set-TargetResource @mockSetTargetResourceParameters -ErrorAction 'Stop'
}

Should -Invoke -CommandName Connect-SQL -Exactly -Times 1 -Scope It
Should -Invoke -CommandName New-SQLServerLogin -ParameterFilter {
$Login.Name -eq 'SqlLogin1' -and $Login.Language -eq 'Français'
} -Exactly -Times 1 -Scope It
}
}

Context 'When creating a new login of type SqlLogin and specifying that it should be disabled' {
BeforeAll {
$mockConnectSQL = {
Expand Down Expand Up @@ -1226,6 +1304,7 @@ Describe 'SqlLogin\Set-TargetResource' -Tag 'Set' {
# Using the stub class Login from the SMO.cs file.
$mockLoginObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList ($null, 'Windows\Login1')
$mockLoginObject.DefaultDatabase = 'master'
$mockLoginObject.Language = 'us_english'

return @{
'Windows\Login1' = $mockLoginObject
Expand Down Expand Up @@ -1283,6 +1362,7 @@ Describe 'SqlLogin\Set-TargetResource' -Tag 'Set' {
$mockLoginObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList ($null, 'SqlLogin1')
$mockLoginObject.LoginType = 'SqlLogin'
$mockLoginObject.DefaultDatabase = 'master'
$mockLoginObject.Language = 'us_english'
# Switch the mock value to the opposite of what should be the desired state.
$mockLoginObject.PasswordPolicyEnforced = -not $MockPropertyValue
$mockLoginObject.PasswordExpirationEnabled = -not $MockPropertyValue
Expand Down Expand Up @@ -1386,6 +1466,10 @@ Describe 'SqlLogin\Set-TargetResource' -Tag 'Set' {
MockPropertyName = 'DefaultDatabase'
MockPropertyValue = 'Database1'
}
@{
MockPropertyName = 'Language'
MockPropertyValue = 'Français'
}
) {
BeforeAll {
$mockConnectSQL = {
Expand All @@ -1395,6 +1479,7 @@ Describe 'SqlLogin\Set-TargetResource' -Tag 'Set' {
$mockLoginObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList ($null, 'SqlLogin1')
$mockLoginObject.LoginType = 'SqlLogin'
$mockLoginObject.DefaultDatabase = 'master'
$mockLoginObject.Language = 'us_english'

return @{
'SqlLogin1' = $mockLoginObject
Expand Down
Loading