✨ feat(file-check): 添加 PLC 应答后命中文件删除

* 新增默认关闭的删除开关,仅在收到 PLC 放行应答后执行

* 本地与 SFTP Provider 校验根目录并支持幂等删除

* 补充工作流、设置页和文件删除相关测试与文档
This commit is contained in:
2026-08-01 16:42:28 +08:00
parent 404ebadbe7
commit c67509ec82
15 changed files with 700 additions and 1 deletions

View File

@@ -124,6 +124,56 @@ public sealed class LocalFileCheckProviderTests : IDisposable
Assert.Equal(filePath, outcome.MatchedFilePath);
}
/// <summary>
/// 删除目标位于配置根目录内时,应删除文件并返回成功。
/// </summary>
/// <returns>异步测试任务。</returns>
[Fact]
public async Task DeleteFileAsync_ShouldDeleteFile_WhenFileIsWithinConfiguredRoot()
{
string filePath = Path.Combine(_rootPath, "PCB-DELETE-001.txt");
await File.WriteAllTextAsync(filePath, "ok");
var provider = CreateProvider();
FileDeleteOutcome outcome = await provider.DeleteFileAsync(
filePath,
CreateConfig(_rootPath),
CancellationToken.None);
Assert.True(outcome.IsSuccess);
Assert.False(outcome.WasAlreadyMissing);
Assert.False(File.Exists(filePath));
}
/// <summary>
/// 删除目标位于配置根目录之外时,应拒绝删除以防止误删其他文件。
/// </summary>
/// <returns>异步测试任务。</returns>
[Fact]
public async Task DeleteFileAsync_ShouldRejectFile_WhenFileIsOutsideConfiguredRoot()
{
string parentPath = Directory.GetParent(_rootPath)!.FullName;
string filePath = Path.Combine(parentPath, $"{Guid.NewGuid():N}.txt");
await File.WriteAllTextAsync(filePath, "keep");
var provider = CreateProvider();
try
{
FileDeleteOutcome outcome = await provider.DeleteFileAsync(
filePath,
CreateConfig(_rootPath),
CancellationToken.None);
Assert.False(outcome.IsSuccess);
Assert.Contains("根目录之外", outcome.ErrorMessage);
Assert.True(File.Exists(filePath));
}
finally
{
File.Delete(filePath);
}
}
/// <summary>
/// 创建本地文件校验提供程序。
/// </summary>