From 85acf750b3a7a3eb851d25964d5ef04b9b58d643 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Tue, 21 Apr 2026 14:10:08 +0700 Subject: [PATCH] [CLAUDE] Scripts: update cho SQLEXPRESS instance + Invoke-Sqlcmd (no sqlcmd.exe binary needed) - setup-sql-db.ps1: Server=.\SQLEXPRESS default, dung Invoke-Sqlcmd (SqlServer PS module) voi credential + TrustServerCertificate - appsettings.Production.json.example: Server=.\SQLEXPRESS (voi escaped backslash JSON) - DB_CONNECTION Gitea secret da update (qua API) VPS Windows Server 2022 minimal, co VIETREPORT da chay 4 site, SQL instance SQLEXPRESS. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/setup-sql-db.ps1 | 53 +++++++++++-------- .../appsettings.Production.json.example | 2 +- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/scripts/setup-sql-db.ps1 b/scripts/setup-sql-db.ps1 index 927d20c..d42d09c 100644 --- a/scripts/setup-sql-db.ps1 +++ b/scripts/setup-sql-db.ps1 @@ -1,42 +1,54 @@ # Setup SQL Server DB cho SOLUTION_ERP trên VPS chia sẻ với VIETREPORT. # Tạo database + grant quyền cho user vrapp (đã có sẵn trên server). +# Dùng Invoke-Sqlcmd (PowerShell SqlServer module) — không cần sqlcmd.exe binary. # Idempotent: chạy lại không phá gì. # # Usage (chạy trên VPS với admin privilege): +# Install-Module SqlServer -Force -Scope AllUsers # 1 lần duy nhất nếu chưa có # .\setup-sql-db.ps1 -SaPassword 'your-sa-password' # # Prereq: -# - SQL Server cài sẵn +# - SQL Server cài sẵn (mặc định instance SQLEXPRESS) # - Login vrapp đã tồn tại (dùng chung với VIETREPORT) -# - sqlcmd CLI available (đi kèm SQL Server) +# - Module SqlServer installed param( [Parameter(Mandatory=$true)] [string]$SaPassword, - [string]$Server = ".", + [string]$Server = ".\SQLEXPRESS", [string]$Database = "SolutionErp", [string]$AppUser = "vrapp" ) $ErrorActionPreference = 'Stop' +Import-Module SqlServer -ErrorAction Stop -function Invoke-Sql($query) { - $output = sqlcmd -S $Server -U sa -P $SaPassword -Q $query -b 2>&1 - if ($LASTEXITCODE -ne 0) { - throw "SQL fail (exit $LASTEXITCODE):`n$output" +$secureSa = ConvertTo-SecureString $SaPassword -AsPlainText -Force +$creds = New-Object System.Management.Automation.PSCredential('sa', $secureSa) + +function Invoke-Sql($query, [switch]$NoDb) { + $params = @{ + ServerInstance = $Server + Credential = $creds + Query = $query + TrustServerCertificate = $true + ErrorAction = 'Stop' } - return $output + if (-not $NoDb) { $params.Database = 'master' } + Invoke-Sqlcmd @params } -Write-Host "==> Check SQL Server reachable" -Invoke-Sql "SELECT @@VERSION" | Select-Object -First 2 +Write-Host "==> Check SQL Server reachable ($Server)" +$ver = Invoke-Sql "SELECT @@VERSION AS V" -NoDb +Write-Host " $($ver.V -split '`n' | Select-Object -First 1)" Write-Host "`n==> Check login '$AppUser' exists" $check = Invoke-Sql "SELECT name FROM sys.sql_logins WHERE name = '$AppUser'" -if ($check -notmatch $AppUser) { - Write-Error "Login '$AppUser' KHONG ton tai. Tao tay truoc: CREATE LOGIN [$AppUser] WITH PASSWORD='...'" - exit 1 +if (-not $check -or $check.name -ne $AppUser) { + Write-Warning "Login '$AppUser' KHONG ton tai. Tao truoc voi:" + Write-Warning " Invoke-Sqlcmd -ServerInstance '$Server' -Credential -Query `"CREATE LOGIN [$AppUser] WITH PASSWORD='...', CHECK_POLICY=OFF;`"" + throw "Login vrapp missing" } -Write-Host " OK" +Write-Host " OK ($AppUser exists)" Write-Host "`n==> Create database '$Database' (if not exists)" Invoke-Sql @" @@ -49,7 +61,7 @@ ELSE PRINT 'Database $Database already exists'; "@ Write-Host "`n==> Grant db_owner cho '$AppUser' tren '$Database'" -Invoke-Sql @" +$grantQuery = @" USE [$Database]; IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = '$AppUser') BEGIN @@ -61,14 +73,11 @@ ALTER ROLE db_owner ADD MEMBER [$AppUser]; PRINT 'Added $AppUser to db_owner'; "@ -Write-Host "`n==> Verify kết nối với vrapp (test login)" -Write-Host " (skip — tự test khi app chạy)" - -Write-Host "`n==> Setup backup schedule" -Write-Host " Chạy: schtasks /Create /TN 'SolutionErp SQL Backup' /TR 'pwsh -File C:\solution-erp\scripts\backup-sql.ps1 -Server . -Database $Database' /SC DAILY /ST 02:00 /RU SYSTEM /F" -Write-Host " (hoặc tạo tay qua Task Scheduler)" +Invoke-Sqlcmd -ServerInstance $Server -Credential $creds -Database $Database -Query $grantQuery -TrustServerCertificate Write-Host "`n✅ SQL Server setup DONE" -ForegroundColor Green +Write-Host " Server: $Server" Write-Host " Database: $Database" Write-Host " App user: $AppUser (db_owner)" -Write-Host " Connection string production: Server=localhost;Database=$Database;User Id=$AppUser;Password=***" +Write-Host " Connection string production:" +Write-Host " Server=$Server;Database=$Database;User Id=$AppUser;Password=***;MultipleActiveResultSets=true;TrustServerCertificate=true;Encrypt=true" diff --git a/src/Backend/SolutionErp.Api/appsettings.Production.json.example b/src/Backend/SolutionErp.Api/appsettings.Production.json.example index 12938f7..e00835c 100644 --- a/src/Backend/SolutionErp.Api/appsettings.Production.json.example +++ b/src/Backend/SolutionErp.Api/appsettings.Production.json.example @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "Default": "Server=localhost;Database=SolutionErp;User Id=vrapp;Password=__SET_VIA_SECRETS__;MultipleActiveResultSets=true;TrustServerCertificate=true;Encrypt=true" + "Default": "Server=.\\SQLEXPRESS;Database=SolutionErp;User Id=vrapp;Password=__SET_VIA_SECRETS__;MultipleActiveResultSets=true;TrustServerCertificate=true;Encrypt=true" }, "Jwt": { "Issuer": "SolutionErp.Api",