mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-08-02 18:18:39 +00:00
Merge branch 'main' of https://github.com/LBPUnion/project-lighthouse
This commit is contained in:
commit
e82c2afbe4
30 changed files with 400 additions and 110 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -60,13 +60,13 @@ jobs:
|
||||||
|
|
||||||
- name: Process Test Results (Control)
|
- name: Process Test Results (Control)
|
||||||
if: ${{ matrix.os.prettyName == 'Linux' }}
|
if: ${{ matrix.os.prettyName == 'Linux' }}
|
||||||
uses: im-open/process-dotnet-test-results@v2.0.0
|
uses: im-open/process-dotnet-test-results@v2.0.1
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Process Test Results
|
- name: Process Test Results
|
||||||
if: ${{ matrix.os.prettyName != 'Linux' }}
|
if: ${{ matrix.os.prettyName != 'Linux' }}
|
||||||
uses: im-open/process-dotnet-test-results@v2.0.0
|
uses: im-open/process-dotnet-test-results@v2.0.1
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
create-status-check: false
|
create-status-check: false
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -14,3 +14,6 @@ riderModule.iml
|
||||||
.vs/
|
.vs/
|
||||||
.vscode/
|
.vscode/
|
||||||
.editorconfig
|
.editorconfig
|
||||||
|
lighthouse.config.json
|
||||||
|
gitBranch.txt
|
||||||
|
gitVersion.txt
|
||||||
|
|
|
@ -8,8 +8,9 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
{
|
{
|
||||||
public DatabaseFact()
|
public DatabaseFact()
|
||||||
{
|
{
|
||||||
ServerSettings.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse";
|
ServerSettings.Instance = new ServerSettings();
|
||||||
if (!ServerSettings.DbConnected)
|
ServerSettings.Instance.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse";
|
||||||
|
if (!ServerStatics.DbConnected)
|
||||||
{
|
{
|
||||||
this.Skip = "Database not available";
|
this.Skip = "Database not available";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
@ -55,6 +56,14 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
return this.Client.SendAsync(requestMessage);
|
return this.Client.SendAsync(requestMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<HttpResponseMessage> UploadFileEndpointRequest(string filePath)
|
||||||
|
{
|
||||||
|
byte[] bytes = Encoding.UTF8.GetBytes(await File.ReadAllTextAsync(filePath));
|
||||||
|
string hash = HashHelper.Sha1Hash(bytes);
|
||||||
|
|
||||||
|
return await this.Client.PostAsync($"/LITTLEBIGPLANETPS3_XML/upload/{hash}", new ByteArrayContent(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath)
|
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath)
|
||||||
=> await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
|
=> await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
Assert.True(response.IsSuccessStatusCode);
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
string responseContent = await response.Content.ReadAsStringAsync();
|
string responseContent = await response.Content.ReadAsStringAsync();
|
||||||
Assert.Contains("MM_AUTH=", responseContent);
|
Assert.Contains("MM_AUTH=", responseContent);
|
||||||
Assert.Contains(ServerSettings.ServerName, responseContent);
|
Assert.Contains(ServerStatics.ServerName, responseContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
|
@ -41,7 +41,7 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
Assert.NotNull(loginResult.LbpEnvVer);
|
Assert.NotNull(loginResult.LbpEnvVer);
|
||||||
|
|
||||||
Assert.Contains("MM_AUTH=", loginResult.AuthTicket);
|
Assert.Contains("MM_AUTH=", loginResult.AuthTicket);
|
||||||
Assert.Equal(ServerSettings.ServerName, loginResult.LbpEnvVer);
|
Assert.Equal(ServerStatics.ServerName, loginResult.LbpEnvVer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
|
@ -59,7 +59,7 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task ShouldReturnForbiddenWhenNotAuthenticated()
|
public async Task ShouldReturnForbiddenWhenNotAuthenticated()
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/eula");
|
HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/announce");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
Assert.True(response.StatusCode == HttpStatusCode.Forbidden);
|
Assert.True(response.StatusCode == HttpStatusCode.Forbidden);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,18 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
User userA = await database.CreateUser("unitTestUser0");
|
User userA = await database.CreateUser("unitTestUser0");
|
||||||
User userB = await database.CreateUser("unitTestUser1");
|
User userB = await database.CreateUser("unitTestUser1");
|
||||||
|
|
||||||
Location l = new();
|
Location l = new()
|
||||||
|
{
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
};
|
||||||
database.Locations.Add(l);
|
database.Locations.Add(l);
|
||||||
await database.SaveChangesAsync();
|
await database.SaveChangesAsync();
|
||||||
|
|
||||||
Slot slotA = new()
|
Slot slotA = new()
|
||||||
{
|
{
|
||||||
Creator = userA,
|
Creator = userA,
|
||||||
|
CreatorId = userA.UserId,
|
||||||
Name = "slotA",
|
Name = "slotA",
|
||||||
Location = l,
|
Location = l,
|
||||||
LocationId = l.Id,
|
LocationId = l.Id,
|
||||||
|
@ -33,6 +38,7 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
Slot slotB = new()
|
Slot slotB = new()
|
||||||
{
|
{
|
||||||
Creator = userB,
|
Creator = userB,
|
||||||
|
CreatorId = userB.UserId,
|
||||||
Name = "slotB",
|
Name = "slotB",
|
||||||
Location = l,
|
Location = l,
|
||||||
LocationId = l.Id,
|
LocationId = l.Id,
|
||||||
|
@ -49,8 +55,10 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
|
|
||||||
LoginResult loginResult = await this.Authenticate();
|
LoginResult loginResult = await this.Authenticate();
|
||||||
|
|
||||||
HttpResponseMessage respMessageA = await this.AuthenticatedRequest("LITTLEBIGPLANETPS3_XML/slots/by?u=unitTestUser0", loginResult.AuthTicket);
|
HttpResponseMessage respMessageA = await this.AuthenticatedRequest
|
||||||
HttpResponseMessage respMessageB = await this.AuthenticatedRequest("LITTLEBIGPLANETPS3_XML/slots/by?u=unitTestUser1", loginResult.AuthTicket);
|
("LITTLEBIGPLANETPS3_XML/slots/by?u=unitTestUser0&pageStart=1&pageSize=1", loginResult.AuthTicket);
|
||||||
|
HttpResponseMessage respMessageB = await this.AuthenticatedRequest
|
||||||
|
("LITTLEBIGPLANETPS3_XML/slots/by?u=unitTestUser1&pageStart=1&pageSize=1", loginResult.AuthTicket);
|
||||||
|
|
||||||
Assert.True(respMessageA.IsSuccessStatusCode);
|
Assert.True(respMessageA.IsSuccessStatusCode);
|
||||||
Assert.True(respMessageB.IsSuccessStatusCode);
|
Assert.True(respMessageB.IsSuccessStatusCode);
|
||||||
|
|
|
@ -17,35 +17,35 @@ namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldNotAcceptScript()
|
public async Task ShouldNotAcceptScript()
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/scriptTest", "ExampleFiles/TestScript.ff");
|
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestScript.ff");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldNotAcceptFarc()
|
public async Task ShouldNotAcceptFarc()
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/farcTest", "ExampleFiles/TestFarc.farc");
|
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestFarc.farc");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldNotAcceptGarbage()
|
public async Task ShouldNotAcceptGarbage()
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/garbageTest", "ExampleFiles/TestGarbage.bin");
|
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestGarbage.bin");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldAcceptTexture()
|
public async Task ShouldAcceptTexture()
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/textureTest", "ExampleFiles/TestTexture.tex");
|
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestTexture.tex");
|
||||||
Assert.True(response.IsSuccessStatusCode);
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldAcceptLevel()
|
public async Task ShouldAcceptLevel()
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/levelTest", "ExampleFiles/TestLevel.lvl");
|
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestLevel.lvl");
|
||||||
Assert.True(response.IsSuccessStatusCode);
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,19 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("lolcatftw/clear")]
|
||||||
|
public async Task<IActionResult> ClearQueuedLevels()
|
||||||
|
{
|
||||||
|
User? user = await this.database.UserFromRequest(this.Request);
|
||||||
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
this.database.QueuedLevels.RemoveRange(this.database.QueuedLevels.Where(q => q.UserId == user.UserId));
|
||||||
|
|
||||||
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
|
return this.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Hearted Levels
|
#region Hearted Levels
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
new LoginResult
|
new LoginResult
|
||||||
{
|
{
|
||||||
AuthTicket = "MM_AUTH=" + token.UserToken,
|
AuthTicket = "MM_AUTH=" + token.UserToken,
|
||||||
LbpEnvVer = ServerSettings.ServerName,
|
LbpEnvVer = ServerStatics.ServerName,
|
||||||
}.Serialize()
|
}.Serialize()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ using Kettu;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
using LBPUnion.ProjectLighthouse.Types;
|
using LBPUnion.ProjectLighthouse.Types;
|
||||||
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
@ -21,11 +22,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("eula")]
|
[HttpGet("eula")]
|
||||||
public async Task<IActionResult> Eula()
|
public IActionResult Eula() => this.Ok(ServerSettings.Instance.EulaText + "\n" + $"{EulaHelper.License}\n");
|
||||||
{
|
|
||||||
User user = await this.database.UserFromRequest(this.Request);
|
|
||||||
return user == null ? this.StatusCode(403, "") : this.Ok(EulaHelper.PrivateInstanceNoticeOrBlank + "\n" + $"{EulaHelper.License}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("announce")]
|
[HttpGet("announce")]
|
||||||
public async Task<IActionResult> Announce()
|
public async Task<IActionResult> Announce()
|
||||||
|
@ -33,7 +30,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
User user = await this.database.UserFromRequest(this.Request);
|
User user = await this.database.UserFromRequest(this.Request);
|
||||||
if (user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
return this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n\n" + EulaHelper.PrivateInstanceNoticeOrBlank);
|
return this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n\n" + ServerSettings.Instance.EulaText);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("notification")]
|
[HttpGet("notification")]
|
||||||
|
|
|
@ -51,10 +51,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
|
||||||
// TODO: check if this is a valid hash
|
// TODO: check if this is a valid hash
|
||||||
[HttpPost("upload/{hash}")]
|
[HttpPost("upload/{hash}")]
|
||||||
[AllowSynchronousIo]
|
|
||||||
public async Task<IActionResult> UploadResource(string hash)
|
public async Task<IActionResult> UploadResource(string hash)
|
||||||
{
|
{
|
||||||
|
|
||||||
string assetsDirectory = FileHelper.ResourcePath;
|
string assetsDirectory = FileHelper.ResourcePath;
|
||||||
string path = FileHelper.GetResourcePath(hash);
|
string path = FileHelper.GetResourcePath(hash);
|
||||||
|
|
||||||
|
@ -70,6 +68,12 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
return this.UnprocessableEntity();
|
return this.UnprocessableEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HashHelper.Sha1Hash(file.Data) != hash)
|
||||||
|
{
|
||||||
|
Logger.Log($"File hash does not match the uploaded file! (hash: {hash}, type: {file.FileType})", LoggerLevelResources.Instance);
|
||||||
|
return this.Conflict();
|
||||||
|
}
|
||||||
|
|
||||||
Logger.Log($"File is OK! (hash: {hash}, type: {file.FileType})", LoggerLevelResources.Instance);
|
Logger.Log($"File is OK! (hash: {hash}, type: {file.FileType})", LoggerLevelResources.Instance);
|
||||||
await IOFile.WriteAllBytesAsync(path, file.Data);
|
await IOFile.WriteAllBytesAsync(path, file.Data);
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
.Include(s => s.Location)
|
.Include(s => s.Location)
|
||||||
.Where(s => s.Creator!.Username == user.Username)
|
.Where(s => s.Creator!.Username == user.Username)
|
||||||
.Skip(pageStart - 1)
|
.Skip(pageStart - 1)
|
||||||
.Take(Math.Min(pageSize, ServerSettings.EntitledSlots)),
|
.Take(Math.Min(pageSize, ServerStatics.EntitledSlots)),
|
||||||
string.Empty,
|
string.Empty,
|
||||||
(current, slot) => current + slot.Serialize()
|
(current, slot) => current + slot.Serialize()
|
||||||
);
|
);
|
||||||
|
@ -56,7 +56,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
new Dictionary<string, object>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"hint_start", pageStart + Math.Min(pageSize, ServerSettings.EntitledSlots)
|
"hint_start", pageStart + Math.Min(pageSize, ServerStatics.EntitledSlots)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"total", user.UsedSlots
|
"total", user.UsedSlots
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
|
@ -20,18 +18,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
|
||||||
[HttpGet("playersInPodCount")]
|
[HttpGet("playersInPodCount")]
|
||||||
[HttpGet("totalPlayerCount")]
|
[HttpGet("totalPlayerCount")]
|
||||||
public async Task<IActionResult> TotalPlayerCount()
|
public async Task<IActionResult> TotalPlayerCount() => this.Ok((await StatisticsHelper.RecentMatches()).ToString()!);
|
||||||
{
|
|
||||||
int recentMatches = await this.database.LastMatches.Where(l => TimestampHelper.Timestamp - l.Timestamp < 60).CountAsync();
|
|
||||||
|
|
||||||
return this.Ok(recentMatches.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("planetStats")]
|
[HttpGet("planetStats")]
|
||||||
public async Task<IActionResult> PlanetStats()
|
public async Task<IActionResult> PlanetStats()
|
||||||
{
|
{
|
||||||
int totalSlotCount = await this.database.Slots.CountAsync();
|
int totalSlotCount = await StatisticsHelper.SlotCount();
|
||||||
int mmPicksCount = await this.database.Slots.CountAsync(s => s.TeamPick);
|
int mmPicksCount = await StatisticsHelper.MMPicksCount();
|
||||||
|
|
||||||
return this.Ok
|
return this.Ok
|
||||||
(
|
(
|
||||||
|
@ -41,6 +34,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("planetStats/totalLevelCount")]
|
[HttpGet("planetStats/totalLevelCount")]
|
||||||
public async Task<IActionResult> TotalLevelCount() => this.Ok((await this.database.Slots.CountAsync()).ToString());
|
public async Task<IActionResult> TotalLevelCount() => this.Ok((await StatisticsHelper.SlotCount()).ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
public DbSet<RatedReview> RatedReviews { get; set; }
|
public DbSet<RatedReview> RatedReviews { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||||
=> options.UseMySql(ServerSettings.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
=> options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
||||||
|
|
||||||
public async Task<User> CreateUser(string username)
|
public async Task<User> CreateUser(string username)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
|
||||||
{
|
|
||||||
// Yoinked from https://stackoverflow.com/a/68530667
|
|
||||||
// Thanks to T-moty!
|
|
||||||
/// <summary>
|
|
||||||
/// Allows synchronous stream operations for this request.
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
|
||||||
public class AllowSynchronousIoAttribute : ActionFilterAttribute
|
|
||||||
{
|
|
||||||
public override void OnResultExecuting(ResultExecutingContext context)
|
|
||||||
{
|
|
||||||
IHttpBodyControlFeature syncIoFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
|
|
||||||
if (syncIoFeature != null) syncIoFeature.AllowSynchronousIO = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
{
|
{
|
||||||
public static class EulaHelper
|
public static class EulaHelper
|
||||||
|
@ -17,13 +15,5 @@ GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.";
|
along with this program. If not, see <https://www.gnu.org/licenses/>.";
|
||||||
|
|
||||||
public const string PrivateInstanceNotice = @"This server is a private testing instance.
|
|
||||||
Please do not make anything public for now, and keep in mind security isn't as tight as a full release would.";
|
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "HeuristicUnreachableCode")]
|
|
||||||
public const string PrivateInstanceNoticeOrBlank = ShowPrivateInstanceNotice ? PrivateInstanceNotice : "";
|
|
||||||
|
|
||||||
public const bool ShowPrivateInstanceNotice = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -78,6 +78,18 @@ namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
|
||||||
public static bool ResourceExists(string hash) => File.Exists(GetResourcePath(hash));
|
public static bool ResourceExists(string hash) => File.Exists(GetResourcePath(hash));
|
||||||
|
|
||||||
|
public static int ResourceSize(string hash)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (int)new FileInfo(GetResourcePath(hash)).Length;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void EnsureDirectoryCreated(string path)
|
public static void EnsureDirectoryCreated(string path)
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(path)) Directory.CreateDirectory(path ?? throw new ArgumentNullException(nameof(path)));
|
if (!Directory.Exists(path)) Directory.CreateDirectory(path ?? throw new ArgumentNullException(nameof(path)));
|
||||||
|
|
56
ProjectLighthouse/Helpers/GitVersionHelper.cs
Normal file
56
ProjectLighthouse/Helpers/GitVersionHelper.cs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Kettu;
|
||||||
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
{
|
||||||
|
public static class GitVersionHelper
|
||||||
|
{
|
||||||
|
static GitVersionHelper()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CommitHash = readManifestFile("gitVersion.txt");
|
||||||
|
Branch = readManifestFile("gitBranch.txt");
|
||||||
|
CanCheckForUpdates = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Logger.Log
|
||||||
|
(
|
||||||
|
"Project Lighthouse was built incorrectly. Please make sure git is available when building. " +
|
||||||
|
"Because of this, you will not be notified of updates.",
|
||||||
|
LoggerLevelStartup.Instance
|
||||||
|
);
|
||||||
|
CommitHash = "invalid";
|
||||||
|
Branch = "invalid";
|
||||||
|
CanCheckForUpdates = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDirty)
|
||||||
|
{
|
||||||
|
Logger.Log
|
||||||
|
(
|
||||||
|
"This is a modified version of Project Lighthouse. " +
|
||||||
|
"Please make sure you are properly disclosing the source code to any users who may be using this instance.",
|
||||||
|
LoggerLevelStartup.Instance
|
||||||
|
);
|
||||||
|
CanCheckForUpdates = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string readManifestFile(string fileName)
|
||||||
|
{
|
||||||
|
using Stream stream = typeof(Program).Assembly.GetManifestResourceStream($"{typeof(Program).Namespace}.{fileName}");
|
||||||
|
using StreamReader reader = new(stream ?? throw new Exception("The assembly or manifest resource is null."));
|
||||||
|
|
||||||
|
return reader.ReadToEnd().Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string CommitHash { get; set; }
|
||||||
|
public static string Branch { get; set; }
|
||||||
|
public static bool IsDirty => CommitHash.EndsWith("-dirty");
|
||||||
|
public static bool CanCheckForUpdates { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
public static class HashHelper
|
public static class HashHelper
|
||||||
{
|
{
|
||||||
// private static readonly SHA1 sha1 = SHA1.Create();
|
private static readonly SHA1 sha1 = SHA1.Create();
|
||||||
private static readonly SHA256 sha256 = SHA256.Create();
|
private static readonly SHA256 sha256 = SHA256.Create();
|
||||||
private static readonly Random random = new();
|
private static readonly Random random = new();
|
||||||
|
|
||||||
|
@ -67,11 +67,11 @@ namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
|
||||||
public static string Sha256Hash(string str) => Sha256Hash(Encoding.UTF8.GetBytes(str));
|
public static string Sha256Hash(string str) => Sha256Hash(Encoding.UTF8.GetBytes(str));
|
||||||
|
|
||||||
public static string Sha256Hash(byte[] bytes)
|
public static string Sha256Hash(byte[] bytes) => BitConverter.ToString(sha256.ComputeHash(bytes)).Replace("-", "");
|
||||||
{
|
|
||||||
byte[] hash = sha256.ComputeHash(bytes);
|
public static string Sha1Hash(string str) => Sha1Hash(Encoding.UTF8.GetBytes(str));
|
||||||
return Encoding.UTF8.GetString(hash, 0, hash.Length);
|
|
||||||
}
|
public static string Sha1Hash(byte[] bytes) => BitConverter.ToString(sha1.ComputeHash(bytes)).Replace("-", "");
|
||||||
|
|
||||||
public static string BCryptHash(string str) => BCrypt.Net.BCrypt.HashPassword(str);
|
public static string BCryptHash(string str) => BCrypt.Net.BCrypt.HashPassword(str);
|
||||||
|
|
||||||
|
|
50
ProjectLighthouse/Helpers/InfluxHelper.cs
Normal file
50
ProjectLighthouse/Helpers/InfluxHelper.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using InfluxDB.Client;
|
||||||
|
using InfluxDB.Client.Writes;
|
||||||
|
using Kettu;
|
||||||
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
{
|
||||||
|
public static class InfluxHelper
|
||||||
|
{
|
||||||
|
public static readonly InfluxDBClient Client = InfluxDBClientFactory.Create(ServerSettings.Instance.InfluxUrl, ServerSettings.Instance.InfluxToken);
|
||||||
|
|
||||||
|
public static async void Log()
|
||||||
|
{
|
||||||
|
using WriteApi writeApi = Client.GetWriteApi();
|
||||||
|
PointData point = PointData.Measurement("lighthouse")
|
||||||
|
.Field("playerCount", await StatisticsHelper.RecentMatches())
|
||||||
|
.Field("slotCount", await StatisticsHelper.SlotCount());
|
||||||
|
|
||||||
|
writeApi.WritePoint(ServerSettings.Instance.InfluxBucket, ServerSettings.Instance.InfluxOrg, point);
|
||||||
|
|
||||||
|
writeApi.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task StartLogging()
|
||||||
|
{
|
||||||
|
await Client.ReadyAsync();
|
||||||
|
Logger.Log("InfluxDB is now ready.", LoggerLevelInflux.Instance);
|
||||||
|
Thread t = new
|
||||||
|
(
|
||||||
|
delegate()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
#pragma warning disable CS4014
|
||||||
|
Log();
|
||||||
|
#pragma warning restore CS4014
|
||||||
|
// Logger.Log("Logged.", LoggerLevelInflux.Instance);
|
||||||
|
Thread.Sleep(60000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
t.IsBackground = true;
|
||||||
|
t.Name = "InfluxDB Logger";
|
||||||
|
t.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
ProjectLighthouse/Helpers/StatisticsHelper.cs
Normal file
17
ProjectLighthouse/Helpers/StatisticsHelper.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
{
|
||||||
|
public static class StatisticsHelper
|
||||||
|
{
|
||||||
|
private static readonly Database database = new();
|
||||||
|
|
||||||
|
public static async Task<int> RecentMatches() => await database.LastMatches.Where(l => TimestampHelper.Timestamp - l.Timestamp < 300).CountAsync();
|
||||||
|
|
||||||
|
public static async Task<int> SlotCount() => await database.Slots.CountAsync();
|
||||||
|
|
||||||
|
public static async Task<int> MMPicksCount() => await database.Slots.CountAsync(s => s.TeamPick);
|
||||||
|
}
|
||||||
|
}
|
27
ProjectLighthouse/Logging/InfluxLogger.cs
Normal file
27
ProjectLighthouse/Logging/InfluxLogger.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using InfluxDB.Client;
|
||||||
|
using InfluxDB.Client.Writes;
|
||||||
|
using Kettu;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Logging
|
||||||
|
{
|
||||||
|
public class InfluxLogger : LoggerBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public override void Send(LoggerLine line)
|
||||||
|
{
|
||||||
|
string channel = string.IsNullOrEmpty(line.LoggerLevel.Channel) ? "" : $"[{line.LoggerLevel.Channel}] ";
|
||||||
|
|
||||||
|
string level = $"{$"{line.LoggerLevel.Name} {channel}".TrimEnd()}";
|
||||||
|
string content = line.LineData;
|
||||||
|
|
||||||
|
using WriteApi writeApi = InfluxHelper.Client.GetWriteApi();
|
||||||
|
|
||||||
|
PointData point = PointData.Measurement("lighthouseLog").Field("level", level).Field("content", content);
|
||||||
|
|
||||||
|
writeApi.WritePoint(ServerSettings.Instance.InfluxBucket, ServerSettings.Instance.InfluxOrg, point);
|
||||||
|
}
|
||||||
|
public override bool AllowMultiple => false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,18 @@ namespace LBPUnion.ProjectLighthouse.Logging
|
||||||
public override string Name => "Photos";
|
public override string Name => "Photos";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class LoggerLevelConfig : LoggerLevel
|
||||||
|
{
|
||||||
|
public static readonly LoggerLevelConfig Instance = new();
|
||||||
|
public override string Name => "Config";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LoggerLevelInflux : LoggerLevel
|
||||||
|
{
|
||||||
|
public static readonly LoggerLevelInflux Instance = new();
|
||||||
|
public override string Name => "Influx";
|
||||||
|
}
|
||||||
|
|
||||||
public class LoggerLevelAspNet : LoggerLevel
|
public class LoggerLevelAspNet : LoggerLevel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Kettu;
|
using Kettu;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
@ -28,8 +29,13 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
Logger.AddLogger(new LighthouseFileLogger());
|
Logger.AddLogger(new LighthouseFileLogger());
|
||||||
|
|
||||||
Logger.Log("Welcome to Project Lighthouse!", LoggerLevelStartup.Instance);
|
Logger.Log("Welcome to Project Lighthouse!", LoggerLevelStartup.Instance);
|
||||||
|
Logger.Log($"Running {ServerStatics.ServerName} {GitVersionHelper.CommitHash}@{GitVersionHelper.Branch}", LoggerLevelStartup.Instance);
|
||||||
|
|
||||||
|
// This loads the config, see ServerSettings.cs for more information
|
||||||
|
Logger.Log("Loaded config file version " + ServerSettings.Instance.ConfigVersion, LoggerLevelStartup.Instance);
|
||||||
|
|
||||||
Logger.Log("Determining if the database is available...", LoggerLevelStartup.Instance);
|
Logger.Log("Determining if the database is available...", LoggerLevelStartup.Instance);
|
||||||
bool dbConnected = ServerSettings.DbConnected;
|
bool dbConnected = ServerStatics.DbConnected;
|
||||||
Logger.Log(dbConnected ? "Connected to the database." : "Database unavailable! Exiting.", LoggerLevelStartup.Instance);
|
Logger.Log(dbConnected ? "Connected to the database." : "Database unavailable! Exiting.", LoggerLevelStartup.Instance);
|
||||||
|
|
||||||
if (!dbConnected) Environment.Exit(1);
|
if (!dbConnected) Environment.Exit(1);
|
||||||
|
@ -38,6 +44,15 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
Logger.Log("Migrating database...", LoggerLevelDatabase.Instance);
|
Logger.Log("Migrating database...", LoggerLevelDatabase.Instance);
|
||||||
MigrateDatabase(database);
|
MigrateDatabase(database);
|
||||||
|
|
||||||
|
if (ServerSettings.Instance.InfluxEnabled)
|
||||||
|
{
|
||||||
|
Logger.Log("Influx logging is enabled. Starting influx logging...", LoggerLevelStartup.Instance);
|
||||||
|
#pragma warning disable CS4014
|
||||||
|
InfluxHelper.StartLogging();
|
||||||
|
#pragma warning restore CS4014
|
||||||
|
if (ServerSettings.Instance.InfluxLoggingEnabled) Logger.AddLogger(new InfluxLogger());
|
||||||
|
}
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
Logger.Log($"Ready! Startup took {stopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...", LoggerLevelStartup.Instance);
|
Logger.Log($"Ready! Startup took {stopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...", LoggerLevelStartup.Instance);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2"/>
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2"/>
|
||||||
|
<PackageReference Include="InfluxDB.Client" Version="3.1.0"/>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0"/>
|
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0"/>
|
||||||
<PackageReference Include="Kettu" Version="1.2.1"/>
|
<PackageReference Include="Kettu" Version="1.2.1"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.0"/>
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.0"/>
|
||||||
|
@ -21,7 +22,19 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Types\SlotXsd.cs"/>
|
<None Remove="gitVersion.txt"/>
|
||||||
|
<EmbeddedResource Include="gitVersion.txt">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<None Remove="gitBranch.txt"/>
|
||||||
|
<EmbeddedResource Include="gitBranch.txt">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||||
|
<Exec Command="git describe --long --always --dirty --exclude=\* --abbrev=8 > "$(ProjectDir)/gitVersion.txt""/>
|
||||||
|
<Exec Command="git branch --show-current > "$(ProjectDir)/gitBranch.txt""/>
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Reviews;
|
using LBPUnion.ProjectLighthouse.Types.Reviews;
|
||||||
|
@ -206,7 +207,8 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||||
|
|
||||||
public string SerializeResources()
|
public string SerializeResources()
|
||||||
{
|
{
|
||||||
return this.Resources.Aggregate("", (current, resource) => current + LbpSerializer.StringElement("resource", resource));
|
return this.Resources.Aggregate("", (current, resource) => current + LbpSerializer.StringElement("resource", resource)) +
|
||||||
|
LbpSerializer.StringElement("sizeOfResources", this.Resources.Sum(FileHelper.ResourceSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Serialize(RatedLevel? yourRatingStats = null, VisitedLevel? yourVisitedStats = null, Review? yourReview = null)
|
public string Serialize(RatedLevel? yourRatingStats = null, VisitedLevel? yourVisitedStats = null, Review? yourReview = null)
|
||||||
|
|
|
@ -1,44 +1,91 @@
|
||||||
#nullable enable
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Kettu;
|
using Kettu;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Settings
|
namespace LBPUnion.ProjectLighthouse.Types.Settings
|
||||||
{
|
{
|
||||||
public static class ServerSettings
|
[Serializable]
|
||||||
|
public class ServerSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
static ServerSettings()
|
||||||
/// The maximum amount of slots allowed on users' earth
|
|
||||||
/// </summary>
|
|
||||||
public const int EntitledSlots = 50;
|
|
||||||
|
|
||||||
public const int ListsQuota = 50;
|
|
||||||
|
|
||||||
public const string ServerName = "ProjectLighthouse";
|
|
||||||
|
|
||||||
private static string? dbConnectionString;
|
|
||||||
|
|
||||||
public static string DbConnectionString {
|
|
||||||
get {
|
|
||||||
if (dbConnectionString == null) return dbConnectionString = Environment.GetEnvironmentVariable("LIGHTHOUSE_DB_CONNECTION_STRING") ?? "";
|
|
||||||
|
|
||||||
return dbConnectionString;
|
|
||||||
}
|
|
||||||
set => dbConnectionString = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool DbConnected {
|
|
||||||
get {
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
return new Database().Database.CanConnect();
|
if (ServerStatics.IsUnitTesting) return; // Unit testing, we don't want to read configurations here since the tests will provide their own
|
||||||
}
|
|
||||||
catch(Exception e)
|
if (File.Exists(ConfigFileName))
|
||||||
{
|
{
|
||||||
Logger.Log(e.ToString(), LoggerLevelDatabase.Instance);
|
string configFile = File.ReadAllText(ConfigFileName);
|
||||||
return false;
|
|
||||||
}
|
Instance = JsonSerializer.Deserialize<ServerSettings>(configFile) ?? throw new ArgumentNullException(nameof(ConfigFileName));
|
||||||
|
|
||||||
|
if (Instance.ConfigVersion >= CurrentConfigVersion) return;
|
||||||
|
|
||||||
|
Logger.Log($"Upgrading config file from version {Instance.ConfigVersion} to version {CurrentConfigVersion}", LoggerLevelConfig.Instance);
|
||||||
|
Instance.ConfigVersion = CurrentConfigVersion;
|
||||||
|
configFile = JsonSerializer.Serialize
|
||||||
|
(
|
||||||
|
Instance,
|
||||||
|
typeof(ServerSettings),
|
||||||
|
new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
File.WriteAllText(ConfigFileName, configFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string configFile = JsonSerializer.Serialize
|
||||||
|
(
|
||||||
|
new ServerSettings(),
|
||||||
|
typeof(ServerSettings),
|
||||||
|
new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
File.WriteAllText(ConfigFileName, configFile);
|
||||||
|
|
||||||
|
Logger.Log
|
||||||
|
(
|
||||||
|
"The configuration file was not found. " +
|
||||||
|
"A blank configuration file has been created for you at " +
|
||||||
|
$"{Path.Combine(Environment.CurrentDirectory, ConfigFileName)}",
|
||||||
|
LoggerLevelConfig.Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Meta
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public static ServerSettings Instance;
|
||||||
|
|
||||||
|
public const int CurrentConfigVersion = 4;
|
||||||
|
|
||||||
|
[JsonPropertyName("ConfigVersionDoNotModifyOrYouWillBeSlapped")]
|
||||||
|
public int ConfigVersion { get; set; } = CurrentConfigVersion;
|
||||||
|
|
||||||
|
public const string ConfigFileName = "lighthouse.config.json";
|
||||||
|
|
||||||
|
#endregion Meta
|
||||||
|
|
||||||
|
public bool InfluxEnabled { get; set; }
|
||||||
|
public bool InfluxLoggingEnabled { get; set; }
|
||||||
|
public string InfluxOrg { get; set; } = "lighthouse";
|
||||||
|
public string InfluxBucket { get; set; } = "lighthouse";
|
||||||
|
public string InfluxToken { get; set; } = "";
|
||||||
|
public string InfluxUrl { get; set; } = "http://localhost:8086";
|
||||||
|
|
||||||
|
public string EulaText { get; set; } = "";
|
||||||
|
|
||||||
|
public string DbConnectionString { get; set; } = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse";
|
||||||
}
|
}
|
||||||
}
|
}
|
36
ProjectLighthouse/Types/Settings/ServerStatics.cs
Normal file
36
ProjectLighthouse/Types/Settings/ServerStatics.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Kettu;
|
||||||
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Types.Settings
|
||||||
|
{
|
||||||
|
public static class ServerStatics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum amount of slots allowed on users' earth
|
||||||
|
/// </summary>
|
||||||
|
public const int EntitledSlots = 50;
|
||||||
|
|
||||||
|
public const int ListsQuota = 50;
|
||||||
|
|
||||||
|
public const string ServerName = "ProjectLighthouse";
|
||||||
|
|
||||||
|
public static bool DbConnected {
|
||||||
|
get {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new Database().Database.CanConnect();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Logger.Log(e.ToString(), LoggerLevelDatabase.Instance);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsUnitTesting => AppDomain.CurrentDomain.GetAssemblies().Any(assembly => assembly.FullName.StartsWith("xunit"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -105,7 +105,7 @@ namespace LBPUnion.ProjectLighthouse.Types
|
||||||
LbpSerializer.StringElement("game", this.Game) +
|
LbpSerializer.StringElement("game", this.Game) +
|
||||||
this.SerializeSlots(gameVersion == GameVersion.LittleBigPlanetVita) +
|
this.SerializeSlots(gameVersion == GameVersion.LittleBigPlanetVita) +
|
||||||
LbpSerializer.StringElement("lists", this.Lists) +
|
LbpSerializer.StringElement("lists", this.Lists) +
|
||||||
LbpSerializer.StringElement("lists_quota", ServerSettings.ListsQuota) + // technically not a part of the user but LBP expects it
|
LbpSerializer.StringElement("lists_quota", ServerStatics.ListsQuota) + // technically not a part of the user but LBP expects it
|
||||||
LbpSerializer.StringElement("biography", this.Biography) +
|
LbpSerializer.StringElement("biography", this.Biography) +
|
||||||
LbpSerializer.StringElement("reviewCount", this.Reviews) +
|
LbpSerializer.StringElement("reviewCount", this.Reviews) +
|
||||||
LbpSerializer.StringElement("commentCount", this.Comments) +
|
LbpSerializer.StringElement("commentCount", this.Comments) +
|
||||||
|
@ -147,7 +147,7 @@ namespace LBPUnion.ProjectLighthouse.Types
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of slots remaining on the earth
|
/// The number of slots remaining on the earth
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int FreeSlots => ServerSettings.EntitledSlots - this.UsedSlots;
|
public int FreeSlots => ServerStatics.EntitledSlots - this.UsedSlots;
|
||||||
|
|
||||||
private static readonly string[] slotTypes =
|
private static readonly string[] slotTypes =
|
||||||
{
|
{
|
||||||
|
@ -177,12 +177,12 @@ namespace LBPUnion.ProjectLighthouse.Types
|
||||||
slotTypesLocal = slotTypes;
|
slotTypesLocal = slotTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
slots += LbpSerializer.StringElement("entitledSlots", ServerSettings.EntitledSlots);
|
slots += LbpSerializer.StringElement("entitledSlots", ServerStatics.EntitledSlots);
|
||||||
slots += LbpSerializer.StringElement("freeSlots", this.FreeSlots);
|
slots += LbpSerializer.StringElement("freeSlots", this.FreeSlots);
|
||||||
|
|
||||||
foreach (string slotType in slotTypesLocal)
|
foreach (string slotType in slotTypesLocal)
|
||||||
{
|
{
|
||||||
slots += LbpSerializer.StringElement(slotType + "EntitledSlots", ServerSettings.EntitledSlots);
|
slots += LbpSerializer.StringElement(slotType + "EntitledSlots", ServerStatics.EntitledSlots);
|
||||||
// ReSharper disable once StringLiteralTypo
|
// ReSharper disable once StringLiteralTypo
|
||||||
slots += LbpSerializer.StringElement(slotType + slotType == "crossControl" ? "PurchsedSlots" : "PurchasedSlots", 0);
|
slots += LbpSerializer.StringElement(slotType + slotType == "crossControl" ? "PurchsedSlots" : "PurchasedSlots", 0);
|
||||||
slots += LbpSerializer.StringElement(slotType + "FreeSlots", this.FreeSlots);
|
slots += LbpSerializer.StringElement(slotType + "FreeSlots", this.FreeSlots);
|
||||||
|
|
|
@ -62,7 +62,7 @@ Finally, take a break. Chances are that took a while.
|
||||||
|
|
||||||
## Contributing Tips
|
## Contributing Tips
|
||||||
|
|
||||||
### Database
|
### Database migrations
|
||||||
|
|
||||||
Some modifications may require updates to the database schema. You can automatically create a migration file by:
|
Some modifications may require updates to the database schema. You can automatically create a migration file by:
|
||||||
|
|
||||||
|
@ -72,6 +72,12 @@ Some modifications may require updates to the database schema. You can automatic
|
||||||
you're doing.
|
you're doing.
|
||||||
4. Running `dotnet ef migrations add <NameOfMigrationInPascalCase> --project ProjectLighthouse`.
|
4. Running `dotnet ef migrations add <NameOfMigrationInPascalCase> --project ProjectLighthouse`.
|
||||||
|
|
||||||
|
### Running tests
|
||||||
|
|
||||||
|
You can run tests either through your IDE or by running `dotnet tests`.
|
||||||
|
|
||||||
|
Keep in mind while running database tests you need to have `LIGHTHOUSE_DB_CONNECTION_STRING` set.
|
||||||
|
|
||||||
## Compatibility across games and platforms
|
## Compatibility across games and platforms
|
||||||
|
|
||||||
| Game | Console (PS3/Vita) | Emulator (RPCS3) | Next-Gen (PS4/PS5) |
|
| Game | Console (PS3/Vita) | Emulator (RPCS3) | Next-Gen (PS4/PS5) |
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue