Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(#996) Create config directory if it doesn't exist #1045

Merged
merged 1 commit into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,22 @@ protected override void Load(ContainerBuilder builder)
var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true");

LiteDatabase globalDatabase;
var globalConfigDirectory = Path.Combine(Bootstrapper.AppDataPath, "Config");
var globalConfigDatabaseFile = Path.Combine(globalConfigDirectory, "data.db");

if (Hacks.IsElevated)
{
globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true");
if (!Directory.Exists(globalConfigDirectory))
{
Directory.CreateDirectory(globalConfigDirectory);
Hacks.LockDirectory(globalConfigDirectory);
}

globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};upgrade=true");
}
else
{
if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")))
if (!File.Exists(globalConfigDatabaseFile))
{
// 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.
Expand All @@ -163,7 +172,7 @@ protected override void Load(ContainerBuilder builder)
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");
globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};readonly=true");
}
}

Expand Down
31 changes: 31 additions & 0 deletions Source/ChocolateyGui.Common/Hacks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,43 @@
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;

namespace ChocolateyGui.Common
{
public static class Hacks
{
public static bool IsElevated => (WindowsIdentity.GetCurrent().Owner?.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid)).GetValueOrDefault(false);

// TODO: Replace this LockDirectory with calls to DotNetFileSystem's LockDirectory when https://github.com/chocolatey/ChocolateyGUI/issues/1046 is completed.
/// <summary>
/// Lock the given directory path to just Administrators being able to write. This method is copied from chocolatey.infrastructure.filesystem.DotNetFileSystem, and should be replaced with that call when the minimum Chocolatey.lib is bumped to 2.2.0 or greater.
/// </summary>
/// <param name="directoryPath">Directory path to lock down.</param>
public static void LockDirectory(string directoryPath)
{
var permissions = Directory.GetAccessControl(directoryPath);
var rules = permissions.GetAccessRules(includeExplicit: true, includeInherited: true, targetType: typeof(NTAccount));

// We first need to remove all rules
foreach (FileSystemAccessRule rule in rules)
{
permissions.RemoveAccessRuleAll(rule);
}

var bultinAdmins = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).Translate(typeof(NTAccount));
var localsystem = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null).Translate(typeof(NTAccount));
var builtinUsers = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null).Translate(typeof(NTAccount));
var inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
permissions.SetAccessRule(new FileSystemAccessRule(bultinAdmins, FileSystemRights.FullControl, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow));
permissions.SetAccessRule(new FileSystemAccessRule(localsystem, FileSystemRights.FullControl, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow));
permissions.SetAccessRule(new FileSystemAccessRule(builtinUsers, FileSystemRights.ReadAndExecute, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow));
permissions.SetOwner(bultinAdmins);
permissions.SetAccessRuleProtection(isProtected: true, preserveInheritance: false);
Directory.SetAccessControl(directoryPath, permissions);
}
}
}
15 changes: 12 additions & 3 deletions Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,22 @@ protected override void Load(ContainerBuilder builder)
var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true");

LiteDatabase globalDatabase;
var globalConfigDirectory = Path.Combine(Bootstrapper.AppDataPath, "Config");
var globalConfigDatabaseFile = Path.Combine(globalConfigDirectory, "data.db");

if (Hacks.IsElevated)
{
globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true");
if (!Directory.Exists(globalConfigDirectory))
{
Directory.CreateDirectory(globalConfigDirectory);
Hacks.LockDirectory(globalConfigDirectory);
}

globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};upgrade=true");
}
else
{
if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")))
if (!File.Exists(globalConfigDatabaseFile))
{
// 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.
Expand All @@ -63,7 +72,7 @@ protected override void Load(ContainerBuilder builder)
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");
globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};readonly=true");
}
}

Expand Down
Loading