mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-25 05:56:58 +01:00
Merge pull request #156 from Cyberboss/WhoCapitalizesIRCChannels
Adds HTTPS interface and makes the GUI/CLI work remotely
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
using System.Collections.Generic;
|
||||
using TGServiceInterface;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
class AdminCommand : RootCommand
|
||||
{
|
||||
public AdminCommand()
|
||||
{
|
||||
Keyword = "admin";
|
||||
Children = new Command[] { new AdminViewGroupCommand(), new AdminSetGroupCommand(), new AdminClearGroupCommand() };
|
||||
}
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Manage server service authentication";
|
||||
}
|
||||
}
|
||||
|
||||
class AdminViewGroupCommand : Command
|
||||
{
|
||||
public AdminViewGroupCommand()
|
||||
{
|
||||
Keyword = "view-group";
|
||||
}
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Print the name of the windows group that is allowed to use the service";
|
||||
}
|
||||
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var group = Server.GetComponent<ITGAdministration>().GetCurrentAuthorizedGroup();
|
||||
OutputProc(group ?? "ERROR");
|
||||
return group != null ? ExitCode.Normal : ExitCode.ServerError;
|
||||
}
|
||||
}
|
||||
|
||||
class AdminSetGroupCommand : Command
|
||||
{
|
||||
public AdminSetGroupCommand()
|
||||
{
|
||||
Keyword = "set-group";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Set the windows group allowed to use the service";
|
||||
}
|
||||
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<windows group name>";
|
||||
}
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var result = Server.GetComponent<ITGAdministration>().SetAuthorizedGroup(parameters[0]);
|
||||
if(result != null)
|
||||
{
|
||||
OutputProc("Group set to: " + result);
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputProc("Failed to find a group named: " + parameters[0]);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AdminClearGroupCommand : Command
|
||||
{
|
||||
public AdminClearGroupCommand()
|
||||
{
|
||||
Keyword = "clear-group";
|
||||
}
|
||||
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Clears the groups allowed to use the service, leaving only windows administrators";
|
||||
}
|
||||
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Server.GetComponent<ITGAdministration>().SetAuthorizedGroup(null);
|
||||
if(res != "ADMIN")
|
||||
{
|
||||
OutputProc("Failed to clear the group??? We are currently set to: " + res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,55 @@ namespace TGCommandLine
|
||||
{
|
||||
static ExitCode RunCommandLine(IList<string> argsAsList)
|
||||
{
|
||||
//first lookup the connection string
|
||||
bool badConnectionString = false;
|
||||
for (var I = 0; I < argsAsList.Count - 1; ++I) {
|
||||
var lowerarg = argsAsList[I].ToLower();
|
||||
if (lowerarg == "-c" || lowerarg == "--connect")
|
||||
{
|
||||
var connectionString = argsAsList[I + 1];
|
||||
var splits = connectionString.Split('@');
|
||||
var userpass = splits[0].Split(':');
|
||||
if (splits.Length != 2 || userpass.Length != 2)
|
||||
{
|
||||
badConnectionString = true;
|
||||
break;
|
||||
}
|
||||
var username = userpass[0];
|
||||
var password = userpass[1];
|
||||
var address = splits[1];
|
||||
if(String.IsNullOrWhiteSpace(username) || String.IsNullOrWhiteSpace(password) || String.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
badConnectionString = true;
|
||||
break;
|
||||
}
|
||||
argsAsList.RemoveAt(I);
|
||||
argsAsList.RemoveAt(I);
|
||||
Server.SetRemoteLoginInformation(address, username, password);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (badConnectionString)
|
||||
{
|
||||
Console.WriteLine("Remote connection usage: <-c/--connect> username:password@address");
|
||||
return ExitCode.BadCommand;
|
||||
}
|
||||
|
||||
var res = Server.VerifyConnection();
|
||||
if (res != null)
|
||||
{
|
||||
Console.WriteLine("Unable to connect to service: " + res);
|
||||
Console.WriteLine("Remote connection usage: <-c/--connect> username:password@address");
|
||||
return ExitCode.ConnectionError;
|
||||
}
|
||||
|
||||
if (!Server.Authenticate())
|
||||
{
|
||||
Console.WriteLine("Authentication error: Username/password/windows identity is not authorized!");
|
||||
return ExitCode.ConnectionError;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new CLICommand().DoRun(argsAsList);
|
||||
@@ -50,6 +93,7 @@ namespace TGCommandLine
|
||||
Console.Write("*");
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -59,6 +103,7 @@ namespace TGCommandLine
|
||||
if (args.Length != 0)
|
||||
return (int)RunCommandLine(new List<string>(args));
|
||||
|
||||
Console.WriteLine("Type 'remote' to connect to a remote service");
|
||||
//interactive mode
|
||||
while (true)
|
||||
{
|
||||
@@ -66,6 +111,35 @@ namespace TGCommandLine
|
||||
var NextCommand = Console.ReadLine();
|
||||
switch (NextCommand.ToLower())
|
||||
{
|
||||
case "remote":
|
||||
Console.Write("Enter server address: ");
|
||||
var address = Console.ReadLine();
|
||||
Console.Write("Enter username: ");
|
||||
var username = Console.ReadLine();
|
||||
Console.Write("Enter password: ");
|
||||
var password = ReadLineSecure();
|
||||
Server.SetRemoteLoginInformation(address, username, password);
|
||||
var res = Server.VerifyConnection();
|
||||
if (res != null)
|
||||
{
|
||||
Console.WriteLine("Unable to connect: " + res);
|
||||
Server.SetRemoteLoginInformation(null, null, null);
|
||||
}
|
||||
else if (!Server.Authenticate())
|
||||
{
|
||||
Console.WriteLine("Authentication error: Username/password/windows identity is not authorized! Returning to local mode...");
|
||||
Server.SetRemoteLoginInformation(null, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Connected remotely");
|
||||
Console.WriteLine("Type 'disconnect' to return to local mode");
|
||||
}
|
||||
break;
|
||||
case "disconnect":
|
||||
Server.SetRemoteLoginInformation(null, null, null);
|
||||
Console.WriteLine("Switch to local mode");
|
||||
break;
|
||||
case "quit":
|
||||
case "exit":
|
||||
return (int)ExitCode.Normal;
|
||||
|
||||
@@ -8,7 +8,10 @@ namespace TGCommandLine
|
||||
{
|
||||
public CLICommand()
|
||||
{
|
||||
Children = new Command[] { new UpdateCommand(), new TestmergeCommand(), new RepoCommand(), new BYONDCommand(), new DMCommand(), new DDCommand(), new ConfigCommand(), new IRCCommand(), new DiscordCommand() };
|
||||
var tmp = new List<Command> { new UpdateCommand(), new TestmergeCommand(), new RepoCommand(), new BYONDCommand(), new DMCommand(), new DDCommand(), new ConfigCommand(), new IRCCommand(), new DiscordCommand() };
|
||||
if (Server.VerifyConnection() == null && Server.Authenticate() && Server.AuthenticateAdmin())
|
||||
tmp.Add(new AdminCommand());
|
||||
Children = tmp.ToArray();
|
||||
}
|
||||
|
||||
public override void PrintHelp()
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<ApplicationIcon>tgs.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AdminCommands.cs" />
|
||||
<Compile Include="BYONDCommands.cs" />
|
||||
<Compile Include="ConfigCommands.cs" />
|
||||
<Compile Include="DDCommands.cs" />
|
||||
|
||||
@@ -26,6 +26,12 @@
|
||||
<setting name="LastChatProvider" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="RemoteIP" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="RemoteUsername" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</TGControlPanel.Properties.Settings>
|
||||
<TGControlPanel.Properties.Settings1>
|
||||
<setting name="LastPageIndex" serializeAs="String">
|
||||
|
||||
Generated
+187
@@ -0,0 +1,187 @@
|
||||
namespace TGControlPanel
|
||||
{
|
||||
partial class Login
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Login));
|
||||
this.LocalLoginButton = new System.Windows.Forms.Button();
|
||||
this.CurrentRevisionTitle = new System.Windows.Forms.Label();
|
||||
this.IPTextBox = new System.Windows.Forms.TextBox();
|
||||
this.UsernameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.PasswordTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RemoteLoginButton = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// LocalLoginButton
|
||||
//
|
||||
this.LocalLoginButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.LocalLoginButton.Location = new System.Drawing.Point(51, 12);
|
||||
this.LocalLoginButton.Name = "LocalLoginButton";
|
||||
this.LocalLoginButton.Size = new System.Drawing.Size(188, 25);
|
||||
this.LocalLoginButton.TabIndex = 13;
|
||||
this.LocalLoginButton.Text = "Connect to Local Service";
|
||||
this.LocalLoginButton.UseVisualStyleBackColor = true;
|
||||
this.LocalLoginButton.Click += new System.EventHandler(this.LocalLoginButton_Click);
|
||||
//
|
||||
// CurrentRevisionTitle
|
||||
//
|
||||
this.CurrentRevisionTitle.AutoSize = true;
|
||||
this.CurrentRevisionTitle.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.CurrentRevisionTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
|
||||
this.CurrentRevisionTitle.Location = new System.Drawing.Point(81, 76);
|
||||
this.CurrentRevisionTitle.Name = "CurrentRevisionTitle";
|
||||
this.CurrentRevisionTitle.Size = new System.Drawing.Size(128, 18);
|
||||
this.CurrentRevisionTitle.TabIndex = 14;
|
||||
this.CurrentRevisionTitle.Text = "Remote Login:";
|
||||
this.CurrentRevisionTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// IPTextBox
|
||||
//
|
||||
this.IPTextBox.Location = new System.Drawing.Point(73, 97);
|
||||
this.IPTextBox.Name = "IPTextBox";
|
||||
this.IPTextBox.Size = new System.Drawing.Size(199, 20);
|
||||
this.IPTextBox.TabIndex = 15;
|
||||
//
|
||||
// UsernameTextBox
|
||||
//
|
||||
this.UsernameTextBox.Location = new System.Drawing.Point(73, 130);
|
||||
this.UsernameTextBox.Name = "UsernameTextBox";
|
||||
this.UsernameTextBox.Size = new System.Drawing.Size(199, 20);
|
||||
this.UsernameTextBox.TabIndex = 16;
|
||||
//
|
||||
// PasswordTextBox
|
||||
//
|
||||
this.PasswordTextBox.Location = new System.Drawing.Point(73, 162);
|
||||
this.PasswordTextBox.Name = "PasswordTextBox";
|
||||
this.PasswordTextBox.Size = new System.Drawing.Size(199, 20);
|
||||
this.PasswordTextBox.TabIndex = 17;
|
||||
this.PasswordTextBox.UseSystemPasswordChar = true;
|
||||
//
|
||||
// RemoteLoginButton
|
||||
//
|
||||
this.RemoteLoginButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.RemoteLoginButton.Location = new System.Drawing.Point(51, 197);
|
||||
this.RemoteLoginButton.Name = "RemoteLoginButton";
|
||||
this.RemoteLoginButton.Size = new System.Drawing.Size(188, 25);
|
||||
this.RemoteLoginButton.TabIndex = 18;
|
||||
this.RemoteLoginButton.Text = "Connect to Remote Service";
|
||||
this.RemoteLoginButton.UseVisualStyleBackColor = true;
|
||||
this.RemoteLoginButton.Click += new System.EventHandler(this.RemoteLoginButton_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
|
||||
this.label1.Location = new System.Drawing.Point(9, 99);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(32, 18);
|
||||
this.label1.TabIndex = 19;
|
||||
this.label1.Text = "IP:";
|
||||
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
|
||||
this.label2.Location = new System.Drawing.Point(9, 132);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(52, 18);
|
||||
this.label2.TabIndex = 20;
|
||||
this.label2.Text = "User:";
|
||||
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
|
||||
this.label3.Location = new System.Drawing.Point(9, 164);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(53, 18);
|
||||
this.label3.TabIndex = 21;
|
||||
this.label3.Text = "Pass:";
|
||||
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label4.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(242)))));
|
||||
this.label4.Location = new System.Drawing.Point(-19, 40);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(468, 18);
|
||||
this.label4.TabIndex = 22;
|
||||
this.label4.Text = "______________________________________________";
|
||||
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// Login
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(39)))), ((int)(((byte)(40)))), ((int)(((byte)(34)))));
|
||||
this.ClientSize = new System.Drawing.Size(284, 237);
|
||||
this.Controls.Add(this.label4);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.RemoteLoginButton);
|
||||
this.Controls.Add(this.PasswordTextBox);
|
||||
this.Controls.Add(this.UsernameTextBox);
|
||||
this.Controls.Add(this.IPTextBox);
|
||||
this.Controls.Add(this.CurrentRevisionTitle);
|
||||
this.Controls.Add(this.LocalLoginButton);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "Login";
|
||||
this.Text = "Login";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button LocalLoginButton;
|
||||
private System.Windows.Forms.Label CurrentRevisionTitle;
|
||||
private System.Windows.Forms.TextBox IPTextBox;
|
||||
private System.Windows.Forms.TextBox UsernameTextBox;
|
||||
private System.Windows.Forms.TextBox PasswordTextBox;
|
||||
private System.Windows.Forms.Button RemoteLoginButton;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Label label4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using TGServiceInterface;
|
||||
|
||||
namespace TGControlPanel
|
||||
{
|
||||
public partial class Login : Form
|
||||
{
|
||||
public Login()
|
||||
{
|
||||
InitializeComponent();
|
||||
IPTextBox.Text = Properties.Settings.Default.RemoteIP;
|
||||
UsernameTextBox.Text = Properties.Settings.Default.RemoteUsername;
|
||||
AcceptButton = RemoteLoginButton;
|
||||
}
|
||||
|
||||
private void RemoteLoginButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
IPTextBox.Text = IPTextBox.Text.Trim();
|
||||
UsernameTextBox.Text = UsernameTextBox.Text.Trim();
|
||||
Server.SetRemoteLoginInformation(IPTextBox.Text, UsernameTextBox.Text, PasswordTextBox.Text);
|
||||
Properties.Settings.Default.RemoteIP = IPTextBox.Text;
|
||||
Properties.Settings.Default.RemoteUsername = UsernameTextBox.Text;
|
||||
VerifyAndConnect();
|
||||
}
|
||||
|
||||
private void LocalLoginButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Server.SetRemoteLoginInformation(null, null, null);
|
||||
VerifyAndConnect();
|
||||
}
|
||||
|
||||
void VerifyAndConnect()
|
||||
{
|
||||
var res = Server.VerifyConnection();
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show("Unable to connect to service! Error: " + res);
|
||||
return;
|
||||
}
|
||||
if (!Server.Authenticate())
|
||||
{
|
||||
MessageBox.Show("Authentication error: Username/password/windows identity is not authorized! Ensure you are a system administrator or in the correct Windows group on the service machine.");
|
||||
return;
|
||||
}
|
||||
Hide();
|
||||
new Main().ShowDialog();
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,16 +18,9 @@ namespace TGControlPanel
|
||||
Properties.Settings.Default.UpgradeRequired = false;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
var res = Server.VerifyConnection();
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show("Unable to connect to service! Error: " + res);
|
||||
return;
|
||||
}
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Main());
|
||||
return;
|
||||
Application.Run(new Login());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
+25
-1
@@ -12,7 +12,7 @@ namespace TGControlPanel.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -70,5 +70,29 @@ namespace TGControlPanel.Properties {
|
||||
this["LastChatProvider"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string RemoteIP {
|
||||
get {
|
||||
return ((string)(this["RemoteIP"]));
|
||||
}
|
||||
set {
|
||||
this["RemoteIP"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string RemoteUsername {
|
||||
get {
|
||||
return ((string)(this["RemoteUsername"]));
|
||||
}
|
||||
set {
|
||||
this["RemoteUsername"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,11 @@
|
||||
<Setting Name="LastChatProvider" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="RemoteIP" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="RemoteUsername" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -39,10 +39,12 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms">
|
||||
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Windows.Forms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ByondPage.cs">
|
||||
@@ -57,6 +59,12 @@
|
||||
<Compile Include="ConfigPage.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Login.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Login.Designer.cs">
|
||||
<DependentUpon>Login.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Main.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -77,6 +85,9 @@
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="..\Version.cs" />
|
||||
<EmbeddedResource Include="Login.resx">
|
||||
<DependentUpon>Login.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Main.resx">
|
||||
<DependentUpon>Main.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
||||
+16
-3
@@ -1,11 +1,12 @@
|
||||
$src = $Env:APPVEYOR_BUILD_FOLDER + "\TGInstallerWrapper\bin\Release"
|
||||
$bf = $Env:APPVEYOR_BUILD_FOLDER
|
||||
$src = "$bf\TGInstallerWrapper\bin\Release"
|
||||
|
||||
Remove-Item "$src\Microsoft.Deployment.WindowsInstaller.xml"
|
||||
Remove-Item "$src\TG Station Server Installer.exe.config"
|
||||
Remove-Item "$src\TG Station Server Installer.pdb"
|
||||
Remove-Item "$src\TGServiceInterface.pdb"
|
||||
|
||||
$destination = $Env:APPVEYOR_BUILD_FOLDER + "\TGS3.zip"
|
||||
$destination = "$bf\TGS3-Server.zip"
|
||||
|
||||
If(Test-path $destination) {Remove-item $destination}
|
||||
|
||||
@@ -13,6 +14,18 @@ Add-Type -assembly "system.io.compression.filesystem"
|
||||
|
||||
[io.compression.zipfile]::CreateFromDirectory($src, $destination)
|
||||
|
||||
$destination_md5sha = $Env:APPVEYOR_BUILD_FOLDER + "\MD5-SHA1.txt"
|
||||
$destination_md5sha = $Env:APPVEYOR_BUILD_FOLDER + "\MD5-SHA1-Server.txt"
|
||||
|
||||
$src2 = $Env:APPVEYOR_BUILD_FOLDER + "\ClientApps"
|
||||
[system.io.directory]::CreateDirectory($src2)
|
||||
Copy-Item "$bf\TGCommandLine\bin\Release\TGCommandLine.exe" "$src2\TGCommandLine.exe"
|
||||
Copy-Item "$bf\TGControlPanel\bin\Release\TGControlPanel.exe" "$src2\TGControlPanel.exe"
|
||||
Copy-Item "$bf\TGServiceInterface\bin\Release\TGServiceInterface.dll" "$src2\TGServiceInterface.dll"
|
||||
|
||||
$dest2 = "$bf\TGS3-Client.zip"
|
||||
|
||||
[io.compression.zipfile]::CreateFromDirectory($src2, $dest2)
|
||||
$destination_md5sha2 = $Env:APPVEYOR_BUILD_FOLDER + "\MD5-SHA1-Client.txt"
|
||||
|
||||
& fciv -both $destination > $destination_md5sha
|
||||
& fciv -both $dest2 > $destination_md5sha2
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceModel;
|
||||
using TGServiceInterface;
|
||||
|
||||
namespace TGServerService
|
||||
{
|
||||
//note this only works with MACHINE LOCAL groups and admins for now
|
||||
//if someone wants AD shit, code it yourself
|
||||
partial class TGStationServer : ServiceAuthorizationManager, ITGAdministration
|
||||
{
|
||||
SecurityIdentifier TheDroidsWereLookingFor;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCurrentAuthorizedGroup()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (TheDroidsWereLookingFor == null)
|
||||
return "ADMIN";
|
||||
|
||||
var pc = new PrincipalContext(ContextType.Machine);
|
||||
return GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value).Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SetAuthorizedGroup(string groupName)
|
||||
{
|
||||
if(groupName == null)
|
||||
{
|
||||
TheDroidsWereLookingFor = null;
|
||||
var config = Properties.Settings.Default;
|
||||
config.AuthorizedGroupSID = null;
|
||||
config.Save();
|
||||
return "ADMIN";
|
||||
}
|
||||
return FindTheDroidsWereLookingFor(groupName);
|
||||
}
|
||||
|
||||
string FindTheDroidsWereLookingFor(string search = null)
|
||||
{
|
||||
//find the group that is authorized to use the tools
|
||||
var pc = new PrincipalContext(ContextType.Machine);
|
||||
var config = Properties.Settings.Default;
|
||||
var groupName = search ?? config.AuthorizedGroupSID;
|
||||
if (String.IsNullOrWhiteSpace(groupName))
|
||||
return null;
|
||||
var gp = GroupPrincipal.FindByIdentity(pc, search != null ? IdentityType.Name : IdentityType.Sid, groupName);
|
||||
if (gp == null)
|
||||
{
|
||||
if (search != null)
|
||||
//try again with all types
|
||||
gp = GroupPrincipal.FindByIdentity(pc, search);
|
||||
if (gp == null)
|
||||
return null;
|
||||
}
|
||||
TheDroidsWereLookingFor = gp.Sid;
|
||||
if (search != null)
|
||||
{
|
||||
config.AuthorizedGroupSID = TheDroidsWereLookingFor.Value;
|
||||
config.Save();
|
||||
}
|
||||
return gp.Name;
|
||||
}
|
||||
|
||||
//This function checks for authorization whenever an API call is made
|
||||
//This does NOT validate the windows account, that is done when the user connects internally
|
||||
protected override bool CheckAccessCore(OperationContext operationContext)
|
||||
{
|
||||
if (operationContext.EndpointDispatcher.ContractName == typeof(ITGConnectivity).Name) //always allow connectivity checks
|
||||
return true;
|
||||
|
||||
var windowsIdent = operationContext.ServiceSecurityContext.WindowsIdentity;
|
||||
var wp = new WindowsPrincipal(windowsIdent);
|
||||
//first allow admins
|
||||
var authSuccess = wp.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
|
||||
//if we're not an admin, check that we aren't trying to access the admin interface
|
||||
if (!authSuccess && operationContext.EndpointDispatcher.ContractName != typeof(ITGAdministration).Name && TheDroidsWereLookingFor != null)
|
||||
{
|
||||
var pc = new PrincipalContext(ContextType.Machine);
|
||||
var up = UserPrincipal.FindByIdentity(pc, IdentityType.Sid, windowsIdent.User.Value);
|
||||
//tiny bit of ad support here just cause i was debugging at work
|
||||
//if up is null check it on a domain
|
||||
if (up == null)
|
||||
try
|
||||
{
|
||||
up = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain), IdentityType.Sid, windowsIdent.User.Value);
|
||||
}
|
||||
catch { }
|
||||
if (up != null)
|
||||
{
|
||||
var gp = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value);
|
||||
if (gp != null)
|
||||
{
|
||||
//and allow those in the authorized group
|
||||
authSuccess = up.IsMemberOf(gp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TGServerService.WriteAccess(operationContext.ServiceSecurityContext.WindowsIdentity.Name, authSuccess);
|
||||
return authSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="SettingsVersion" serializeAs="String">
|
||||
<value>1</value>
|
||||
<value>3</value>
|
||||
</setting>
|
||||
<setting name="ReattachCommsKey" serializeAs="String">
|
||||
<value />
|
||||
@@ -64,6 +64,12 @@
|
||||
<setting name="Webclient" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="CertificateURL" serializeAs="String">
|
||||
<value>localhost</value>
|
||||
</setting>
|
||||
<setting name="AuthorizedGroupSID" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</TGServerService.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
||||
@@ -9,13 +9,14 @@ namespace TGServerService
|
||||
|
||||
//this line basically says make one instance of the service, use it multithreaded for requests, and never delete it
|
||||
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
|
||||
partial class TGStationServer : IDisposable, ITGSService
|
||||
partial class TGStationServer : IDisposable, ITGSService, ITGConnectivity
|
||||
{
|
||||
|
||||
//call partial constructors/destructors from here
|
||||
//called when the service is started
|
||||
public TGStationServer()
|
||||
{
|
||||
FindTheDroidsWereLookingFor();
|
||||
InitChat();
|
||||
InitByond();
|
||||
InitCompiler();
|
||||
|
||||
+25
-1
@@ -205,7 +205,7 @@ namespace TGServerService.Properties {
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("1")]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("3")]
|
||||
public int SettingsVersion {
|
||||
get {
|
||||
return ((int)(this["SettingsVersion"]));
|
||||
@@ -238,5 +238,29 @@ namespace TGServerService.Properties {
|
||||
this["Webclient"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("localhost")]
|
||||
public string CertificateURL {
|
||||
get {
|
||||
return ((string)(this["CertificateURL"]));
|
||||
}
|
||||
set {
|
||||
this["CertificateURL"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string AuthorizedGroupSID {
|
||||
get {
|
||||
return ((string)(this["AuthorizedGroupSID"]));
|
||||
}
|
||||
set {
|
||||
this["AuthorizedGroupSID"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="SettingsVersion" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">1</Value>
|
||||
<Value Profile="(Default)">3</Value>
|
||||
</Setting>
|
||||
<Setting Name="ReattachCommsKey" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
@@ -56,5 +56,11 @@
|
||||
<Setting Name="Webclient" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="CertificateURL" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">localhost</Value>
|
||||
</Setting>
|
||||
<Setting Name="AuthorizedGroupSID" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading;
|
||||
using TGServiceInterface;
|
||||
|
||||
namespace TGServerService
|
||||
@@ -13,6 +14,7 @@ namespace TGServerService
|
||||
//only deprecate events, do not reuse them
|
||||
public enum EventID
|
||||
{
|
||||
Authentication = 1,
|
||||
ChatCommand = 100,
|
||||
ChatConnectFail = 200,
|
||||
ChatProviderStartFail = 300,
|
||||
@@ -95,6 +97,11 @@ namespace TGServerService
|
||||
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Warning, (int)id);
|
||||
}
|
||||
|
||||
public static void WriteAccess(string username, bool authSuccess)
|
||||
{
|
||||
ActiveService.EventLog.WriteEntry(String.Format("Access from: {0}", username), authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, (int)EventID.Authentication);
|
||||
}
|
||||
|
||||
ServiceHost host; //the WCF host
|
||||
|
||||
void MigrateSettings(int oldVersion, int newVersion)
|
||||
@@ -142,21 +149,32 @@ namespace TGServerService
|
||||
}
|
||||
Environment.CurrentDirectory = Config.ServerDirectory;
|
||||
|
||||
host = new ServiceHost(typeof(TGStationServer), new Uri[] { new Uri("net.pipe://localhost") })
|
||||
var instance = new TGStationServer();
|
||||
|
||||
host = new ServiceHost(instance, new Uri[] { new Uri("net.pipe://localhost"), new Uri(String.Format("https://localhost:{0}", Server.HTTPSPort)) })
|
||||
{
|
||||
CloseTimeout = new TimeSpan(0, 0, 5)
|
||||
}; //construction runs here
|
||||
};
|
||||
|
||||
foreach (var I in Server.ValidInterfaces)
|
||||
AddEndpoint(I);
|
||||
|
||||
host.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, Config.CertificateURL);
|
||||
host.Authorization.ServiceAuthorizationManager = instance;
|
||||
|
||||
host.Open(); //...or maybe here, doesn't really matter
|
||||
}
|
||||
|
||||
//shorthand for adding the WCF endpoint
|
||||
void AddEndpoint(Type typetype)
|
||||
{
|
||||
host.AddServiceEndpoint(typetype, new NetNamedPipeBinding(), Server.MasterPipeName + "/" + typetype.Name);
|
||||
var bindingName = Server.MasterInterfaceName + "/" + typetype.Name;
|
||||
host.AddServiceEndpoint(typetype, new NetNamedPipeBinding(), bindingName);
|
||||
var httpsBinding = new WSHttpBinding();
|
||||
var requireAuth = typetype.Name != typeof(ITGConnectivity).Name;
|
||||
httpsBinding.Security.Mode = requireAuth ? SecurityMode.TransportWithMessageCredential : SecurityMode.Transport; //do not require auth for a connectivity check
|
||||
httpsBinding.Security.Message.ClientCredentialType = requireAuth ? MessageCredentialType.UserName : MessageCredentialType.None;
|
||||
host.AddServiceEndpoint(typetype, httpsBinding, bindingName);
|
||||
}
|
||||
|
||||
//when we is kill
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.DirectoryServices.AccountManagement" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Numerics" />
|
||||
@@ -83,6 +84,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Administration.cs" />
|
||||
<Compile Include="Byond.cs" />
|
||||
<Compile Include="Chat.cs" />
|
||||
<Compile Include="ChatCommands.cs" />
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace TGServiceInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Manage the group that is used to access the service, can only be used by an administrator
|
||||
/// </summary>
|
||||
[ServiceContract]
|
||||
public interface ITGAdministration
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the name of the windows group allowed to use the service other than administrator
|
||||
/// </summary>
|
||||
/// <returns>The name of the windows group allowed to use the service other than administrator, "ADMIN" if it's unset, null on failure</returns>
|
||||
[OperationContract]
|
||||
string GetCurrentAuthorizedGroup();
|
||||
|
||||
/// <summary>
|
||||
/// Searches the windows machine for the group named <paramref name="groupName"/>, sets it as the authorized group if it's found
|
||||
/// </summary>
|
||||
/// <param name="groupName">The name of the windows group to search for or null to clear the setting</param>
|
||||
/// <returns>The name of the windows group that is now authorized to use the service on success, null on failure, "ADMIN" on clearing</returns>
|
||||
[OperationContract]
|
||||
string SetAuthorizedGroup(string groupName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace TGServiceInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for testing connections to the service without authentication
|
||||
/// </summary>
|
||||
[ServiceContract]
|
||||
public interface ITGConnectivity
|
||||
{
|
||||
/// <summary>
|
||||
/// Does nothing on the server end, but if the call completes, you can be sure you are connected. WCF won't throw until you try until you actually use the API
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void VerifyConnection();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.ServiceModel;
|
||||
namespace TGServiceInterface
|
||||
{
|
||||
@@ -8,13 +9,53 @@ namespace TGServiceInterface
|
||||
/// <summary>
|
||||
/// List of types that can be used with GetComponen
|
||||
/// </summary>
|
||||
public static readonly IList<Type> ValidInterfaces = new List<Type> { typeof(ITGByond), typeof(ITGChat), typeof(ITGCompiler), typeof(ITGConfig), typeof(ITGDreamDaemon), typeof(ITGRepository), typeof(ITGSService) };
|
||||
public static readonly IList<Type> ValidInterfaces = new List<Type> { typeof(ITGByond), typeof(ITGChat), typeof(ITGCompiler), typeof(ITGConfig), typeof(ITGDreamDaemon), typeof(ITGRepository), typeof(ITGSService), typeof(ITGConnectivity), typeof(ITGAdministration) };
|
||||
|
||||
/// <summary>
|
||||
/// Base name of the communication pipe
|
||||
/// they are formatted as MasterPipeName/ComponentName
|
||||
/// </summary>
|
||||
public static string MasterPipeName = "TGStationServerService";
|
||||
public static string MasterInterfaceName = "TGStationServerService";
|
||||
|
||||
/// <summary>
|
||||
/// If this is set, we will try and connect to an HTTPS server running at this address
|
||||
/// </summary>
|
||||
static string HTTPSURL;
|
||||
|
||||
/// <summary>
|
||||
/// The port used by the service
|
||||
/// </summary>
|
||||
public const ushort HTTPSPort = 38607;
|
||||
|
||||
/// <summary>
|
||||
/// Username for remote operations
|
||||
/// </summary>
|
||||
static string HTTPSUsername;
|
||||
|
||||
/// <summary>
|
||||
/// Password for remote operations
|
||||
/// </summary>
|
||||
static string HTTPSPassword;
|
||||
|
||||
/// <summary>
|
||||
/// Set the interface to look for services on the current computer
|
||||
/// </summary>
|
||||
public static void MakeLocalConnection()
|
||||
{
|
||||
HTTPSURL = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the interface to look for services on a remote computer
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
public static void SetRemoteLoginInformation(string address, string username, string password)
|
||||
{
|
||||
HTTPSURL = address;
|
||||
HTTPSUsername = username;
|
||||
HTTPSPassword = password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the requested server component interface. This does not guarantee a successful connection
|
||||
@@ -26,8 +67,27 @@ namespace TGServiceInterface
|
||||
var ToT = typeof(T);
|
||||
if (!ValidInterfaces.Contains(ToT))
|
||||
throw new Exception("Invalid type!");
|
||||
var InterfaceName = typeof(T).Name;
|
||||
if (HTTPSURL == null)
|
||||
return new ChannelFactory<T>(new NetNamedPipeBinding { SendTimeout = new TimeSpan(0, 10, 0) }, new EndpointAddress(String.Format("net.pipe://localhost/{0}/{1}", MasterInterfaceName, InterfaceName))).CreateChannel();
|
||||
|
||||
return new ChannelFactory<T>(new NetNamedPipeBinding { SendTimeout = new TimeSpan(0, 10, 0) }, new EndpointAddress(String.Format("net.pipe://localhost/{0}/{1}", MasterPipeName, typeof(T).Name))).CreateChannel();
|
||||
//okay we're going over
|
||||
var binding = new WSHttpBinding();
|
||||
var requireAuth = InterfaceName != typeof(ITGConnectivity).Name;
|
||||
binding.Security.Mode = requireAuth ? SecurityMode.TransportWithMessageCredential : SecurityMode.Transport; //do not require auth for a connectivity check
|
||||
binding.Security.Message.ClientCredentialType = requireAuth ? MessageCredentialType.UserName : MessageCredentialType.None;
|
||||
var address = new EndpointAddress(String.Format("https://{0}:{1}/{2}/{3}", HTTPSURL, HTTPSPort, MasterInterfaceName, InterfaceName));
|
||||
var cf = new ChannelFactory<T>(binding, address);
|
||||
if (requireAuth)
|
||||
{
|
||||
cf.Credentials.UserName.UserName = HTTPSUsername;
|
||||
cf.Credentials.UserName.Password = HTTPSPassword;
|
||||
}
|
||||
#if DEBUG
|
||||
//allow self signed certs in debug mode
|
||||
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) => true;
|
||||
#endif
|
||||
return cf.CreateChannel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -40,7 +100,7 @@ namespace TGServiceInterface
|
||||
{
|
||||
try
|
||||
{
|
||||
GetComponent<ITGSService>().VerifyConnection();
|
||||
GetComponent<ITGConnectivity>().VerifyConnection();
|
||||
return null;
|
||||
}
|
||||
catch(Exception e)
|
||||
@@ -48,31 +108,41 @@ namespace TGServiceInterface
|
||||
return e.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for managing the service
|
||||
/// </summary>
|
||||
[ServiceContract]
|
||||
public interface ITGSService
|
||||
{
|
||||
/// <summary>
|
||||
/// Does nothing on the server end, but if the call completes, you can be sure you are connected. WCF won't throw until you try until you actually use the API
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void VerifyConnection();
|
||||
|
||||
/// <summary>
|
||||
/// Next stop of the service will not close DD and sets a flag for it to reattach once it restarts
|
||||
/// As opposed to VerifyConnection(), this check user credentials
|
||||
/// Requires a prior call to <see cref="VerifyConnection"/>
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void PrepareForUpdate();
|
||||
/// <returns>true if credentials are valid, false otherwise</returns>
|
||||
public static bool Authenticate()
|
||||
{
|
||||
try
|
||||
{
|
||||
GetComponent<ITGSService>().Version();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve's the service's version
|
||||
/// As opposed to Authentication() this returns true if the current login can use the <see cref="ITGAdministration"/> interface.
|
||||
/// Requires a prior call to <see cref="Authenticate"/>
|
||||
/// </summary>
|
||||
/// <returns>The service's version</returns>
|
||||
[OperationContract]
|
||||
string Version();
|
||||
/// <returns>true if the connection may use the <see cref="ITGAdministration"/> interface, false otherwise</returns>
|
||||
public static bool AuthenticateAdmin()
|
||||
{
|
||||
try
|
||||
{
|
||||
GetComponent<ITGAdministration>().GetCurrentAuthorizedGroup();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace TGServiceInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for managing the service
|
||||
/// </summary>
|
||||
[ServiceContract]
|
||||
public interface ITGSService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Next stop of the service will not close DD and sets a flag for it to reattach once it restarts
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void PrepareForUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve's the service's version
|
||||
/// </summary>
|
||||
/// <returns>The service's version</returns>
|
||||
[OperationContract]
|
||||
string Version();
|
||||
}
|
||||
}
|
||||
@@ -34,21 +34,25 @@
|
||||
<ApplicationIcon>tgs.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Administration.cs" />
|
||||
<Compile Include="Byond.cs" />
|
||||
<Compile Include="Command.cs" />
|
||||
<Compile Include="Compiler.cs" />
|
||||
<Compile Include="Config.cs" />
|
||||
<Compile Include="Connectivity.cs" />
|
||||
<Compile Include="DreamDaemon.cs" />
|
||||
<Compile Include="Chat.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Repository.cs" />
|
||||
<Compile Include="Server.cs" />
|
||||
<Compile Include="..\Version.cs" />
|
||||
<Compile Include="Service.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="tgs.ico" />
|
||||
|
||||
+9
-5
@@ -5,10 +5,14 @@ image: Visual Studio 2017
|
||||
configuration: Release
|
||||
shallow_clone: true
|
||||
artifacts:
|
||||
- path: TGS3.zip
|
||||
name: TGS3
|
||||
- path: MD5-SHA1.txt
|
||||
name: MD5SHA1
|
||||
- path: TGS3-Server.zip
|
||||
name: TGS3Server
|
||||
- path: MD5-SHA1-Server.txt
|
||||
name: MD5SHA1Server
|
||||
- path: TGS3-Client.zip
|
||||
name: TGS3Client
|
||||
- path: MD5-SHA1-Client.txt
|
||||
name: MD5SHA1Client
|
||||
install:
|
||||
- choco install fciv
|
||||
before_build:
|
||||
@@ -27,7 +31,7 @@ deploy:
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: lJNGAXwiB5HlWdthz3K4PetqpTG5IEAyRgKaiKxFMQ8HW8CcOjRtB97B05op7BsK
|
||||
artifact: TGS3,MD5SHA1
|
||||
artifact: TGS3Server,MD5SHA1Server,TGS3Client,MD5SHA1Client
|
||||
draft: false
|
||||
prerelease: true
|
||||
on:
|
||||
|
||||
Reference in New Issue
Block a user