diff --git a/src/ScadaLink.CentralUI/Components/Pages/Admin/ApiKeyForm.razor b/src/ScadaLink.CentralUI/Components/Pages/Admin/ApiKeyForm.razor index 3e2dbd6..b47872d 100644 --- a/src/ScadaLink.CentralUI/Components/Pages/Admin/ApiKeyForm.razor +++ b/src/ScadaLink.CentralUI/Components/Pages/Admin/ApiKeyForm.razor @@ -57,6 +57,37 @@ + @if (IsEditMode) + { +
+ + @if (_allMethods.Count == 0) + { +
+ No API methods configured. + Create one to grant access. +
+ } + else + { +
+ @foreach (var method in _allMethods.OrderBy(m => m.Name)) + { + var checkboxId = $"method-access-{method.Id}"; +
+ + +
+ } +
+
+ Callers using this key can invoke any checked method. +
+ } +
+ } @if (_formError != null) {
@_formError
@@ -81,6 +112,10 @@ private bool _loading = true; private bool _saved; + private List _allMethods = new(); + private HashSet _initialMethodIds = new(); + private HashSet _selectedMethodIds = new(); + private ToastNotification _toast = default!; protected override async Task OnInitializedAsync() @@ -97,6 +132,12 @@ else { _formName = _editingKey.Name; + _allMethods = (await InboundApiRepository.GetAllApiMethodsAsync()).ToList(); + _initialMethodIds = _allMethods + .Where(m => ParseApprovedKeyIds(m.ApprovedApiKeyIds).Contains(_editingKey.Id)) + .Select(m => m.Id) + .ToHashSet(); + _selectedMethodIds = new HashSet(_initialMethodIds); } } } @@ -118,6 +159,22 @@ { _editingKey.Name = _formName.Trim(); await InboundApiRepository.UpdateApiKeyAsync(_editingKey); + + var changedIds = _selectedMethodIds + .Except(_initialMethodIds) + .Concat(_initialMethodIds.Except(_selectedMethodIds)) + .ToHashSet(); + foreach (var method in _allMethods.Where(m => changedIds.Contains(m.Id))) + { + var ids = ParseApprovedKeyIds(method.ApprovedApiKeyIds); + if (_selectedMethodIds.Contains(method.Id)) ids.Add(_editingKey.Id); + else ids.Remove(_editingKey.Id); + method.ApprovedApiKeyIds = ids.Count == 0 + ? null + : string.Join(",", ids.OrderBy(x => x)); + await InboundApiRepository.UpdateApiMethodAsync(method); + } + await InboundApiRepository.SaveChangesAsync(); NavigationManager.NavigateTo("/admin/api-keys"); } @@ -139,6 +196,22 @@ private void GoBack() => NavigationManager.NavigateTo("/admin/api-keys"); + private void ToggleMethod(int methodId, bool isChecked) + { + if (isChecked) _selectedMethodIds.Add(methodId); + else _selectedMethodIds.Remove(methodId); + } + + private static HashSet ParseApprovedKeyIds(string? value) + { + if (string.IsNullOrWhiteSpace(value)) + return new HashSet(); + return value.Split(',', StringSplitOptions.RemoveEmptyEntries) + .Select(s => int.TryParse(s.Trim(), out var id) ? id : -1) + .Where(id => id > 0) + .ToHashSet(); + } + private async Task CopyKeyToClipboard() { if (_newlyCreatedKeyValue == null) return;