diff --git a/src/Components/AutoCompleteMoreItemsFound.razor b/src/Components/AutoCompleteMoreItemsFound.razor new file mode 100644 index 0000000..3bd0c3c --- /dev/null +++ b/src/Components/AutoCompleteMoreItemsFound.razor @@ -0,0 +1,3 @@ + + Too much Items found - please refine your search + \ No newline at end of file diff --git a/src/Components/AutoCompleteNoItemsFound.razor b/src/Components/AutoCompleteNoItemsFound.razor new file mode 100644 index 0000000..0cfee63 --- /dev/null +++ b/src/Components/AutoCompleteNoItemsFound.razor @@ -0,0 +1,3 @@ + + No items found + \ No newline at end of file diff --git a/src/Components/LapsInformationDetail.razor b/src/Components/LapsInformationDetail.razor index 482a155..e307019 100644 --- a/src/Components/LapsInformationDetail.razor +++ b/src/Components/LapsInformationDetail.razor @@ -1,16 +1,31 @@ @inherits MudComponentBase +@inject ISnackbar Snackbar +@inject ClipboardService clipboard +@using CurrieTechnologies.Razor.Clipboard + @if (LapsInfo != null) { - @LapsInfo.Password + + + + + + + + + + + + @if (LapsInfo.Account != null) { - @LapsInfo.Account + } @if (LapsInfo.PasswordSetDate != null) { - @LapsInfo.PasswordSetDate + } - @LapsInfo.PasswordExpireDate + } \ No newline at end of file diff --git a/src/Components/LapsInformationDetail.razor.cs b/src/Components/LapsInformationDetail.razor.cs index 6771ba4..a641fad 100644 --- a/src/Components/LapsInformationDetail.razor.cs +++ b/src/Components/LapsInformationDetail.razor.cs @@ -7,5 +7,32 @@ namespace LAPS_WebUI.Components public partial class LapsInformationDetail : MudComponentBase { [Parameter] public LapsInformation? LapsInfo { get; set; } + [Parameter] public MudTabs? MudTab { get; set; } + private bool IsCopyToClipboardSupported { get; set; } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + IsCopyToClipboardSupported = await clipboard.IsSupportedAsync(); + } + } + + private bool IsCopyButtonDisabled() + { + return !IsCopyToClipboardSupported || LapsInfo is null || string.IsNullOrEmpty(LapsInfo.Password); + } + private async Task CopyLAPSPasswordToClipboardAsync() + { + if (LapsInfo != null && !string.IsNullOrEmpty(LapsInfo.Password)) + { + await clipboard.WriteTextAsync(LapsInfo.Password); + Snackbar.Add("Copied password to clipboard!", Severity.Success); + } + else + { + Snackbar.Add("Failed to copy password to clipboard!", Severity.Error); + } + } } } diff --git a/src/Dockerfile b/src/Dockerfile index 568a176..0931a9c 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -27,4 +27,5 @@ RUN apt update && \ ln -s /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 /usr/lib/liblber.so.2 && \ pip3 install dpapi-ng[kerberos] COPY --from=publish /app/publish . +HEALTHCHECK CMD curl --fail http://localhost/healthz || exit ENTRYPOINT ["dotnet", "LAPS-WebUI.dll"] \ No newline at end of file diff --git a/src/LAPS-WebUI.csproj b/src/LAPS-WebUI.csproj index 4636fc0..6284e2a 100644 --- a/src/LAPS-WebUI.csproj +++ b/src/LAPS-WebUI.csproj @@ -11,15 +11,16 @@ - + + - - + + - + diff --git a/src/Models/LapsInformation.cs b/src/Models/LapsInformation.cs index 3dabe8a..832be4c 100644 --- a/src/Models/LapsInformation.cs +++ b/src/Models/LapsInformation.cs @@ -4,6 +4,7 @@ namespace LAPS_WebUI.Models { public class LapsInformation { + public required string ComputerName { get; set; } public string? Password { get; set; } public string? Account { get; set; } public DateTime? PasswordExpireDate { get; set; } diff --git a/src/Pages/LAPS.razor b/src/Pages/LAPS.razor index 216a227..6cd6183 100644 --- a/src/Pages/LAPS.razor +++ b/src/Pages/LAPS.razor @@ -3,10 +3,8 @@ @inject NavigationManager NavigationManager @inject ILdapService LDAPService @inject ISnackbar Snackbar -@inject ClipboardService clipboard -@using CurrieTechnologies.Razor.Clipboard - + @if (!Authenticated) { @@ -14,9 +12,9 @@ } else { - + @($"{e.Name}") @@ -27,20 +25,31 @@ @($"{e.Name}") + + + + + + @foreach(var computer in SelectedComputers) { - + @computer.Name - + + + + + + @@ -48,7 +57,7 @@ { @if(!computer.FailedToRetrieveLAPSDetails) { - + x.Version == Enums.LAPSVersion.v1 && x.IsCurrent))> @@ -98,14 +107,6 @@ } - - - - - - - - } diff --git a/src/Pages/LAPS.razor.cs b/src/Pages/LAPS.razor.cs index 45a9907..939aaaa 100644 --- a/src/Pages/LAPS.razor.cs +++ b/src/Pages/LAPS.razor.cs @@ -5,18 +5,11 @@ namespace LAPS_WebUI.Pages { public partial class LAPS { - private bool IsCopyToClipboardSupported { get; set; } - + private readonly Dictionary MudTabsDict = new(); + private MudAutocomplete? AutoCompleteSearchBox; private bool Authenticated { get; set; } = true; - private LdapForNet.LdapCredential? LdapCredential { get; set; } - private List SelectedComputers { get; set; } = new List(); - - private MudTabs? _tabs; - - readonly Func _ADComputerToStringConverter = p => (p is null ? string.Empty : p.Name); - protected override async Task OnAfterRenderAsync(bool firstRender) { Authenticated = await sessionManager.IsUserLoggedInAsync(); @@ -26,14 +19,9 @@ protected override async Task OnAfterRenderAsync(bool firstRender) NavigationManager.NavigateTo("/login"); } - if (firstRender) + if (firstRender && Authenticated) { - if (Authenticated) - { - LdapCredential = await sessionManager.GetLdapCredentialsAsync(); - } - - IsCopyToClipboardSupported = await clipboard.IsSupportedAsync(); + LdapCredential = await sessionManager.GetLdapCredentialsAsync(); } await InvokeAsync(StateHasChanged); @@ -43,40 +31,11 @@ private async Task OnSelectedItemChangedAsync(ADComputer value) { if (value != null && !string.IsNullOrEmpty(value.Name) && !SelectedComputers.Exists(x => x.Name == value.Name)) { + AutoCompleteSearchBox?.Clear(); + MudTabsDict.Add(value.Name, null); await FetchComputerDetailsAsync(value.Name); } } - - private async Task CopyLAPSPasswordToClipboardAsync(ADComputer computer) - { - string password = string.Empty; - - if (_tabs != null && _tabs.ActivePanel != null) - { - if (_tabs.ActivePanel.ID.ToString() == "v1") // aka LAPS v1 - { - password = computer.LAPSInformations!.Single(x => x.IsCurrent && x.Version == Enums.LAPSVersion.v1).Password!; - } - if (_tabs.ActivePanel.ID.ToString() == "v2") // aka LAPS v2 - { - password = computer.LAPSInformations!.Single(x => x.IsCurrent && x.Version == Enums.LAPSVersion.v2).Password!; - } - } - - if (!string.IsNullOrEmpty(password)) - { - await clipboard.WriteTextAsync(password); - Snackbar.Add("Copied password to clipboard!", Severity.Success); - } - else - { - Snackbar.Add("Failed to copy password to clipboard!", Severity.Error); - } - - - - } - private async Task RefreshComputerDetailsAsync(string computerName) { @@ -135,10 +94,12 @@ private async Task FetchComputerDetailsAsync(string computerName) selectedComputer.LAPSInformations = AdComputerObject.LAPSInformations; selectedComputer.FailedToRetrieveLAPSDetails = AdComputerObject.FailedToRetrieveLAPSDetails; - if (!selectedComputer.FailedToRetrieveLAPSDetails && _tabs != null) + MudTabsDict.TryGetValue(computerName, out MudTabs? _tab); + + if (!selectedComputer.FailedToRetrieveLAPSDetails && _tab != null) { await InvokeAsync(StateHasChanged); - _tabs.ActivatePanel(_tabs.Panels.First(x => !x.Disabled)); + _tab.ActivatePanel(_tab.Panels.First(x => !x.Disabled)); } } @@ -164,7 +125,7 @@ private async Task> SearchAsync(string value) return new List(); } - var tmp = (await LDAPService.SearchADComputersAsync(LdapCredential ?? await sessionManager.GetLdapCredentialsAsync(), value)); + var tmp = await LDAPService.SearchADComputersAsync(LdapCredential ?? await sessionManager.GetLdapCredentialsAsync(), value); if (tmp != null) { diff --git a/src/Pages/Login.razor b/src/Pages/Login.razor index ad19ec9..d9592b2 100644 --- a/src/Pages/Login.razor +++ b/src/Pages/Login.razor @@ -12,17 +12,14 @@ - - @if (_processing) - { - - Logging you in... - } - else - { - Log in - } - + + + Login + + + Logging in... + + diff --git a/src/Program.cs b/src/Program.cs index 181c1b3..2e00d14 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -25,6 +25,7 @@ builder.Services.AddBlazoredSessionStorage(); builder.Services.AddClipboard(); builder.Services.AddDataProtection(); +builder.Services.AddHealthChecks(); builder.Services.Configure(builder.Configuration.GetSection("LDAP")); builder.Services.Configure(builder.Configuration.GetSection("LAPS")); @@ -50,5 +51,6 @@ app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); +app.MapHealthChecks("/healthz"); app.Run(); diff --git a/src/Services/LDAPService.cs b/src/Services/LDAPService.cs index 15e8e80..0ece79c 100644 --- a/src/Services/LDAPService.cs +++ b/src/Services/LDAPService.cs @@ -108,6 +108,7 @@ public async Task TestCredentialsAsync(LdapCredential ldapCredential) { LapsInformation lapsInformationEntry = new() { + ComputerName = ADComputer.Name, Version = Enums.LAPSVersion.v1, Account = null, Password = ldapSearchResult.DirectoryAttributes["ms-Mcs-AdmPwd"].GetValues().First().ToString(), @@ -144,6 +145,7 @@ public async Task TestCredentialsAsync(LdapCredential ldapCredential) LapsInformation lapsInformationEntry = new() { + ComputerName = ADComputer.Name, Version = Enums.LAPSVersion.v2, Account = msLAPS_Payload.ManagedAccountName, Password = msLAPS_Payload.Password, @@ -168,6 +170,7 @@ public async Task TestCredentialsAsync(LdapCredential ldapCredential) { LapsInformation historicLapsInformationEntry = new() { + ComputerName = ADComputer.Name, Version = Enums.LAPSVersion.v2, Account = historic_msLAPS_Payload.ManagedAccountName, Password = historic_msLAPS_Payload.Password, diff --git a/src/_Imports.razor b/src/_Imports.razor index e5c3a03..a8bd040 100644 --- a/src/_Imports.razor +++ b/src/_Imports.razor @@ -7,6 +7,7 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using MudBlazor +@using MudExtensions @using LAPS_WebUI @using LAPS_WebUI.Shared @using LAPS_WebUI.Interfaces