Skip to content

Commit 7096e46

Browse files
StephenMolloyHongGit
authored andcommitted
User secrets vs install (#9)
* Create ID and link secrets.xml in 'Properties' via Install.ps1 * Handle Uninstall.
1 parent 79b2cbc commit 7096e46

7 files changed

Lines changed: 174 additions & 5 deletions

File tree

src/UserSecrets/UserSecretsConfigBuilder.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,16 @@ private string GetSecretsFileFromId(string secretsId)
9292
throw new InvalidOperationException($"UserSecretsConfigBuilder '{Name}': Invalid character '{secretsId[badCharIndex]}' in '{userSecretsIdTag}'.");
9393
}
9494

95-
string root = Environment.GetEnvironmentVariable("APPDATA") ?? Environment.GetEnvironmentVariable("HOME");
96-
95+
// Try Windows-style first
96+
string root = Environment.GetEnvironmentVariable("APPDATA");
9797
if (!String.IsNullOrWhiteSpace(root))
9898
return Path.Combine(root, "Microsoft", "UserSecrets", secretsId, "secrets.xml");
9999

100+
// Then try unix-style
101+
root = Environment.GetEnvironmentVariable("HOME");
102+
if (!String.IsNullOrWhiteSpace(root))
103+
return Path.Combine(root, ".microsoft", "usersecrets", secretsId, "secrets.xml");
104+
100105
return null;
101106
}
102107

src/packages/ConfigurationBuilders.UserSecrets.nupkg/Microsoft.Configuration.ConfigurationBuilders.UserSecrets.nuproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,18 @@
3434
<NuGetContent Include="Content\Net471\config.uninstall.xdt">
3535
<Destination>content\Net471\web.config.uninstall.xdt</Destination>
3636
</NuGetContent>
37+
<NuGetContent Include="Content\sample.xml">
38+
<Destination>content\sample.xml</Destination>
39+
</NuGetContent>
3740
<NuGetContent Include="build\Net471\$(NuGetPackageId).props">
3841
<Destination>build\Net471\$(NuGetPackageId).props</Destination>
3942
</NuGetContent>
4043
<NuGetContent Include="build\Net471\$(NuGetPackageId).targets">
4144
<Destination>build\Net471\$(NuGetPackageId).targets</Destination>
4245
</NuGetContent>
46+
<NuGetContent Include="tools\Net471\*.ps1">
47+
<Destination>tools\Net471\</Destination>
48+
</NuGetContent>
4349
</ItemGroup>
4450
<Import Project="$(RepositoryRoot)Tools\NuGetProj.targets"/>
4551
</Project>

src/packages/ConfigurationBuilders.UserSecrets.nupkg/content/Net471/config.install.xdt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
<configBuilders xdt:Transform="InsertAfter(/configuration/configSections)" />
55

