mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-25 05:00:07 +00:00
88e779c1e7
When an ExcessiveSessionEvents (or other session-bound) ops alert fires,
the operator only has a sessionId in hand. Looking up tenant + serial to
fill the manual Block form was a friction point during incident response.
- Backend: POST /api/devices/block now accepts optional blockedSessionId
and forwards it to the existing BlockedDeviceService session-aware path;
audit log + warn log carry the session id.
- Web (Device Block form): new "Session ID" shortcut input + Resolve
button fills Tenant + Serial via GET /api/sessions/{id} (GA cross-tenant
lookup already supported); resolved-device confirmation pill; URL
deep-linking via ?sessionId=, ?action=, ?reason= for auto-fill on mount;
blockedSessionId only forwarded when the resolved device still matches
Serial+Tenant so manual edits don't bind to a stale session.
- Web (Ops Events modal): when the event details JSON carries a sessionId,
surface "Block this device" / "Kill this device" deep-link buttons with
an auto-generated reason scoped to the event type.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
1.3 KiB
C#
36 lines
1.3 KiB
C#
using AutopilotMonitor.Functions.Functions.Admin;
|
|
using Xunit;
|
|
|
|
namespace AutopilotMonitor.Functions.Tests;
|
|
|
|
/// <summary>
|
|
/// Covers the small body-parsing helper in <see cref="DeviceBlockFunction"/>.
|
|
/// <para>
|
|
/// The HTTP entry point is intentionally not tested here — mocking <c>HttpRequestData</c>
|
|
/// + the entire middleware chain would be more setup than the test is worth, and the
|
|
/// underlying <c>BlockedDeviceService.BlockDeviceAsync</c> session-id behavior is covered
|
|
/// by <see cref="BlockedDeviceServiceCrossInstanceTests"/>. The wire-up between the
|
|
/// function and the service is a single-line forward.
|
|
/// </para>
|
|
/// </summary>
|
|
public class DeviceBlockFunctionTests
|
|
{
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
[InlineData(" ")]
|
|
[InlineData("\t\n")]
|
|
public void NormalizeOptionalSessionId_ReturnsNull_ForMissingOrWhitespace(string? raw)
|
|
{
|
|
Assert.Null(DeviceBlockFunction.NormalizeOptionalSessionId(raw));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("806f61c3-1978-4e5c-8fd7-a571cb0fe6bc", "806f61c3-1978-4e5c-8fd7-a571cb0fe6bc")]
|
|
[InlineData(" 806f61c3-1978-4e5c-8fd7-a571cb0fe6bc ", "806f61c3-1978-4e5c-8fd7-a571cb0fe6bc")]
|
|
public void NormalizeOptionalSessionId_TrimsValidValue(string raw, string expected)
|
|
{
|
|
Assert.Equal(expected, DeviceBlockFunction.NormalizeOptionalSessionId(raw));
|
|
}
|
|
}
|