diff --git a/DnnWebsiteManagement/DnnWebsiteManagement.psm1 b/DnnWebsiteManagement/DnnWebsiteManagement.psm1 index 5241fda..b6bbaca 100644 --- a/DnnWebsiteManagement/DnnWebsiteManagement.psm1 +++ b/DnnWebsiteManagement/DnnWebsiteManagement.psm1 @@ -11,6 +11,16 @@ if ($null -eq $www) { $sqlDataDir = $env:dnn_website_mgmt_sql_data_dir; $sqlLogsDir = if ($env:dnn_website_mgmt_sql_logs_dir) { $env:dnn_website_mgmt_sql_logs_dir } else { $sqlDataDir } +$serverConnectionString = $env:dnn_website_mgmt_sql_connection; +if ($null -eq $serverConnectionString) { + $serverConnectionString = 'Data Source=localhost;Integrated Security=true;Encrypt=false'; +} + +$connectionStringBuilder = New-Object -TypeName 'System.Data.SqlClient.SqlConnectionStringBuilder' -ArgumentList @($serverConnectionString); +$connectionStringBuilder['Database'] = 'master'; +$masterConnectionString = $connectionStringBuilder.ToString(); + + function Install-DNNResource { [Alias("Install-DNNResources")] param( @@ -112,15 +122,11 @@ function Remove-DNNSite { Write-Information "$sitePath does not exist" } - $sqlPath = Join-Path 'SQLSERVER:' 'SQL'; - $localhostSqlPath = Join-Path $sqlPath '(local)'; - $localSqlPath = Join-Path $localhostSqlPath 'DEFAULT'; - $databasesSqlPath = Join-Path $localSqlPath 'Databases'; - $databasePath = Join-Path $databasesSqlPath (ConvertTo-EncodedSqlName $Name); - if (Test-Path $databasePath) { + $databaseCount = invokeSql -Query "SELECT COUNT(*) AS Count FROM sys.databases WHERE name = '$Name'" -ConnectionString $masterConnectionString; + if ($databaseCount.Count -gt 0) { if ($PSCmdlet.ShouldProcess($Name, 'Drop Database')) { - invokeSql -Query:"ALTER DATABASE [$Name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;" -Database:master - invokeSql -Query:"DROP DATABASE [$Name];" -Database:master + invokeSql -Query:"ALTER DATABASE [$Name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;" -ConnectionString:$masterConnectionString + invokeSql -Query:"DROP DATABASE [$Name];" -ConnectionString:$masterConnectionString } } else { @@ -128,11 +134,10 @@ function Remove-DNNSite { } $loginName = "IIS AppPool\$Name"; - $loginsPath = Join-Path $localSqlPath 'Logins'; - $loginPath = Join-Path $loginsPath (ConvertTo-EncodedSqlName $loginName); - if (Test-Path $loginPath) { + $loginCount = invokeSql -Query "SELECT COUNT(*) AS Count FROM sys.sql_logins WHERE name = '$loginName'" -ConnectionString $masterConnectionString; + if ($loginCount.Count -gt 0) { if ($PSCmdlet.ShouldProcess($loginName, 'Drop login')) { - invokeSql -Query:"DROP LOGIN [$loginName];" -Database:master + invokeSql -Query:"DROP LOGIN [$loginName];" -ConnectionString:$masterConnectionString } } else { @@ -212,58 +217,57 @@ function Rename-DNNSite { $serverManager.CommitChanges(); - $sqlPath = Join-Path 'SQLSERVER:' 'SQL'; - $localhostSqlPath = Join-Path $sqlPath '(local)'; - $localSqlPath = Join-Path $localhostSqlPath 'DEFAULT'; - $databasesSqlPath = Join-Path $localSqlPath 'Databases'; - $databasePath = Join-Path $databasesSqlPath (ConvertTo-EncodedSqlName $Name); - if (Test-Path $databasePath) { + $databaseCount = invokeSql -Query "SELECT COUNT(*) AS Count FROM sys.databases WHERE name = '$Name'" -ConnectionString $masterConnectionString; + if ($databaseCount.Count -gt 0) { if ($PSCmdlet.ShouldProcess("$Name", "Close database connection")) { - invokeSql -Query:"ALTER DATABASE [$Name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;" -Database:master + invokeSql -Query:"ALTER DATABASE [$Name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;" -ConnectionString:$masterConnectionString } if ($PSCmdlet.ShouldProcess("$Name", "Rename database to $NewName")) { - invokeSql -Query:"ALTER DATABASE [$Name] MODIFY NAME = [$NewName];" -Database:master - invokeSql -Query:"ALTER DATABASE [$NewName] SET MULTI_USER WITH ROLLBACK IMMEDIATE;" -Database:master + invokeSql -Query:"ALTER DATABASE [$Name] MODIFY NAME = [$NewName];" -ConnectionString:$masterConnectionString + invokeSql -Query:"ALTER DATABASE [$NewName] SET MULTI_USER WITH ROLLBACK IMMEDIATE;" -ConnectionString:$masterConnectionString } } else { Write-Information "$Name database not found" } - $oldLoginName = "IIS AppPool\$Name"; - $newLoginName = "IIS AppPool\$NewName"; - $loginsPath = Join-Path $localSqlPath 'Logins'; - $newLoginPath = Join-Path $loginsPath (ConvertTo-EncodedSqlName $newLoginName); - if (-not (Test-Path $newLoginPath)) { - if ($PSCmdlet.ShouldProcess($newLoginName, "Create SQL Server login")) { - invokeSql -Query:"CREATE LOGIN [$newLoginName] FROM WINDOWS WITH DEFAULT_DATABASE = [$NewName];" -Database:master + if ($connectionStringBuilder.IntegratedSecurity) { + $oldLoginName = "IIS AppPool\$Name"; + $newLoginName = "IIS AppPool\$NewName"; + $loginCount = invokeSql -Query "SELECT COUNT(*) AS Count FROM sys.sql_logins WHERE name = '$newLoginName'" -ConnectionString $masterConnectionString; + if ($loginCount.Count -eq 0) { + if ($PSCmdlet.ShouldProcess($newLoginName, "Create SQL Server login")) { + invokeSql -Query:"CREATE LOGIN [$newLoginName] FROM WINDOWS WITH DEFAULT_DATABASE = [$NewName];" -ConnectionString:$masterConnectionString + } } } + $connectionStringBuilder['Database'] = $NewName; + $newConnectionString = $connectionStringBuilder.ToString(); if ($PSCmdlet.ShouldProcess($newLoginName, "Create SQL Server user")) { - invokeSql -Query:"CREATE USER [$newLoginName] FOR LOGIN [$newLoginName];" -Database:$NewName + invokeSql -Query:"CREATE USER [$newLoginName] FOR LOGIN [$newLoginName];" -Database:$newConnectionString } if ($PSCmdlet.ShouldProcess($newLoginName, "Add SQL Server user to db_owner role")) { - invokeSql -Query:"EXEC sp_addrolemember N'db_owner', N'$newLoginName';" -Database:$NewName + invokeSql -Query:"EXEC sp_addrolemember N'db_owner', N'$newLoginName';" -Database:$newConnectionString } - $ownedRoles = invokeSql -Query:"SELECT p2.name FROM sys.database_principals p1 JOIN sys.database_principals p2 ON p1.principal_id = p2.owning_principal_id WHERE p1.name = '$newLoginName';" -Database:$NewName + $ownedRoles = invokeSql -Query:"SELECT p2.name FROM sys.database_principals p1 JOIN sys.database_principals p2 ON p1.principal_id = p2.owning_principal_id WHERE p1.name = '$newLoginName';" -ConnectionString:$newConnectionString foreach ($roleRow in $ownedRoles) { $roleName = $roleRow.name if ($PSCmdlet.ShouldProcess("$roleName", "Transfer role ownership to $newLoginName")) { - invokeSql -Query:"ALTER AUTHORIZATION ON ROLE::[$roleName] TO [$newLoginName];" -Database:$NewName + invokeSql -Query:"ALTER AUTHORIZATION ON ROLE::[$roleName] TO [$newLoginName];" -ConnectionString:$newConnectionString } } if ($PSCmdlet.ShouldProcess($oldLoginName, "Drop SQL Server user")) { - invokeSql -Query:"DROP USER [$oldLoginName];" -Database:$NewName + invokeSql -Query:"DROP USER [$oldLoginName];" -ConnectionString:$newConnectionString } $oldLoginPath = Join-Path $loginsPath (ConvertTo-EncodedSqlName $oldLoginName); if (Test-Path $oldLoginPath) { if ($PSCmdlet.ShouldProcess($oldLoginName, "Drop SQL Server login")) { - invokeSql -Query:"DROP LOGIN [$oldLoginName];" -Database:master + invokeSql -Query:"DROP LOGIN [$oldLoginName];" -ConnectionString:$masterConnectionString } } else { @@ -276,17 +280,17 @@ function Rename-DNNSite { $webConfigPath = Join-Path $newWebsitePath 'web.config'; if ($PSCmdlet.ShouldProcess($webConfigPath, "Update connection string")) { - [xml]$webConfig = Get-Content $webConfigPath - $ObjectQualifier = $webConfig.configuration.dotnetnuke.data.providers.add.objectQualifier.TrimEnd('_') - $DatabaseOwner = $webConfig.configuration.dotnetnuke.data.providers.add.databaseOwner.TrimEnd('.') - $connectionString = "Data Source=.`;Initial Catalog=$NewName`;Integrated Security=true" - $webConfig.configuration.connectionStrings.add | Where-Object { $_.name -eq 'SiteSqlServer' } | ForEach-Object { $_.connectionString = $connectionString } - $webConfig.configuration.appSettings.add | Where-Object { $_.key -eq 'SiteSqlServer' } | ForEach-Object { $_.value = $connectionString } - $webConfig.Save($webConfigPath) + [xml]$webConfig = Get-Content $webConfigPath; + $ObjectQualifier = $webConfig.configuration.dotnetnuke.data.providers.add.objectQualifier.TrimEnd('_'); + $DatabaseOwner = $webConfig.configuration.dotnetnuke.data.providers.add.databaseOwner.TrimEnd('.'); + $connectionString = $newConnectionString; + $webConfig.configuration.connectionStrings.add | Where-Object { $_.name -eq 'SiteSqlServer' } | ForEach-Object { $_.connectionString = $connectionString }; + $webConfig.configuration.appSettings.add | Where-Object { $_.key -eq 'SiteSqlServer' } | ForEach-Object { $_.value = $connectionString }; + $webConfig.Save($webConfigPath); } if ($PSCmdlet.ShouldProcess("$NewName", "Replace $Name in portal aliases")) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET HTTPAlias = REPLACE(HTTPAlias, '$Name', '$NewName')" -Database:$NewName + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET HTTPAlias = REPLACE(HTTPAlias, '$Name', '$NewName')" -ConnectionString:$newConnectionString } if ($PSCmdlet.ShouldProcess("$Name", "Remove HOSTS file entry")) { @@ -554,6 +558,9 @@ function New-DNNSite { Remove-Item $clonePath -Recurse -Force -Confirm:$false; } + $connectionStringBuilder['Database'] = $Name; + $newConnectionString = $connectionStringBuilder.ToString(); + $webConfigPath = Join-Path $websitePath 'web.config'; [xml]$webConfig = Get-Content $webConfigPath; if ($DatabaseBackupPath -eq '') { @@ -565,14 +572,14 @@ function New-DNNSite { else { if ($PSCmdlet.ShouldProcess($DatabaseBackupPath, 'Restore Database')) { restoreDnnDatabase $Name (Get-Item $DatabaseBackupPath).FullName -ErrorAction Stop; - invokeSql -Query:"ALTER DATABASE [$Name] SET RECOVERY SIMPLE" -Database:master + invokeSql -Query:"ALTER DATABASE [$Name] SET RECOVERY SIMPLE" -ConnectionString:$masterConnectionString } $ObjectQualifier = $webConfig.configuration.dotnetnuke.data.providers.add.objectQualifier.TrimEnd('_') $DatabaseOwner = $webConfig.configuration.dotnetnuke.data.providers.add.databaseOwner.TrimEnd('.') if ($PSCmdlet.ShouldProcess($Name, 'Update Portal Aliases')) { - $aliases = @(invokeSql -Query:"SELECT PortalID, HTTPAlias FROM $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) ORDER BY PortalID, HTTPAlias" -Database:$Name); + $aliases = @(invokeSql -Query:"SELECT PortalID, HTTPAlias FROM $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) ORDER BY PortalID, HTTPAlias" -ConnectionString:$newConnectionString); if ($Domain -ne '') { $aliasCount = $aliases.Count $ProcessManual = $false @@ -590,13 +597,13 @@ function New-DNNSite { $newAlias = if ($customAlias) { $customAlias } else { $newAlias } } if ($PSCmdlet.ShouldProcess($newAlias, 'Rename alias')) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET HTTPAlias = '$newAlias' WHERE HTTPAlias = '$alias'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '$newAlias' WHERE SettingName = 'DefaultPortalAlias' AND SettingValue = '$alias'" -Database:$Name + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET HTTPAlias = '$newAlias' WHERE HTTPAlias = '$alias'" -ConnectionString:$newConnectionString + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '$newAlias' WHERE SettingName = 'DefaultPortalAlias' AND SettingValue = '$alias'" -ConnectionString:$newConnectionString } } } - $aliases = invokeSql -Query:"SELECT HTTPAlias FROM $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) ORDER BY PortalID, HTTPAlias" -Database:$Name + $aliases = invokeSql -Query:"SELECT HTTPAlias FROM $(getDnnDatabaseObjectName -objectName:'PortalAlias' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) ORDER BY PortalID, HTTPAlias" -ConnectionString:$newConnectionString foreach ($aliasRow in $aliases) { $aliasInfo = readPortalAlias -Alias:$aliasRow.HTTPAlias; $aliasHost = $aliasInfo.host; @@ -627,43 +634,31 @@ function New-DNNSite { $oq = '' } - $sqlPath = Join-Path 'SQLSERVER:' 'SQL'; - $localhostSqlPath = Join-Path $sqlPath '(local)'; - $localSqlPath = Join-Path $localhostSqlPath 'DEFAULT'; - $databasesPath = Join-Path $localSqlPath 'Databases'; - $databasePath = Join-Path $databasesPath (ConvertTo-EncodedSqlName $Name); - $tablesPath = Join-Path $databasePath 'Tables'; - $catalookSettingsTablePath = Join-Path $tablesPath "$DatabaseOwner.${oq}CAT_Settings"; - if ((Test-Path $catalookSettingsTablePath) -and ($PSCmdlet.ShouldProcess($Name, 'Set Catalook to test mode'))) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'CAT_Settings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET PostItems = 0, StorePaymentTypes = 32, StoreCCTypes = 23, CCLogin = '${env:CatalookTestCCLogin}', CCPassword = '${env:CatalookTestCCPassword}', CCMerchantHash = '${env:CatalookTestCCMerchantHash}', StoreCurrencyid = 2, CCPaymentProcessorID = 59, LicenceKey = '${env:CatalookTestLicenseKey}', StoreEmail = '${env:CatalookTestStoreEmail}', Skin = '${env:CatalookTestSkin}', EmailTemplatePackage = '${env:CatalookTestEmailTemplatePackage}', CCTestMode = 1, EnableAJAX = 1" -Database:$Name + if ((tableExists -TableName:"${oq}CAT_Settings" -ConnectionString:$newConnectionString) -and ($PSCmdlet.ShouldProcess($Name, 'Set Catalook to test mode'))) { + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'CAT_Settings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET PostItems = 0, StorePaymentTypes = 32, StoreCCTypes = 23, CCLogin = '${env:CatalookTestCCLogin}', CCPassword = '${env:CatalookTestCCPassword}', CCMerchantHash = '${env:CatalookTestCCMerchantHash}', StoreCurrencyid = 2, CCPaymentProcessorID = 59, LicenceKey = '${env:CatalookTestLicenseKey}', StoreEmail = '${env:CatalookTestStoreEmail}', Skin = '${env:CatalookTestSkin}', EmailTemplatePackage = '${env:CatalookTestEmailTemplatePackage}', CCTestMode = 1, EnableAJAX = 1" -ConnectionString:$newConnectionString } - $esmSettingsTablePath = Join-Path $tablesPath "$DatabaseOwner.${oq}esm_Settings"; - $esmSettingsColumnsPath = Join-Path $esmSettingsTablePath 'Columns'; - $esmSettingsFattmerchantPath = Join-Path $esmSettingsColumnsPath 'FattmerchantMerchantId'; - if ((Test-Path $esmSettingsFattmerchantPath) -and ($PSCmdlet.ShouldProcess($Name, 'Set FattMerchant to test mode'))) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'esm_Settings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET MerchantRegistrationStatusId = null, FattmerchantMerchantId = null, FattmerchantApiKey = '${env:FattmerchantTestApiKey}', FattmerchantPaymentsToken = '${env:FattmerchantTestPaymentsToken}' WHERE CCPaymentProcessorID = 185" -Database:$Name + $hasFattMerchantColumn = columnExists -TableName "${oq}esm_Settings" -ColumnName 'FattmerchantMerchantId' -ConnectionString $newConnectionString; + if ($hasFattMerchantColumn -and ($PSCmdlet.ShouldProcess($Name, 'Set FattMerchant to test mode'))) { + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'esm_Settings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET MerchantRegistrationStatusId = null, FattmerchantMerchantId = null, FattmerchantApiKey = '${env:FattmerchantTestApiKey}', FattmerchantPaymentsToken = '${env:FattmerchantTestPaymentsToken}' WHERE CCPaymentProcessorID = 185" -ConnectionString:$newConnectionString } - $esmSettingsStaxPath = Join-Path $esmSettingsColumnsPath 'StaxMerchantId'; - if ((Test-Path $esmSettingsStaxPath) -and ($PSCmdlet.ShouldProcess($Name, 'Set Stax to test mode'))) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'esm_Settings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET MerchantRegistrationStatusId = null, StaxMerchantId = null, StaxApiKey = '${env:StaxTestApiKey}', StaxPaymentsToken = '${env:StaxTestPaymentsToken}' WHERE CCPaymentProcessorID = 185" -Database:$Name + $hasStaxMerchantColumn = columnExists -TableName "${oq}esm_Settings" -ColumnName 'StaxMerchantId' -ConnectionString $newConnectionString; + if ($hasStaxMerchantColumn -and ($PSCmdlet.ShouldProcess($Name, 'Set Stax to test mode'))) { + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'esm_Settings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET MerchantRegistrationStatusId = null, StaxMerchantId = null, StaxApiKey = '${env:StaxTestApiKey}', StaxPaymentsToken = '${env:StaxTestPaymentsToken}' WHERE CCPaymentProcessorID = 185" -ConnectionString:$newConnectionString } - $esmParticipantTablePath = Join-Path $tablesPath "$DatabaseOwner.${oq}esm_Participant"; - if ((Test-Path $esmParticipantTablePath) -and ($PSCmdlet.ShouldProcess($Name, 'Turn off payment processing for Engage: AMS'))) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'esm_Participant' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET PaymentProcessorCustomerId = NULL" -Database:$Name + if ((tableExists -TableName:"${oq}esm_Participant" -ConnectionString:$newConnectionString) -and ($PSCmdlet.ShouldProcess($Name, 'Turn off payment processing for Engage: AMS'))) { + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'esm_Participant' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET PaymentProcessorCustomerId = NULL" -ConnectionString:$newConnectionString } if ($PSCmdlet.ShouldProcess($Name, 'Turn off SMTP for Mandeeps Live Campaign')) { - $liveCampaignSettingTablePath = Join-Path $tablesPath "$DatabaseOwner.${oq}LiveCampaign_Setting"; - if (Test-Path $liveCampaignSettingTablePath) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'LiveCampaign_Setting' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SMTPServerMode = 'DNNHostSettings', SendGridAPI = NULL WHERE SMTPServerMode = 'Sendgrid'" -Database:$Name + if (tableExists -TableName:"${oq}LiveCampaign_Setting" -ConnectionString:$newConnectionString) { + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'LiveCampaign_Setting' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SMTPServerMode = 'DNNHostSettings', SendGridAPI = NULL WHERE SMTPServerMode = 'Sendgrid'" -ConnectionString:$newConnectionString } - $liveCampaignSmtpTablePath = Join-Path $tablesPath "$DatabaseOwner.${oq}LiveCampaign_SmtpServer"; - if (Test-Path $liveCampaignSmtpTablePath) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'LiveCampaign_SmtpServer' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET Server = 'localhost', Username = '', Password = ''" -Database:$Name + if (tableExists -TableName:"${oq}LiveCampaign_SmtpServer" -ConnectionString:$newConnectionString) { + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'LiveCampaign_SmtpServer' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET Server = 'localhost', Username = '', Password = ''" -ConnectionString:$newConnectionString } } @@ -675,55 +670,81 @@ function New-DNNSite { Write-Information "Setting SMTP to localhost" if ($PSCmdlet.ShouldProcess($Name, 'Set SMTP to localhost')) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'localhost' WHERE SettingName = 'SMTPServer'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '0' WHERE SettingName = 'SMTPAuthentication'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'N' WHERE SettingName = 'SMTPEnableSSL'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPUsername'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPPassword'" -Database:$Name - - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'localhost' WHERE SettingName = 'SMTPServer'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '0' WHERE SettingName = 'SMTPAuthentication'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'N' WHERE SettingName = 'SMTPEnableSSL'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPUsername'" -Database:$Name - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPPassword'" -Database:$Name - } - + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'localhost' WHERE SettingName = 'SMTPServer'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPServer setting to localhost"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '0' WHERE SettingName = 'SMTPAuthentication'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPAuthentication setting to 0"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'N' WHERE SettingName = 'SMTPEnableSSL'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPEnableSSL setting to N"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPUsername'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPUsername setting to ''"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPPassword'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPPassword setting to ''"; + + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'localhost' WHERE SettingName = 'SMTPServer'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPServer setting to localhost"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '0' WHERE SettingName = 'SMTPAuthentication'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPAuthentication setting to 0"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'N' WHERE SettingName = 'SMTPEnableSSL'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPEnableSSL setting to N"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPUsername'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPUsername setting to ''"; + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'PortalSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = '' WHERE SettingName = 'SMTPPassword'" -ConnectionString:$newConnectionString + Write-Verbose "Updated SMTPPassword setting to ''"; + Write-Debug "Finished settings SMTP to localhost"; + } + + Write-Debug "About to clear WebServers table"; if ($PSCmdlet.ShouldProcess($Name, 'Clear WebServers table')) { - invokeSql -Query:"TRUNCATE TABLE $(getDnnDatabaseObjectName -objectName:'WebServers' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier)" -Database:$Name + invokeSql -Query:"TRUNCATE TABLE $(getDnnDatabaseObjectName -objectName:'WebServers' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier)" -ConnectionString:$newConnectionString + Write-Verbose "Processed clear WebServers table"; } + Write-Debug "About to turn off event log buffer"; if ($PSCmdlet.ShouldProcess($Name, 'Turn off event log buffer')) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'N' WHERE SettingName = 'EventLogBuffer'" -Database:$Name + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'HostSettings' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET SettingValue = 'N' WHERE SettingName = 'EventLogBuffer'" -ConnectionString:$newConnectionString + Write-Verbose "Turned off event log buffer"; } + Write-Debug "About to turn off search crawler"; if ($PSCmdlet.ShouldProcess($Name, 'Turn off search crawler')) { - invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'Schedule' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET Enabled = 0 WHERE TypeFullName = 'DotNetNuke.Professional.SearchCrawler.SearchSpider.SearchSpider, DotNetNuke.Professional.SearchCrawler'" -Database:$Name + invokeSql -Query:"UPDATE $(getDnnDatabaseObjectName -objectName:'Schedule' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) SET Enabled = 0 WHERE TypeFullName = 'DotNetNuke.Professional.SearchCrawler.SearchSpider.SearchSpider, DotNetNuke.Professional.SearchCrawler'" -ConnectionString:$newConnectionString + Write-Verbose 'Turned off search crawler'; } + Write-Debug 'About to reset all passwords'; if ($PSCmdlet.ShouldProcess($Name, "Set all passwords to 'pass'")) { - invokeSql -Query:"UPDATE aspnet_Membership SET PasswordFormat = 0, Password = 'pass'" -Database:$Name + invokeSql -Query:"UPDATE aspnet_Membership SET PasswordFormat = 0, Password = 'pass'" -ConnectionString:$newConnectionString + Write-Verbose 'Reset all passwords'; } + Write-Debug 'About to watermark site logos'; if ($PSCmdlet.ShouldProcess($Name, 'Watermark site logo(s)')) { watermarkLogos $Name $NameExtension + Write-Verbose 'Watermarked logos'; } + Write-Debug 'About to remove App Insights config'; $appInsightsPath = Join-Path $websitePath 'ApplicationInsights.config'; if ((Test-Path $appInsightsPath) -and ($PSCmdlet.ShouldProcess($Name, 'Remove Application Insights config'))) { Remove-Item $appInsightsPath -WhatIf:$WhatIfPreference -Confirm:$false; + Write-Verbose 'Remove App Insights config'; } } + Write-Debug 'About to set connectionString in web.config'; if ($PSCmdlet.ShouldProcess($webConfigPath, 'Set connectionString in web.config')) { - $connectionString = "Data Source=.`;Initial Catalog=$Name`;Integrated Security=true" - $webConfig.configuration.connectionStrings.add | Where-Object { $_.name -eq 'SiteSqlServer' } | ForEach-Object { $_.connectionString = $connectionString } - $webConfig.configuration.appSettings.add | Where-Object { $_.key -eq 'SiteSqlServer' } | ForEach-Object { $_.value = $connectionString } + $webConfig.configuration.connectionStrings.add | Where-Object { $_.name -eq 'SiteSqlServer' } | ForEach-Object { $_.connectionString = $newConnectionString } + $webConfig.configuration.appSettings.add | Where-Object { $_.key -eq 'SiteSqlServer' } | ForEach-Object { $_.value = $newConnectionString } $webConfig.Save($webConfigPath) + Write-Verbose 'Set connectionString in web.config'; } + Write-Debug 'About to set objectQualifier and databaseOwner in web.config'; if ($PSCmdlet.ShouldProcess($webConfigPath, 'Set objectQualifier and databaseOwner in web.config')) { $webConfig.configuration.dotnetnuke.data.providers.add | Where-Object { $_.name -eq 'SqlDataProvider' } | ForEach-Object { $_.objectQualifier = $ObjectQualifier; $_.databaseOwner = $DatabaseOwner } $webConfig.Save($webConfigPath) + Write-Verbose 'Set objectQualifier and databaseOwner in web.config'; } $systemWebSection = $webConfig.configuration['system.web']; @@ -731,35 +752,39 @@ function New-DNNSite { $systemWebSection = $webConfig.configuration.location['system.web']; } + Write-Debug 'About to update web.config to allow short passwords'; if ($PSCmdlet.ShouldProcess($webConfigPath, 'Update web.config to allow short passwords')) { $systemWebSection.membership.providers.add | Where-Object { $_.type -eq 'System.Web.Security.SqlMembershipProvider' } | ForEach-Object { $_.minRequiredPasswordLength = '4' } $webConfig.Save($webConfigPath) + Write-Verbose 'Updated web.config to allow short passwords'; } + Write-Debug 'About to turn off debug mode in web.config'; if ($PSCmdlet.ShouldProcess($webConfigPath, 'Turn on debug mode in web.config')) { $systemWebSection.compilation.debug = 'true' $webConfig.Save($webConfigPath) + Write-Verbose 'Turned on debug mode in web.config'; } - $loginName = "IIS AppPool\$Name"; - $sqlPath = Join-Path 'SQLSERVER:' 'SQL'; - $localhostSqlPath = Join-Path $sqlPath '(local)'; - $localSqlPath = Join-Path $localhostSqlPath 'DEFAULT'; - $loginsPath = Join-Path $localSqlPath 'Logins'; - $loginPath = Join-Path $loginsPath (ConvertTo-EncodedSqlName $loginName); - if ((-not (Test-Path $loginPath)) -and ($PSCmdlet.ShouldProcess($loginName, 'Create SQL Server login'))) { - invokeSql -Query:"CREATE LOGIN [$loginName] FROM WINDOWS WITH DEFAULT_DATABASE = [$Name];" -Database:master - } + if ($connectionStringBuilder.IntegratedSecurity) { + $loginName = "IIS AppPool\$Name"; + $loginCount = invokeSql -Query:"SELECT COUNT(*) AS Count FROM sys.sql_logins WHERE name = '$loginName'" -ConnectionString:$masterConnectionString; + if (($loginCount.Count -eq 0) -and ($PSCmdlet.ShouldProcess($loginName, 'Create SQL Server login'))) { + invokeSql -Query:"CREATE LOGIN [$loginName] FROM WINDOWS WITH DEFAULT_DATABASE = [$Name];" -ConnectionString:$masterConnectionString + } - if ($PSCmdlet.ShouldProcess($loginName, 'Create SQL Server User')) { - invokeSql -Query:"CREATE USER [$loginName] FOR LOGIN [$loginName];" -Database:$Name - } - if ($PSCmdlet.ShouldProcess($loginName, 'Add db_owner role')) { - invokeSql -Query:"EXEC sp_addrolemember N'db_owner', N'$loginName';" -Database:$Name + if ($PSCmdlet.ShouldProcess($loginName, 'Create SQL Server User')) { + invokeSql -Query:"CREATE USER [$loginName] FOR LOGIN [$loginName];" -ConnectionString:$newConnectionString + } + if ($PSCmdlet.ShouldProcess($loginName, 'Add db_owner role')) { + invokeSql -Query:"EXEC sp_addrolemember N'db_owner', N'$loginName';" -ConnectionString:$newConnectionString + } } + Write-Debug 'About to add HTTPS bindings'; if ($PSCmdlet.ShouldProcess($Name, 'Add HTTPS bindings')) { New-SslWebBinding $Name $domains -WhatIf:$WhatIfPreference -Confirm:$false; + Write-Verbose 'Added HTTPS bindings'; } if ($PSCmdlet.ShouldProcess("https://$Name", 'Open browser')) { @@ -1033,21 +1058,41 @@ function processFilesWithProgress($from, $to, [scriptblock]$process, $activity, Write-Progress -Activity:$activity -PercentComplete 100 -Completed; } -$sqlModuleHasEncryptParam = $null -ne (Get-Command Invoke-Sqlcmd).Parameters['Encrypt']; function invokeSql { param( [parameter(Mandatory = $true, position = 0)] [string]$Query, [parameter(Mandatory = $true, position = 1)] - [string]$Database + [string]$ConnectionString ); - if ($sqlModuleHasEncryptParam) { - Invoke-Sqlcmd -Query:$Query -Database:$Database -Encrypt:Optional; + Invoke-Sqlcmd -Query:$Query -ConnectionString:$ConnectionString; } - else { - Invoke-Sqlcmd -Query:$Query -Database:$Database -EncryptConnection:$false; + +function tableExists { + param( + [parameter(Mandatory = $true, position = 0)] + [string]$TableName, + [parameter(Mandatory = $true, position = 1)] + [string]$ConnectionString + ); + + $result = invokeSql -Query:"SELECT COUNT(*) AS Count FROM sys.tables WHERE name = '$TableName'" -ConnectionString:$ConnectionString; + return $result.Count -gt 0; } + +function columnExists { + param( + [parameter(Mandatory = $true, position = 0)] + [string]$TableName, + [parameter(Mandatory = $true, position = 1)] + [string]$ColumnName, + [parameter(Mandatory = $true, position = 2)] + [string]$ConnectionString + ); + + $result = invokeSql -Query:"SELECT COUNT(*) AS Count FROM sys.tables t JOIN sys.columns c ON t.object_id = c.object_id WHERE t.name = '$TableName' AND c.name = '$ColumnName'" -ConnectionString:$ConnectionString; + return $result.Count -gt 0; } @@ -1057,8 +1102,8 @@ function newDnnDatabase { [string]$Name ); - invokeSql -Query:"CREATE DATABASE [$Name];" -Database:master; - invokeSql -Query:"ALTER DATABASE [$Name] SET RECOVERY SIMPLE;" -Database:master; + invokeSql -Query:"CREATE DATABASE [$Name];" -ConnectionString:$masterConnectionString; + invokeSql -Query:"ALTER DATABASE [$Name] SET RECOVERY SIMPLE;" -ConnectionString:$masterConnectionString; } function restoreDnnDatabase { @@ -1100,24 +1145,33 @@ function restoreDnnDatabase { $logicalLogFileName = $Name; #based on http://redmondmag.com/articles/2009/12/21/automated-restores.aspx - $server = New-Object Microsoft.SqlServer.Management.Smo.Server('(local)'); - $dbRestore = New-Object Microsoft.SqlServer.Management.Smo.Restore; - $dbRestore.Devices.AddDevice($DatabaseBackupPath, [Microsoft.SqlServer.Management.Smo.DeviceType]::File) - foreach ($file in $dbRestore.ReadFileList($server)) { - switch ($file.Type) { - 'D' { $logicalDataFileName = $file.LogicalName } - 'L' { $logicalLogFileName = $file.LogicalName } + $connection = $null; + try { + $connection = New-Object Microsoft.Data.SqlClient.SqlConnection($masterConnectionString); + $server = New-Object Microsoft.SqlServer.Management.Smo.Server($connection); + $dbRestore = New-Object Microsoft.SqlServer.Management.Smo.Restore; + $dbRestore.Devices.AddDevice($DatabaseBackupPath, [Microsoft.SqlServer.Management.Smo.DeviceType]::File) + foreach ($file in $dbRestore.ReadFileList($server)) { + switch ($file.Type) { + 'D' { $logicalDataFileName = $file.LogicalName } + 'L' { $logicalLogFileName = $file.LogicalName } + } } - } - $dbRestoreFile.LogicalFileName = $logicalDataFileName; - $dataDir = if ($sqlDataDir) { $sqlDataDir } else { $server.Information.MasterDBPath } - $dbRestoreFile.PhysicalFileName = Join-Path $dataDir ($Name + '_Data.mdf'); - $dbRestoreLog.LogicalFileName = $logicalLogFileName; - $logsDir = if ($sqlLogsDir) { $sqlLogsDir } else { $server.Information.MasterDBLogPath } - $dbRestoreLog.PhysicalFileName = Join-Path $logsDir ($Name + '_Log.ldf'); + $dbRestoreFile.LogicalFileName = $logicalDataFileName; + $dataDir = if ($sqlDataDir) { $sqlDataDir } else { $server.Information.MasterDBPath } + $dbRestoreFile.PhysicalFileName = Join-Path $dataDir ($Name + '_Data.mdf'); + $dbRestoreLog.LogicalFileName = $logicalLogFileName; + $logsDir = if ($sqlLogsDir) { $sqlLogsDir } else { $server.Information.MasterDBLogPath } + $dbRestoreLog.PhysicalFileName = Join-Path $logsDir ($Name + '_Log.ldf'); - Restore-SqlDatabase -ReplaceDatabase -Database:$Name -RelocateFile:@($dbRestoreFile, $dbRestoreLog) -BackupFile:$DatabaseBackupPath -ServerInstance:'(local)' -Confirm:$false; + Restore-SqlDatabase -ReplaceDatabase -Database:$Name -RelocateFile:@($dbRestoreFile, $dbRestoreLog) -BackupFile:$DatabaseBackupPath -ServerInstance:$connectionStringBuilder.DataSource -Confirm:$false; +} + finally { + if ($connection) { + $connection.Dispose(); + } + } } function getDnnDatabaseObjectName { @@ -1180,7 +1234,10 @@ function watermarkLogos { $sitePath = Join-Path $www $Name; $websitePath = Join-Path $sitePath 'Website'; - $logos = invokeSql -Query:"SELECT HomeDirectory + N'/' + LogoFile AS Logo FROM $(getDnnDatabaseObjectName -objectName:'Vw_Portals' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) WHERE LogoFile IS NOT NULL" -Database:$Name + + $connectionStringBuilder['Database'] = $Name; + $newConnectionString = $connectionStringBuilder.ToString(); + $logos = invokeSql -Query:"SELECT HomeDirectory + N'/' + LogoFile AS Logo FROM $(getDnnDatabaseObjectName -objectName:'Vw_Portals' -DatabaseOwner:$DatabaseOwner -ObjectQualifier:$ObjectQualifier) WHERE LogoFile IS NOT NULL" -ConnectionString:$newConnectionString; $watermarkText = $NameExtension.Substring(1) foreach ($logo in $logos) { $logoFile = Join-Path $websitePath $logo.Logo.Replace('/', '\');