diff --git a/TGCommandLine/AdminCommands.cs b/TGCommandLine/AdminCommands.cs index 95c5de9056..7822c9dd4c 100644 --- a/TGCommandLine/AdminCommands.cs +++ b/TGCommandLine/AdminCommands.cs @@ -9,14 +9,39 @@ namespace TGCommandLine public AdminCommand() { Keyword = "admin"; - Children = new Command[] { new AdminViewGroupCommand(), new AdminSetGroupCommand(), new AdminClearGroupCommand(), new AdminViewPortCommand(), new AdminSetPortCommand() }; + Children = new Command[] { new AdminViewGroupCommand(), new AdminSetGroupCommand(), new AdminClearGroupCommand(), new AdminViewPortCommand(), new AdminSetPortCommand(), new AdminMoveServerCommand() }; } public override string GetHelpText() { return "Manage server service authentication"; } } + + class AdminMoveServerCommand : Command + { + public AdminMoveServerCommand() + { + Keyword = "move-server"; + RequiredParameters = 1; + } + protected override ExitCode Run(IList parameters) + { + var res = Server.GetComponent().MoveServer(parameters[0]); + OutputProc(res ?? "Success"); + return res == null ? ExitCode.Normal : ExitCode.ServerError; + } + + public override string GetArgumentString() + { + return ""; + } + + public override string GetHelpText() + { + return "Move the server installation (BYOND, Repo, Game) to a new location. Nothing else may be running for this task to complete"; + } + } class AdminSetPortCommand : Command { diff --git a/TGCommandLine/ConfigCommands.cs b/TGCommandLine/ConfigCommands.cs index 3c4ce10894..e95c7d482a 100644 --- a/TGCommandLine/ConfigCommands.cs +++ b/TGCommandLine/ConfigCommands.cs @@ -10,7 +10,7 @@ namespace TGCommandLine public ConfigCommand() { Keyword = "config"; - Children = new Command[] { new ConfigMoveServerCommand(), new ConfigServerDirectoryCommand(), new ConfigDownloadCommand(), new ConfigUploadCommand() }; + Children = new Command[] { new ConfigServerDirectoryCommand(), new ConfigDownloadCommand(), new ConfigUploadCommand() }; } public override string GetHelpText() { @@ -18,32 +18,6 @@ namespace TGCommandLine } } - class ConfigMoveServerCommand : Command - { - public ConfigMoveServerCommand() - { - Keyword = "move-server"; - RequiredParameters = 1; - } - - protected override ExitCode Run(IList parameters) - { - var res = Server.GetComponent().MoveServer(parameters[0]); - OutputProc(res ?? "Success"); - return res == null ? ExitCode.Normal : ExitCode.ServerError; - } - - public override string GetArgumentString() - { - return ""; - } - - public override string GetHelpText() - { - return "Move the server installation (BYOND, Repo, Game) to a new location. Nothing else may be running for this task to complete"; - } - } - class ConfigServerDirectoryCommand : Command { public ConfigServerDirectoryCommand() diff --git a/TGControlPanel/ServerPage.cs b/TGControlPanel/ServerPage.cs index 71c6b60277..2216023f64 100644 --- a/TGControlPanel/ServerPage.cs +++ b/TGControlPanel/ServerPage.cs @@ -88,13 +88,17 @@ namespace TGControlPanel void UpdateServerPath() { - var Config = Server.GetComponent(); - if (updatingFields || ServerPathTextbox.Text.Trim() == Config.ServerDirectory()) + if (!Server.AuthenticateAdmin()) + { + MessageBox.Show("Only system administrators may move the server installation"); + return; + } + if (updatingFields || ServerPathTextbox.Text.Trim() == Server.GetComponent().ServerDirectory()) return; var DialogResult = MessageBox.Show("This will move the entire server installation.", "Confim", MessageBoxButtons.YesNo); if (DialogResult != DialogResult.Yes) return; - MessageBox.Show(Config.MoveServer(ServerPathTextbox.Text) ?? "Success!"); + MessageBox.Show(Server.GetComponent().MoveServer(ServerPathTextbox.Text) ?? "Success!"); } void LoadServerPage() diff --git a/TGServerService/Administration.cs b/TGServerService/Administration.cs index 80caa90f7b..a9a24818fd 100644 --- a/TGServerService/Administration.cs +++ b/TGServerService/Administration.cs @@ -1,7 +1,9 @@ using System; using System.DirectoryServices.AccountManagement; +using System.IO; using System.Security.Principal; using System.ServiceModel; +using System.Threading; using TGServiceInterface; namespace TGServerService @@ -123,5 +125,119 @@ namespace TGServerService Config.Save(); return null; } + + /// + public string MoveServer(string new_location) + { + var Config = Properties.Settings.Default; + try + { + var di1 = new DirectoryInfo(Config.ServerDirectory); + var di2 = new DirectoryInfo(new_location); + + var copy = di1.Root.FullName != di2.Root.FullName; + + if (copy && File.Exists(PrivateKeyPath)) + return String.Format("Unable to perform a cross drive server move with the {0}. Copy aborted!", PrivateKeyPath); + + new_location = di2.FullName; + + while (di2.Parent != null) + if (di2.Parent.FullName == di1.FullName) + return "Cannot move to child of current directory!"; + else + di2 = di2.Parent; + + if (!Monitor.TryEnter(RepoLock)) + return "Repo locked!"; + try + { + if (RepoBusy) + return "Repo busy!"; + DisposeRepo(); + if (!Monitor.TryEnter(ByondLock)) + return "BYOND locked"; + try + { + if (updateStat != TGByondStatus.Idle) + return "BYOND busy!"; + if (!Monitor.TryEnter(CompilerLock)) + return "Compiler locked!"; + + try + { + if (compilerCurrentStatus != TGCompilerStatus.Uninitialized && compilerCurrentStatus != TGCompilerStatus.Initialized) + return "Compiler busy!"; + if (!Monitor.TryEnter(watchdogLock)) + return "Watchdog locked!"; + try + { + if (currentStatus != TGDreamDaemonStatus.Offline) + return "Watchdog running!"; + lock (configLock) + { + CleanGameFolder(); + Program.DeleteDirectory(GameDir); + string error = null; + if (copy) + { + Program.CopyDirectory(Config.ServerDirectory, new_location); + Directory.CreateDirectory(new_location); + Environment.CurrentDirectory = new_location; + try + { + Program.DeleteDirectory(Config.ServerDirectory); + } + catch (Exception e) + { + error = "The move was successful, but the path " + Config.ServerDirectory + " was unable to be deleted fully!"; + TGServerService.WriteWarning(String.Format("Server move from {0} to {1} partial success: {2}", Config.ServerDirectory, new_location, e.ToString()), TGServerService.EventID.ServerMovePartial); + } + } + else + { + try + { + Environment.CurrentDirectory = di2.Root.FullName; + Directory.Move(Config.ServerDirectory, new_location); + Environment.CurrentDirectory = new_location; + } + catch + { + Environment.CurrentDirectory = Config.ServerDirectory; + throw; + } + } + TGServerService.WriteInfo(String.Format("Server moved from {0} to {1}", Config.ServerDirectory, new_location), TGServerService.EventID.ServerMoveComplete); + Config.ServerDirectory = new_location; + return null; + } + } + finally + { + Monitor.Exit(watchdogLock); + } + } + finally + { + Monitor.Exit(CompilerLock); + } + } + finally + { + Monitor.Exit(ByondLock); + } + } + finally + { + Monitor.Exit(RepoLock); + } + } + catch (Exception e) + { + TGServerService.WriteError(String.Format("Server move from {0} to {1} failed: {2}", Config.ServerDirectory, new_location, e.ToString()), TGServerService.EventID.ServerMoveFailed); + return e.ToString(); + } + } } } diff --git a/TGServerService/Config.cs b/TGServerService/Config.cs index f0c4796723..11d0f5c2ce 100644 --- a/TGServerService/Config.cs +++ b/TGServerService/Config.cs @@ -2,8 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using TGServiceInterface; +using System.ServiceModel; using System.Threading; +using TGServiceInterface; namespace TGServerService { @@ -11,121 +12,6 @@ namespace TGServerService partial class TGStationServer : ITGConfig { object configLock = new object(); //for atomic reads/writes - - //public api - public string MoveServer(string new_location) - { - var Config = Properties.Settings.Default; - try - { - var di1 = new DirectoryInfo(Config.ServerDirectory); - var di2 = new DirectoryInfo(new_location); - - var copy = di1.Root.FullName != di2.Root.FullName; - - if (copy && File.Exists(PrivateKeyPath)) - return String.Format("Unable to perform a cross drive server move with the {0}. Copy aborted!", PrivateKeyPath); - - new_location = di2.FullName; - - while (di2.Parent != null) - if (di2.Parent.FullName == di1.FullName) - return "Cannot move to child of current directory!"; - else - di2 = di2.Parent; - - if (!Monitor.TryEnter(RepoLock)) - return "Repo locked!"; - try - { - if (RepoBusy) - return "Repo busy!"; - DisposeRepo(); - if (!Monitor.TryEnter(ByondLock)) - return "BYOND locked"; - try - { - if (updateStat != TGByondStatus.Idle) - return "BYOND busy!"; - if (!Monitor.TryEnter(CompilerLock)) - return "Compiler locked!"; - - try - { - if (compilerCurrentStatus != TGCompilerStatus.Uninitialized && compilerCurrentStatus != TGCompilerStatus.Initialized) - return "Compiler busy!"; - if (!Monitor.TryEnter(watchdogLock)) - return "Watchdog locked!"; - try - { - if (currentStatus != TGDreamDaemonStatus.Offline) - return "Watchdog running!"; - lock (configLock) - { - CleanGameFolder(); - Program.DeleteDirectory(GameDir); - string error = null; - if (copy) - { - Program.CopyDirectory(Config.ServerDirectory, new_location); - Directory.CreateDirectory(new_location); - Environment.CurrentDirectory = new_location; - try - { - Program.DeleteDirectory(Config.ServerDirectory); - } - catch (Exception e) - { - error = "The move was successful, but the path " + Config.ServerDirectory + " was unable to be deleted fully!"; - TGServerService.WriteWarning(String.Format("Server move from {0} to {1} partial success: {2}", Config.ServerDirectory, new_location, e.ToString()), TGServerService.EventID.ServerMovePartial); - } - } - else - { - try - { - Environment.CurrentDirectory = di2.Root.FullName; - Directory.Move(Config.ServerDirectory, new_location); - Environment.CurrentDirectory = new_location; - } - catch - { - Environment.CurrentDirectory = Config.ServerDirectory; - throw; - } - } - TGServerService.WriteInfo(String.Format("Server moved from {0} to {1}", Config.ServerDirectory, new_location), TGServerService.EventID.ServerMoveComplete); - Config.ServerDirectory = new_location; - return null; - } - } - finally - { - Monitor.Exit(watchdogLock); - } - } - finally - { - Monitor.Exit(CompilerLock); - } - } - finally - { - Monitor.Exit(ByondLock); - } - } - finally - { - Monitor.Exit(RepoLock); - } - } - catch (Exception e) - { - TGServerService.WriteError(String.Format("Server move from {0} to {1} failed: {2}", Config.ServerDirectory, new_location, e.ToString()), TGServerService.EventID.ServerMoveFailed); - return e.ToString(); - } - } - //public api public string ServerDirectory() { @@ -133,6 +19,7 @@ namespace TGServerService } //public api + [OperationBehavior(Impersonation = ImpersonationOption.Required)] public string ReadText(string staticRelativePath, bool repo, out string error) { try @@ -197,7 +84,7 @@ namespace TGServerService return null; } } - + [OperationBehavior(Impersonation = ImpersonationOption.Required)] public string WriteText(string staticRelativePath, string data) { try diff --git a/TGServiceInterface/Administration.cs b/TGServiceInterface/Administration.cs index 5e16dc4221..d5f211a7f4 100644 --- a/TGServiceInterface/Administration.cs +++ b/TGServiceInterface/Administration.cs @@ -38,5 +38,13 @@ namespace TGServiceInterface /// The name of the windows group that is now authorized to use the service on success, null on failure, "ADMIN" on clearing [OperationContract] string SetAuthorizedGroup(string groupName); + + /// + /// Moves the entire server installation, requires no operations to be running + /// + /// The new path to place the server + /// null on success, error message on failure + [OperationContract] + string MoveServer(string new_location); } } diff --git a/TGServiceInterface/Config.cs b/TGServiceInterface/Config.cs index 09ce40d69c..a06dcdaec3 100644 --- a/TGServiceInterface/Config.cs +++ b/TGServiceInterface/Config.cs @@ -18,14 +18,6 @@ namespace TGServiceInterface [OperationContract] string ServerDirectory(); - /// - /// Moves the entire server installation, requires no operations to be running - /// - /// The new path to place the server - /// null on success, error message on failure - [OperationContract] - string MoveServer(string new_location); - /// /// For when you really just need to see the raw data of the config ///