diff --git a/Docker/run/compose/mare-standalone.yml b/Docker/run/compose/mare-standalone.yml index c6a0a93..5eb8859 100644 --- a/Docker/run/compose/mare-standalone.yml +++ b/Docker/run/compose/mare-standalone.yml @@ -28,10 +28,10 @@ services: image: darkarchon/mare-synchronos-server:latest restart: on-failure ports: - - 6000:6000/tcp - - 6050:6050/tcp + - 6300:6300/tcp + - 6350:6350/tcp environment: - MareSynchronos__CdnFullUrl: "${DEV_MARE_CDNURL}" + MareSynchronos__CdnFullUrl: "http://127.0.0.1:6200/marecache" MareSynchronos__XIVAPIKey: "${DEV_MARE_XIVAPIKEY}" DOTNET_USE_POLLING_FILE_WATCHER: 1 volumes: @@ -42,34 +42,34 @@ services: postgres: condition: service_healthy healthcheck: - test: ["CMD-SHELL", "curl --fail http://localhost:6000/health || exit 1"] + test: ["CMD-SHELL", "curl --fail http://localhost:6300/health || exit 1"] retries: 60 start_period: 10s timeout: 1s - - mare-auth: - image: darkarchon/mare-synchronos-authservice:latest - restart: on-failure - environment: - DOTNET_USE_POLLING_FILE_WATCHER: 1 - volumes: - - ../config/standalone/authservice-standalone.json:/opt/MareSynchronosAuthService/appsettings.json - - ../log/authservice-standalone/:/opt/MareSynchronosAuthService/logs/:rw - - postgres_socket:/var/run/postgresql/:rw - depends_on: - mare-server: - condition: service_healthy - postgres: - condition: service_healthy +# +# mare-auth: +# image: darkarchon/mare-synchronos-authservice:latest +# restart: on-failure +# environment: +# DOTNET_USE_POLLING_FILE_WATCHER: 1 +# volumes: +# - ../config/standalone/authservice-standalone.json:/opt/MareSynchronosAuthService/appsettings.json +# - ../log/authservice-standalone/:/opt/MareSynchronosAuthService/logs/:rw +# - postgres_socket:/var/run/postgresql/:rw +# depends_on: +# mare-server: +# condition: service_healthy +# postgres: +# condition: service_healthy mare-services: image: darkarchon/mare-synchronos-services:latest restart: on-failure environment: MareSynchronos__DiscordBotToken: "${DEV_MARE_DISCORDTOKEN}" - MareSynchronos__DiscordChannelForMessages: "${DEV_MARE_DISCORDCHANNEL}" - MareSynchronos__DiscordChannelForReports: "${DEV_MARE_DISCORDCHANNEL}" - MareSynchronos__DiscordChannelForCommands: "${DEV_MARE_DISCORDCHANNEL}" + MareSynchronos__DiscordChannelForMessages: "926997505848254507" + MareSynchronos__DiscordChannelForReports: "926997505848254507" + MareSynchronos__DiscordChannelForCommands: "926997505848254507" DOTNET_USE_POLLING_FILE_WATCHER: 1 volumes: - ../config/standalone/services-standalone.json:/opt/MareSynchronosServices/appsettings.json @@ -87,13 +87,13 @@ services: - 6200:6200/tcp restart: on-failure environment: - MareSynchronos__CdnFullUrl: "${DEV_MARE_CDNURL}" + MareSynchronos__CdnFullUrl: "http://127.0.0.1:6200/marecache" DOTNET_USE_POLLING_FILE_WATCHER: 1 volumes: - ../config/standalone/files-standalone.json:/opt/MareSynchronosStaticFilesServer/appsettings.json - ../log/files-standalone/:/opt/MareSynchronosStaticFilesServer/logs/:rw - postgres_socket:/var/run/postgresql/:rw - - ../data/files-standalone/:/marecache/:rw + - D:\mareserverfiles\:/marecache/:rw depends_on: postgres: condition: service_healthy diff --git a/Docker/run/config/standalone/files-standalone.json b/Docker/run/config/standalone/files-standalone.json index 0d28810..a116869 100644 --- a/Docker/run/config/standalone/files-standalone.json +++ b/Docker/run/config/standalone/files-standalone.json @@ -7,8 +7,8 @@ "Default": "Warning", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", - "MareSynchronosStaticFilesServer": "Debug", - "MareSynchronosShared": "Debug", + "MareSynchronosStaticFilesServer": "Trace", + "MareSynchronosShared": "Trace", "System.IO": "Information", }, "File": { diff --git a/Docker/run/config/standalone/server-standalone.json b/Docker/run/config/standalone/server-standalone.json index d77469e..47ca518 100644 --- a/Docker/run/config/standalone/server-standalone.json +++ b/Docker/run/config/standalone/server-standalone.json @@ -8,7 +8,7 @@ "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", "Microsoft.EntityFramework": "Warning", - "MareSynchronosServer": "Debug", + "MareSynchronosServer": "Trace", "MareSynchronosShared": "Debug", "System.IO": "Information", "MareSynchronosServer.Services.SystemInfoService": "Warning" @@ -29,7 +29,7 @@ "MareSynchronos": { "DbContextPoolSize": 512, "ShardName": "Main", - "MetricsPort": 6050, + "MetricsPort": 6350, "MainServerAddress": "", "FailedAuthForTempBan": 5, "TempBanDurationInMinutes": 5, @@ -38,20 +38,20 @@ "" ], "RedisConnectionString": "redis,password=secretredispassword", - "CdnFullUrl": "http://localhost:6200", + "CdnFullUrl": "http://localhost:6200/marecache", "MaxExistingGroupsByUser": 6, "MaxJoinedGroupsByUser": 10, "MaxGroupUserCount": 100, "PurgeUnusedAccounts": false, "PurgeUnusedAccountsPeriodInDays": 14, - "ExpectedClientVersion": "0.9.0", + "ExpectedClientVersion": "0.11.22", "XIVAPIKey": "" }, "AllowedHosts": "*", "Kestrel": { "Endpoints": { "Http": { - "Url": "http://+:6000" + "Url": "http://+:6300" } } }, diff --git a/Docker/run/config/standalone/services-standalone.json b/Docker/run/config/standalone/services-standalone.json index 44100be..ca9f55d 100644 --- a/Docker/run/config/standalone/services-standalone.json +++ b/Docker/run/config/standalone/services-standalone.json @@ -29,14 +29,14 @@ "ShardName": "Services", "MetricsPort": 6150, "CdnFullUrl": "http://localhost:6200/", - "MainServerAddress": "http://mare-server:6000/", + "MainServerAddress": "http://mare-server:6300/", "MainServerGrpcAddress": "http://mare-server:6005/", "DiscordBotToken": "", "DiscordChannelForMessages": "", "DiscordChannelForCommands": "", "Jwt": "teststringteststringteststringteststringteststringteststringteststringteststringteststringteststring", "RedisConnectionString": "redis,password=secretredispassword", - "VanityRoles": {"984484868241096724":"Main Developer", "1012008556259725398":"Patreon Subscriber"} + "VanityRoles": {"1097028541666836500":"Main Developer", "1012008556259725398":"Patreon Subscriber"} }, "AllowedHosts": "*", "Kestrel": { diff --git a/Docker/run/windows-standalone.bat b/Docker/run/windows-standalone.bat index 747225f..6605d6d 100644 --- a/Docker/run/windows-standalone.bat +++ b/Docker/run/windows-standalone.bat @@ -1,2 +1,2 @@ @echo off -docker compose -f compose\mare-standalone.yml -p standalone up \ No newline at end of file +docker compose -f compose\mare-standalone.yml -p standalone up -d \ No newline at end of file diff --git a/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/.gitignore b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/.gitignore new file mode 100644 index 0000000..66ef68e --- /dev/null +++ b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/.idea.MareSynchronosServer.iml +/projectSettingsUpdater.xml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/encodings.xml b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/indexLayout.xml b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/vcs.xml b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/vcs.xml new file mode 100644 index 0000000..9baacd2 --- /dev/null +++ b/MareSynchronosServer/.idea/.idea.MareSynchronosServer/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosAuthService/MareSynchronosAuthService.csproj b/MareSynchronosServer/MareSynchronosAuthService/MareSynchronosAuthService.csproj index 3c76881..2a88b79 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/MareSynchronosAuthService.csproj +++ b/MareSynchronosServer/MareSynchronosAuthService/MareSynchronosAuthService.csproj @@ -19,4 +19,9 @@ + + + + + diff --git a/MareSynchronosServer/MareSynchronosAuthService/Services/GeoIPService.cs b/MareSynchronosServer/MareSynchronosAuthService/Services/GeoIPService.cs deleted file mode 100644 index 3d3c21c..0000000 --- a/MareSynchronosServer/MareSynchronosAuthService/Services/GeoIPService.cs +++ /dev/null @@ -1,143 +0,0 @@ -using MareSynchronosShared; -using MareSynchronosShared.Services; -using MareSynchronosShared.Utils.Configuration; -using MaxMind.GeoIP2; - -namespace MareSynchronosAuthService.Services; - -public class GeoIPService : IHostedService -{ - private readonly ILogger _logger; - private readonly IConfigurationService _mareConfiguration; - private bool _useGeoIP = false; - private string _cityFile = string.Empty; - private DatabaseReader? _dbReader; - private DateTime _dbLastWriteTime = DateTime.MinValue; - private CancellationTokenSource _fileWriteTimeCheckCts = new(); - private bool _processingReload = false; - - public GeoIPService(ILogger logger, - IConfigurationService mareConfiguration) - { - _logger = logger; - _mareConfiguration = mareConfiguration; - } - - public async Task GetCountryFromIP(IHttpContextAccessor httpContextAccessor) - { - if (!_useGeoIP) - { - return "*"; - } - - try - { - var ip = httpContextAccessor.GetIpAddress(); - - using CancellationTokenSource waitCts = new(); - waitCts.CancelAfter(TimeSpan.FromSeconds(5)); - while (_processingReload) await Task.Delay(100, waitCts.Token).ConfigureAwait(false); - - if (_dbReader!.TryCity(ip, out var response)) - { - string? continent = response?.Continent.Code; - if (!string.IsNullOrEmpty(continent) && - string.Equals(continent, "NA", StringComparison.Ordinal) - && response?.Location.Longitude != null) - { - if (response.Location.Longitude < -102) - { - continent = "NA-W"; - } - else - { - continent = "NA-E"; - } - } - - return continent ?? "*"; - } - - return "*"; - } - catch (Exception ex) - { - _logger.LogWarning(ex, "Error handling Geo IP country in request"); - return "*"; - } - } - - public Task StartAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("GeoIP module starting update task"); - - var token = _fileWriteTimeCheckCts.Token; - _ = PeriodicReloadTask(token); - - return Task.CompletedTask; - } - - private async Task PeriodicReloadTask(CancellationToken token) - { - while (!token.IsCancellationRequested) - { - try - { - _processingReload = true; - - var useGeoIP = _mareConfiguration.GetValueOrDefault(nameof(AuthServiceConfiguration.UseGeoIP), false); - var cityFile = _mareConfiguration.GetValueOrDefault(nameof(AuthServiceConfiguration.GeoIPDbCityFile), string.Empty); - DateTime lastWriteTime = DateTime.MinValue; - if (File.Exists(cityFile)) - { - lastWriteTime = new FileInfo(cityFile).LastWriteTimeUtc; - } - - if (useGeoIP && (!string.Equals(cityFile, _cityFile, StringComparison.OrdinalIgnoreCase) || lastWriteTime > _dbLastWriteTime)) - { - _cityFile = cityFile; - if (!File.Exists(_cityFile)) throw new FileNotFoundException($"Could not open GeoIP City Database, path does not exist: {_cityFile}"); - _dbReader?.Dispose(); - _dbReader = null; - _dbReader = new DatabaseReader(_cityFile); - _dbLastWriteTime = lastWriteTime; - - _ = _dbReader.City("8.8.8.8").Continent; - - _logger.LogInformation($"Loaded GeoIP city file from {_cityFile}"); - - if (_useGeoIP != useGeoIP) - { - _logger.LogInformation("GeoIP module is now enabled"); - _useGeoIP = useGeoIP; - } - } - - if (_useGeoIP != useGeoIP && !useGeoIP) - { - _logger.LogInformation("GeoIP module is now disabled"); - _useGeoIP = useGeoIP; - } - } - catch (Exception e) - { - _logger.LogWarning(e, "Error during periodic GeoIP module reload task, disabling GeoIP"); - _useGeoIP = false; - } - finally - { - _processingReload = false; - } - - await Task.Delay(TimeSpan.FromMinutes(1)).ConfigureAwait(false); - } - } - - public Task StopAsync(CancellationToken cancellationToken) - { - _fileWriteTimeCheckCts.Cancel(); - _fileWriteTimeCheckCts.Dispose(); - _dbReader?.Dispose(); - return Task.CompletedTask; - } -} diff --git a/MareSynchronosServer/MareSynchronosServer.sln b/MareSynchronosServer/MareSynchronosServer.sln index 9df8f0d..84f8d6f 100644 --- a/MareSynchronosServer/MareSynchronosServer.sln +++ b/MareSynchronosServer/MareSynchronosServer.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosServer", "Mar EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronos.API", "..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj", "{326BFB1B-5571-47A6-8513-1FFDB32D53B0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosServerTest", "MareSynchronosServerTest\MareSynchronosServerTest.csproj", "{25A82A2A-35C2-4EE0-A0E8-DFDD77978DDA}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosShared", "MareSynchronosShared\MareSynchronosShared.csproj", "{67B1461D-E215-4BA8-A64D-E1836724D5E6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosStaticFilesServer", "MareSynchronosStaticFilesServer\MareSynchronosStaticFilesServer.csproj", "{3C7F43BB-FE4C-48BC-BF42-D24E70E8FCB7}" @@ -36,10 +34,6 @@ Global {326BFB1B-5571-47A6-8513-1FFDB32D53B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {326BFB1B-5571-47A6-8513-1FFDB32D53B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {326BFB1B-5571-47A6-8513-1FFDB32D53B0}.Release|Any CPU.Build.0 = Release|Any CPU - {25A82A2A-35C2-4EE0-A0E8-DFDD77978DDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {25A82A2A-35C2-4EE0-A0E8-DFDD77978DDA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {25A82A2A-35C2-4EE0-A0E8-DFDD77978DDA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {25A82A2A-35C2-4EE0-A0E8-DFDD77978DDA}.Release|Any CPU.Build.0 = Release|Any CPU {67B1461D-E215-4BA8-A64D-E1836724D5E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {67B1461D-E215-4BA8-A64D-E1836724D5E6}.Debug|Any CPU.Build.0 = Debug|Any CPU {67B1461D-E215-4BA8-A64D-E1836724D5E6}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/MareSynchronosServer/MareSynchronosAuthService/Authentication/SecretKeyAuthReply.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthReply.cs similarity index 72% rename from MareSynchronosServer/MareSynchronosAuthService/Authentication/SecretKeyAuthReply.cs rename to MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthReply.cs index 210c197..bbecc89 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/Authentication/SecretKeyAuthReply.cs +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthReply.cs @@ -1,3 +1,3 @@ -namespace MareSynchronosAuthService.Authentication; +namespace MareSynchronosServer.Authentication; public record SecretKeyAuthReply(bool Success, string? Uid, string? PrimaryUid, string? Alias, bool TempBan, bool Permaban, bool MarkedForBan); diff --git a/MareSynchronosServer/MareSynchronosAuthService/Authentication/SecretKeyFailedAuthorization.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyFailedAuthorization.cs similarity index 83% rename from MareSynchronosServer/MareSynchronosAuthService/Authentication/SecretKeyFailedAuthorization.cs rename to MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyFailedAuthorization.cs index fcf6581..a5bae15 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/Authentication/SecretKeyFailedAuthorization.cs +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyFailedAuthorization.cs @@ -1,4 +1,4 @@ -namespace MareSynchronosAuthService.Authentication; +namespace MareSynchronosServer.Authentication; internal record SecretKeyFailedAuthorization { diff --git a/MareSynchronosServer/MareSynchronosAuthService/Controllers/AuthControllerBase.cs b/MareSynchronosServer/MareSynchronosServer/Controllers/AuthControllerBase.cs similarity index 95% rename from MareSynchronosServer/MareSynchronosAuthService/Controllers/AuthControllerBase.cs rename to MareSynchronosServer/MareSynchronosServer/Controllers/AuthControllerBase.cs index eb88b4e..6c0a068 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/Controllers/AuthControllerBase.cs +++ b/MareSynchronosServer/MareSynchronosServer/Controllers/AuthControllerBase.cs @@ -1,5 +1,4 @@ -using MareSynchronosAuthService.Authentication; -using MareSynchronosAuthService.Services; +using MareSynchronosAuthService.Services; using MareSynchronosShared.Data; using MareSynchronosShared.Models; using MareSynchronosShared.Services; @@ -13,6 +12,7 @@ using System.Globalization; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; +using MareSynchronosServer.Authentication; namespace MareSynchronosAuthService.Controllers; @@ -24,18 +24,16 @@ public abstract class AuthControllerBase : Controller protected readonly IDbContextFactory MareDbContextFactory; protected readonly SecretKeyAuthenticatorService SecretKeyAuthenticatorService; private readonly IDatabase _redis; - private readonly GeoIPService _geoIPProvider; protected AuthControllerBase(ILogger logger, IHttpContextAccessor accessor, IDbContextFactory mareDbContextFactory, SecretKeyAuthenticatorService secretKeyAuthenticatorService, IConfigurationService configuration, - IDatabase redisDb, GeoIPService geoIPProvider) + IDatabase redisDb) { Logger = logger; HttpAccessor = accessor; _redis = redisDb; - _geoIPProvider = geoIPProvider; MareDbContextFactory = mareDbContextFactory; SecretKeyAuthenticatorService = secretKeyAuthenticatorService; Configuration = configuration; @@ -106,7 +104,6 @@ public abstract class AuthControllerBase : Controller new Claim(MareClaimTypes.CharaIdent, charaIdent), new Claim(MareClaimTypes.Alias, alias), new Claim(MareClaimTypes.Expires, DateTime.UtcNow.AddHours(6).Ticks.ToString(CultureInfo.InvariantCulture)), - new Claim(MareClaimTypes.Continent, await _geoIPProvider.GetCountryFromIP(HttpAccessor)) }); return Content(token.RawData); diff --git a/MareSynchronosServer/MareSynchronosServer/Controllers/ClientMessageController.cs b/MareSynchronosServer/MareSynchronosServer/Controllers/ClientMessageController.cs index 8ac846b..e7640b8 100644 --- a/MareSynchronosServer/MareSynchronosServer/Controllers/ClientMessageController.cs +++ b/MareSynchronosServer/MareSynchronosServer/Controllers/ClientMessageController.cs @@ -20,6 +20,8 @@ public class ClientMessageController : Controller _hubContext = hubContext; } + + [Route("sendMessage")] [HttpPost] public async Task SendMessage(ClientMessage msg) diff --git a/MareSynchronosServer/MareSynchronosAuthService/Controllers/JwtController.cs b/MareSynchronosServer/MareSynchronosServer/Controllers/JwtController.cs similarity index 97% rename from MareSynchronosServer/MareSynchronosAuthService/Controllers/JwtController.cs rename to MareSynchronosServer/MareSynchronosServer/Controllers/JwtController.cs index 447635e..09d21b2 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/Controllers/JwtController.cs +++ b/MareSynchronosServer/MareSynchronosServer/Controllers/JwtController.cs @@ -19,9 +19,9 @@ public class JwtController : AuthControllerBase IHttpContextAccessor accessor, IDbContextFactory mareDbContextFactory, SecretKeyAuthenticatorService secretKeyAuthenticatorService, IConfigurationService configuration, - IDatabase redisDb, GeoIPService geoIPProvider) + IDatabase redisDb) : base(logger, accessor, mareDbContextFactory, secretKeyAuthenticatorService, - configuration, redisDb, geoIPProvider) + configuration, redisDb) { } diff --git a/MareSynchronosServer/MareSynchronosAuthService/Controllers/OAuthController.cs b/MareSynchronosServer/MareSynchronosServer/Controllers/OAuthController.cs similarity index 99% rename from MareSynchronosServer/MareSynchronosAuthService/Controllers/OAuthController.cs rename to MareSynchronosServer/MareSynchronosServer/Controllers/OAuthController.cs index 1ca4912..8bac2f7 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/Controllers/OAuthController.cs +++ b/MareSynchronosServer/MareSynchronosServer/Controllers/OAuthController.cs @@ -29,9 +29,9 @@ public class OAuthController : AuthControllerBase IHttpContextAccessor accessor, IDbContextFactory mareDbContext, SecretKeyAuthenticatorService secretKeyAuthenticatorService, IConfigurationService configuration, - IDatabase redisDb, GeoIPService geoIPProvider) + IDatabase redisDb) : base(logger, accessor, mareDbContext, secretKeyAuthenticatorService, - configuration, redisDb, geoIPProvider) + configuration, redisDb) { } diff --git a/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj b/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj index fad027b..a95f33b 100644 --- a/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj +++ b/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj @@ -25,6 +25,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/MareSynchronosServer/MareSynchronosAuthService/Services/SecretKeyAuthenticatorService.cs b/MareSynchronosServer/MareSynchronosServer/Services/SecretKeyAuthenticatorService.cs similarity index 99% rename from MareSynchronosServer/MareSynchronosAuthService/Services/SecretKeyAuthenticatorService.cs rename to MareSynchronosServer/MareSynchronosServer/Services/SecretKeyAuthenticatorService.cs index 0f57261..d441c9d 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/Services/SecretKeyAuthenticatorService.cs +++ b/MareSynchronosServer/MareSynchronosServer/Services/SecretKeyAuthenticatorService.cs @@ -1,5 +1,5 @@ using System.Collections.Concurrent; -using MareSynchronosAuthService.Authentication; +using MareSynchronosServer.Authentication; using MareSynchronosShared.Data; using MareSynchronosShared.Metrics; using MareSynchronosShared.Models; diff --git a/MareSynchronosServer/MareSynchronosServer/Startup.cs b/MareSynchronosServer/MareSynchronosServer/Startup.cs index b8317a6..94ce20c 100644 --- a/MareSynchronosServer/MareSynchronosServer/Startup.cs +++ b/MareSynchronosServer/MareSynchronosServer/Startup.cs @@ -18,6 +18,8 @@ using StackExchange.Redis.Extensions.Core.Configuration; using System.Net; using StackExchange.Redis.Extensions.System.Text.Json; using MareSynchronos.API.SignalR; +using MareSynchronosAuthService.Controllers; +using MareSynchronosAuthService.Services; using MessagePack; using MessagePack.Resolvers; using Microsoft.AspNetCore.Mvc.Controllers; @@ -44,9 +46,17 @@ public class Startup services.AddHttpContextAccessor(); services.AddTransient(_ => Configuration); - + services.AddSingleton, MareConfigurationServiceServer>(); var mareConfig = Configuration.GetRequiredSection("MareSynchronos"); - + ConfigureRedis(services, mareConfig); + + services.AddSingleton(); + // services.AddSingleton(); + // services.AddHostedService(provider => provider.GetRequiredService()); + services.AddSingleton(); + + services.Configure(Configuration.GetRequiredSection("MareSynchronos")); + // configure metrics ConfigureMetrics(services); @@ -71,7 +81,8 @@ public class Startup a.FeatureProviders.Remove(a.FeatureProviders.OfType().First()); if (mareConfig.GetValue(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null) { - a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(MareServerConfigurationController), typeof(MareBaseConfigurationController), typeof(ClientMessageController))); + a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(MareServerConfigurationController), typeof(MareBaseConfigurationController), typeof(ClientMessageController), typeof(JwtController), typeof(OAuthController))); + } else { @@ -80,18 +91,68 @@ public class Startup }); } + private void ConfigureRedis(IServiceCollection services, IConfigurationSection mareConfig) + { + // configure redis for SignalR + var redisConnection = mareConfig.GetValue(nameof(ServerConfiguration.RedisConnectionString), string.Empty); + var options = ConfigurationOptions.Parse(redisConnection); + + var endpoint = options.EndPoints[0]; + string address = ""; + int port = 0; + + if (endpoint is DnsEndPoint dnsEndPoint) { address = dnsEndPoint.Host; port = dnsEndPoint.Port; } + if (endpoint is IPEndPoint ipEndPoint) { address = ipEndPoint.Address.ToString(); port = ipEndPoint.Port; } + /* + var redisConfiguration = new RedisConfiguration() + { + AbortOnConnectFail = true, + KeyPrefix = "", + Hosts = new RedisHost[] + { + new RedisHost(){ Host = address, Port = port }, + }, + AllowAdmin = true, + ConnectTimeout = options.ConnectTimeout, + Database = 0, + Ssl = false, + Password = options.Password, + ServerEnumerationStrategy = new ServerEnumerationStrategy() + { + Mode = ServerEnumerationStrategy.ModeOptions.All, + TargetRole = ServerEnumerationStrategy.TargetRoleOptions.Any, + UnreachableServerAction = ServerEnumerationStrategy.UnreachableServerActionOptions.Throw, + }, + MaxValueLength = 1024, + PoolSize = mareConfig.GetValue(nameof(ServerConfiguration.RedisPool), 50), + SyncTimeout = options.SyncTimeout, + };*/ + + var muxer = ConnectionMultiplexer.Connect(options); + var db = muxer.GetDatabase(); + services.AddSingleton(db); + + _logger.LogInformation("Setting up Redis to connect to {host}:{port}", address, port); + } + private void ConfigureMareServices(IServiceCollection services, IConfigurationSection mareConfig) { bool isMainServer = mareConfig.GetValue(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null; services.Configure(Configuration.GetRequiredSection("MareSynchronos")); services.Configure(Configuration.GetRequiredSection("MareSynchronos")); - + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + + services.Configure(Configuration.GetRequiredSection("MareSynchronos")); + services.AddHostedService(provider => provider.GetService()); + + services.AddHttpLogging(o => { }); // configure services based on main server status + _logger.LogWarning($"IsMainServer = {isMainServer}"); ConfigureServicesBasedOnShardType(services, mareConfig, isMainServer); services.AddSingleton(s => new MareCensus(s.GetRequiredService>())); @@ -193,6 +254,8 @@ public class Startup private static void ConfigureAuthorization(IServiceCollection services) { + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -210,6 +273,8 @@ public class Startup }; }); + services.AddLogging(); + services.AddAuthentication(o => { o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; @@ -222,6 +287,13 @@ public class Startup options.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().Build(); + options.AddPolicy("OAuthToken", policy => + { + policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme); + policy.AddRequirements(new ValidTokenRequirement()); + policy.AddRequirements(new ExistingUserRequirement()); + policy.RequireClaim(MareClaimTypes.OAuthLoginToken, "True"); + }); options.AddPolicy("Authenticated", policy => { policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme); @@ -253,6 +325,8 @@ public class Startup { services.AddDbContextPool(options => { + var defaultConnection = Configuration.GetConnectionString("DefaultConnection"); + _logger.LogDebug("Connecting to DB using: '{0}'", defaultConnection); options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"), builder => { builder.MigrationsHistoryTable("_efmigrationshistory", "public"); @@ -337,13 +411,17 @@ public class Startup app.UseWebSockets(); app.UseHttpMetrics(); + app.UseExceptionHandler("/Error"); var metricServer = new KestrelMetricServer(config.GetValueOrDefault(nameof(MareConfigurationBase.MetricsPort), 4980)); metricServer.Start(); app.UseAuthentication(); app.UseAuthorization(); + app.UseHttpLogging(); + + app.UseEndpoints(endpoints => { endpoints.MapHub(IMareHub.Path, options => @@ -355,11 +433,12 @@ public class Startup endpoints.MapHealthChecks("/health").AllowAnonymous(); endpoints.MapControllers(); + foreach (var source in endpoints.DataSources.SelectMany(e => e.Endpoints).Cast()) { if (source == null) continue; - _logger.LogInformation("Endpoint: {url} ", source.RoutePattern.RawText); + _logger.LogWarning("Endpoint: {url} ", source.RoutePattern.RawText); } }); diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs index bffa35e..1c74b1f 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs @@ -117,8 +117,8 @@ internal class DiscordBot : IHostedService _botServices.UpdateGuild(guild); await _botServices.LogToChannel("Bot startup complete.").ConfigureAwait(false); _ = UpdateVanityRoles(guild, _clientConnectedCts.Token); - _ = RemoveUsersNotInVanityRole(_clientConnectedCts.Token); - _ = RemoveUnregisteredUsers(_clientConnectedCts.Token); + // _ = RemoveUsersNotInVanityRole(_clientConnectedCts.Token); + // 1_ = RemoveUnregisteredUsers(_clientConnectedCts.Token); } private async Task UpdateVanityRoles(RestGuild guild, CancellationToken token) diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.AprilFools2024.cs b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.AprilFools2024.cs deleted file mode 100644 index 6b44712..0000000 --- a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.AprilFools2024.cs +++ /dev/null @@ -1,215 +0,0 @@ -using Discord; -using Discord.Interactions; -using MareSynchronosShared.Utils.Configuration; -using System.Text.Json; - -namespace MareSynchronosServices.Discord; - -public partial class MareWizardModule : InteractionModuleBase -{ - private const int _totalAprilFoolsRoles = 200; - private const string _persistentFileName = "april2024.json"; - - private static readonly SemaphoreSlim _fileSemaphore = new(1, 1); - - [ComponentInteraction("wizard-fools")] - public async Task ComponentFools() - { - if (!(await ValidateInteraction().ConfigureAwait(false))) return; - - _logger.LogInformation("{method}:{userId}", nameof(ComponentFools), Context.Interaction.User.Id); - - EmbedBuilder eb = new(); - eb.WithTitle("WorryCoin™ and MareToken© Balance"); - eb.WithColor(Color.Gold); - eb.WithDescription("You currently have" + Environment.NewLine + Environment.NewLine - + "**200000** MaTE©" + Environment.NewLine - + "**0** WorryCoin™" + Environment.NewLine + Environment.NewLine - + "You have no payment method set up. Press the button below to add a payment method."); - ComponentBuilder cb = new(); - AddHome(cb); - cb.WithButton("Add Payment Method", "wizard-fools-start", ButtonStyle.Primary, emote: new Emoji("💲")); - await ModifyInteraction(eb, cb).ConfigureAwait(false); - } - - [ComponentInteraction("wizard-fools-start")] - public async Task ComponentFoolsStart() - { - if (!(await ValidateInteraction().ConfigureAwait(false))) return; - - _logger.LogInformation("{method}:{userId}", nameof(ComponentFoolsStart), Context.Interaction.User.Id); - - EmbedBuilder eb = new(); - var user = await Context.Guild.GetUserAsync(Context.User.Id).ConfigureAwait(false); - bool userIsInPermanentVanityRole = _botServices.VanityRoles.Where(v => !v.Value.Contains('$', StringComparison.Ordinal)) - .Select(v => v.Key).Any(u => user.RoleIds.Contains(u.Id)) || !_botServices.VanityRoles.Any(); - ComponentBuilder cb = new(); - AddHome(cb); - - var participatedUsers = await GetParticipants().ConfigureAwait(false); - var remainingRoles = _totalAprilFoolsRoles - participatedUsers.Count(c => c.Value == true); - - if (userIsInPermanentVanityRole) - { - eb.WithColor(Color.Green); - eb.WithTitle("Happy April Fools!"); - eb.WithDescription("Thank you for participating in Mares 2024 April Fools event." - + Environment.NewLine + Environment.NewLine - + "As you might have already guessed from the post, nothing that was written there had any truth behind it." - + Environment.NewLine + Environment.NewLine - + "This entire thing was a jab at the ridiculousness of cryptocurrency, microtransactions and games featuring multiple currencies. I hope you enjoyed the announcement post!" - + Environment.NewLine + Environment.NewLine - + "__As you already have a role that gives you a permanent Vanity ID, you cannot win another one here. " - + "However, tell your friends as this bot will give them a chance to win one of " + _totalAprilFoolsRoles + " lifetime vanity roles.__" - + Environment.NewLine + Environment.NewLine - + "The giveaway is active until ."); - } - else if (participatedUsers.ContainsKey(Context.User.Id)) - { - eb.WithColor(Color.Orange); - eb.WithTitle("Happy April Fools!"); - eb.WithDescription("Thank you for participating in Mares 2024 April Fools event." - + Environment.NewLine + Environment.NewLine - + "As you might have already guessed from the post, nothing that was written there had any truth behind it." - + Environment.NewLine + Environment.NewLine - + "This entire thing was a jab at the ridiculousness of cryptocurrency, microtransactions and games featuring multiple currencies. I hope you enjoyed the announcement post!" - + Environment.NewLine + Environment.NewLine - + "__You already participated in the giveaway of the permanent Vanity roles and therefore cannot participate again. Better luck next time!__"); - } - else if (remainingRoles > 0) - { - eb.WithColor(Color.Green); - eb.WithTitle("Happy April Fools!"); - eb.WithDescription("Thank you for participating in Mares 2024 April Fools event." - + Environment.NewLine + Environment.NewLine - + "As you might have already guessed from the post, nothing that was written there had any truth behind it." - + Environment.NewLine + Environment.NewLine - + "This entire thing was a jab at the ridiculousness of cryptocurrency, microtransactions and games featuring multiple currencies. I hope you enjoyed the announcement post!" - + Environment.NewLine + Environment.NewLine - + "You have currently no permanent role that allows you to set a Vanity ID, however I am giving away a total of " + _totalAprilFoolsRoles + " permanent vanity roles " - + "(" + remainingRoles + " still remain) and you can win one using this bot!" - + Environment.NewLine + Environment.NewLine - + "To win you simply have to pick one of the buttons labeled \"Win\" below this post. Which button will win is random. " - + "There is a 1 in 5 chance that you can win the role. __You can only participate once.__" - + Environment.NewLine + Environment.NewLine - + "The giveaway is active until ."); - cb.WithButton("Win", "wizard-fools-win:1", ButtonStyle.Primary, new Emoji("1️⃣")); - cb.WithButton("Win", "wizard-fools-win:2", ButtonStyle.Primary, new Emoji("2️⃣")); - cb.WithButton("Win", "wizard-fools-win:3", ButtonStyle.Primary, new Emoji("3️⃣")); - cb.WithButton("Win", "wizard-fools-win:4", ButtonStyle.Primary, new Emoji("4️⃣")); - cb.WithButton("Win", "wizard-fools-win:5", ButtonStyle.Primary, new Emoji("5️⃣")); - } - else - { - eb.WithColor(Color.Orange); - eb.WithTitle("Happy April Fools!"); - eb.WithDescription("Thank you for participating in Mares 2024 April Fools event." - + Environment.NewLine + Environment.NewLine - + "As you might have already guessed from the post, nothing that was written there had any truth behind it." - + Environment.NewLine + Environment.NewLine - + "This entire thing was a jab at the ridiculousness of cryptocurrency, microtransactions and games featuring multiple currencies. I hope you enjoyed the announcement post!" - + Environment.NewLine + Environment.NewLine - + "__I have been giving away " + _totalAprilFoolsRoles + " permanent Vanity ID roles for this server, however you are sadly too late as they ran out by now. " - + "Better luck next year with whatever I will come up with!__"); - } - await ModifyInteraction(eb, cb).ConfigureAwait(false); - } - - [ComponentInteraction("wizard-fools-win:*")] - public async Task ComponentFoolsWin(int number) - { - if (!(await ValidateInteraction().ConfigureAwait(false))) return; - - _logger.LogInformation("{method}:{userId}", nameof(ComponentFoolsWin), Context.Interaction.User.Id); - - var winningNumber = new Random().Next(1, 6); - EmbedBuilder eb = new(); - ComponentBuilder cb = new(); - AddHome(cb); - bool hasWon = winningNumber == number; - - await WriteParticipants(Context.Interaction.User.Id, hasWon).ConfigureAwait(false); - - if (hasWon) - { - eb.WithColor(Color.Gold); - eb.WithTitle("Congratulations you are winner!"); - eb.WithDescription("You, by pure accident and sheer luck, picked the right number and have won yourself a lifetime Vanity ID role on this server!" - + Environment.NewLine + Environment.NewLine - + "The role will remain as long as you remain on this server, if you happen to leave it you will not get the role back." - + Environment.NewLine + Environment.NewLine - + "Head over to Home and to the Vanity IDs section to set it up for your account!" - + Environment.NewLine + Environment.NewLine - + "Once again, thank you for participating and have a great day."); - - var user = await Context.Guild.GetUserAsync(Context.User.Id).ConfigureAwait(false); - await user.AddRoleAsync(_mareServicesConfiguration.GetValue(nameof(ServicesConfiguration.DiscordRoleAprilFools2024)).Value).ConfigureAwait(false); - } - else - { - eb.WithColor(Color.Red); - eb.WithTitle("Fortune did not bless you"); - eb.WithDescription("You, through sheer misfortune, sadly did not pick the right number. (The winning number was " + winningNumber + ")" - + Environment.NewLine + Environment.NewLine - + "Better luck next time!" - + Environment.NewLine + Environment.NewLine - + "Once again, thank you for participating and regardless, have a great day."); - } - - await ModifyInteraction(eb, cb).ConfigureAwait(false); - } - - private async Task> GetParticipants() - { - await _fileSemaphore.WaitAsync().ConfigureAwait(false); - - try - { - if (!File.Exists(_persistentFileName)) - { - return new(); - } - - var json = await File.ReadAllTextAsync(_persistentFileName).ConfigureAwait(false); - return JsonSerializer.Deserialize>(json); - } - catch - { - return new(); - } - finally - { - _fileSemaphore.Release(); - } - } - - private async Task WriteParticipants(ulong participant, bool win) - { - await _fileSemaphore.WaitAsync().ConfigureAwait(false); - - try - { - Dictionary participants = new(); - if (File.Exists(_persistentFileName)) - { - try - { - var json = await File.ReadAllTextAsync(_persistentFileName).ConfigureAwait(false); - participants = JsonSerializer.Deserialize>(json); - } - catch - { - // probably empty file just deal with it - } - } - - participants[participant] = win; - - await File.WriteAllTextAsync(_persistentFileName, JsonSerializer.Serialize(participants)).ConfigureAwait(false); - } - finally - { - _fileSemaphore.Release(); - } - } -} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs index 72411c2..e22296d 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.Register.cs @@ -24,13 +24,14 @@ public partial class MareWizardModule eb.WithColor(Color.Blue); eb.WithTitle("Start Registration"); eb.WithDescription("Here you can start the registration process with the Mare Synchronos server of this Discord." + Environment.NewLine + Environment.NewLine - + "- Have your Lodestone URL ready (i.e. https://eu.finalfantasyxiv.com/lodestone/character/XXXXXXXXX)" + Environment.NewLine - + " - The registration requires you to modify your Lodestone profile with a generated code for verification" + Environment.NewLine + /*+ "- Have your Lodestone URL ready (i.e. https://eu.finalfantasyxiv.com/lodestone/character/XXXXXXXXX)" + Environment.NewLine + + " - The registration requires you to modify your Lodestone profile with a generated code for verification" + Environment.NewLine*/ + "- Do not use this on mobile because you will need to be able to copy the generated secret key" + Environment.NewLine + "# Follow the bot instructions precisely. Slow down and read."); ComponentBuilder cb = new(); AddHome(cb); - cb.WithButton("Start Registration", "wizard-register-start", ButtonStyle.Primary, emote: new Emoji("🌒")); + cb.WithButton("Register", "wizard-register-verify-check:OK", ButtonStyle.Primary, emote: new Emoji("❓")); + // cb.WithButton("Start Registration", "wizard-register-start", ButtonStyle.Primary, emote: new Emoji("🌒")); await ModifyInteraction(eb, cb).ConfigureAwait(false); } @@ -97,79 +98,34 @@ public partial class MareWizardModule public async Task ComponentRegisterVerifyCheck(string verificationCode) { if (!(await ValidateInteraction().ConfigureAwait(false))) return; - + _logger.LogInformation("{method}:{userId}:{uid}", nameof(ComponentRegisterVerifyCheck), Context.Interaction.User.Id, verificationCode); EmbedBuilder eb = new(); ComponentBuilder cb = new(); - bool stillEnqueued = _botServices.VerificationQueue.Any(k => k.Key == Context.User.Id); - bool verificationRan = _botServices.DiscordVerifiedUsers.TryGetValue(Context.User.Id, out bool verified); - bool registerSuccess = false; - if (!verificationRan) - { - if (stillEnqueued) - { - eb.WithColor(Color.Gold); - eb.WithTitle("Your verification is still pending"); - eb.WithDescription("Please try again and click Check in a few seconds"); - cb.WithButton("Cancel", "wizard-register", ButtonStyle.Secondary, emote: new Emoji("❌")); - cb.WithButton("Check", "wizard-register-verify-check:" + verificationCode, ButtonStyle.Primary, emote: new Emoji("❓")); - } - else - { - eb.WithColor(Color.Red); - eb.WithTitle("Something went wrong"); - eb.WithDescription("Your verification was processed but did not arrive properly. Please try to start the registration from the start."); - cb.WithButton("Restart", "wizard-register", ButtonStyle.Primary, emote: new Emoji("🔁")); - } - } - else - { - if (verified) - { - eb.WithColor(Color.Green); - using var db = await GetDbContext().ConfigureAwait(false); - var (uid, key) = await HandleAddUser(db).ConfigureAwait(false); - eb.WithTitle($"Registration successful, your UID: {uid}"); - eb.WithDescription("This is your private secret key. Do not share this private secret key with anyone. **If you lose it, it is irrevocably lost.**" - + Environment.NewLine + Environment.NewLine - + "**__NOTE: Secret keys are considered legacy. Using the suggested OAuth2 authentication in Mare, you do not need to use this Secret Key.__**" - + Environment.NewLine + Environment.NewLine - + $"||**`{key}`**||" - + Environment.NewLine + Environment.NewLine - + "If you want to continue using legacy authentication, enter this key in Mare Synchronos and hit save to connect to the service." - + Environment.NewLine - + "__NOTE: The Secret Key only contains the letters ABCDEF and numbers 0 - 9.__" - + Environment.NewLine - + "You should connect as soon as possible to not get caught by the automatic cleanup process." - + Environment.NewLine - + "Have fun."); - AddHome(cb); - registerSuccess = true; - } - else - { - eb.WithColor(Color.Gold); - eb.WithTitle("Failed to verify registration"); - eb.WithDescription("The bot was not able to find the required verification code on your Lodestone profile." - + Environment.NewLine + Environment.NewLine - + "Please restart your verification process, make sure to save your profile _twice_ for it to be properly saved." - + Environment.NewLine + Environment.NewLine - + "If this link does not lead to your profile edit page, you __need__ to configure the privacy settings first: https://na.finalfantasyxiv.com/lodestone/my/setting/profile/" - + Environment.NewLine + Environment.NewLine - + "**Make sure your profile is set to public (All Users) for your character. The bot cannot read profiles with privacy settings set to \"logged in\" or \"private\".**" - + Environment.NewLine + Environment.NewLine - + "## You __need__ to enter following the code this bot provided onto your Lodestone in the character profile:" - + Environment.NewLine + Environment.NewLine - + "**`" + verificationCode + "`**"); - cb.WithButton("Cancel", "wizard-register", emote: new Emoji("❌")); - cb.WithButton("Retry", "wizard-register-verify:" + verificationCode, ButtonStyle.Primary, emote: new Emoji("🔁")); - } - } + + eb.WithColor(Color.Green); + using var db = await GetDbContext().ConfigureAwait(false); + var (uid, key) = await HandleAddUser(db).ConfigureAwait(false); + eb.WithTitle($"Registration successful, your UID: {uid}"); + eb.WithDescription("This is your private secret key. Do not share this private secret key with anyone. **If you lose it, it is irrevocably lost.**" + /*+ Environment.NewLine + Environment.NewLine + + "**__NOTE: Secret keys are considered legacy. Using the suggested OAuth2 authentication in Mare, you do not need to use this Secret Key.__**"*/ + + Environment.NewLine + Environment.NewLine + + $"**`{key}`**" + + Environment.NewLine + Environment.NewLine + /*+ "If you want to continue using legacy authentication, enter this key in Mare Synchronos and hit save to connect to the service." + + Environment.NewLine*/ + + "__NOTE: The Secret Key only contains the letters ABCDEF and numbers 0 - 9.__" + + Environment.NewLine + //+ "You should connect as soon as possible to not get caught by the automatic cleanup process." + //+ Environment.NewLine + + "Have fun."); + AddHome(cb); await ModifyInteraction(eb, cb).ConfigureAwait(false); - if (registerSuccess) - await _botServices.AddRegisteredRoleAsync(Context.Interaction.User).ConfigureAwait(false); + + // if (registerSuccess)await _botServices.AddRegisteredRoleAsync(Context.Interaction.User).ConfigureAwait(false); } private async Task<(bool, string)> HandleRegisterModalAsync(EmbedBuilder embed, LodestoneModal arg) @@ -262,8 +218,14 @@ public partial class MareWizardModule private async Task<(string, string)> HandleAddUser(MareDbContext db) { + _logger.LogWarning($"Adding User: {Context.User.Username}"); var lodestoneAuth = db.LodeStoneAuth.SingleOrDefault(u => u.DiscordId == Context.User.Id); - + if (lodestoneAuth == null) { + lodestoneAuth = new LodeStoneAuth() { DiscordId = Context.User.Id, HashedLodestoneId = $"{Context.User.Id}", User = null, LodestoneAuthString = string.Empty }; + await db.LodeStoneAuth.AddAsync(lodestoneAuth).ConfigureAwait(false); + } + + var user = new User(); var hasValidUid = false; @@ -294,10 +256,12 @@ public partial class MareWizardModule await db.Users.AddAsync(user).ConfigureAwait(false); await db.Auth.AddAsync(auth).ConfigureAwait(false); + lodestoneAuth.StartedAt = null; lodestoneAuth.User = user; lodestoneAuth.LodestoneAuthString = null; - + + await db.SaveChangesAsync().ConfigureAwait(false); _botServices.Logger.LogInformation("User registered: {userUID}:{hashedKey}", user.UID, hashedKey); diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs index 1a6227e..5b7e4a3 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/MareWizardModule.cs @@ -160,18 +160,17 @@ public partial class MareWizardModule : InteractionModuleBase + (!hasAccount ? string.Empty : ("- Check your account status press \"ℹ️ User Info\"" + Environment.NewLine)) + (hasAccount ? string.Empty : ("- Register a new Mare Account press \"🌒 Register\"" + Environment.NewLine)) + (!hasAccount ? string.Empty : ("- You lost your secret key press \"🏥 Recover\"" + Environment.NewLine)) - + (hasAccount ? string.Empty : ("- If you have changed your Discord account press \"🔗 Relink\"" + Environment.NewLine)) + // + (hasAccount ? string.Empty : ("- If you have changed your Discord account press \"🔗 Relink\"" + Environment.NewLine)) + (!hasAccount ? string.Empty : ("- Create a secondary UIDs press \"2️⃣ Secondary UID\"" + Environment.NewLine)) + (!hasAccount ? string.Empty : ("- Set a Vanity UID press \"💅 Vanity IDs\"" + Environment.NewLine)) - + (!hasAccount ? string.Empty : (!isInAprilFoolsMode ? string.Empty : ("- Check your WorryCoin™ and MareToken© balance and add payment options" + Environment.NewLine))) + (!hasAccount ? string.Empty : ("- Delete your primary or secondary accounts with \"⚠️ Delete\"")) ); eb.WithColor(Color.Blue); ComponentBuilder cb = new(); if (!hasAccount) { - cb.WithButton("Register", "wizard-register", ButtonStyle.Primary, new Emoji("🌒")); - cb.WithButton("Relink", "wizard-relink", ButtonStyle.Secondary, new Emoji("🔗")); + cb.WithButton("Register", "wizard-register-verify-check:OK", ButtonStyle.Primary, new Emoji("🌒")); + // cb.WithButton("Relink", "wizard-relink", ButtonStyle.Secondary, new Emoji("🔗")); } else { @@ -179,10 +178,6 @@ public partial class MareWizardModule : InteractionModuleBase cb.WithButton("Recover", "wizard-recover", ButtonStyle.Secondary, new Emoji("🏥")); cb.WithButton("Secondary UID", "wizard-secondary", ButtonStyle.Secondary, new Emoji("2️⃣")); cb.WithButton("Vanity IDs", "wizard-vanity", ButtonStyle.Secondary, new Emoji("💅")); - if (isInAprilFoolsMode) - { - cb.WithButton("WorryCoin™ and MareToken© management", "wizard-fools", ButtonStyle.Primary, new Emoji("💲")); - } cb.WithButton("Delete", "wizard-delete", ButtonStyle.Danger, new Emoji("⚠️")); } diff --git a/build_run.bat b/build_run.bat new file mode 100644 index 0000000..a22f92d --- /dev/null +++ b/build_run.bat @@ -0,0 +1,3 @@ +docker build -t darkarchon/mare-synchronos-server:latest . -f Docker\build\Dockerfile-MareSynchronosServer --no-cache --pull --force-rm +docker build -t darkarchon/mare-synchronos-services:latest . -f Docker\build\Dockerfile-MareSynchronosServices --no-cache --pull --force-rm +docker compose -f Docker\run\compose\mare-standalone.yml -p standalone up -d \ No newline at end of file