Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add preparation for serverside localisation #129

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions NetEvent/Server/Data/SystemSettings/ISystemSetttingsManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Threading.Tasks;

using NetEvent.Server.Models;

namespace NetEvent.Server.Data.SystemSettings
{
public interface ISystemSettingsManager
{
Task<SystemSettingsResult> UpdateAsync(SystemSettingValue systemSettingValueToUpdate);

}
}
16 changes: 16 additions & 0 deletions NetEvent/Server/Data/SystemSettings/SystemSettingsError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace NetEvent.Server.Data.SystemSettings
{
/// <summary>
/// Encapsulates an error from the event subsystem.
/// </summary>
public class SystemSettingsError
{
/// <summary>
/// Gets or sets the description for this error.
/// </summary>
/// <value>
/// The description for this error.
/// </value>
public string? Description { get; set; }
}
}
65 changes: 65 additions & 0 deletions NetEvent/Server/Data/SystemSettings/SystemSettingsManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NetEvent.Server.Models;
using System.Globalization;
using Slugify;

namespace NetEvent.Server.Data.SystemSettings
{
public class SystemSettingsManager : ISystemSettingsManager
{
private readonly ApplicationDbContext _DbContext;
private readonly ILogger<SystemSettingsManager> _Logger;
private readonly ISlugHelper _SlugHelper;

public SystemSettingsManager(ApplicationDbContext dbContext, ILogger<SystemSettingsManager> logger, ISlugHelper slugHelper)
{
_DbContext = dbContext;
_Logger = logger;
_SlugHelper = slugHelper;
}

protected CancellationToken CancellationToken => CancellationToken.None;


public async Task<SystemSettingsResult> UpdateAsync(SystemSettingValue systemSettingValueToUpdate)
{

if (systemSettingValueToUpdate?.Key == null)
{
_Logger.LogError("Empty key is not allowed");
return SystemSettingsResult.Failed(new SystemSettingsError { Description = "Empty key is not allowed" });
}


var result = _DbContext.SystemSettingValues.Update(systemSettingValueToUpdate);

if (result.State == EntityState.Modified)
{
await _DbContext.SaveChangesAsync();
CheckForCultureChange(systemSettingValueToUpdate);
_Logger.LogInformation("Successfully updated Systemsetting {name}", systemSettingValueToUpdate.Key);
return SystemSettingsResult.Success;
}

_Logger.LogError("Error updating Systemsetting {name}", systemSettingValueToUpdate.Key);
return SystemSettingsResult.Failed(new SystemSettingsError());


}


private void CheckForCultureChange(SystemSettingValue systemSettingValueToUpdate)
{
if (systemSettingValueToUpdate?.Key == NetEvent.Shared.Config.SystemSettings.OrganizationData.DataCultureInfo && systemSettingValueToUpdate.SerializedValue != null)
{
var cultureInfo = new CultureInfo(systemSettingValueToUpdate.SerializedValue);
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
}
}

}
}
65 changes: 65 additions & 0 deletions NetEvent/Server/Data/SystemSettings/SystemSettingsResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace NetEvent.Server.Data.SystemSettings
{
/// <summary>
/// Represents the result of an Event operation.
/// </summary>
public class SystemSettingsResult
{
private static readonly SystemSettingsResult _Success = new() { Succeeded = true };
private readonly List<SystemSettingsError> _Errors = new();

/// <summary>
/// Flag indicating whether if the operation succeeded or not.
/// </summary>
/// <value>True if the operation succeeded, otherwise false.</value>
public bool Succeeded { get; protected set; }

/// <summary>
/// An <see cref="IEnumerable{T}"/> of <see cref="SystemSettingsError"/> instances containing errors
/// that occurred during the Event operation.
/// </summary>
/// <value>An <see cref="IEnumerable{T}"/> of <see cref="SystemSettingsError"/> instances.</value>
public IEnumerable<SystemSettingsError> Errors => _Errors;

/// <summary>
/// Returns an <see cref="SystemSettingsResult"/> indicating a successful Event operation.
/// </summary>
/// <returns>An <see cref="SystemSettingsResult"/> indicating a successful operation.</returns>
public static SystemSettingsResult Success => _Success;

/// <summary>
/// Creates an <see cref="SystemSettingsResult"/> indicating a failed Event operation, with a list of <paramref name="errors"/> if applicable.
/// </summary>
/// <param name="errors">An optional array of <see cref="SystemSettingsError"/>s which caused the operation to fail.</param>
/// <returns>An <see cref="SystemSettingsResult"/> indicating a failed Event operation, with a list of <paramref name="errors"/> if applicable.</returns>
public static SystemSettingsResult Failed(params SystemSettingsError[] errors)
{
var result = new SystemSettingsResult { Succeeded = false };
if (errors != null)
{
result._Errors.AddRange(errors);
}

return result;
}

/// <summary>
/// Converts the value of the current <see cref="SystemSettingsResult"/> object to its equivalent string representation.
/// </summary>
/// <returns>A string representation of the current <see cref="SystemSettingsResult"/> object.</returns>
/// <remarks>
/// If the operation was successful the ToString() will return "Succeeded" otherwise it returned
/// "Failed : " followed by a comma delimited list of error codes from its <see cref="Errors"/> collection, if any.
/// </remarks>
public override string ToString()
{
return Succeeded ?
"Succeeded" :
string.Format(CultureInfo.InvariantCulture, "{0} : {1}", "Failed", string.Join(",", Errors.Select(x => x.Description).ToList()));
}
}
}
46 changes: 46 additions & 0 deletions NetEvent/Server/Extensions/DefaultCultureExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using NetEvent.Server.Data;
using NetEvent.Shared.Config;

namespace NetEvent.Server.Extensions;

public static class DefaultCultureExtension
{
public static async Task SetDefaultCulture(this WebApplication app)
{
var logger = app.Services.GetRequiredService<ILogger<WebApplication>>();

try
{
using (var scope = app.Services.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
using (var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>())
{

var organizationCulture = await context.SystemSettingValues.Where(s => s.Key == SystemSettings.OrganizationData.DataCultureInfo).FirstAsync().ConfigureAwait(false);

if (organizationCulture?.SerializedValue == null)
{
return;
}

var cultureInfo = new CultureInfo(organizationCulture.SerializedValue);
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
}
}
}
catch (Exception ex)
{
logger.LogError(ex, "Unable to get Culture");
}

}
}
6 changes: 6 additions & 0 deletions NetEvent/Server/Localize.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace NetEvent.Server
{
public class Localize
{
}
}
151 changes: 80 additions & 71 deletions NetEvent/Server/Modules/System/Endpoints/GetSystemInfo.cs
Original file line number Diff line number Diff line change
@@ -1,71 +1,80 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using NetEvent.Shared.Dto;

namespace NetEvent.Server.Modules.System.Endpoints
{
public static class GetSystemInfo
{
public sealed class Handler : IRequestHandler<Request, Response>
{
public Handler()
{
}

public Task<Response> Handle(Request request, CancellationToken cancellationToken)
{
var systeminfocomponents = new List<SystemInfoComponentEntryDto>();
var systeminfohealth = new List<SystemInfoHealthEntryDto>();
var systeminfoversions = new List<SystemInfoVersionEntryDto>();

AppDomain currentDomain = AppDomain.CurrentDomain;
Assembly[] assems = currentDomain.GetAssemblies();
foreach (Assembly assem in assems)
{
systeminfocomponents.Add(new SystemInfoComponentEntryDto(assem.ManifestModule.Name, assem.ToString()));
}

systeminfoversions.Add(new SystemInfoVersionEntryDto("NETEVENT", Assembly.GetEntryAssembly()?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNODE"));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDID"));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNUMBER"));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("SOURCE_COMMIT"));

// TODO: think about healthchecks and healthcheck modularity (to perform checks on various services like game servers, the mail server, payment apis ...) and remove dummy services
systeminfohealth.Add(new SystemInfoHealthEntryDto("NETEVENT Server", string.Empty, true));
systeminfohealth.Add(new SystemInfoHealthEntryDto("Email Service", "servername", false));

var systeminfo = new SystemInfoDto(systeminfocomponents, systeminfohealth, systeminfoversions);

return Task.FromResult(new Response(systeminfo));
}

private static SystemInfoVersionEntryDto CreateSystemInfoVersionEntryFromEnv(string envName)
{
return new SystemInfoVersionEntryDto(envName, string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName)) ? "dev" : Environment.GetEnvironmentVariable(envName));
}
}

public sealed class Request : IRequest<Response>
{
public Request()
{
}
}

public sealed class Response : ResponseBase<SystemInfoDto>
{
public Response(SystemInfoDto value) : base(value)
{
}

public Response(ReturnType returnType, string error) : base(returnType, error)
{
}
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Extensions.Localization;
using NetEvent.Shared.Dto;

namespace NetEvent.Server.Modules.System.Endpoints
{
public static class GetSystemInfo
{
public sealed class Handler : IRequestHandler<Request, Response>
{
// TODO: remove localizer as soon as it is implemented somewhere where it makes sense
private IStringLocalizer<Localize> Localizer { get; set; }

// TODO: remove localizer as soon as it is implemented somewhere where it makes sense
public Handler(IStringLocalizer<Localize> localizer)
{
Localizer = localizer;
}

public Task<Response> Handle(Request request, CancellationToken cancellationToken)
{
var systeminfocomponents = new List<SystemInfoComponentEntryDto>();
var systeminfohealth = new List<SystemInfoHealthEntryDto>();
var systeminfoversions = new List<SystemInfoVersionEntryDto>();

AppDomain currentDomain = AppDomain.CurrentDomain;
Assembly[] assems = currentDomain.GetAssemblies();
foreach (Assembly assem in assems)
{
systeminfocomponents.Add(new SystemInfoComponentEntryDto(assem.ManifestModule.Name, assem.ToString()));
}

systeminfoversions.Add(new SystemInfoVersionEntryDto("NETEVENT", Assembly.GetEntryAssembly()?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNODE"));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDID"));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNUMBER"));
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("SOURCE_COMMIT"));

// TODO: think about healthchecks and healthcheck modularity (to perform checks on various services like game servers, the mail server, payment apis ...) and remove dummy services
systeminfohealth.Add(new SystemInfoHealthEntryDto("NETEVENT Server", string.Empty, true));
systeminfohealth.Add(new SystemInfoHealthEntryDto("Email Service", "servername", false));

var systeminfo = new SystemInfoDto(systeminfocomponents, systeminfohealth, systeminfoversions);

// TODO: remove localizer as soon as it is implemented somewhere where it makes sense
Console.WriteLine(Localizer["test.test"]);

return Task.FromResult(new Response(systeminfo));
}

private static SystemInfoVersionEntryDto CreateSystemInfoVersionEntryFromEnv(string envName)
{
return new SystemInfoVersionEntryDto(envName, string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName)) ? "dev" : Environment.GetEnvironmentVariable(envName));
}
}

public sealed class Request : IRequest<Response>
{
public Request()
{
}
}

public sealed class Response : ResponseBase<SystemInfoDto>
{
public Response(SystemInfoDto value) : base(value)
{
}

public Response(ReturnType returnType, string error) : base(returnType, error)
{
}
}
}
}
Loading