UI for key update
This commit is contained in:
137
EpsonPrintService/UsbKeyScanner.cs
Normal file
137
EpsonPrintService/UsbKeyScanner.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace EpsonPrintService;
|
||||
|
||||
public record UsbKeyResult(bool Found, string? Base64Content, string? DecodedApiUrl, string? DecodedRestaurantId, string? Error);
|
||||
|
||||
public static class UsbKeyScanner
|
||||
{
|
||||
private const string KeyFileName = "print_server_key.txt";
|
||||
|
||||
public static async Task<UsbKeyResult> ScanForKeyAsync()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return new UsbKeyResult(false, null, null, null, "USB scanning is only supported on Linux.");
|
||||
|
||||
try
|
||||
{
|
||||
var lsblkJson = await RunCommandAsync("lsblk", "-J -o NAME,RM,MOUNTPOINT,TYPE");
|
||||
if (lsblkJson == null)
|
||||
return new UsbKeyResult(false, null, null, null, "Failed to run lsblk.");
|
||||
|
||||
var doc = JsonDocument.Parse(lsblkJson);
|
||||
var devices = doc.RootElement.GetProperty("blockdevices");
|
||||
|
||||
foreach (var device in devices.EnumerateArray())
|
||||
{
|
||||
var result = await ScanDeviceAsync(device);
|
||||
if (result != null)
|
||||
return result;
|
||||
|
||||
// Check children (partitions)
|
||||
if (device.TryGetProperty("children", out var children))
|
||||
{
|
||||
foreach (var child in children.EnumerateArray())
|
||||
{
|
||||
result = await ScanDeviceAsync(child);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new UsbKeyResult(false, null, null, null, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new UsbKeyResult(false, null, null, null, $"USB scan failed: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<UsbKeyResult?> ScanDeviceAsync(JsonElement device)
|
||||
{
|
||||
var isRemovable = device.TryGetProperty("rm", out var rm) && (rm.ValueKind == JsonValueKind.True || (rm.ValueKind == JsonValueKind.Number && rm.GetInt32() == 1));
|
||||
if (!isRemovable)
|
||||
return null;
|
||||
|
||||
var type = device.TryGetProperty("type", out var t) ? t.GetString() : null;
|
||||
if (type != "part")
|
||||
return null;
|
||||
|
||||
var name = device.TryGetProperty("name", out var n) ? n.GetString() : null;
|
||||
if (name == null)
|
||||
return null;
|
||||
|
||||
var mountpoint = device.TryGetProperty("mountpoint", out var mp) && mp.ValueKind == JsonValueKind.String ? mp.GetString() : null;
|
||||
|
||||
if (!string.IsNullOrEmpty(mountpoint))
|
||||
{
|
||||
return CheckMountpoint(mountpoint);
|
||||
}
|
||||
|
||||
// Try to mount and check
|
||||
var tempMount = $"/tmp/usb_scan_{name}";
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(tempMount);
|
||||
var mountResult = await RunCommandAsync("mount", $"-o ro /dev/{name} {tempMount}");
|
||||
if (mountResult == null)
|
||||
return null;
|
||||
|
||||
return CheckMountpoint(tempMount);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { await RunCommandAsync("umount", tempMount); } catch { }
|
||||
try { Directory.Delete(tempMount); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private static UsbKeyResult? CheckMountpoint(string mountpoint)
|
||||
{
|
||||
var keyPath = Path.Combine(mountpoint, KeyFileName);
|
||||
if (!File.Exists(keyPath))
|
||||
return null;
|
||||
|
||||
var content = File.ReadAllText(keyPath).Trim();
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
return null;
|
||||
|
||||
var validation = ConfigurationLoader.TryLoadFromBase64(content);
|
||||
if (!validation.Success)
|
||||
return new UsbKeyResult(true, content, null, null, $"Key file found but invalid: {validation.Error}");
|
||||
|
||||
return new UsbKeyResult(true, content, validation.Config!.ApiUrl, validation.Config.RestaurantId, null);
|
||||
}
|
||||
|
||||
private static async Task<string?> RunCommandAsync(string command, string arguments)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = command,
|
||||
Arguments = arguments,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
var output = await process.StandardOutput.ReadToEndAsync();
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
return process.ExitCode == 0 ? output : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user