6-
<!-- Always configure for $(UserSecretsId), since the VS dev scenario is the target use case for this feature -->
6+
<!-- Always configure for ${UserSecretsId}, since the VS dev scenario is the target use case for this feature -->
77
<configBuilders xdt:Locator="XPath(/configuration/configBuilders[last()])">
88
<builders xdt:Transform="InsertIfMissing">
9-
<add name="Secrets" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" type="Microsoft.Configuration.ConfigurationBuilders.UserSecretsConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.UserSecrets, Version=$version$, Culture=neutral" />
9+
<add name="Secrets" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" userSecretsId="${UserSecretsId}" type="Microsoft.Configuration.ConfigurationBuilders.UserSecretsConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.UserSecrets, Version=$version$, Culture=neutral" />
1010
</builders>
1111
</configBuilders>
1212

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<root>
2+
<!--
3+
This is the secrets storage file for Microsoft.Configuration.ConfigurationBuilders.UserSecrets.
4+
Using this config builder to store connection strings may prevent some Visual Studio datasource
5+
controls from working correctly.
6+
-->
7+
<secrets ver="1.0">
8+
<!-- <secret name="sampleSecret" value="foo" /> -->
9+
</secrets>
10+
</root>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Copyright (c) .NET Foundation. All rights reserved.
2+
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
param($installPath, $toolsPath, $package, $project)
5+
6+
##### Supporting Functions #####
7+
function EnsureUserSecretsId {
8+
$id = $null
9+
foreach ($prop in $root.Properties) {
10+
if ($prop.Name -eq 'UserSecretsId') {
11+
$id=$prop.Value
12+
}
13+
}
14+
if ([string]::IsNullOrEmpty($id)) {
15+
Write-Host ("Generating new UserSecretsId for project " + $project.FullName + "...")
16+
$newUserSecretsId=New-Guid
17+
$id=$newUserSecretsId
18+
$root.AddProperty('UserSecretsId', $newUserSecretsId.ToString())
19+
Write-Host ("Set UserSecretsId for project to " + $newUserSecretsId)
20+
}
21+
return $id
22+
}
23+
24+
function EnsureUserSecretsFile {
25+
$datadir=$env:APPDATA
26+
$dirpath=[io.path]::combine($datadir, "Microsoft", "UserSecrets", $userSecretsId)
27+
$envpath=[io.path]::combine('$(APPDATA)', "Microsoft", "UserSecrets", $userSecretsId, "secrets.xml")
28+
if ([string]::IsNullOrEmpty($datadir) -or !(Test-Path $datadir)) {
29+
$datadir=$env:HOME
30+
$dirpath=[io.path]::combine($datadir, ".microsoft", "usersecrets", $userSecretsId)
31+
$envpath=[io.path]::combine('~', ".microsoft", "usersecrets", $userSecretsId, "secrets.xml")
32+
}
33+
if ([string]::IsNullOrEmpty($datadir) -or !(Test-Path $datadir)) {
34+
return $null,$null
35+
}
36+
37+
$filepath=[io.path]::combine($dirpath, "secrets.xml")
38+
$sourcepath=[io.path]::combine($installPath, "content", "sample.xml")
39+
40+
41+
# Don't overwrite an existing secrets file
42+
if (!(Test-Path $filepath)) {
43+
New-Item $dirpath -Type Directory -Force
44+
Copy-Item $sourcepath $filepath -Force
45+
}
46+
47+
return $envpath,$filepath
48+
}
49+
50+
function LinkSecretsFile {
51+
# Make sure there is something to link
52+
if ($secretsFile -eq $null) {
53+
return
54+
}
55+
56+
# Be smart about the special 'Properties' folder
57+
$appDesignerFolder=$root.Properties | Where-Object {$_.Name -eq 'AppDesignerFolderIsNotHere'} | Select-Object -ExpandProperty Value
58+
if ([string]::IsNullOrEmpty($appDesignerFolder)) {
59+
$appDesignerFolder="Properties"
60+
}
61+
62+
# Add secrets.xml as a 'Link'
63+
$propertiesDir=$project.ProjectItems.Item($appDesignerFolder)
64+
$item=$propertiesDir.ProjectItems.AddFromFile($expandedSecretsFile)
65+
if (!($item -eq $null)) {
66+
# If we successfully added the link, update the location to use $(APPDATA) variable instead of an expanded path.
67+
$msbuildItem=$root.Items | Where-Object {$_.Metadata | Where-Object {($_.Name -eq 'Link') -and ($_.Value -eq "$appDesignerFolder\secrets.xml")} } | Select-Object
68+
$msbuildItem.Include=$secretsFile
69+
}
70+
}
71+
72+
73+
74+
##### Begin Installation #####
75+
Write-Host ('Executing Install.ps1 in UserSecrets package...')
76+
$project.Save()
77+
$root = [Microsoft.Build.Construction.ProjectRootElement]::Open($project.FullName)
78+
79+
# Ensure UserSecretsId exists
80+
$userSecretsId = EnsureUserSecretsId
81+
82+
# Ensure the secrets file exists
83+
$secretsFile, $expandedSecretsFile = EnsureUserSecretsFile
84+
85+
# Ensure the file is linked in AppDesignerFolder, aka 'Properties'
86+
LinkSecretsFile
87+
88+
# Done
89+
$project.Save()
90+
Write-Host ('Done.')
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Copyright (c) .NET Foundation. All rights reserved.
2+
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
param($installPath, $toolsPath, $package, $project)
5+
6+
##### Supporting Functions #####
7+
function GetPropertyValues {
8+
# $(UserSecretsId)
9+
$id=$root.Properties | Where-Object {$_.Name -eq 'UserSecretsId'} | Select-Object -ExpandProperty Value
10+
if ([string]::IsNullOrEmpty($id)) {
11+
$id=$null
12+
}
13+
14+
# $(AppDesignerFoler), aka the special 'Properties' folder
15+
$appDesignerFolder=$root.Properties | Where-Object {$_.Name -eq 'AppDesignerFolderIsNotHere'} | Select-Object -ExpandProperty Value
16+
if ([string]::IsNullOrEmpty($appDesignerFolder)) {
17+
$appDesignerFolder="Properties"
18+
}
19+
20+
return $id,$appDesignerFolder
21+
}
22+
23+
function UnlinkSecretsFile {
24+
# Remove secrets.xml 'Link'
25+
$propertiesDir=$project.ProjectItems.Item($propertiesFolder)
26+
$secretsItem=$propertiesDir.ProjectItems.Item('secrets.xml')
27+
if (!($secretsItem -eq $null)) {
28+
$secretsItem.Remove()
29+
}
30+
}
31+
32+
33+
34+
##### Begin Uninstall #####
35+
Write-Host ('Executing Uninstall.ps1 for UserSecrets package...')
36+
$project.Save()
37+
$root = [Microsoft.Build.Construction.ProjectRootElement]::Open($project.FullName)
38+
39+
# Use ProjectRootElement to reliably get the property values we need...
40+
# Then get rid of it. If we hang on to it till the end, it will undo our work
41+
# in the $project object.
42+
$userSecretsId,$propertiesFolder=GetPropertyValues
43+
$root.Save()
44+
$root=$null
45+
46+
if (!($userSecretsId -eq $null)) {
47+
# Just unlink Properties\secrets.xml. Leave the actual xml file and $(UserSecretsId) property as orphans*.
48+
# * - Recoverable orphans, by re-installing this package.
49+
UnlinkSecretsFile
50+
}
51+
52+
# Done
53+
$project.Save()
54+
Write-Host ('Done.')

