Skip to content

Commit f833fc2

Browse files
This adds the ability to add vaults from the same tenant, by subscription id, rg name and vault name, since traversing the dep tree can often not show all the vaults the user has access to. (#116) [skip ci]
1 parent 0350e07 commit f833fc2

5 files changed

Lines changed: 132 additions & 15 deletions

File tree

KeyVaultExplorer/Services/VaultService.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ public VaultService(AuthService authService, IMemoryCache memoryCache, KvExplore
3434
private KvExplorerDb _dbContext { get; set; }
3535
private IMemoryCache _memoryCache { get; set; }
3636

37+
public static async IAsyncEnumerable<KeyVaultResource> GetWithKeyVaultsBySubscriptionAsync(KvSubscriptionModel resource)
38+
{
39+
await foreach (var kvResource in resource.Subscription.GetKeyVaultsAsync())
40+
{
41+
yield return kvResource;
42+
}
43+
}
44+
3745
public async Task<KeyVaultKey> CreateKey(KeyVaultKey key, Uri KeyVaultUri)
3846
{
3947
var token = new CustomTokenCredential(await _authService.GetAzureKeyVaultTokenSilent());
@@ -144,6 +152,16 @@ public async IAsyncEnumerable<KeyVaultResource> GetKeyVaultResource()
144152
}
145153
}
146154

155+
156+
public async Task<KeyVaultResource> GetKeyVaultResource(string subscriptionId, string resourceGroupName, string vaultName)
157+
{
158+
var token = new CustomTokenCredential(await _authService.GetAzureArmTokenSilent());
159+
var client = new ArmClient(token);
160+
var resourceIdentifier = KeyVaultResource.CreateResourceIdentifier(subscriptionId: subscriptionId, resourceGroupName: resourceGroupName, vaultName: vaultName);
161+
return await client.GetKeyVaultResource(resourceIdentifier).GetAsync();
162+
}
163+
164+
147165
/// <summary>
148166
/// returns all key vaults based on all the subscriptions the user has rights to view.
149167
/// </summary>
@@ -164,7 +182,7 @@ public async IAsyncEnumerable<KvSubscriptionModel> GetKeyVaultResourceBySubscrip
164182
{
165183
f.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1);
166184

167-
var savedSubscriptions = await _dbContext.GetStoredSubscriptions(_authService.TenantId ?? null);
185+
var savedSubscriptions = await _dbContext.GetStoredSubscriptions(_authService.TenantId ?? null);
168186
List<SubscriptionResource> subscriptionCollection = [];
169187
foreach (var sub in savedSubscriptions)
170188
{
@@ -326,14 +344,6 @@ public async IAsyncEnumerable<SecretProperties> GetVaultAssociatedSecrets(Uri kv
326344
}
327345
}
328346

329-
public static async IAsyncEnumerable<KeyVaultResource> GetWithKeyVaultsBySubscriptionAsync(KvSubscriptionModel resource)
330-
{
331-
await foreach (var kvResource in resource.Subscription.GetKeyVaultsAsync())
332-
{
333-
yield return kvResource;
334-
}
335-
}
336-
337347
public async Task<KeyVaultKey> UpdateKey(KeyProperties properties, Uri KeyVaultUri)
338348
{
339349
var token = new CustomTokenCredential(await _authService.GetAzureKeyVaultTokenSilent());

KeyVaultExplorer/Views/CustomControls/KeyVaultTreeList.axaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,17 @@
121121
UriSource="avares://KeyVaultExplorer/Assets/CollapseAll.png" />
122122
</StackPanel>
123123
</Button>
124+
125+
<Button
126+
Margin="5,0,0,0"
127+
VerticalAlignment="Center"
128+
Click="OpenExternalVaultFromUriDialogBox_Click"
129+
Content="&#xE8a7;"
130+
FontFamily="{StaticResource SymbolThemeFontFamily}"
131+
FontSize="16"
132+
Theme="{StaticResource TransparentButton}"
133+
ToolTip.Tip="Open Vault From Uri"
134+
ToolTip.VerticalOffset="10" />
124135
</StackPanel>
125136
</Border>
126137

KeyVaultExplorer/Views/CustomControls/KeyVaultTreeList.axaml.cs

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,21 @@
55
using Azure.ResourceManager.KeyVault;
66
using FluentAvalonia.Core;
77
using FluentAvalonia.UI.Controls;
8+
using KeyVaultExplorer.Exceptions;
89
using KeyVaultExplorer.Models;
10+
using KeyVaultExplorer.Services;
911
using KeyVaultExplorer.ViewModels;
12+
using System;
1013
using System.Linq;
1114

1215
namespace KeyVaultExplorer.Views.CustomControls;
1316

1417
public partial class KeyVaultTreeList : UserControl
1518
{
1619
private readonly TabViewPageViewModel _tabViewViewModel;
17-
//public static readonly StyledProperty<string> TitleProperty = AvaloniaProperty.Register<KeyVaultTreeList, string>(nameof(Title), defaultValue: "test");
20+
private readonly NotificationViewModel _notificationViewModel = Defaults.Locator.GetRequiredService<NotificationViewModel>();
21+
private readonly VaultService _vaultSerivce = Defaults.Locator.GetRequiredService<VaultService>();
1822

19-
//public string Title
20-
//{
21-
// get => GetValue(TitleProperty);
22-
// set => SetValue(TitleProperty, value);
23-
//}
2423
public KeyVaultTreeList()
2524
{
2625
InitializeComponent();
@@ -104,6 +103,56 @@ private void OnDoubleClicked(object sender, TappedEventArgs args)
104103
control.RaiseEvent(new RoutedEventArgs(MainView.NavigateHomeEvent));
105104
}
106105

106+
private void OpenExternalVaultFromUriDialogBox_Click(object sender, RoutedEventArgs args)
107+
{
108+
var dialog = new ContentDialog()
109+
{
110+
Name = "OpenExternalVaultDialog",
111+
Title = "Open Key Vault By URI",
112+
IsPrimaryButtonEnabled = true,
113+
PrimaryButtonText = "Open",
114+
DefaultButton = ContentDialogButton.Primary,
115+
CloseButtonText = "Cancel",
116+
Content = new OpenExternalVault(),
117+
MinWidth = 750
118+
};
119+
120+
dialog.PrimaryButtonClick += async (sender, args) =>
121+
{
122+
var def = args.GetDeferral();
123+
try
124+
{
125+
var vaultName = (dialog.Content as UserControl).FindControl<TextBox>("VaultName").Text.Trim();
126+
var subscriptionId = (dialog.Content as UserControl).FindControl<TextBox>("SubscriptionId").Text.Trim();
127+
var rgName = (dialog.Content as UserControl).FindControl<TextBox>("ResourceGroupName").Text.Trim();
128+
129+
var vaultData = await _vaultSerivce.GetKeyVaultResource(subscriptionId: subscriptionId, resourceGroupName: rgName, vaultName: vaultName);
130+
131+
Dispatcher.UIThread.Post(async () =>
132+
{
133+
await (DataContext as KeyVaultTreeListViewModel).PinVaultToQuickAccessCommand.ExecuteAsync(vaultData);
134+
135+
_tabViewViewModel.AddVaultPageCommand.Execute(vaultData.Data);
136+
}, DispatcherPriority.ContextIdle);
137+
//_notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification("Success", "The properties have been updated."));
138+
}
139+
catch (KeyVaultInsufficientPrivilegesException ex)
140+
{
141+
_notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification { Message = ex.Message, Title = "Insufficient Privileges" });
142+
}
143+
catch (Exception ex)
144+
{
145+
_notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification { Message = ex.Message, Title = "Error" });
146+
}
147+
finally
148+
{
149+
def.Complete();
150+
}
151+
};
152+
153+
dialog.ShowAsync();
154+
}
155+
107156
private void TreeListFlyoutItem_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
108157
{
109158
var sx = (MenuFlyoutItem)sender!;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<UserControl
2+
x:Class="KeyVaultExplorer.OpenExternalVault"
3+
xmlns="https://github.com/avaloniaui"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:armmodels="clr-namespace:Azure.ResourceManager.KeyVault;assembly=Azure.ResourceManager.KeyVault"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
xmlns:models="clr-namespace:KeyVaultExplorer.Models;assembly=KeyVaultExplorer"
9+
xmlns:ui="using:FluentAvalonia.UI.Controls"
10+
xmlns:vm="clr-namespace:KeyVaultExplorer.ViewModels"
11+
d:DesignHeight="450"
12+
d:DesignWidth="600"
13+
mc:Ignorable="d">
14+
15+
<StackPanel Spacing="8">
16+
<TextBox
17+
Name="SubscriptionId"
18+
MinWidth="450"
19+
HorizontalAlignment="Stretch"
20+
VerticalAlignment="Stretch"
21+
Watermark="Subscription Id e.g. cd7a227e-4..." />
22+
<TextBox
23+
Name="ResourceGroupName"
24+
MinWidth="450"
25+
HorizontalAlignment="Stretch"
26+
VerticalAlignment="Stretch"
27+
Watermark="Resource Group Name e.g. rg-my-resource-group" />
28+
<TextBox
29+
Name="VaultName"
30+
MinWidth="450"
31+
HorizontalAlignment="Stretch"
32+
VerticalAlignment="Stretch"
33+
Watermark="Key Vault Name e.g. my-key-vault" />
34+
</StackPanel>
35+
36+
</UserControl>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Avalonia.Controls;
2+
3+
namespace KeyVaultExplorer;
4+
5+
public partial class OpenExternalVault : UserControl
6+
{
7+
public OpenExternalVault()
8+
{
9+
InitializeComponent();
10+
}
11+
}

0 commit comments

Comments
 (0)