@rendermode InteractiveServer @attribute [Authorize] @using Microsoft.AspNetCore.Authorization @using MudBlazor @using System.Net.Http.Json @using Microsoft.AspNetCore.Identity @using Microsoft.AspNetCore.Components @using OpenIddict.Abstractions @using RobotNet.IdentityServer.Data @using Microsoft.EntityFrameworkCore @using System.Threading @using static OpenIddict.Abstractions.OpenIddictConstants @inherits LayoutComponentBase @inject AuthenticationStateProvider AuthenticationStateProvider @inject ISnackbar Snackbar @inject IDialogService DialogService @inject NavigationManager NavigationManager @inject IOpenIddictApplicationManager ApplicationManager @inject IOpenIddictScopeManager ScopeManager
OpenIddict Scopes
Quản lý phạm vi truy cập OAuth2 & OpenID Connect
@filteredScopes.Count Scopes
Danh sách Scopes
Làm mới Thêm Scope
Tên hiển thị Tên Scope Resources Thao tác @(string.IsNullOrEmpty(context.DisplayName) ? context.Name : context.DisplayName) @context.Id[..12]... @{ var validResources = GetValidResources(context.Resources); } @if (validResources.Any()) { GetResourceDisplayName(r)))"> 1 ? "s" : "")}")" Size="Size.Small" Class="resource-chip" /> @if (context.Resources.Count > validResources.Count) { } } else if (context.Resources.Any()) { } else { Không có resources }
@if (HasInvalidResources(context.Resources)) { }
Đang tải dữ liệu...
@(editingScope?.Name != null ? "Chỉnh sửa Scope" : "Thêm Scope mới")
Chọn Resources @foreach (var resource in availableResources) {
@resource.DisplayName @resource.ClientId
}
@if (GetSelectedResources().Any()) { Resources đã chọn:
@foreach (var selectedResource in GetSelectedResources()) { var resourceInfo = availableResources.FirstOrDefault(r => r.ClientId == selectedResource); }
}
Hủy Lưu
Chi tiết Scope
@if (selectedScope != null) {
ID @selectedScope.Id
Tên @selectedScope.Name
Tên hiển thị @(string.IsNullOrEmpty(selectedScope.DisplayName) ? "Không có" : selectedScope.DisplayName)
Resources
@if (selectedScope.Resources.Any()) { var validResources = GetValidResources(selectedScope.Resources); var invalidResources = selectedScope.Resources.Except(validResources).ToList(); @if (validResources.Any()) { Resources hợp lệ:
@foreach (var resource in validResources) { }
} @if (invalidResources.Any()) { Resources không hợp lệ:
@foreach (var resource in invalidResources) { }
} } else { Không có resources }
}
Đóng
@code { private string resourceInput = string.Empty; private List filteredScopes = new(); private List availableResources = new(); private Dictionary resourceChecks = new(); private bool loadingScopes = false; private bool showScopeDialog = false; private bool ShowDetailsDialog = false; private ScopeInfo? editingScope = null; private ScopeInfo? selectedScope = null; private ScopeForm scopeForm = new(); public class ScopeInfo { public string Id { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string DisplayName { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public List Resources { get; set; } = new(); public Dictionary Properties { get; set; } = new(); } public class ScopeForm { public string Name { get; set; } = string.Empty; public string DisplayName { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public List Resources { get; set; } = new(); } public class ResourceInfo { public string ClientId { get; set; } = string.Empty; public string DisplayName { get; set; } = string.Empty; } protected override async Task OnInitializedAsync() { var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); if (authState.User.Identity?.IsAuthenticated == true) { await LoadAvailableResourcesAsync(); await LoadScopesAsync(); } } private async Task LoadAvailableResourcesAsync() { try { availableResources.Clear(); await foreach (var app in ApplicationManager.ListAsync()) { var clientType = await ApplicationManager.GetClientTypeAsync(app); if (clientType == ClientTypes.Confidential) { var clientId = await ApplicationManager.GetClientIdAsync(app); var displayName = await ApplicationManager.GetDisplayNameAsync(app); if (!string.IsNullOrEmpty(clientId)) { availableResources.Add(new ResourceInfo { ClientId = clientId, DisplayName = string.IsNullOrEmpty(displayName) ? clientId : displayName }); } } } resourceChecks.Clear(); foreach (var resource in availableResources) { resourceChecks[resource.ClientId] = false; } } catch (Exception ex) { Snackbar.Add($"Lỗi khi tải resources: {ex.Message}", Severity.Error); } } private List GetValidResources(List resources) { var validResourceIds = availableResources.Select(r => r.ClientId).ToHashSet(); return resources.Where(r => validResourceIds.Contains(r)).ToList(); } private bool HasInvalidResources(List resources) { var validResourceIds = availableResources.Select(r => r.ClientId).ToHashSet(); return resources.Any(r => !validResourceIds.Contains(r)); } private string GetResourceDisplayName(string clientId) { var resource = availableResources.FirstOrDefault(r => r.ClientId == clientId); return resource?.DisplayName ?? clientId; } private async Task CleanupScopeResources(ScopeInfo scope) { var confirm = await DialogService.ShowMessageBox( "Xác nhận dọn dẹp", $"Bạn có muốn xóa các resources không hợp lệ khỏi scope '{scope.Name}'?", yesText: "Dọn dẹp", cancelText: "Hủy" ); if (confirm == true) { try { var existingScope = await ScopeManager.FindByNameAsync(scope.Name); if (existingScope != null) { var validResources = GetValidResources(scope.Resources); var descriptor = new OpenIddictScopeDescriptor { Name = scope.Name, DisplayName = scope.DisplayName, Description = scope.Description }; foreach (var resource in validResources) { descriptor.Resources.Add(resource); } await ScopeManager.PopulateAsync(existingScope, descriptor); await ScopeManager.UpdateAsync(existingScope); Snackbar.Add($"Đã dọn dẹp {scope.Resources.Count - validResources.Count} resources không hợp lệ", Severity.Success); await LoadScopesAsync(); } } catch (Exception ex) { Snackbar.Add($"Lỗi khi dọn dẹp resources: {ex.Message}", Severity.Error); } } } private async Task RefreshScopesAsync() { await LoadAvailableResourcesAsync(); await LoadScopesAsync(); Snackbar.Add("Đã làm mới danh sách scopes", Severity.Success); } private void AddResource() { if (!string.IsNullOrWhiteSpace(resourceInput) && !scopeForm.Resources.Contains(resourceInput)) { scopeForm.Resources.Add(resourceInput); resourceInput = string.Empty; StateHasChanged(); } } private void OnResourceSelectionChanged(IEnumerable selectedValues) { foreach (var key in resourceChecks.Keys.ToList()) { resourceChecks[key] = false; } foreach (var value in selectedValues) { if (resourceChecks.ContainsKey(value)) { resourceChecks[value] = true; } } scopeForm.Resources = selectedValues.ToList(); StateHasChanged(); } private IEnumerable GetSelectedResources() { return resourceChecks.Where(x => x.Value).Select(x => x.Key); } private void RemoveResource(string resource) { if (resourceChecks.ContainsKey(resource)) { resourceChecks[resource] = false; scopeForm.Resources.Remove(resource); StateHasChanged(); } } private async Task LoadScopesAsync() { try { loadingScopes = true; filteredScopes.Clear(); await foreach (var scope in ScopeManager.ListAsync()) { var id = await ScopeManager.GetIdAsync(scope); var name = await ScopeManager.GetNameAsync(scope); var displayName = await ScopeManager.GetDisplayNameAsync(scope); var description = await ScopeManager.GetDescriptionAsync(scope); var resources = await ScopeManager.GetResourcesAsync(scope); var properties = await ScopeManager.GetPropertiesAsync(scope); filteredScopes.Add(new ScopeInfo { Id = id ?? string.Empty, Name = name ?? string.Empty, DisplayName = displayName ?? string.Empty, Description = description ?? string.Empty, Resources = resources.ToList(), Properties = properties.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString() ?? string.Empty) }); } } catch (Exception ex) { Snackbar.Add($"Lỗi khi tải scopes: {ex.Message}", Severity.Error); } finally { loadingScopes = false; StateHasChanged(); } } private void ViewScopeDetails(ScopeInfo scope) { selectedScope = scope; ShowDetailsDialog = true; } private void CloseDetailsDialog() { ShowDetailsDialog = false; selectedScope = null; } private async Task OpenScopeDialog(ScopeInfo? scope = null) { editingScope = scope; ResetScopeForm(); if (scope != null) { scopeForm.Name = scope.Name; scopeForm.DisplayName = scope.DisplayName; scopeForm.Description = scope.Description; var validResources = GetValidResources(scope.Resources); scopeForm.Resources = new List(validResources); foreach (var key in resourceChecks.Keys.ToList()) { resourceChecks[key] = validResources.Contains(key); } if (scope.Resources.Count > validResources.Count) { var invalidCount = scope.Resources.Count - validResources.Count; Snackbar.Add($"Đã loại bỏ {invalidCount} resource không hợp lệ khỏi form chỉnh sửa", Severity.Warning); } } showScopeDialog = true; await Task.CompletedTask; } private async void EditScope(ScopeInfo scope) { await OpenScopeDialog(scope); } private void ResetScopeForm() { scopeForm = new ScopeForm(); foreach (var key in resourceChecks.Keys.ToList()) { resourceChecks[key] = false; } } private async Task SaveScope() { try { if (string.IsNullOrWhiteSpace(scopeForm.Name)) { Snackbar.Add("Name là bắt buộc", Severity.Error); return; } var descriptor = new OpenIddictScopeDescriptor { Name = scopeForm.Name, DisplayName = scopeForm.DisplayName, Description = scopeForm.Description }; var validResources = GetValidResources(scopeForm.Resources); foreach (var resource in validResources) { descriptor.Resources.Add(resource); } if (editingScope != null) { var existingScope = await ScopeManager.FindByNameAsync(editingScope.Name); if (existingScope != null) { await ScopeManager.PopulateAsync(existingScope, descriptor); await ScopeManager.UpdateAsync(existingScope); } } else { await ScopeManager.CreateAsync(descriptor); } Snackbar.Add(editingScope != null ? "Cập nhật scope thành công" : "Tạo scope thành công", Severity.Success); showScopeDialog = false; await LoadScopesAsync(); } catch (Exception ex) { Snackbar.Add($"Lỗi khi lưu scope: {ex.Message}", Severity.Error); } } private void CancelScopeDialog() { showScopeDialog = false; ResetScopeForm(); } private async Task DeleteScope(string name) { var confirm = await DialogService.ShowMessageBox("Xác nhận xóa", $"Bạn có chắc chắn muốn xóa scope '{name}'?", yesText: "Xóa", cancelText: "Hủy"); if (confirm == true) { try { var scope = await ScopeManager.FindByNameAsync(name); if (scope != null) { await ScopeManager.DeleteAsync(scope); Snackbar.Add("Xóa scope thành công", Severity.Success); await LoadScopesAsync(); } } catch (Exception ex) { Snackbar.Add($"Lỗi khi xóa scope: {ex.Message}", Severity.Error); } } } }