diff --git a/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs index 75e14cfd1..d3beb95b3 100644 --- a/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs +++ b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs @@ -111,11 +111,30 @@ protected override void Load(ContainerBuilder builder) { var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true"); - LiteDatabase globalDatabase = null; - - globalDatabase = Hacks.IsElevated - ? new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true") - : new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true;readonly=true"); + LiteDatabase globalDatabase; + if (Hacks.IsElevated) + { + globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true"); + } + else + { + if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db"))) + { + // Since the global configuration database file doesn't exist, we must be running in a state where an administrator user + // has never run Chocolatey GUI. In this case, use null, which will mean attempts to use the global database will be ignored. + globalDatabase = null; + } + else + { + // Since this is a non-administrator user, they should only have read permissions to this database + globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};readonly=true"); + } + } + + if (globalDatabase != null) + { + builder.RegisterInstance(globalDatabase).As().SingleInstance().Named(Bootstrapper.GlobalConfigurationDatabaseName); + } var configService = new ConfigService(globalDatabase, userDatabase); configService.SetEffectiveConfiguration(); @@ -128,7 +147,6 @@ protected override void Load(ContainerBuilder builder) // Since there are two instances of LiteDB, they are added as named instances, so that they can be retrieved when required builder.RegisterInstance(userDatabase).As().SingleInstance().Named(Bootstrapper.UserConfigurationDatabaseName); - builder.RegisterInstance(globalDatabase).As().SingleInstance().Named(Bootstrapper.GlobalConfigurationDatabaseName); } catch (IOException ex) { diff --git a/Source/ChocolateyGui.Common/Services/ConfigService.cs b/Source/ChocolateyGui.Common/Services/ConfigService.cs index 972704db3..de8f04877 100644 --- a/Source/ChocolateyGui.Common/Services/ConfigService.cs +++ b/Source/ChocolateyGui.Common/Services/ConfigService.cs @@ -22,9 +22,6 @@ public class ConfigService : IConfigService { public ConfigService(LiteDatabase globalDatabase, LiteDatabase userDatabase) { - GlobalCollection = globalDatabase.GetCollection(nameof(AppConfiguration)); - UserCollection = userDatabase.GetCollection(nameof(AppConfiguration)); - var defaultGlobalSettings = new AppConfiguration() { Id = "v0.18.0", @@ -39,7 +36,20 @@ public ConfigService(LiteDatabase globalDatabase, LiteDatabase userDatabase) Id = "v0.18.0" }; - GlobalAppConfiguration = GlobalCollection.FindById("v0.18.0") ?? defaultGlobalSettings; + // If the global database is null, the assumption has to be that we are running as a non-administrator + // user, as such, we should proceed with default settings + if (globalDatabase == null) + { + GlobalCollection = null; + GlobalAppConfiguration = defaultGlobalSettings; + } + else + { + GlobalCollection = globalDatabase.GetCollection(nameof(AppConfiguration)); + GlobalAppConfiguration = GlobalCollection.FindById("v0.18.0") ?? defaultGlobalSettings; + } + + UserCollection = userDatabase.GetCollection(nameof(AppConfiguration)); UserAppConfiguration = UserCollection.FindById("v0.18.0") ?? defaultUserSettings; } @@ -149,6 +159,14 @@ public AppConfiguration GetGlobalConfiguration() public void UpdateSettings(AppConfiguration settings, bool global) { + if (global && GlobalCollection == null) + { + // This is very much an edge case, and we shouldn't ever get to here, but it does need to be handled + Logger.Warning("An attempt has been made to save a configuration change globally, when the global configuration database hasn't been created."); + Logger.Warning("No action will be taken, please check with your System Administrator."); + return; + } + var settingsCollection = global ? GlobalCollection : UserCollection; if (settingsCollection.Exists(Query.EQ("_id", "v0.18.0"))) diff --git a/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs b/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs index a0e35d0b7..e2066ed6a 100644 --- a/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs +++ b/Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs @@ -46,9 +46,30 @@ protected override void Load(ContainerBuilder builder) { var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true"); - var globalDatabase = Hacks.IsElevated - ? new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true") - : new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true;readonly=true"); + LiteDatabase globalDatabase; + if (Hacks.IsElevated) + { + globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true"); + } + else + { + if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db"))) + { + // Since the global configuration database file doesn't exist, we must be running in a state where an administrator user + // has never run Chocolatey GUI. In this case, use null, which will mean attempts to use the global database will be ignored. + globalDatabase = null; + } + else + { + // Since this is a non-administrator user, they should only have read permissions to this database + globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};readonly=true"); + } + } + + if (globalDatabase != null) + { + builder.RegisterInstance(globalDatabase).As().SingleInstance().Named(Bootstrapper.GlobalConfigurationDatabaseName); + } var configService = new ConfigService(globalDatabase, userDatabase); configService.SetEffectiveConfiguration(); @@ -58,7 +79,6 @@ protected override void Load(ContainerBuilder builder) // Since there are two instances of LiteDB, they are added as named instances, so that they can be retrieved when required builder.RegisterInstance(userDatabase).As().SingleInstance().Named(Bootstrapper.UserConfigurationDatabaseName); - builder.RegisterInstance(globalDatabase).As().SingleInstance().Named(Bootstrapper.GlobalConfigurationDatabaseName); } catch (IOException ex) {