src/packages/packages.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
<SubType>Designer</SubType>
4141
</None>
4242
<None Include="ConfigurationBuilders.UserSecrets.nupkg\content\Net471\config.uninstall.xdt" />
43+
<None Include="ConfigurationBuilders.UserSecrets.nupkg\tools\Net471\Uninstall.ps1" />
44+
<None Include="ConfigurationBuilders.UserSecrets.nupkg\tools\Net471\Install.ps1" />
4345
<NuGetProject Include="ConfigurationBuilders.UserSecrets.nupkg\Microsoft.Configuration.ConfigurationBuilders.UserSecrets.nuproj" />
4446
<None Include="ConfigurationBuilders.UserSecrets.nupkg\Microsoft.Configuration.ConfigurationBuilders.UserSecrets.nuspec" />
4547
<None Include="ConfigurationBuilders.Environment.nupkg\content\Net471\config.install.xdt" />
@@ -53,7 +55,9 @@
5355
<None Include="ConfigurationBuilders.Json.nupkg\content\Net471\config.uninstall.xdt" />
5456
<None Include="ConfigurationBuilders.Json.nupkg\Microsoft.Configuration.ConfigurationBuilders.Json.nuspec" />
5557
</ItemGroup>
56-
<ItemGroup />
58+
<ItemGroup>
59+
<Content Include="ConfigurationBuilders.UserSecrets.nupkg\content\sample.xml" />
60+
</ItemGroup>
5761
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
5862
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),MicrosoftConfigurationBuilders.sln))\tools\cleanup.targets" />
5963
<Target Name="Build">

0 commit comments

Comments
 (0)