Added user and password input they are now directly fields on the connection configuration and no longer a seperate entity.
Because as long as I have no clear plan for how to manage multiple users per server it is better to keep it simple. Also some other tweaks to make edits appear in the list.
This commit is contained in:
parent
747358297b
commit
18e737e865
11 changed files with 90 additions and 77 deletions
|
|
@ -19,7 +19,8 @@ public class ServerConfigurationMappingTests
|
|||
Port = 5433,
|
||||
InitialDatabase = "appdb",
|
||||
SslMode = SslMode.Require,
|
||||
User = new ServerUser { Name = "alice", Password = "secret" }
|
||||
UserName = "alice",
|
||||
Password = "secret"
|
||||
};
|
||||
|
||||
var extra = new Dictionary<string,string>{{"search_path","public"}};
|
||||
|
|
@ -46,7 +47,8 @@ public class ServerConfigurationMappingTests
|
|||
Name = "Empty",
|
||||
Host = "",
|
||||
InitialDatabase = "",
|
||||
User = new ServerUser { Name = "", Password = "" }
|
||||
UserName = "",
|
||||
Password = "",
|
||||
};
|
||||
|
||||
var d = ServerConfigurationMapping.ToDescriptor(cfg);
|
||||
|
|
@ -79,8 +81,8 @@ public class ServerConfigurationMappingTests
|
|||
Assert.Equal((ushort)5432, cfg.Port);
|
||||
Assert.Equal("stagedb", cfg.InitialDatabase);
|
||||
Assert.Equal(SslMode.VerifyFull, cfg.SslMode);
|
||||
Assert.Equal("bob", cfg.User.Name);
|
||||
Assert.Equal("pwd", cfg.User.Password);
|
||||
Assert.Equal("bob", cfg.UserName);
|
||||
Assert.Equal("pwd", cfg.Password);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -93,7 +95,8 @@ public class ServerConfigurationMappingTests
|
|||
Port = 5432,
|
||||
InitialDatabase = "keepdb",
|
||||
SslMode = SslMode.Prefer,
|
||||
User = new ServerUser { Name = "keepuser", Password = "keeppwd" }
|
||||
UserName = "keepuser",
|
||||
Password = "keeppwd",
|
||||
};
|
||||
|
||||
// Descriptor missing db and user/pass and sslmode
|
||||
|
|
@ -108,8 +111,8 @@ public class ServerConfigurationMappingTests
|
|||
Assert.Equal((ushort)5432, cfg.Port); // unchanged
|
||||
Assert.Equal("keepdb", cfg.InitialDatabase); // preserved
|
||||
Assert.Equal(SslMode.Prefer, cfg.SslMode); // preserved
|
||||
Assert.Equal("keepuser", cfg.User.Name); // preserved
|
||||
Assert.Equal("keeppwd", cfg.User.Password); // preserved
|
||||
Assert.Equal("keepuser", cfg.UserName); // preserved
|
||||
Assert.Equal("keeppwd", cfg.Password); // preserved
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -122,7 +125,8 @@ public class ServerConfigurationMappingTests
|
|||
Port = 5432,
|
||||
InitialDatabase = "postgres",
|
||||
SslMode = SslMode.Allow,
|
||||
User = new ServerUser { Name = "me", Password = "pw" }
|
||||
UserName = "me",
|
||||
Password = "pw",
|
||||
};
|
||||
|
||||
var d = ServerConfigurationMapping.ToDescriptor(cfg);
|
||||
|
|
@ -132,7 +136,7 @@ public class ServerConfigurationMappingTests
|
|||
Assert.Equal(cfg.Port, cfg2.Port);
|
||||
Assert.Equal(cfg.InitialDatabase, cfg2.InitialDatabase);
|
||||
Assert.Equal(cfg.SslMode, cfg2.SslMode);
|
||||
Assert.Equal(cfg.User.Name, cfg2.User.Name);
|
||||
Assert.Equal(cfg.User.Password, cfg2.User.Password);
|
||||
Assert.Equal(cfg.UserName, cfg2.UserName);
|
||||
Assert.Equal(cfg.Password, cfg2.Password);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public class EditServerConfigurationWindowTests
|
|||
public void Parse_and_Generate_roundtrip_via_UI_bindings()
|
||||
{
|
||||
// Arrange: initialize Avalonia headless app once for the test
|
||||
var vm = new EditServerConfigurationViewModel(new ServerConfigurationEntity());
|
||||
var vm = new EditServerConfigurationViewModel(new(new ServerConfigurationEntity()));
|
||||
var window = new EditServerConfigurationWindow(vm);
|
||||
|
||||
// Act: set an URL input, auto mode, then parse
|
||||
|
|
@ -25,8 +25,8 @@ public class EditServerConfigurationWindowTests
|
|||
Assert.Equal("localhost", vm.Configuration.Host);
|
||||
Assert.Equal((ushort)5433, vm.Configuration.Port);
|
||||
Assert.Equal("mydb", vm.Configuration.InitialDatabase);
|
||||
Assert.Equal("user", vm.Configuration.User.Name);
|
||||
Assert.Equal("pass", vm.Configuration.User.Password);
|
||||
Assert.Equal("user", vm.Configuration.UserName);
|
||||
Assert.Equal("pass", vm.Configuration.Password);
|
||||
Assert.Equal(Npgsql.SslMode.Require, vm.Configuration.DefaultSslMode);
|
||||
|
||||
// Generate back as libpq and validate
|
||||
|
|
@ -46,7 +46,7 @@ public class EditServerConfigurationWindowTests
|
|||
[AvaloniaFact]
|
||||
public void Forced_format_overrides_auto_detection()
|
||||
{
|
||||
var vm = new EditServerConfigurationViewModel(new ServerConfigurationEntity());
|
||||
var vm = new EditServerConfigurationViewModel(new(new ServerConfigurationEntity()));
|
||||
|
||||
// Use a string with quoted values that libpq would struggle with due to incorrect quoting
|
||||
vm.InputConnectionString = "Host=\"server with spaces\";Username=\"bob\";Password=\"secret\";Database=\"db1\"";
|
||||
|
|
@ -63,13 +63,13 @@ public class EditServerConfigurationWindowTests
|
|||
vm.ParseConnectionStringCommand.Execute().Subscribe();
|
||||
Assert.Equal("server with spaces", vm.Configuration.Host);
|
||||
Assert.Equal("db1", vm.Configuration.InitialDatabase);
|
||||
Assert.Equal("bob", vm.Configuration.User.Name);
|
||||
Assert.Equal("bob", vm.Configuration.UserName);
|
||||
}
|
||||
|
||||
[AvaloniaFact]
|
||||
public void Parse_Npgsql_with_inline_host_port_updates_all_fields()
|
||||
{
|
||||
var vm = new EditServerConfigurationViewModel(new ServerConfigurationEntity());
|
||||
var vm = new EditServerConfigurationViewModel(new(new ServerConfigurationEntity()));
|
||||
vm.InputConnectionString = "Host=host.docker.internal:5432;Database=kms_quartz;Username=postgres;Password=admin;Trust Server Certificate=true";
|
||||
vm.ForcedFormat = EditServerConfigurationViewModel.ForcedFormatOption.Auto;
|
||||
vm.ParseConnectionStringCommand.Execute().Subscribe();
|
||||
|
|
@ -77,7 +77,7 @@ public class EditServerConfigurationWindowTests
|
|||
Assert.Equal("host.docker.internal", vm.Configuration.Host);
|
||||
Assert.Equal((ushort)5432, vm.Configuration.Port);
|
||||
Assert.Equal("kms_quartz", vm.Configuration.InitialDatabase);
|
||||
Assert.Equal("postgres", vm.Configuration.User.Name);
|
||||
Assert.Equal("admin", vm.Configuration.User.Password);
|
||||
Assert.Equal("postgres", vm.Configuration.UserName);
|
||||
Assert.Equal("admin", vm.Configuration.Password);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ public class LocalDb : DbContext
|
|||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
new ServerConfigurationEntityConfiguration().Configure(modelBuilder.Entity<ServerConfigurationEntity>());
|
||||
new ServerUserEntityConfiguration().Configure(modelBuilder.Entity<ServerUser>());
|
||||
new DocumentEntityConfiguration().Configure(modelBuilder.Entity<Document>());
|
||||
new EditHistoryEntityConfiguration().Configure(modelBuilder.Entity<EditHistoryEntry>());
|
||||
}
|
||||
|
|
@ -55,14 +54,6 @@ public class ServerConfigurationEntityConfiguration : IEntityTypeConfiguration<S
|
|||
}
|
||||
}
|
||||
|
||||
public class ServerUserEntityConfiguration : IEntityTypeConfiguration<ServerUser>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ServerUser> b)
|
||||
{
|
||||
b.HasKey(e => e.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public class DocumentEntityConfiguration : IEntityTypeConfiguration<Document>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Document> b)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public class ServerConfigurationEntity
|
|||
public SslMode SslMode { get; set; } = SslMode.Prefer;
|
||||
public bool ColorEnabled { get; set; } = true;
|
||||
public int ColorArgb { get; set; } = unchecked((int)0xFF_33_33_33); // default dark gray
|
||||
public string UserName { get; set; } = "";
|
||||
|
||||
public Guid UserId { get; set; }
|
||||
public ServerUser User { get; set; } = new();
|
||||
public string Password { get; set; } = "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace pgLabII.Model;
|
||||
|
||||
public class ServerUser : ViewModelBase
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid ServerConfigurationId { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Password { get; set; } = "";
|
||||
}
|
||||
|
|
@ -45,8 +45,8 @@ public static class ServerConfigurationMapping
|
|||
{
|
||||
Hosts = hosts,
|
||||
Database = string.IsNullOrWhiteSpace(cfg.InitialDatabase) ? null : cfg.InitialDatabase,
|
||||
Username = string.IsNullOrWhiteSpace(cfg.User?.Name) ? null : cfg.User!.Name,
|
||||
Password = string.IsNullOrEmpty(cfg.User?.Password) ? null : cfg.User!.Password,
|
||||
Username = string.IsNullOrWhiteSpace(cfg.UserName) ? null : cfg.UserName,
|
||||
Password = string.IsNullOrEmpty(cfg.Password) ? null : cfg.Password,
|
||||
SslMode = cfg.SslMode,
|
||||
ApplicationName = applicationName,
|
||||
TimeoutSeconds = timeoutSeconds,
|
||||
|
|
@ -84,13 +84,10 @@ public static class ServerConfigurationMapping
|
|||
cfg.SslMode = descriptor.SslMode.Value;
|
||||
|
||||
// User
|
||||
// Suspect, should the user object be replaced instead of updated?
|
||||
if (cfg.User == null)
|
||||
cfg.User = new ServerUser();
|
||||
if (!string.IsNullOrWhiteSpace(descriptor.Username))
|
||||
cfg.User.Name = descriptor.Username!;
|
||||
cfg.UserName = descriptor.Username!;
|
||||
if (!string.IsNullOrEmpty(descriptor.Password))
|
||||
cfg.User.Password = descriptor.Password!;
|
||||
cfg.Password = descriptor.Password!;
|
||||
|
||||
// Nothing to do for ApplicationName/TimeoutSeconds here; not represented in ServerConfiguration.
|
||||
return cfg;
|
||||
|
|
@ -112,9 +109,7 @@ public static class ServerConfigurationMapping
|
|||
targetVm.Port = n.Port;
|
||||
targetVm.InitialDatabase = n.InitialDatabase;
|
||||
targetVm.DefaultSslMode = n.SslMode;
|
||||
// Suspect, if we share Users between configurations then we should not be overriding this struct
|
||||
if (targetVm.User == null) targetVm.User = new ServerUser();
|
||||
targetVm.User.Name = n.User?.Name ?? string.Empty;
|
||||
targetVm.User.Password = n.User?.Password ?? string.Empty;
|
||||
targetVm.UserName = n.UserName;
|
||||
targetVm.Password = n.Password;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,10 +98,10 @@ public class EditServerConfigurationViewModel : ViewModelBase
|
|||
CloseCommand = ReactiveCommand.Create(() => { });
|
||||
}
|
||||
|
||||
public EditServerConfigurationViewModel(ServerConfigurationEntity configuration)
|
||||
public EditServerConfigurationViewModel(ServerConfigurationViewModel configuration)
|
||||
: this()
|
||||
{
|
||||
Configuration = new ServerConfigurationViewModel(configuration);
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
private void DetectFormat()
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ public class ServerConfigurationViewModel : ReactiveObject
|
|||
_entity = entity ?? throw new ArgumentNullException(nameof(entity));
|
||||
EditCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
var vm = new EditServerConfigurationViewModel(_entity);
|
||||
var window = new pgLabII.Views.EditServerConfigurationWindow(vm) { New = false };
|
||||
var window = new Views.EditServerConfigurationWindow(new(this)) { New = false };
|
||||
window.Show();
|
||||
});
|
||||
ExploreCommand = ReactiveCommand.Create(() => { /* window coordination can be injected later */ });
|
||||
|
|
@ -71,17 +70,49 @@ public class ServerConfigurationViewModel : ReactiveObject
|
|||
public Color Color
|
||||
{
|
||||
get => Color.FromUInt32((uint)_entity.ColorArgb);
|
||||
set { var argb = unchecked((int)value.ToUInt32()); if (_entity.ColorArgb != argb) { _entity.ColorArgb = argb; this.RaisePropertyChanged(); this.RaisePropertyChanged(nameof(BackgroundBrush)); } }
|
||||
set
|
||||
{
|
||||
var argb = unchecked((int)value.ToUInt32());
|
||||
if (_entity.ColorArgb != argb)
|
||||
{
|
||||
_entity.ColorArgb = argb;
|
||||
this.RaisePropertyChanged();
|
||||
this.RaisePropertyChanged(nameof(BackgroundBrush));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IBrush? BackgroundBrush => ColorEnabled ? new SolidColorBrush(Color) : null;
|
||||
|
||||
public ServerUser User
|
||||
public string UserName
|
||||
{
|
||||
get => _entity.User;
|
||||
set { if (!ReferenceEquals(_entity.User, value)) { _entity.User = value; this.RaisePropertyChanged(); } }
|
||||
get => _entity.UserName;
|
||||
set
|
||||
{
|
||||
if (_entity.UserName != value)
|
||||
{
|
||||
_entity.UserName = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public string Password
|
||||
{
|
||||
get => _entity.Password;
|
||||
set
|
||||
{
|
||||
if (_entity.Password != value)
|
||||
{
|
||||
_entity.Password = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ReactiveCommand<Unit, Unit> EditCommand { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExploreCommand { get; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ public class ServerListViewModel : ViewModelBase
|
|||
Host = "localhost",
|
||||
Port = 5434,
|
||||
InitialDatabase = "dbname",
|
||||
User = new ()
|
||||
{
|
||||
Name = "postgres",
|
||||
Password = "admin",
|
||||
},
|
||||
UserName = "postgres",
|
||||
Password = "admin",
|
||||
})
|
||||
{
|
||||
Color = Colors.Aquamarine,
|
||||
|
|
|
|||
|
|
@ -29,22 +29,28 @@
|
|||
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,8,0" Text="Database"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Configuration.InitialDatabase}"/>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,8,0" Text="SSL Mode"/>
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" SelectedIndex="{Binding Configuration.DefaultSslMode}">
|
||||
<!-- Order must match Npgsql.SslMode enum: Disable(0), Allow(1), Prefer(2), Require(3), VerifyCA(4), VerifyFull(5) -->
|
||||
<ComboBoxItem>Disable</ComboBoxItem>
|
||||
<ComboBoxItem>Allow</ComboBoxItem>
|
||||
<ComboBoxItem>Prefer</ComboBoxItem>
|
||||
<ComboBoxItem>Require</ComboBoxItem>
|
||||
<ComboBoxItem>VerifyCA</ComboBoxItem>
|
||||
<ComboBoxItem>VerifyFull</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,8,0" Text="Username"/>
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Configuration.UserName}"/>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" Margin="16,0,8,0" Text="Host"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="3" Text="{Binding Configuration.Host}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" Margin="16,0,8,0" Text="Port"/>
|
||||
<NumericUpDown Grid.Row="1" Grid.Column="3" Value="{Binding Configuration.Port}" Minimum="0" Maximum="65535" Increment="1"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" Margin="16,0,8,0" Text="SSL Mode"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="3" SelectedIndex="{Binding Configuration.DefaultSslMode}">
|
||||
<!-- Order must match Npgsql.SslMode enum: Disable(0), Allow(1), Prefer(2), Require(3), VerifyCA(4), VerifyFull(5) -->
|
||||
<ComboBoxItem>Disable</ComboBoxItem>
|
||||
<ComboBoxItem>Allow</ComboBoxItem>
|
||||
<ComboBoxItem>Prefer</ComboBoxItem>
|
||||
<ComboBoxItem>Require</ComboBoxItem>
|
||||
<ComboBoxItem>VerifyCA</ComboBoxItem>
|
||||
<ComboBoxItem>VerifyFull</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="2" VerticalAlignment="Center" Margin="16,0,8,0" Text="Password"/>
|
||||
<TextBox Grid.Row="3" Grid.Column="3" PasswordChar="*" Text="{Binding Configuration.Password}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public partial class EditServerConfigurationWindow : Window
|
|||
InitializeComponent();
|
||||
|
||||
DataContext = viewModel ?? new EditServerConfigurationViewModel(
|
||||
new());
|
||||
new(new()));
|
||||
}
|
||||
|
||||
public bool New { get; set; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue