33 lines
1.8 KiB
C#
33 lines
1.8 KiB
C#
using Microsoft.AspNetCore.Http;
|
|
using WxAgent.Service;
|
|
using Xunit;
|
|
|
|
namespace WxAgent.Service.Tests;
|
|
|
|
public sealed class ArtifactStoreTests
|
|
{
|
|
[Fact]
|
|
public async Task ArtifactIdsAreOpaqueOwnedBoundedAndPathSafe()
|
|
{
|
|
var dir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); Directory.CreateDirectory(dir);
|
|
var options = new ServiceOptions { DataDirectory = dir, CredentialFile = "unused" };
|
|
try
|
|
{
|
|
var store = new ArtifactStore(options);
|
|
await using var body = new MemoryStream("safe"u8.ToArray());
|
|
var file = new FormFile(body, 0, body.Length, "file", "note.txt") { Headers = new HeaderDictionary(), ContentType = "text/plain" };
|
|
var info = await store.SaveAsync("alice", file, default);
|
|
Assert.Matches("^[0-9a-f]{32}$", info.ArtifactId);
|
|
Assert.Equal("alice", store.Get("alice", info.ArtifactId).PrincipalId);
|
|
Assert.Throws<ServiceException>(() => store.Get("bob", info.ArtifactId));
|
|
await using var opened = store.Open("alice", info.ArtifactId); using var reader = new StreamReader(opened);
|
|
Assert.Equal("safe", await reader.ReadToEndAsync());
|
|
Assert.Throws<ServiceException>(() => store.Get("alice", "../secrets"));
|
|
await using var badBody = new MemoryStream("x"u8.ToArray());
|
|
var bad = new FormFile(badBody, 0, badBody.Length, "file", "payload.exe") { Headers = new HeaderDictionary(), ContentType = "application/octet-stream" };
|
|
Assert.Equal("FileTypeRejected", (await Assert.ThrowsAsync<ServiceException>(() => store.SaveAsync("alice", bad, default))).Code);
|
|
}
|
|
finally { Microsoft.Data.Sqlite.SqliteConnection.ClearAllPools(); Directory.Delete(dir, true); }
|
|
}
|
|
}
|