Linux admin mode
This commit is contained in:
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"dotnet.defaultSolution": "src/FileTime.sln"
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
using FileTime.App.Core.UserCommand;
|
using FileTime.App.Core.UserCommand;
|
||||||
using FileTime.Providers.LocalAdmin;
|
using FileTime.Providers.LocalAdmin;
|
||||||
using GeneralInputKey;
|
using GeneralInputKey;
|
||||||
@@ -12,9 +13,12 @@ public class MainConfiguration
|
|||||||
|
|
||||||
static MainConfiguration()
|
static MainConfiguration()
|
||||||
{
|
{
|
||||||
|
var serverFileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? "FileTime.Server.exe"
|
||||||
|
: "FileTime.Server";
|
||||||
Configuration = new()
|
Configuration = new()
|
||||||
{
|
{
|
||||||
{AdminElevationConfiguration.SectionName + ":" + nameof(AdminElevationConfiguration.ServerExecutablePath), "FileTime.Server.exe"},
|
{AdminElevationConfiguration.SectionName + ":" + nameof(AdminElevationConfiguration.ServerExecutablePath), serverFileName},
|
||||||
};
|
};
|
||||||
|
|
||||||
PopulateDefaultEditorPrograms(Configuration);
|
PopulateDefaultEditorPrograms(Configuration);
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
namespace FileTime.ConsoleUI.App;
|
using FileTime.Providers.LocalAdmin;
|
||||||
|
|
||||||
|
namespace FileTime.ConsoleUI.App;
|
||||||
|
|
||||||
public class MainConsoleConfiguration
|
public class MainConsoleConfiguration
|
||||||
{
|
{
|
||||||
public static Dictionary<string, string?> Configuration { get; }
|
public static Dictionary<string, string?> Configuration { get; }
|
||||||
static MainConsoleConfiguration()
|
static MainConsoleConfiguration()
|
||||||
{
|
{
|
||||||
Configuration = new();
|
Configuration = new()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
AdminElevationConfiguration.SectionName + ":" + nameof(AdminElevationConfiguration.LinuxElevationTool), "sudo"
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using FileTime.Providers.LocalAdmin;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.App.Configuration;
|
||||||
|
|
||||||
|
public class MainGuiConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
public static Dictionary<string, string?> Configuration { get; }
|
||||||
|
static MainGuiConfiguration()
|
||||||
|
{
|
||||||
|
Configuration = new()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
AdminElevationConfiguration.SectionName + ":" + nameof(AdminElevationConfiguration.LinuxElevationTool), "pkexec"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
<ProjectReference Include="..\FileTime.GuiApp.App.Abstractions\FileTime.GuiApp.App.Abstractions.csproj" />
|
<ProjectReference Include="..\FileTime.GuiApp.App.Abstractions\FileTime.GuiApp.App.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\FileTime.GuiApp.DesignPreview\FileTime.GuiApp.DesignPreview.csproj" />
|
<ProjectReference Include="..\FileTime.GuiApp.DesignPreview\FileTime.GuiApp.DesignPreview.csproj" />
|
||||||
<ProjectReference Include="..\FileTime.GuiApp.Font.Abstractions\FileTime.GuiApp.Font.Abstractions.csproj" />
|
<ProjectReference Include="..\FileTime.GuiApp.Font.Abstractions\FileTime.GuiApp.Font.Abstractions.csproj" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using FileTime.App.Core.Configuration;
|
|||||||
using FileTime.App.Core.Services;
|
using FileTime.App.Core.Services;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
using FileTime.Core.Interactions;
|
using FileTime.Core.Interactions;
|
||||||
|
using FileTime.GuiApp.App.Configuration;
|
||||||
using FileTime.GuiApp.CustomImpl.ViewModels;
|
using FileTime.GuiApp.CustomImpl.ViewModels;
|
||||||
using FileTime.GuiApp.App.IconProviders;
|
using FileTime.GuiApp.App.IconProviders;
|
||||||
using FileTime.GuiApp.App.InstanceManagement;
|
using FileTime.GuiApp.App.InstanceManagement;
|
||||||
@@ -26,6 +27,7 @@ public static class Startup
|
|||||||
{
|
{
|
||||||
var configurationBuilder = new ConfigurationBuilder()
|
var configurationBuilder = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(MainConfiguration.Configuration)
|
.AddInMemoryCollection(MainConfiguration.Configuration)
|
||||||
|
.AddInMemoryCollection(MainGuiConfiguration.Configuration)
|
||||||
.AddJsonFile("appsettings.json", optional: true)
|
.AddJsonFile("appsettings.json", optional: true)
|
||||||
.AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true)
|
.AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true)
|
||||||
.AddJsonFile("appsettings.Local.json", optional: true);
|
.AddJsonFile("appsettings.Local.json", optional: true);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ public class AdminElevationConfiguration
|
|||||||
{
|
{
|
||||||
public const string SectionName = "AdminElevation";
|
public const string SectionName = "AdminElevation";
|
||||||
public string ServerExecutablePath { get; set; }
|
public string ServerExecutablePath { get; set; }
|
||||||
|
public string LinuxElevationTool { get; set; }
|
||||||
public int? ServerPort { get; set; }
|
public int? ServerPort { get; set; }
|
||||||
public bool? StartProcess { get; set; }
|
public bool? StartProcess { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using FileTime.App.Core.Services;
|
using FileTime.App.Core.Services;
|
||||||
using FileTime.Core.Interactions;
|
using FileTime.Core.Interactions;
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
@@ -73,30 +74,28 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
|
|||||||
var port = _configuration.CurrentValue.ServerPort;
|
var port = _configuration.CurrentValue.ServerPort;
|
||||||
_logger.LogTrace("Admin server port is {Port}", port is null ? "<not set>" : $"{port}");
|
_logger.LogTrace("Admin server port is {Port}", port is null ? "<not set>" : $"{port}");
|
||||||
if (StartProcess || port is null)
|
if (StartProcess || port is null)
|
||||||
{
|
{
|
||||||
var portFileName = Path.GetTempFileName();
|
var portFileName = Path.GetTempFileName();
|
||||||
var process = new Process
|
File.Delete(portFileName);
|
||||||
{
|
|
||||||
StartInfo = new()
|
var process = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
{
|
? CreateWindowsAdminProcess(portFileName)
|
||||||
FileName = _configuration.CurrentValue.ServerExecutablePath,
|
: CreateLinuxAdminProcess(portFileName);
|
||||||
ArgumentList =
|
|
||||||
{
|
|
||||||
"--PortWriter:FileName",
|
|
||||||
portFileName
|
|
||||||
},
|
|
||||||
UseShellExecute = true,
|
|
||||||
Verb = "runas"
|
|
||||||
},
|
|
||||||
EnableRaisingEvents = true
|
|
||||||
};
|
|
||||||
process.Exited += ProcessExitHandler;
|
process.Exited += ProcessExitHandler;
|
||||||
process.Start();
|
process.Start();
|
||||||
_adminProcess = process;
|
_adminProcess = process;
|
||||||
|
|
||||||
//TODO: timeout
|
//TODO: timeout
|
||||||
while (!File.Exists(portFileName) || new FileInfo(portFileName).Length == 0)
|
while (!File.Exists(portFileName) || new FileInfo(portFileName).Length == 0)
|
||||||
|
{
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
|
if (process.HasExited)
|
||||||
|
{
|
||||||
|
throw new Exception(
|
||||||
|
$"Server process exited with code {process.ExitCode} without creating the port file"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var content = await File.ReadAllLinesAsync(portFileName);
|
var content = await File.ReadAllLinesAsync(portFileName);
|
||||||
if (int.TryParse(content.FirstOrDefault(), out var parsedPort))
|
if (int.TryParse(content.FirstOrDefault(), out var parsedPort))
|
||||||
@@ -132,6 +131,42 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Process CreateWindowsAdminProcess(string portFileName)
|
||||||
|
=> new()
|
||||||
|
{
|
||||||
|
StartInfo = new()
|
||||||
|
{
|
||||||
|
FileName = _configuration.CurrentValue.ServerExecutablePath,
|
||||||
|
ArgumentList =
|
||||||
|
{
|
||||||
|
"--PortWriter:FileName",
|
||||||
|
portFileName
|
||||||
|
},
|
||||||
|
UseShellExecute = true,
|
||||||
|
Verb = "runas"
|
||||||
|
},
|
||||||
|
EnableRaisingEvents = true
|
||||||
|
};
|
||||||
|
|
||||||
|
private Process CreateLinuxAdminProcess(string portFileName)
|
||||||
|
{
|
||||||
|
return new Process
|
||||||
|
{
|
||||||
|
StartInfo = new()
|
||||||
|
{
|
||||||
|
FileName = _configuration.CurrentValue.LinuxElevationTool,
|
||||||
|
ArgumentList =
|
||||||
|
{
|
||||||
|
_configuration.CurrentValue.ServerExecutablePath,
|
||||||
|
"--PortWriter:FileName",
|
||||||
|
portFileName
|
||||||
|
},
|
||||||
|
CreateNoWindow = true
|
||||||
|
},
|
||||||
|
EnableRaisingEvents = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
//Note: this does not have to return a task
|
//Note: this does not have to return a task
|
||||||
public Task<IRemoteContentProvider> GetRemoteContentProviderAsync()
|
public Task<IRemoteContentProvider> GetRemoteContentProviderAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ public class PortWriterService : IHostedService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var tempFileStream = File.CreateText(filename);
|
|
||||||
var address = GetAddress();
|
var address = GetAddress();
|
||||||
if (address is null)
|
if (address is null)
|
||||||
{
|
{
|
||||||
@@ -59,7 +58,23 @@ public class PortWriterService : IHostedService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Writing port to {PortFile}", filename);
|
||||||
|
using var tempFileStream = File.CreateText(filename);
|
||||||
tempFileStream.Write(port.ToString());
|
tempFileStream.Write(port.ToString());
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(5000);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Deleting port file {PortFile}", filename);
|
||||||
|
File.Delete(filename);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error while deleting port file {PortFile}", filename);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user