diff --git a/ProjectLighthouse.Tests/DatabaseFact.cs b/ProjectLighthouse.Tests/DatabaseFact.cs new file mode 100644 index 00000000..ecb8216f --- /dev/null +++ b/ProjectLighthouse.Tests/DatabaseFact.cs @@ -0,0 +1,11 @@ +using ProjectLighthouse.Types; +using Xunit; + +namespace ProjectLighthouse.Tests { + public sealed class DatabaseFact : FactAttribute { + public DatabaseFact() { + ServerSettings.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse"; + if(!ServerSettings.DbConnected) Skip = "Database not available"; + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse.Tests/LighthouseTest.cs b/ProjectLighthouse.Tests/LighthouseTest.cs new file mode 100644 index 00000000..f76a6e60 --- /dev/null +++ b/ProjectLighthouse.Tests/LighthouseTest.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using System.Xml.Serialization; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using ProjectLighthouse.Serialization; +using ProjectLighthouse.Types; + +namespace ProjectLighthouse.Tests { + public class LighthouseTest { + public readonly TestServer Server; + public readonly HttpClient Client; + + public LighthouseTest() { + this.Server = new TestServer(new WebHostBuilder() + .UseStartup()); + + this.Client = this.Server.CreateClient(); + } + + public async Task AuthenticateResponse(int number = 0) { + const char nullChar = (char)0x00; + const char sepChar = (char)0x20; + const string username = "unitTestUser"; + + string stringContent = $"{nullChar}{sepChar}{username}{number}{nullChar}"; + + HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new StringContent(stringContent)); + return response; + } + + public async Task Authenticate(int number = 0) { + HttpResponseMessage response = await this.AuthenticateResponse(number); + + string responseContent = LbpSerializer.StringElement("loginResult", await response.Content.ReadAsStringAsync()); + + XmlSerializer serializer = new(typeof(LoginResult)); + return (LoginResult)serializer.Deserialize(new StringReader(responseContent))!; + } + + public Task AuthenticatedRequest(string endpoint, string mmAuth) => AuthenticatedRequest(endpoint, mmAuth, HttpMethod.Get); + + public Task AuthenticatedRequest(string endpoint, string mmAuth, HttpMethod method) { + using var requestMessage = new HttpRequestMessage(method, endpoint); + requestMessage.Headers.Add("Cookie", mmAuth); + + return this.Client.SendAsync(requestMessage); + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj b/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj new file mode 100644 index 00000000..cd72611b --- /dev/null +++ b/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj @@ -0,0 +1,29 @@ + + + + enable + + false + + net5.0;net6.0 + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj.DotSettings b/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj.DotSettings new file mode 100644 index 00000000..eccc8454 --- /dev/null +++ b/ProjectLighthouse.Tests/ProjectLighthouse.Tests.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/ProjectLighthouse.Tests/Tests/AuthenticationTests.cs b/ProjectLighthouse.Tests/Tests/AuthenticationTests.cs new file mode 100644 index 00000000..e79bf903 --- /dev/null +++ b/ProjectLighthouse.Tests/Tests/AuthenticationTests.cs @@ -0,0 +1,59 @@ +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using ProjectLighthouse.Types; +using Xunit; + +namespace ProjectLighthouse.Tests { + public class AuthenticationTests : LighthouseTest { + [Fact] + public async Task ShouldReturnErrorOnNoPostData() { + HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", null!); + Assert.False(response.IsSuccessStatusCode); + #if NET6_0_OR_GREATER + Assert.True(response.StatusCode == HttpStatusCode.BadRequest); + #else + Assert.True(response.StatusCode == HttpStatusCode.NotAcceptable); + #endif + } + + [DatabaseFact] + public async Task ShouldReturnWithValidData() { + HttpResponseMessage response = await this.AuthenticateResponse(); + Assert.True(response.IsSuccessStatusCode); + string responseContent = await response.Content.ReadAsStringAsync(); + Assert.Contains("MM_AUTH=", responseContent); + Assert.Contains(ServerSettings.ServerName, responseContent); + } + + [DatabaseFact] + public async Task CanSerializeBack() { + LoginResult loginResult = await this.Authenticate(); + + Assert.NotNull(loginResult); + Assert.NotNull(loginResult.AuthTicket); + Assert.NotNull(loginResult.LbpEnvVer); + + Assert.Contains("MM_AUTH=", loginResult.AuthTicket); + Assert.Equal(ServerSettings.ServerName, loginResult.LbpEnvVer); + } + + [DatabaseFact] + public async Task CanUseToken() { + LoginResult loginResult = await this.Authenticate(); + + HttpResponseMessage response = await AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/eula", loginResult.AuthTicket); + string responseContent = await response.Content.ReadAsStringAsync(); + + Assert.True(response.IsSuccessStatusCode); + Assert.Contains("You are logged in", responseContent); + } + + [DatabaseFact] + public async Task ShouldReturnForbiddenWhenNotAuthenticated() { + HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/eula"); + Assert.False(response.IsSuccessStatusCode); + Assert.True(response.StatusCode == HttpStatusCode.Forbidden); + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse.Tests/Tests/SerializerTests.cs b/ProjectLighthouse.Tests/Tests/SerializerTests.cs new file mode 100644 index 00000000..1f89c2f1 --- /dev/null +++ b/ProjectLighthouse.Tests/Tests/SerializerTests.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using ProjectLighthouse.Serialization; +using Xunit; + +namespace ProjectLighthouse.Tests { + public class SerializerTests : LighthouseTest { + [Fact] + public void BlankElementWorks() { + Assert.Equal("", LbpSerializer.BlankElement("test")); + } + + [Fact] + public void StringElementWorks() { + Assert.Equal("asd", LbpSerializer.StringElement("test", "asd")); + Assert.Equal("asd", LbpSerializer.StringElement(new KeyValuePair("test", "asd"))); + } + + [Fact] + public void TaggedStringElementWorks() { + Assert.Equal("asd", LbpSerializer.TaggedStringElement("test", "asd", "foo", "bar")); + Assert.Equal("asd", LbpSerializer.TaggedStringElement(new KeyValuePair("test", "asd"), + new KeyValuePair("foo", "bar"))); + } + + [Fact] + public void ElementsWorks() { + Assert.Equal("asdbar", LbpSerializer.Elements(new KeyValuePair("test", "asd"), + new KeyValuePair("foo", "bar"))); + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse.sln b/ProjectLighthouse.sln index 12322461..96db324b 100644 --- a/ProjectLighthouse.sln +++ b/ProjectLighthouse.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse", "ProjectLighthouse\ProjectLighthouse.csproj", "{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests", "ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj", "{AFC74569-B289-4ACC-B21C-313A3A62C017}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +14,9 @@ Global {C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Release|Any CPU.ActiveCfg = Release|Any CPU {C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Release|Any CPU.Build.0 = Release|Any CPU + {AFC74569-B289-4ACC-B21C-313A3A62C017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFC74569-B289-4ACC-B21C-313A3A62C017}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFC74569-B289-4ACC-B21C-313A3A62C017}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFC74569-B289-4ACC-B21C-313A3A62C017}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/ProjectLighthouse/Controllers/LoginController.cs b/ProjectLighthouse/Controllers/LoginController.cs index 5f0dd357..51f01b56 100644 --- a/ProjectLighthouse/Controllers/LoginController.cs +++ b/ProjectLighthouse/Controllers/LoginController.cs @@ -1,10 +1,7 @@ #nullable enable -using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Primitives; using ProjectLighthouse.Types; namespace ProjectLighthouse.Controllers { @@ -20,9 +17,6 @@ namespace ProjectLighthouse.Controllers { [HttpPost] public async Task Login() { - if(!this.Request.Query.TryGetValue("titleID", out StringValues _)) - return this.BadRequest(""); - string body = await new StreamReader(Request.Body).ReadToEndAsync(); LoginData loginData; diff --git a/ProjectLighthouse/Controllers/MessageController.cs b/ProjectLighthouse/Controllers/MessageController.cs index 1a6ac5c7..f233b92a 100644 --- a/ProjectLighthouse/Controllers/MessageController.cs +++ b/ProjectLighthouse/Controllers/MessageController.cs @@ -1,6 +1,5 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; using ProjectLighthouse.Types; namespace ProjectLighthouse.Controllers { diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index 4e702974..1c1f16da 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -1,5 +1,4 @@ #nullable enable -using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; diff --git a/ProjectLighthouse/Helpers/BinaryHelper.cs b/ProjectLighthouse/Helpers/BinaryHelper.cs index c62d14c8..6b66ff1c 100644 --- a/ProjectLighthouse/Helpers/BinaryHelper.cs +++ b/ProjectLighthouse/Helpers/BinaryHelper.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Text; diff --git a/ProjectLighthouse/Types/LoginResult.cs b/ProjectLighthouse/Types/LoginResult.cs index f9c20260..64bc5be0 100644 --- a/ProjectLighthouse/Types/LoginResult.cs +++ b/ProjectLighthouse/Types/LoginResult.cs @@ -1,12 +1,17 @@ using System.Collections.Generic; +using System.Xml.Serialization; using ProjectLighthouse.Serialization; namespace ProjectLighthouse.Types { /// /// Response to POST /login /// + [XmlRoot("loginResult"), XmlType("loginResult")] public class LoginResult { + [XmlElement("authTicket")] public string AuthTicket { get; set; } + + [XmlElement("lbpEnvVer")] public string LbpEnvVer { get; set; } public string Serialize() { diff --git a/ProjectLighthouse/Types/ServerSettings.cs b/ProjectLighthouse/Types/ServerSettings.cs index 39fc79d9..bde98a9c 100644 --- a/ProjectLighthouse/Types/ServerSettings.cs +++ b/ProjectLighthouse/Types/ServerSettings.cs @@ -16,10 +16,11 @@ namespace ProjectLighthouse.Types { public static string DbConnectionString { get { if(dbConnectionString == null) { - return dbConnectionString = Environment.GetEnvironmentVariable("LIGHTHOUSE_DB_CONNECTION_STRING") ?? ""; + return dbConnectionString = Environment.GetEnvironmentVariable("") ?? ""; } return dbConnectionString; } + set => dbConnectionString = value; } public static bool DbConnected {