Initial WebhookServer implementation
Add the .NET 8 solution scaffolded against PLAN.md. Three projects share WebhookServer.Core (models, auth, execution, storage, IPC, callbacks) and WebhookServer.Service hosts an embedded Kestrel listener plus the named-pipe admin server. WebhookServer.Gui is a thin MVVM client over the pipe. Includes 25 unit tests covering HMAC verification, bearer auth, IP allowlist parsing, arg-template rendering, DPAPI round-trip, and the encrypt-on-save config store. Install/uninstall PowerShell scripts default to LocalSystem and accept a domain user or gMSA via -ServiceAccount. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<Window x:Class="WebhookServer.Gui.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:WebhookServer.Gui.ViewModels"
|
||||
xmlns:models="clr-namespace:WebhookServer.Core.Models;assembly=WebhookServer.Core"
|
||||
mc:Ignorable="d"
|
||||
Title="Webhook Server" Height="600" Width="1000"
|
||||
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}">
|
||||
<DockPanel LastChildFill="True">
|
||||
<StatusBar DockPanel.Dock="Bottom">
|
||||
<StatusBarItem>
|
||||
<Ellipse Width="10" Height="10"
|
||||
Fill="{Binding IsConnected, Converter={StaticResource ConnFill}}"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding ConnectionStatus}"/>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
|
||||
<ToolBar DockPanel.Dock="Top">
|
||||
<Button Content="Refresh" Command="{Binding RefreshCommand}"/>
|
||||
<Separator/>
|
||||
<Button Content="Add" Command="{Binding AddEndpointCommand}"/>
|
||||
<Button Content="Edit" Command="{Binding EditEndpointCommand}"
|
||||
IsEnabled="{Binding SelectedEndpoint, Converter={StaticResource NotNull}}"/>
|
||||
<Button Content="Delete" Command="{Binding DeleteEndpointCommand}"
|
||||
IsEnabled="{Binding SelectedEndpoint, Converter={StaticResource NotNull}}"/>
|
||||
<Separator/>
|
||||
<Button Content="Server Settings…" Command="{Binding EditServerSettingsCommand}"/>
|
||||
</ToolBar>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="5"/>
|
||||
<RowDefinition Height="200"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<DataGrid Grid.Row="0"
|
||||
ItemsSource="{Binding Endpoints}"
|
||||
SelectedItem="{Binding SelectedEndpoint, Mode=TwoWay}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
CanUserDeleteRows="False"
|
||||
IsReadOnly="True"
|
||||
HeadersVisibility="Column">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Header="Enabled" Width="80">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate DataType="{x:Type models:EndpointConfig}">
|
||||
<CheckBox IsChecked="{Binding Enabled, Mode=OneWay}"
|
||||
Command="{Binding DataContext.ToggleEnabledCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"/>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
<DataGridTextColumn Header="Slug" Binding="{Binding Slug}" Width="*"/>
|
||||
<DataGridTextColumn Header="Auth" Binding="{Binding AuthMode}" Width="80"/>
|
||||
<DataGridTextColumn Header="Executor" Binding="{Binding ExecutorType}" Width="140"/>
|
||||
<DataGridTextColumn Header="Mode" Binding="{Binding ResponseMode}" Width="80"/>
|
||||
<DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="2*"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" Background="#DDD"/>
|
||||
|
||||
<DockPanel Grid.Row="2">
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Recent log entries" FontWeight="Bold" Margin="6,4"/>
|
||||
<Button Grid.Column="1" Content="Refresh" Command="{Binding RefreshLogTailCommand}" Margin="6,2"/>
|
||||
</Grid>
|
||||
<TextBox Text="{Binding LogTail, Mode=OneWay}"
|
||||
IsReadOnly="True"
|
||||
FontFamily="Consolas"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
TextWrapping="NoWrap"/>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
Reference in New Issue
Block a user