PayrollManagementSystem/scripts/tplus/create_tplus_readonly_login.ps1
liuwenxin b0c599e513 fix(脚本): 收紧 T+ 运维脚本校验与恢复行为
login 脚本原先在结尾无条件 SET READ_ONLY:库名误指向其他
可写库时会把它锁成只读。改为开头校验库存在(不存在即中止)
并记录初始 Updateability,结尾仅当初始为 READ_ONLY 时恢复。
inventory 脚本的库名校验统一为 restore 脚本的字符白名单。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-30 09:57:30 +08:00

65 lines
2.7 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$DatabaseName,
[string]$LoginName = "tplus_reader",
[string]$ContainerName = "ys-tplus-sqlserver-dev",
[Parameter(Mandatory = $true)]
[SecureString]$SaPassword,
[Parameter(Mandatory = $true)]
[SecureString]$ReaderPassword
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
. (Join-Path $PSScriptRoot "container_sql.ps1")
function Convert-SecureStringToPlainText([SecureString]$Value) {
$ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Value)
try { return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr) }
finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr) }
}
if ($LoginName -notmatch '^[A-Za-z_][A-Za-z0-9_]{0,63}$') {
throw "只读账号名只能包含字母、数字和下划线,且不能以数字开头。"
}
$readerPasswordText = Convert-SecureStringToPlainText $ReaderPassword
$safeDatabaseIdentifier = $DatabaseName.Replace("]", "]]" )
$safeDatabaseLiteral = $DatabaseName.Replace("'", "''")
$safeLoginIdentifier = $LoginName.Replace("]", "]]" )
$safeReaderPassword = $readerPasswordText.Replace("'", "''")
$sql = @"
IF DB_ID(N'$safeDatabaseLiteral') IS NULL
BEGIN
;THROW 51000, N'目标数据库不存在,已停止配置,未修改任何库。', 1;
END;
DECLARE @initialReadonly bit =
CASE WHEN CAST(DATABASEPROPERTYEX(N'$safeDatabaseLiteral', 'Updateability') AS nvarchar(30)) = N'READ_ONLY'
THEN 1 ELSE 0 END;
IF @initialReadonly = 1
ALTER DATABASE [$safeDatabaseIdentifier] SET READ_WRITE;
IF NOT EXISTS (SELECT 1 FROM sys.server_principals WHERE name = N'$safeLoginIdentifier')
BEGIN
CREATE LOGIN [$safeLoginIdentifier] WITH PASSWORD = N'$safeReaderPassword', CHECK_POLICY = ON;
END;
USE [$safeDatabaseIdentifier];
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = N'$safeLoginIdentifier')
BEGIN
CREATE USER [$safeLoginIdentifier] FOR LOGIN [$safeLoginIdentifier];
END;
IF NOT EXISTS (
SELECT 1 FROM sys.database_role_members rm
JOIN sys.database_principals r ON r.principal_id = rm.role_principal_id
JOIN sys.database_principals u ON u.principal_id = rm.member_principal_id
WHERE r.name=N'db_datareader' AND u.name=N'$safeLoginIdentifier'
)
EXEC sp_addrolemember N'db_datareader', N'$safeLoginIdentifier';
DENY INSERT, UPDATE, DELETE TO [$safeLoginIdentifier];
IF @initialReadonly = 1
ALTER DATABASE [$safeDatabaseIdentifier] SET READ_ONLY;
"@
Invoke-TPlusContainerSql -ContainerName $ContainerName -Sql $sql -SaPassword $SaPassword
Write-Host "只读账号已配置:$LoginName(未输出密码)。仅当目标库初始为 READ_ONLY 时才恢复只读;初始为可写的库保持可写。"