| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- using System.Text.Json;
- using YZWater.Core.Models;
- using YZWater.Core.Services;
- namespace YZWater.Core.Tests.Services;
- /// <summary>
- /// 配置文件路径锚定 + 敏感项落盘加密的回归测试
- /// </summary>
- public class ConfigProtectionTests
- {
- private const string Token = "Hub-Token-S3cr3t";
- [Fact]
- public void HubToken_SerializedAsCiphertext()
- {
- if (!OperatingSystem.IsWindows()) return; // DPAPI 不可用时按明文降级
- var config = new SystemConfig { HubToken = Token };
- var json = JsonSerializer.Serialize(config);
- Assert.DoesNotContain(Token, json);
- Assert.Contains("enc:", json);
- }
- [Fact]
- public void HubToken_SurvivesJsonRoundTrip()
- {
- if (!OperatingSystem.IsWindows()) return;
- var json = JsonSerializer.Serialize(new SystemConfig { HubToken = Token });
- ProtectedStringJsonConverter.BeginRead();
- var restored = JsonSerializer.Deserialize<SystemConfig>(json);
- Assert.Equal(Token, restored?.HubToken);
- Assert.False(ProtectedStringJsonConverter.NeedsRewrite);
- }
- [Fact]
- public void LegacyPlaintextHubToken_StillReadableAndMarkedForRewrite()
- {
- ProtectedStringJsonConverter.BeginRead();
- var restored = JsonSerializer.Deserialize<SystemConfig>("{\"HubToken\":\"" + Token + "\"}");
- Assert.Equal(Token, restored?.HubToken);
- Assert.True(ProtectedStringJsonConverter.NeedsRewrite);
- // ConfigService 据此回写一次,第二次加载就不该再要求改写
- var rewritten = JsonSerializer.Serialize(restored);
- ProtectedStringJsonConverter.BeginRead();
- var reloaded = JsonSerializer.Deserialize<SystemConfig>(rewritten);
- Assert.Equal(Token, reloaded?.HubToken);
- Assert.False(ProtectedStringJsonConverter.NeedsRewrite);
- }
- [Fact]
- public void UndecryptableCiphertext_FallsBackToEmptyInsteadOfThrowing()
- {
- // 配置文件从别的机器/别的 Windows 用户拷来时会走到这里
- ProtectedStringJsonConverter.BeginRead();
- var restored = JsonSerializer.Deserialize<SystemConfig>("{\"HubToken\":\"enc:not-valid-cipher-text\"}");
- Assert.True(string.IsNullOrEmpty(restored?.HubToken));
- Assert.True(ProtectedStringJsonConverter.DecryptFailed);
- // 关键:解不开不等于"等待迁移"。若此处要求回写,ConfigService 会把这段密文
- // 覆盖成空值(还会顺手污染 .lastgood),操作员原机上配的令牌就彻底没了。
- Assert.False(ProtectedStringJsonConverter.NeedsRewrite);
- }
- [Fact]
- public void LegacyPlaintext_MarksRewriteButNotDecryptFailure()
- {
- ProtectedStringJsonConverter.BeginRead();
- JsonSerializer.Deserialize<SystemConfig>("{\"HubToken\":\"" + Token + "\"}");
- Assert.True(ProtectedStringJsonConverter.NeedsRewrite);
- Assert.False(ProtectedStringJsonConverter.DecryptFailed);
- }
- [Fact]
- public void EmptyHubToken_StaysEmptyAndNeedsNoRewrite()
- {
- ProtectedStringJsonConverter.BeginRead();
- var restored = JsonSerializer.Deserialize<SystemConfig>(
- JsonSerializer.Serialize(new SystemConfig { HubToken = string.Empty }));
- Assert.Equal(string.Empty, restored?.HubToken);
- Assert.False(ProtectedStringJsonConverter.NeedsRewrite);
- }
- }
|