refactor(worker): OnlineTokenStore zu DpapiTokenStore verallgemeinert
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
using System.Runtime.Versioning;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using ClaudeDo.Data;
|
||||
|
||||
namespace ClaudeDo.Worker;
|
||||
|
||||
/// <summary>
|
||||
/// Persists a single secret encrypted with DPAPI (CurrentUser scope), one instance per file.
|
||||
/// Windows-only. Used for the Online-Inbox refresh token (~/.claudeDo/online-inbox.token) and
|
||||
/// the ticket-system PAT (~/.claudeDo/ticket.pat).
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
public sealed class DpapiTokenStore
|
||||
{
|
||||
private readonly string _tokenPath;
|
||||
|
||||
public DpapiTokenStore(string tokenPath) => _tokenPath = tokenPath;
|
||||
|
||||
public static DpapiTokenStore InAppData(string fileName)
|
||||
=> new(Path.Combine(Paths.AppDataRoot(), fileName));
|
||||
|
||||
public void Save(string secret)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(secret);
|
||||
var cipher = ProtectedData.Protect(Encoding.UTF8.GetBytes(secret), null, DataProtectionScope.CurrentUser);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(_tokenPath)!);
|
||||
File.WriteAllBytes(_tokenPath, cipher);
|
||||
}
|
||||
|
||||
public string? Read()
|
||||
{
|
||||
if (!File.Exists(_tokenPath)) return null;
|
||||
try
|
||||
{
|
||||
var plain = ProtectedData.Unprotect(File.ReadAllBytes(_tokenPath), null, DataProtectionScope.CurrentUser);
|
||||
return Encoding.UTF8.GetString(plain);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Exists() => File.Exists(_tokenPath);
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (File.Exists(_tokenPath)) File.Delete(_tokenPath);
|
||||
}
|
||||
}
|
||||
|
||||
/// DI-Marker: der Online-Inbox-Refresh-Token.
|
||||
public sealed record OnlineRefreshTokenStore(DpapiTokenStore Store);
|
||||
|
||||
/// DI-Marker: der Personal Access Token des Ticketsystems.
|
||||
public sealed record TicketPatStore(DpapiTokenStore Store);
|
||||
Reference in New Issue
Block a user