mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-04-19 19:14:51 +00:00
Rewrite captcha system (#754)
Rewrite captcha and remove many unused directives
This commit is contained in:
parent
aefecc7b12
commit
3aa9033b67
36 changed files with 101 additions and 111 deletions
|
@ -1,7 +1,6 @@
|
|||
#nullable enable
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users;
|
||||
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
|
|
|
@ -3,7 +3,6 @@ using Discord;
|
|||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Files;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#nullable enable
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
|
@ -17,7 +16,6 @@ using LBPUnion.ProjectLighthouse.Types.Users;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging.Configuration;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Text.Json;
|
|||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Files;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
|
61
ProjectLighthouse.Servers.Website/Captcha/CaptchaService.cs
Normal file
61
ProjectLighthouse.Servers.Website/Captcha/CaptchaService.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Types.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Servers.Website.Captcha;
|
||||
|
||||
public class CaptchaService : ICaptchaService
|
||||
{
|
||||
private readonly HttpClient client;
|
||||
|
||||
public CaptchaService(HttpClient client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public async Task<bool> VerifyCaptcha(HttpRequest request)
|
||||
{
|
||||
if (!ServerConfiguration.Instance.Captcha.CaptchaEnabled) return true;
|
||||
|
||||
string keyName = ServerConfiguration.Instance.Captcha.Type switch
|
||||
{
|
||||
CaptchaType.HCaptcha => "h-captcha-response",
|
||||
CaptchaType.ReCaptcha => "g-recaptcha-response",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(request),
|
||||
@$"Unknown captcha type: {ServerConfiguration.Instance.Captcha.Type}"),
|
||||
};
|
||||
|
||||
bool gotCaptcha = request.Form.TryGetValue(keyName, out StringValues values);
|
||||
if (!gotCaptcha) return false;
|
||||
|
||||
string? captchaToken = values[0];
|
||||
if (captchaToken == null) return false;
|
||||
|
||||
List<KeyValuePair<string, string>> payload = new()
|
||||
{
|
||||
new KeyValuePair<string, string>("secret", ServerConfiguration.Instance.Captcha.Secret),
|
||||
new KeyValuePair<string, string>("response", captchaToken),
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
using HttpResponseMessage response =
|
||||
await this.client.PostAsync("siteverify", new FormUrlEncodedContent(payload));
|
||||
if (!response.IsSuccessStatusCode) return false;
|
||||
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// We only really care about the success result, so we just parse that
|
||||
return bool.Parse(JObject.Parse(responseBody)["success"]?.ToString() ?? "false");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(ex.ToDetailedException(), LogArea.HTTP);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace LBPUnion.ProjectLighthouse.Servers.Website.Captcha;
|
||||
|
||||
public interface ICaptchaService
|
||||
{
|
||||
Task<bool> VerifyCaptcha(HttpRequest request);
|
||||
}
|
|
@ -3,10 +3,10 @@ using System.Web;
|
|||
using JetBrains.Annotations;
|
||||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Localization.StringLists;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Servers.Website.Captcha;
|
||||
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
|
||||
|
@ -18,8 +18,12 @@ namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login;
|
|||
|
||||
public class LoginForm : BaseLayout
|
||||
{
|
||||
public LoginForm(DatabaseContext database) : base(database)
|
||||
{}
|
||||
private readonly ICaptchaService captchaService;
|
||||
|
||||
public LoginForm(DatabaseContext database, ICaptchaService captchaService) : base(database)
|
||||
{
|
||||
this.captchaService = captchaService;
|
||||
}
|
||||
|
||||
public string? Error { get; private set; }
|
||||
|
||||
|
@ -38,7 +42,7 @@ public class LoginForm : BaseLayout
|
|||
return this.Page();
|
||||
}
|
||||
|
||||
if (!await this.Request.CheckCaptchaValidity())
|
||||
if (!await this.captchaService.VerifyCaptcha(this.Request))
|
||||
{
|
||||
this.Error = this.Translate(ErrorStrings.CaptchaFailed);
|
||||
return this.Page();
|
||||
|
|
|
@ -2,9 +2,9 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using JetBrains.Annotations;
|
||||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Localization.StringLists;
|
||||
using LBPUnion.ProjectLighthouse.Servers.Website.Captcha;
|
||||
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
|
||||
|
@ -15,8 +15,12 @@ namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login;
|
|||
|
||||
public class RegisterForm : BaseLayout
|
||||
{
|
||||
public RegisterForm(DatabaseContext database) : base(database)
|
||||
{ }
|
||||
private readonly ICaptchaService captchaService;
|
||||
|
||||
public RegisterForm(DatabaseContext database, ICaptchaService captchaService) : base(database)
|
||||
{
|
||||
this.captchaService = captchaService;
|
||||
}
|
||||
|
||||
public string? Error { get; private set; }
|
||||
|
||||
|
@ -68,7 +72,7 @@ public class RegisterForm : BaseLayout
|
|||
return this.Page();
|
||||
}
|
||||
|
||||
if (!await this.Request.CheckCaptchaValidity())
|
||||
if (!await this.captchaService.VerifyCaptcha(this.Request))
|
||||
{
|
||||
this.Error = this.Translate(ErrorStrings.CaptchaFailed);
|
||||
return this.Page();
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
using System.Globalization;
|
||||
using System.Net;
|
||||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Localization;
|
||||
using LBPUnion.ProjectLighthouse.Middlewares;
|
||||
using LBPUnion.ProjectLighthouse.Servers.Website.Captcha;
|
||||
using LBPUnion.ProjectLighthouse.Servers.Website.Middlewares;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
|
@ -44,6 +47,20 @@ public class WebsiteStartup
|
|||
|
||||
services.AddDbContext<DatabaseContext>();
|
||||
|
||||
services.AddHttpClient<ICaptchaService, CaptchaService>("CaptchaAPI",
|
||||
client =>
|
||||
{
|
||||
Uri captchaUri = ServerConfiguration.Instance.Captcha.Type switch
|
||||
{
|
||||
CaptchaType.HCaptcha => new Uri("https://hcaptcha.com"),
|
||||
CaptchaType.ReCaptcha => new Uri("https://www.google.com/recaptcha/api/"),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(client)),
|
||||
};
|
||||
client.BaseAddress = captchaUri;
|
||||
client.Timeout = TimeSpan.FromSeconds(5);
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "Project Lighthouse");
|
||||
});
|
||||
|
||||
services.Configure<ForwardedHeadersOptions>
|
||||
(
|
||||
options =>
|
||||
|
|
|
@ -1,36 +1,12 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net.Http;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Extensions;
|
||||
|
||||
public static partial class RequestExtensions
|
||||
{
|
||||
static RequestExtensions()
|
||||
{
|
||||
Uri captchaUri = ServerConfiguration.Instance.Captcha.Type switch
|
||||
{
|
||||
CaptchaType.HCaptcha => new Uri("https://hcaptcha.com"),
|
||||
CaptchaType.ReCaptcha => new Uri("https://www.google.com/recaptcha/api/"),
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
|
||||
client = new HttpClient
|
||||
{
|
||||
BaseAddress = captchaUri,
|
||||
};
|
||||
}
|
||||
|
||||
#region Mobile Checking
|
||||
|
||||
// yoinked and adapted from https://stackoverflow.com/a/68641796
|
||||
|
@ -42,51 +18,4 @@ public static partial class RequestExtensions
|
|||
public static bool IsMobile(this HttpRequest request) => MobileCheckRegex().IsMatch(request.Headers[HeaderNames.UserAgent].ToString());
|
||||
|
||||
#endregion
|
||||
|
||||
#region Captcha
|
||||
|
||||
private static readonly HttpClient client;
|
||||
|
||||
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")]
|
||||
private static async Task<bool> verifyCaptcha(string? token)
|
||||
{
|
||||
if (!ServerConfiguration.Instance.Captcha.CaptchaEnabled) return true;
|
||||
|
||||
if (token == null) return false;
|
||||
|
||||
List<KeyValuePair<string, string>> payload = new()
|
||||
{
|
||||
new("secret", ServerConfiguration.Instance.Captcha.Secret),
|
||||
new("response", token),
|
||||
};
|
||||
|
||||
HttpResponseMessage response = await client.PostAsync("siteverify", new FormUrlEncodedContent(payload));
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// We only really care about the success result, nothing else that hcaptcha sends us, so lets only parse that.
|
||||
bool success = bool.Parse(JObject.Parse(responseBody)["success"]?.ToString() ?? "false");
|
||||
return success;
|
||||
}
|
||||
|
||||
public static async Task<bool> CheckCaptchaValidity(this HttpRequest request)
|
||||
{
|
||||
if (!ServerConfiguration.Instance.Captcha.CaptchaEnabled) return true;
|
||||
|
||||
string keyName = ServerConfiguration.Instance.Captcha.Type switch
|
||||
{
|
||||
CaptchaType.HCaptcha => "h-captcha-response",
|
||||
CaptchaType.ReCaptcha => "g-recaptcha-response",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(request), @$"Unknown captcha type: {ServerConfiguration.Instance.Captcha.Type}"),
|
||||
};
|
||||
|
||||
bool gotCaptcha = request.Form.TryGetValue(keyName, out StringValues values);
|
||||
if (!gotCaptcha) return false;
|
||||
|
||||
return await verifyCaptcha(values[0]);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Linq;
|
|||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Threading.Tasks;
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Moderation;
|
||||
using LBPUnion.ProjectLighthouse.Types.Moderation.Reports;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
|
|
@ -7,7 +7,6 @@ using System.Threading.Tasks;
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Configuration;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#nullable enable
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue