diff --git a/src/XtremeIdiots.Portal.Integrations.Forums/AdminActionTopics.cs b/src/XtremeIdiots.Portal.Integrations.Forums/AdminActionTopics.cs index a495401ae..f5200522c 100644 --- a/src/XtremeIdiots.Portal.Integrations.Forums/AdminActionTopics.cs +++ b/src/XtremeIdiots.Portal.Integrations.Forums/AdminActionTopics.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; using System.Globalization; using MX.InvisionCommunity.Api.Abstractions; using XtremeIdiots.Portal.Integrations.Forums.Extensions; @@ -11,39 +12,22 @@ namespace XtremeIdiots.Portal.Integrations.Forums; /// /// Logger for tracking operations and errors /// Invision Community API client for forum operations -public class AdminActionTopics(ILogger logger, IInvisionApiClient forumsClient) : IAdminActionTopics +public class AdminActionTopics(ILogger logger, IInvisionApiClient forumsClient, IConfiguration configuration) : IAdminActionTopics { /// /// Creates a forum topic for a new admin action /// - /// Type of admin action (warning, ban, etc.) - /// Game type to determine appropriate forum section - /// Unique identifier of the player - /// Player's username - /// When the admin action was created - /// Admin action description/reason - /// ID of the admin who created the action - /// Cancellation token for the async operation - /// Topic ID of the created forum topic, or 0 if creation failed public async Task CreateTopicForAdminAction(AdminActionType type, GameType gameType, Guid playerId, string username, DateTime created, string text, string? adminId, CancellationToken cancellationToken = default) { try { - var userId = 21145; + var userId = int.TryParse(configuration["XtremeIdiots:Forums:DefaultAdminUserId"], out var defaultUserId) ? defaultUserId : 21145; if (adminId is not null) userId = Convert.ToInt32(adminId); - var forumId = type switch - { - AdminActionType.Observation => gameType.ForumIdForObservations(), - AdminActionType.Warning => gameType.ForumIdForWarnings(), - AdminActionType.Kick => gameType.ForumIdForKicks(), - AdminActionType.TempBan => gameType.ForumIdForTempBans(), - AdminActionType.Ban => gameType.ForumIdForBans(), - _ => 28 - }; + var forumId = ResolveForumId(type, gameType); var postTopicResult = await forumsClient.Forums.PostTopic(forumId, userId, $"{username} - {type}", PostContent(type, playerId, username, created, text), type.ToString(), cancellationToken).ConfigureAwait(false); @@ -83,7 +67,7 @@ public async Task UpdateTopicForAdminAction(int topicId, AdminActionType type, G if (topicId == 0) return; - var userId = 21145; + var userId = int.TryParse(configuration["XtremeIdiots:Forums:DefaultAdminUserId"], out var defaultUserId) ? defaultUserId : 21145; if (adminId is not null) userId = Convert.ToInt32(adminId); @@ -91,11 +75,12 @@ public async Task UpdateTopicForAdminAction(int topicId, AdminActionType type, G await forumsClient.Forums.UpdateTopic(topicId, userId, PostContent(type, playerId, username, created, text), cancellationToken).ConfigureAwait(false); } - private static string PostContent(AdminActionType type, Guid playerId, string username, DateTime created, string text) + private string PostContent(AdminActionType type, Guid playerId, string username, DateTime created, string text) { + var portalBaseUrl = (configuration["XtremeIdiots:PortalBaseUrl"] ?? "https://portal.xtremeidiots.com").TrimEnd('/'); return "

" + $" Username: {username}
" + - $" Player Link: Portal
" + + $" Player Link: Portal
" + $" {type} Created: {created.ToString(CultureInfo.InvariantCulture)}" + "

" + "

" + @@ -105,4 +90,40 @@ private static string PostContent(AdminActionType type, Guid playerId, string us " Do not edit this post directly as it will be overwritten by the Portal. Add comments on posts below or edit the record in the Portal." + "

"; } + + private int ResolveForumId(AdminActionType type, GameType gameType) + { + var defaultForumId = int.TryParse(configuration["XtremeIdiots:Forums:DefaultForumId"], out var parsedForumId) ? parsedForumId : 28; + + var category = type switch + { + AdminActionType.Observation or AdminActionType.Warning or AdminActionType.Kick => "AdminLogs", + AdminActionType.TempBan or AdminActionType.Ban => "Bans", + _ => null + }; + + if (category is null) + return defaultForumId; + + var gameKey = gameType switch + { + GameType.Arma or GameType.Arma2 or GameType.Arma3 => "Arma", + _ => gameType.ToString() + }; + + var configValue = configuration[$"XtremeIdiots:Forums:{category}:{gameKey}"]; + if (configValue is not null && int.TryParse(configValue, out var forumId)) + return forumId; + + // Fallback to hardcoded values from GameTypeExtensions + return type switch + { + AdminActionType.Observation => gameType.ForumIdForObservations(), + AdminActionType.Warning => gameType.ForumIdForWarnings(), + AdminActionType.Kick => gameType.ForumIdForKicks(), + AdminActionType.TempBan => gameType.ForumIdForTempBans(), + AdminActionType.Ban => gameType.ForumIdForBans(), + _ => defaultForumId + }; + } } \ No newline at end of file diff --git a/src/XtremeIdiots.Portal.Web/ApiControllers/BannersController.cs b/src/XtremeIdiots.Portal.Web/ApiControllers/BannersController.cs index 3b2b38889..c7b6b2057 100644 --- a/src/XtremeIdiots.Portal.Web/ApiControllers/BannersController.cs +++ b/src/XtremeIdiots.Portal.Web/ApiControllers/BannersController.cs @@ -38,6 +38,7 @@ public class BannersController( IConfiguration configuration) : BaseApiController(telemetryClient, logger, configuration) { private const string GameServersListCacheKey = nameof(GameServersListCacheKey); + private readonly string gameTrackerBannerBaseUrl = (configuration["GameTracker:BannerBaseUrl"] ?? "https://cache.gametracker.com/server_info/").TrimEnd('/') + "/"; /// /// Gets HTML banners for game servers that are enabled for banner display @@ -168,7 +169,7 @@ public async Task GetGameTrackerBanner(string ipAddress, string q { "BannerUrl", bannerData.BannerUrl ?? "null" } }); - return Redirect(bannerData.BannerUrl ?? $"https://cache.gametracker.com/server_info/{ipAddress}:{queryPort}/{imageName}"); + return Redirect(bannerData.BannerUrl ?? $"{gameTrackerBannerBaseUrl}{ipAddress}:{queryPort}/{imageName}"); } Logger.LogWarning("Failed to retrieve GameTracker banner data for {IpAddress}:{QueryPort}/{ImageName}, falling back to default GameTracker URL", @@ -184,7 +185,7 @@ public async Task GetGameTrackerBanner(string ipAddress, string q { "Fallback", "true" } }); - return Redirect($"https://cache.gametracker.com/server_info/{ipAddress}:{queryPort}/{imageName}"); + return Redirect($"{gameTrackerBannerBaseUrl}{ipAddress}:{queryPort}/{imageName}"); }, nameof(GetGameTrackerBanner), $"ipAddress: {ipAddress}, queryPort: {queryPort}, imageName: {imageName}").ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/XtremeIdiots.Portal.Web/ApiControllers/ExternalController.cs b/src/XtremeIdiots.Portal.Web/ApiControllers/ExternalController.cs index 24f26abfc..3364e5756 100644 --- a/src/XtremeIdiots.Portal.Web/ApiControllers/ExternalController.cs +++ b/src/XtremeIdiots.Portal.Web/ApiControllers/ExternalController.cs @@ -24,6 +24,7 @@ public class ExternalController( ILogger logger, IConfiguration configuration) : BaseApiController(telemetryClient, logger, configuration) { + private readonly string portalBaseUrl = (configuration["XtremeIdiots:PortalBaseUrl"] ?? "https://portal.xtremeidiots.com").TrimEnd('/'); /// /// Retrieves the latest admin actions for display in external forum widgets @@ -60,13 +61,13 @@ public async Task GetLatestAdminActions(CancellationToken cancell results.Add(new { - GameIconUrl = $"https://portal.xtremeidiots.com/images/game-icons/{adminActionDto.Player?.GameType.ToString()}.png", + GameIconUrl = $"{portalBaseUrl}/images/game-icons/{adminActionDto.Player?.GameType.ToString()}.png", AdminName = adminName, AdminId = adminId, ActionType = adminActionDto.Type.ToString(), ActionText = actionText, PlayerName = adminActionDto.Player?.Username, - PlayerLink = $"https://portal.xtremeidiots.com/Players/Details/{adminActionDto.PlayerId}" + PlayerLink = $"{portalBaseUrl}/Players/Details/{adminActionDto.PlayerId}" }); } diff --git a/src/XtremeIdiots.Portal.Web/ApiControllers/HealthCheckController.cs b/src/XtremeIdiots.Portal.Web/ApiControllers/HealthCheckController.cs index 3179d324f..7ec489186 100644 --- a/src/XtremeIdiots.Portal.Web/ApiControllers/HealthCheckController.cs +++ b/src/XtremeIdiots.Portal.Web/ApiControllers/HealthCheckController.cs @@ -32,6 +32,9 @@ public HealthCheckController( ArgumentNullException.ThrowIfNull(forumsClient); this.forumsClient = forumsClient; + var expectedCommunityUrl = configuration["XtremeIdiots:Forums:BaseUrl"] ?? "https://www.xtremeidiots.com"; + var expectedCommunityUrlWithTrailingSlash = expectedCommunityUrl.TrimEnd('/') + "/"; + healthCheckComponents.Add(new HealthCheckComponent { Name = "forums-api", @@ -41,7 +44,7 @@ public HealthCheckController( try { var response = await this.forumsClient.Core.GetCoreHello().ConfigureAwait(false); - var checkResponse = response?.Result?.Data?.CommunityUrl == "https://www.xtremeidiots.com/"; + var checkResponse = response?.Result?.Data?.CommunityUrl == expectedCommunityUrlWithTrailingSlash; return new Tuple(checkResponse, checkResponse ? "OK" : "Unexpected or missing CommunityUrl in forums API response"); } catch (Exception ex) diff --git a/src/XtremeIdiots.Portal.Web/Areas/Identity/IdentityHostingStartup.cs b/src/XtremeIdiots.Portal.Web/Areas/Identity/IdentityHostingStartup.cs index 65090fb0d..d939b12b7 100644 --- a/src/XtremeIdiots.Portal.Web/Areas/Identity/IdentityHostingStartup.cs +++ b/src/XtremeIdiots.Portal.Web/Areas/Identity/IdentityHostingStartup.cs @@ -113,9 +113,10 @@ private static void ConfigureAuthentication(IServiceCollection services, IConfig options.CallbackPath = new PathString("/signin-xtremeidiots"); - options.AuthorizationEndpoint = configuration["xtremeidiots_auth_authorization_endpoint"] ?? "https://www.xtremeidiots.com/oauth/authorize/"; - options.TokenEndpoint = configuration["xtremeidiots_auth_token_endpoint"] ?? "https://www.xtremeidiots.com/oauth/token/"; - options.UserInformationEndpoint = configuration["xtremeidiots_auth_userinfo_endpoint"] ?? "https://www.xtremeidiots.com/api/core/me"; + var forumSiteUrl = (configuration["XtremeIdiots:Forums:BaseUrl"] ?? "https://www.xtremeidiots.com").TrimEnd('/'); + options.AuthorizationEndpoint = configuration["xtremeidiots_auth_authorization_endpoint"] ?? $"{forumSiteUrl}/oauth/authorize/"; + options.TokenEndpoint = configuration["xtremeidiots_auth_token_endpoint"] ?? $"{forumSiteUrl}/oauth/token/"; + options.UserInformationEndpoint = configuration["xtremeidiots_auth_userinfo_endpoint"] ?? $"{forumSiteUrl}/api/core/me"; options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id"); options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name"); diff --git a/src/XtremeIdiots.Portal.Web/Controllers/AdminActionsController.cs b/src/XtremeIdiots.Portal.Web/Controllers/AdminActionsController.cs index 12771b0bd..06de075c2 100644 --- a/src/XtremeIdiots.Portal.Web/Controllers/AdminActionsController.cs +++ b/src/XtremeIdiots.Portal.Web/Controllers/AdminActionsController.cs @@ -24,9 +24,6 @@ public class AdminActionsController( ILogger logger, IConfiguration configuration) : BaseController(telemetryClient, logger, configuration) { - private const string DefaultForumBaseUrl = "https://www.xtremeidiots.com/forums/topic/"; - private const string DefaultFallbackAdminId = "21145"; - private const int DefaultTempBanDurationDays = 7; /// /// Displays the create admin action form for a specific player @@ -58,12 +55,14 @@ public async Task Create(Guid id, AdminActionType adminActionType if (authResult is not null) return authResult; + var tempBanDurationDays = int.TryParse(Configuration["XtremeIdiots:Forums:DefaultTempBanDays"], out var days) ? days : 7; + var createAdminActionViewModel = new CreateAdminActionViewModel { Type = adminActionType, PlayerId = playerData.PlayerId, PlayerDto = playerData, - Expires = adminActionType == AdminActionType.TempBan ? DateTime.UtcNow.AddDays(DefaultTempBanDurationDays) : null + Expires = adminActionType == AdminActionType.TempBan ? DateTime.UtcNow.AddDays(tempBanDurationDays) : null }; return View(createAdminActionViewModel); @@ -607,12 +606,12 @@ public async Task DeleteConfirmed(Guid id, Guid playerId, Cancell private string GetForumBaseUrl() { - return GetConfigurationValue("AdminActions:ForumBaseUrl", DefaultForumBaseUrl); + return (Configuration["XtremeIdiots:Forums:TopicBaseUrl"] ?? "https://www.xtremeidiots.com/forums/topic/").TrimEnd('/') + "/"; } private string GetFallbackAdminId() { - return GetConfigurationValue("AdminActions:FallbackAdminId", DefaultFallbackAdminId); + return Configuration["XtremeIdiots:Forums:DefaultAdminUserId"] ?? "21145"; } private async Task GetPlayerDataAsync(Guid playerId, CancellationToken cancellationToken = default) diff --git a/src/XtremeIdiots.Portal.Web/Controllers/ServerAdminController.cs b/src/XtremeIdiots.Portal.Web/Controllers/ServerAdminController.cs index d90296d0d..c2e9e3db3 100644 --- a/src/XtremeIdiots.Portal.Web/Controllers/ServerAdminController.cs +++ b/src/XtremeIdiots.Portal.Web/Controllers/ServerAdminController.cs @@ -48,9 +48,6 @@ public class ServerAdminController( ILogger logger, IConfiguration configuration) : BaseController(telemetryClient, logger, configuration) { - private const string DefaultForumBaseUrl = "https://www.xtremeidiots.com/forums/topic/"; - private const string DefaultFallbackAdminId = "21145"; - private const int DefaultTempBanDurationDays = 7; /// /// Displays the main server administration dashboard with available game servers @@ -854,9 +851,11 @@ public async Task TempBanRconPlayer(Guid id, int playerSlot, stri } // Create admin action record with expiry if we have a GUID + var tempBanDurationDays = int.TryParse(Configuration["XtremeIdiots:Forums:DefaultTempBanDays"], out var days) ? days : 7; + if (!string.IsNullOrWhiteSpace(playerGuid)) { - var expiryDate = DateTime.UtcNow.AddDays(DefaultTempBanDurationDays); + var expiryDate = DateTime.UtcNow.AddDays(tempBanDurationDays); await CreateAdminActionForRconOperationAsync( gameServerData.GameType, playerGuid, playerName, AdminActionType.TempBan, $"Player temp banned from {gameServerData.Title} via RCON by {User.Username()}. Please update with proper reason.", @@ -871,7 +870,7 @@ await CreateAdminActionForRconOperationAsync( { "GameType", gameServerData.GameType.ToString() } }); - return Json(new { success = true, message = $"Player {playerName} has been temp banned for {DefaultTempBanDurationDays} days" }); + return Json(new { success = true, message = $"Player {playerName} has been temp banned for {tempBanDurationDays} days" }); } catch (Exception ex) { diff --git a/src/XtremeIdiots.Portal.Web/Helpers/GameTypeIconTagHelper.cs b/src/XtremeIdiots.Portal.Web/Helpers/GameTypeIconTagHelper.cs index 1fea635a8..c02eb666f 100644 --- a/src/XtremeIdiots.Portal.Web/Helpers/GameTypeIconTagHelper.cs +++ b/src/XtremeIdiots.Portal.Web/Helpers/GameTypeIconTagHelper.cs @@ -4,7 +4,7 @@ namespace XtremeIdiots.Portal.Web.Helpers; [HtmlTargetElement("game-type-icon")] -public class GameTypeIconTagHelper : TagHelper +public class GameTypeIconTagHelper(IConfiguration configuration) : TagHelper { [HtmlAttributeName("game")] public GameType Game { get; set; } [HtmlAttributeName("external")] public bool External { get; set; } @@ -14,7 +14,7 @@ public class GameTypeIconTagHelper : TagHelper public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "img"; - var baseUrl = External ? "https://portal.xtremeidiots.com" : string.Empty; + var baseUrl = External ? (configuration["XtremeIdiots:PortalBaseUrl"] ?? "https://portal.xtremeidiots.com").TrimEnd('/') : string.Empty; output.Attributes.SetAttribute("src", $"{baseUrl}/images/game-icons/{Game}.png"); output.Attributes.SetAttribute("alt", Game.ToString()); output.Attributes.SetAttribute("width", Size.ToString()); diff --git a/src/XtremeIdiots.Portal.Web/Helpers/ServerTagHelpers.cs b/src/XtremeIdiots.Portal.Web/Helpers/ServerTagHelpers.cs index 27b41ab52..046ed054c 100644 --- a/src/XtremeIdiots.Portal.Web/Helpers/ServerTagHelpers.cs +++ b/src/XtremeIdiots.Portal.Web/Helpers/ServerTagHelpers.cs @@ -47,7 +47,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output) } [HtmlTargetElement("server-link")] -public class ServerLinkTagHelper : TagHelper +public class ServerLinkTagHelper(IConfiguration configuration) : TagHelper { [HtmlAttributeName("type")] public string Type { get; set; } = string.Empty; // gametracker|hlsw|steam [HtmlAttributeName("game")] public string? Game { get; set; } @@ -60,7 +60,8 @@ public override void Process(TagHelperContext context, TagHelperOutput output) switch (Type.ToLowerInvariant()) { case "gametracker": - output.Attributes.SetAttribute("href", $"https://www.gametracker.com/server_info/{Host}:{Port}"); + var gameTrackerBaseUrl = (configuration["GameTracker:ServerInfoBaseUrl"] ?? "https://www.gametracker.com/server_info/").TrimEnd('/') + "/"; + output.Attributes.SetAttribute("href", $"{gameTrackerBaseUrl}{Host}:{Port}"); output.Attributes.SetAttribute("target", "_blank"); output.Content.SetHtmlContent("\"gametracker\"/"); break; diff --git a/src/XtremeIdiots.Portal.Web/Program.cs b/src/XtremeIdiots.Portal.Web/Program.cs index 69d0fc3b5..d66b7cedf 100644 --- a/src/XtremeIdiots.Portal.Web/Program.cs +++ b/src/XtremeIdiots.Portal.Web/Program.cs @@ -3,72 +3,48 @@ namespace XtremeIdiots.Portal.Web; -/// -/// Entry point for the XtremeIdiots Portal web application -/// public class Program { - private readonly static string[] appConfigurationKeyFilters = - [ - "XtremeIdiots.Portal.Web:*", - "RepositoryApi:*", - "ServersIntegrationApi:*", - "FeatureManagement:*", - ]; - - /// - /// Main entry point for the application - /// - /// Command line arguments public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } - /// - /// Creates the host builder with default configuration and Startup class - /// - /// Command line arguments - /// Configured host builder public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder(args) - .ConfigureAppConfiguration((context, configBuilder) => + .ConfigureAppConfiguration((context, builder) => { - var builtConfig = configBuilder.Build(); + var builtConfig = builder.Build(); var appConfigEndpoint = builtConfig["AzureAppConfiguration:Endpoint"]; - if (string.IsNullOrWhiteSpace(appConfigEndpoint)) - { - return; - } - - var managedIdentityClientId = builtConfig["AzureAppConfiguration:ManagedIdentityClientId"]; - var environmentLabel = builtConfig["AzureAppConfiguration:Environment"] ?? context.HostingEnvironment.EnvironmentName; - - var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions + if (!string.IsNullOrWhiteSpace(appConfigEndpoint)) { - ManagedIdentityClientId = managedIdentityClientId, - }); + var managedIdentityClientId = builtConfig["AzureAppConfiguration:ManagedIdentityClientId"]; + var environmentLabel = builtConfig["AzureAppConfiguration:Environment"] ?? context.HostingEnvironment.EnvironmentName; - configBuilder.AddAzureAppConfiguration(options => - { - var appConfig = options - .Connect(new Uri(appConfigEndpoint), credential) - .ConfigureKeyVault(kv => kv.SetCredential(credential)); - - foreach (var keyFilter in appConfigurationKeyFilters) + var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { - var selection = appConfig.Select(keyFilter, environmentLabel); - - if (keyFilter == "XtremeIdiots.Portal.Web:*") - { - selection.TrimKeyPrefix("XtremeIdiots.Portal.Web:"); - } - } + ManagedIdentityClientId = managedIdentityClientId, + }); - appConfig.Select(KeyFilter.Any, LabelFilter.Null); - }); + builder.AddAzureAppConfiguration(options => + { + options.Connect(new Uri(appConfigEndpoint), credential) + .Select("XtremeIdiots.Portal.Web:*", environmentLabel) + .TrimKeyPrefix("XtremeIdiots.Portal.Web:") + .Select("RepositoryApi:*", environmentLabel) + .Select("ServersIntegrationApi:*", environmentLabel) + .Select("GeoLocationApi:*", environmentLabel) + .Select("XtremeIdiots:*", environmentLabel) + .Select("ProxyCheck:*", environmentLabel) + .Select("GameTracker:*", environmentLabel) + .Select("Google:*", environmentLabel) + .Select("FeatureManagement:*", environmentLabel); + + options.ConfigureKeyVault(kv => kv.SetCredential(credential)); + }); + } }) .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); } diff --git a/src/XtremeIdiots.Portal.Web/Services/ProxyCheckService.cs b/src/XtremeIdiots.Portal.Web/Services/ProxyCheckService.cs index 749ec5c00..5c7b47612 100644 --- a/src/XtremeIdiots.Portal.Web/Services/ProxyCheckService.cs +++ b/src/XtremeIdiots.Portal.Web/Services/ProxyCheckService.cs @@ -26,7 +26,7 @@ public class ProxyCheckService : IProxyCheckService private readonly IMemoryCache memoryCache; private readonly ILogger logger; private readonly string? apiKey; - private readonly string apiBaseUrl = "https://proxycheck.io/v2/"; + private readonly string apiBaseUrl; private readonly TimeSpan cacheDuration = TimeSpan.FromHours(1); /// @@ -50,6 +50,7 @@ public ProxyCheckService( this.memoryCache = memoryCache; this.logger = logger; + apiBaseUrl = (configuration["ProxyCheck:BaseUrl"] ?? "https://proxycheck.io/v2/").TrimEnd('/') + "/"; apiKey = configuration["ProxyCheck:ApiKey"]; if (string.IsNullOrWhiteSpace(apiKey)) { diff --git a/src/XtremeIdiots.Portal.Web/Startup.cs b/src/XtremeIdiots.Portal.Web/Startup.cs index 4af08d00a..32c6e30e3 100644 --- a/src/XtremeIdiots.Portal.Web/Startup.cs +++ b/src/XtremeIdiots.Portal.Web/Startup.cs @@ -31,9 +31,9 @@ public void ConfigureServices(IServiceCollection services) telemetryProcessorChainBuilder.UseAdaptiveSampling( settings: new SamplingPercentageEstimatorSettings { - InitialSamplingPercentage = 5, - MinSamplingPercentage = 5, - MaxSamplingPercentage = 60 + InitialSamplingPercentage = double.TryParse(Configuration["ApplicationInsights:InitialSamplingPercentage"], out var initPct) ? initPct : 5, + MinSamplingPercentage = double.TryParse(Configuration["ApplicationInsights:MinSamplingPercentage"], out var minPct) ? minPct : 5, + MaxSamplingPercentage = double.TryParse(Configuration["ApplicationInsights:MaxSamplingPercentage"], out var maxPct) ? maxPct : 60 }, callback: null, excludedTypes: "Exception"); diff --git a/src/XtremeIdiots.Portal.Web/Views/AdminActions/_MyAdminActionDetailsPanel.cshtml b/src/XtremeIdiots.Portal.Web/Views/AdminActions/_MyAdminActionDetailsPanel.cshtml index e21cec5f4..b2d049b25 100644 --- a/src/XtremeIdiots.Portal.Web/Views/AdminActions/_MyAdminActionDetailsPanel.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/AdminActions/_MyAdminActionDetailsPanel.cshtml @@ -1,7 +1,7 @@ @using XtremeIdiots.Portal.Repository.Abstractions.Constants.V1 @using XtremeIdiots.Portal.Repository.Abstractions.Models.V1.AdminActions @model XtremeIdiots.Portal.Web.ViewModels.MyAdminActionDetailsViewModel -@inject Microsoft.Extensions.Configuration.IConfiguration Configuration +@inject IConfiguration Configuration @if (Model?.AdminAction is null) { @@ -27,7 +27,7 @@ }; var gameType = player?.GameType; var userForumId = adminAction.UserProfile?.XtremeIdiotsForumId; - var forumBase = Configuration["AdminActions:ForumBaseUrl"] ?? "https://www.xtremeidiots.com/forums/topic/"; + var forumBase = (Configuration["XtremeIdiots:Forums:TopicBaseUrl"] ?? "https://www.xtremeidiots.com/forums/topic/").TrimEnd('/') + "/"; }
diff --git a/src/XtremeIdiots.Portal.Web/Views/External/LatestAdminActions.cshtml b/src/XtremeIdiots.Portal.Web/Views/External/LatestAdminActions.cshtml index ec216334b..4712a2033 100644 --- a/src/XtremeIdiots.Portal.Web/Views/External/LatestAdminActions.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/External/LatestAdminActions.cshtml @@ -1,4 +1,5 @@ -@using XtremeIdiots.Portal.Web.Extensions +@inject IConfiguration Configuration +@using XtremeIdiots.Portal.Web.Extensions @using XtremeIdiots.Portal.Repository.Abstractions.Constants.V1 @using XtremeIdiots.Portal.Repository.Abstractions.Models.V1.AdminActions @model List @@ -39,7 +40,7 @@ @Html.Raw(text) @item.Player?.Username + href="@((Configuration["XtremeIdiots:PortalBaseUrl"] ?? "https://portal.xtremeidiots.com").TrimEnd('/'))/Players/Details/@item.PlayerId">@item.Player?.Username

diff --git a/src/XtremeIdiots.Portal.Web/Views/IPAddresses/Details.cshtml b/src/XtremeIdiots.Portal.Web/Views/IPAddresses/Details.cshtml index 566a9440a..86ff2e2cd 100644 --- a/src/XtremeIdiots.Portal.Web/Views/IPAddresses/Details.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/IPAddresses/Details.cshtml @@ -1,6 +1,7 @@ @using XtremeIdiots.Portal.Web.Extensions @using XtremeIdiots.Portal.Repository.Abstractions.Constants.V1 @using System.Linq +@inject IConfiguration Configuration @model XtremeIdiots.Portal.Web.ViewModels.IPAddressDetailsViewModel @{ @@ -308,7 +309,11 @@ @section Scripts { - @if (Model.GeoLocation != null && Model.GeoLocation.Latitude != 0 && Model.GeoLocation.Longitude != 0) + @{ + var mapsApiKey = Configuration["Google:MapsApiKey"]; + var isValidMapsApiKey = !string.IsNullOrEmpty(mapsApiKey) && System.Text.RegularExpressions.Regex.IsMatch(mapsApiKey, @"^[A-Za-z0-9_-]+$", System.Text.RegularExpressions.RegexOptions.None, TimeSpan.FromSeconds(1)); + } + @if (Model.GeoLocation != null && Model.GeoLocation.Latitude != 0 && Model.GeoLocation.Longitude != 0 && isValidMapsApiKey) { - + } } diff --git a/src/XtremeIdiots.Portal.Web/Views/Players/Details.cshtml b/src/XtremeIdiots.Portal.Web/Views/Players/Details.cshtml index 44b453abf..d8e50456c 100644 --- a/src/XtremeIdiots.Portal.Web/Views/Players/Details.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/Players/Details.cshtml @@ -1,4 +1,5 @@ @inject IAuthorizationService AuthorizationService +@inject IConfiguration Configuration @using Microsoft.AspNetCore.Authorization @using XtremeIdiots.Portal.Web.Auth.Constants @using XtremeIdiots.Portal.Web.Extensions @@ -469,7 +470,14 @@ - + @{ + var mapsApiKey = Configuration["Google:MapsApiKey"]; + var isValidMapsApiKey = !string.IsNullOrEmpty(mapsApiKey) && System.Text.RegularExpressions.Regex.IsMatch(mapsApiKey, @"^[A-Za-z0-9_-]+$", System.Text.RegularExpressions.RegexOptions.None, TimeSpan.FromSeconds(1)); + } + @if (isValidMapsApiKey) + { + + } - + @{ + var mapsApiKey = Configuration["Google:MapsApiKey"]; + var isValidMapsApiKey = !string.IsNullOrEmpty(mapsApiKey) && System.Text.RegularExpressions.Regex.IsMatch(mapsApiKey, @"^[A-Za-z0-9_-]+$", System.Text.RegularExpressions.RegexOptions.None, TimeSpan.FromSeconds(1)); + } + @if (isValidMapsApiKey) + { + + } } \ No newline at end of file diff --git a/src/XtremeIdiots.Portal.Web/Views/Servers/ServerInfo.cshtml b/src/XtremeIdiots.Portal.Web/Views/Servers/ServerInfo.cshtml index 1e3799430..e0eacbc3c 100644 --- a/src/XtremeIdiots.Portal.Web/Views/Servers/ServerInfo.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/Servers/ServerInfo.cshtml @@ -1,5 +1,6 @@ @using XtremeIdiots.Portal.Web.Extensions @using XtremeIdiots.Portal.Web.ViewModels +@inject IConfiguration Configuration @model ServersGameServerViewModel @{ @@ -300,7 +301,11 @@ @section Scripts { - @if (Model.GameServer.LivePlayers.Any()) + @{ + var mapsApiKey = Configuration["Google:MapsApiKey"]; + var isValidMapsApiKey = !string.IsNullOrEmpty(mapsApiKey) && System.Text.RegularExpressions.Regex.IsMatch(mapsApiKey, @"^[A-Za-z0-9_-]+$", System.Text.RegularExpressions.RegexOptions.None, TimeSpan.FromSeconds(1)); + } + @if (Model.GameServer.LivePlayers.Any() && isValidMapsApiKey) { + src="https://maps.googleapis.com/maps/api/js?key=@mapsApiKey&signed_in=false&callback=initMap"> } diff --git a/src/XtremeIdiots.Portal.Web/Views/Shared/Components/AdminActions/Default.cshtml b/src/XtremeIdiots.Portal.Web/Views/Shared/Components/AdminActions/Default.cshtml index 4939efd0c..63e69eb6a 100644 --- a/src/XtremeIdiots.Portal.Web/Views/Shared/Components/AdminActions/Default.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/Shared/Components/AdminActions/Default.cshtml @@ -1,4 +1,5 @@ @inject IAuthorizationService AuthorizationService +@inject IConfiguration Configuration @using Microsoft.AspNetCore.Authorization @using XtremeIdiots.Portal.Web.Auth.Constants @using XtremeIdiots.Portal.Repository.Abstractions.Constants.V1 @@ -174,7 +175,7 @@
Discussion Topic
- View Forum Topic diff --git a/src/XtremeIdiots.Portal.Web/Views/Shared/_Layout.cshtml b/src/XtremeIdiots.Portal.Web/Views/Shared/_Layout.cshtml index 653f260be..6bffdec2d 100644 --- a/src/XtremeIdiots.Portal.Web/Views/Shared/_Layout.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/Shared/_Layout.cshtml @@ -1,17 +1,25 @@ @using XtremeIdiots.Portal.Web.Extensions +@inject IConfiguration Configuration - - + + gtag('config', '@analyticsId'); + + } diff --git a/src/XtremeIdiots.Portal.Web/Views/_ViewImports.cshtml b/src/XtremeIdiots.Portal.Web/Views/_ViewImports.cshtml index 301570a89..3a5ecabaa 100644 --- a/src/XtremeIdiots.Portal.Web/Views/_ViewImports.cshtml +++ b/src/XtremeIdiots.Portal.Web/Views/_ViewImports.cshtml @@ -1,6 +1,7 @@ @using XtremeIdiots.Portal.Web @using XtremeIdiots.Portal.Web.Extensions @using Microsoft.AspNetCore.Authorization +@using Microsoft.Extensions.Configuration @using XtremeIdiots.Portal.Web.Auth.Constants @using XtremeIdiots.Portal.Repository.Abstractions.Constants.V1 @addTagHelper XtremeIdiots.Portal.Web.Helpers.PolicyTagHelper, XtremeIdiots.Portal.Web diff --git a/src/XtremeIdiots.Portal.Web/appsettings.json b/src/XtremeIdiots.Portal.Web/appsettings.json index 1e440a700..c98e15581 100644 --- a/src/XtremeIdiots.Portal.Web/appsettings.json +++ b/src/XtremeIdiots.Portal.Web/appsettings.json @@ -53,10 +53,6 @@ "PlayerAuthQueueName": "player-auth", "ChatMessageQueueName": "chat-message" }, - "AdminActions": { - "FallbackAdminId": "21145", - "ForumBaseUrl": "https://www.xtremeidiots.com/forums/topic/" - }, "repository_api_application_audience": "api://portal-repository-prd", "ServersIntegrationApi:ApplicationAudience": "api://portal-servers-integration-prd" } \ No newline at end of file diff --git a/terraform/tfvars/dev.tfvars b/terraform/tfvars/dev.tfvars index 3c971a039..7482cd3a1 100644 --- a/terraform/tfvars/dev.tfvars +++ b/terraform/tfvars/dev.tfvars @@ -40,13 +40,6 @@ portal_core_state = { tenant_id = "e56a6947-bb9a-4a6e-846a-1f118d1c3a14" } -geo_location_api = { - base_url = "https://apim-geo-location-prd-swedencentral-6f10eaac01a0.azure-api.net/geolocation" - application_audience = "api://e56a6947-bb9a-4a6e-846a-1f118d1c3a14/geolocation-api-prd" - keyvault_primary_ref = "https://kv-03bc577ff535-swe.vault.azure.net/secrets/portal-web-dev-apim-subscription-key/" - keyvault_secondary_ref = "https://kv-03bc577ff535-swe.vault.azure.net/secrets/portal-web-dev-apim-subscription-key-secondary/" -} - dns_subscription_id = "db34f572-8b71-40d6-8f99-f29a27612144" dns_resource_group_name = "rg-platform-dns-prd-uksouth-01" dns_subdomain = "portal.dev" diff --git a/terraform/tfvars/prd.tfvars b/terraform/tfvars/prd.tfvars index aee91fd3f..4fc7e96fa 100644 --- a/terraform/tfvars/prd.tfvars +++ b/terraform/tfvars/prd.tfvars @@ -40,13 +40,6 @@ portal_core_state = { tenant_id = "e56a6947-bb9a-4a6e-846a-1f118d1c3a14" } -geo_location_api = { - base_url = "https://apim-geo-location-prd-swedencentral-6f10eaac01a0.azure-api.net/geolocation" - application_audience = "api://e56a6947-bb9a-4a6e-846a-1f118d1c3a14/geolocation-api-prd" - keyvault_primary_ref = "https://kv-18ac60675297-swe.vault.azure.net/secrets/portal-web-prd-apim-subscription-key/" - keyvault_secondary_ref = "https://kv-18ac60675297-swe.vault.azure.net/secrets/portal-web-prd-apim-subscription-key-secondary/" -} - dns_subscription_id = "db34f572-8b71-40d6-8f99-f29a27612144" dns_resource_group_name = "rg-platform-dns-prd-uksouth-01" dns_subdomain = "portal" diff --git a/terraform/variables.tf b/terraform/variables.tf index 0261bbf3a..91ccfab3e 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -62,15 +62,6 @@ variable "portal_core_state" { }) } -variable "geo_location_api" { - type = object({ - base_url = string - application_audience = string - keyvault_primary_ref = string - keyvault_secondary_ref = string - }) -} - variable "dns_subscription_id" {} variable "dns_resource_group_name" {} variable "dns_subdomain" {} diff --git a/terraform/web_app.tf b/terraform/web_app.tf index 5aca3237f..5a30db344 100644 --- a/terraform/web_app.tf +++ b/terraform/web_app.tf @@ -44,10 +44,6 @@ resource "azurerm_linux_web_app" "app" { "ASPNETCORE_ENVIRONMENT" = var.environment == "prd" ? "Production" : "Development" "WEBSITE_RUN_FROM_PACKAGE" = "1" - "GeoLocationApi__BaseUrl" = var.geo_location_api.base_url - "GeoLocationApi__ApiKey" = format("@Microsoft.KeyVault(SecretUri=%s)", var.geo_location_api.keyvault_primary_ref) - "GeoLocationApi__ApplicationAudience" = var.geo_location_api.application_audience - "sql_connection_string" = format("Server=tcp:%s;Authentication=Active Directory Default; Database=%s;User ID=%s;", data.azurerm_mssql_server.sql_server.fully_qualified_domain_name, local.sql_database_name, local.web_identity.client_id) // https://learn.microsoft.com/en-us/azure/azure-monitor/profiler/profiler-azure-functions#app-settings-for-enabling-profiler