diff --git a/BlueWest.Api.Gateway/.dockerignore b/BlueWest.Api.Gateway/.dockerignore new file mode 100644 index 0000000..38bece4 --- /dev/null +++ b/BlueWest.Api.Gateway/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/BlueWest.Api.Gateway/BlueWest.Api.Gateway.csproj b/BlueWest.Api.Gateway/BlueWest.Api.Gateway.csproj new file mode 100644 index 0000000..62993b8 --- /dev/null +++ b/BlueWest.Api.Gateway/BlueWest.Api.Gateway.csproj @@ -0,0 +1,15 @@ + + + + Exe + net6.0 + enable + enable + Linux + + + + + + + diff --git a/BlueWest.Api.Gateway/Dockerfile b/BlueWest.Api.Gateway/Dockerfile new file mode 100644 index 0000000..d7187ef --- /dev/null +++ b/BlueWest.Api.Gateway/Dockerfile @@ -0,0 +1,18 @@ +FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["BlueWest.Api.Gateway/BlueWest.Api.Gateway.csproj", "BlueWest.Api.Gateway/"] +RUN dotnet restore "BlueWest.Api.Gateway/BlueWest.Api.Gateway.csproj" +COPY . . +WORKDIR "/src/BlueWest.Api.Gateway" +RUN dotnet build "BlueWest.Api.Gateway.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "BlueWest.Api.Gateway.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "BlueWest.Api.Gateway.dll"] diff --git a/BlueWest.Api.Gateway/Program.cs b/BlueWest.Api.Gateway/Program.cs new file mode 100644 index 0000000..7977a00 --- /dev/null +++ b/BlueWest.Api.Gateway/Program.cs @@ -0,0 +1,11 @@ +// See https://aka.ms/new-console-template for more information + +using BlueWest.Core; +using BlueWest.Tools; + +EventManager EventManager = new EventManager(new Dictionary>(10000)); +ThreadServer _threadServer; + +System.Threading.Thread.Sleep(2500); +_threadServer = new ThreadServer(EventManager); +_threadServer.Init(); \ No newline at end of file diff --git a/BlueWest.Api/BlueWest.Api.csproj b/BlueWest.Api/BlueWest.Api.csproj index 4a620bb..e2b7653 100644 --- a/BlueWest.Api/BlueWest.Api.csproj +++ b/BlueWest.Api/BlueWest.Api.csproj @@ -12,6 +12,8 @@ + + @@ -23,4 +25,8 @@ + + + + diff --git a/BlueWest.Api/MySQL/CountryDbContext.cs b/BlueWest.Api/Context/CountryDbContext.cs similarity index 100% rename from BlueWest.Api/MySQL/CountryDbContext.cs rename to BlueWest.Api/Context/CountryDbContext.cs diff --git a/BlueWest.Api/MySQL/FinanceDbContext.cs b/BlueWest.Api/Context/FinanceDbContext.cs similarity index 100% rename from BlueWest.Api/MySQL/FinanceDbContext.cs rename to BlueWest.Api/Context/FinanceDbContext.cs diff --git a/BlueWest.Api/Context/Interfaces/ExchangeInterface.cs b/BlueWest.Api/Context/Interfaces/ExchangeInterface.cs new file mode 100644 index 0000000..d933525 --- /dev/null +++ b/BlueWest.Api/Context/Interfaces/ExchangeInterface.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading.Tasks; +using BlueWest.Tools; +using BlueWest.WebApi.MySQL; + +namespace BlueWest.WebApi.Interfaces +{ + public struct ExchangeEvent { } + public class ExchangeInterface : EventListener, IDisposable, IAsyncDisposable + + { + private readonly EventManager _eventManager; + private readonly CountryDbContext _countryDbContext; + private readonly FinanceDbContext _financeDbContext; + private readonly UserDbContext _userDbContext; + + + public ExchangeInterface( + CountryDbContext countryDbContext, + FinanceDbContext financeDbContext, + UserDbContext userDbContext, + EventManager eventManager) + { + _countryDbContext = countryDbContext; + _financeDbContext = financeDbContext; + _userDbContext = userDbContext; + _eventManager = eventManager; + Init(); + } + + public ExchangeInterface() { } + + private void Init() + { + _eventManager.EventStartListening(this); + _eventManager.TriggerEvent(new ExchangeEvent()); + Console.WriteLine($"{nameof(ExchangeInterface)} Just started!"); + } + + + public void OnEvent(ExchangeEvent eventType) + { + Console.WriteLine($"Service received exchange {nameof(ExchangeEvent)}"); + } + + /// + /// Stop Listening for events + /// + public void Dispose() + { + _eventManager.EventStopListening(this); + } + + public ValueTask DisposeAsync() + { + _eventManager.EventStopListening(this); + return ValueTask.CompletedTask; + + } + } +} + diff --git a/BlueWest.Api/MySQL/ModelBuilderExtensions.cs b/BlueWest.Api/Context/MySQL/ModelBuilderExtensions.cs similarity index 84% rename from BlueWest.Api/MySQL/ModelBuilderExtensions.cs rename to BlueWest.Api/Context/MySQL/ModelBuilderExtensions.cs index 9e77f5b..71ccde3 100644 --- a/BlueWest.Api/MySQL/ModelBuilderExtensions.cs +++ b/BlueWest.Api/Context/MySQL/ModelBuilderExtensions.cs @@ -35,19 +35,18 @@ namespace BlueWest.WebApi.MySQL } - private static void UserModel(ModelBuilder modelBuilder) + private static ModelBuilder UserModel(ModelBuilder modelBuilder) { - modelBuilder.Entity(builder => - builder - .HasMany() - .WithOne(user => user.Country)); - modelBuilder .Entity(builder => builder .HasOne() .WithMany(co => co.Users)); + modelBuilder.Entity(builder => builder + .HasMany() + .WithOne(co => co.Country) + .HasForeignKey(x => x.CountryId)); modelBuilder.Entity(builder => @@ -56,6 +55,8 @@ namespace BlueWest.WebApi.MySQL .WithMany(x => x.FinanceTransactions) .HasForeignKey(x => x.UserId); }); + + return modelBuilder; } } } diff --git a/BlueWest.Api/MySQL/UserDbContext.cs b/BlueWest.Api/Context/UserDbContext.cs similarity index 100% rename from BlueWest.Api/MySQL/UserDbContext.cs rename to BlueWest.Api/Context/UserDbContext.cs diff --git a/BlueWest.Api/Tools/SwaggerEnumSchemaFilter.cs b/BlueWest.Api/Controllers/SwaggerEnumSchemaFilter.cs similarity index 100% rename from BlueWest.Api/Tools/SwaggerEnumSchemaFilter.cs rename to BlueWest.Api/Controllers/SwaggerEnumSchemaFilter.cs diff --git a/BlueWest.Api/Controllers/UserController.cs b/BlueWest.Api/Controllers/UserController.cs index 2b380c3..7efc74a 100644 --- a/BlueWest.Api/Controllers/UserController.cs +++ b/BlueWest.Api/Controllers/UserController.cs @@ -70,7 +70,7 @@ namespace BlueWest.WebApi.Controllers [HttpPost] public ActionResult AddUser(UserCreate userCreate) { - var user = new User(userCreate, 0, new List(), null); + var user = new User(userCreate, 0, new List(), null, -1); _dbContext.Users.Add(user); _dbContext.SaveChanges(); return CreatedAtRoute(nameof(GetUserById), new {userId = user.Id}, user); diff --git a/BlueWest.Api/Identity/AuthManager.cs b/BlueWest.Api/Identity/AuthManager.cs new file mode 100644 index 0000000..37712c8 --- /dev/null +++ b/BlueWest.Api/Identity/AuthManager.cs @@ -0,0 +1,6 @@ +namespace BlueWest.Data; + +public class AuthManager +{ + +} \ No newline at end of file diff --git a/BlueWest.Api/Identity/EntityDbContext.cs b/BlueWest.Api/Identity/EntityDbContext.cs new file mode 100644 index 0000000..41cb472 --- /dev/null +++ b/BlueWest.Api/Identity/EntityDbContext.cs @@ -0,0 +1,9 @@ +using BlueWest.WebApi.MySQL; +using Microsoft.AspNetCore.Identity; + +namespace BlueWest.WebApi; + +public class EntityDbContext : IdentityUser +{ + +} \ No newline at end of file diff --git a/BlueWest.Api/Identity/IdentityContext.cs b/BlueWest.Api/Identity/IdentityContext.cs new file mode 100644 index 0000000..d405f8a --- /dev/null +++ b/BlueWest.Api/Identity/IdentityContext.cs @@ -0,0 +1,10 @@ +using System.Security.Principal; + +namespace BlueWest.Data; + +public class IdentityContext : IIdentity +{ + public string AuthenticationType { get; } + public bool IsAuthenticated { get; } + public string Name { get; } +} \ No newline at end of file diff --git a/BlueWest.Api/Program.cs b/BlueWest.Api/Program.cs index c4f1863..0a83f98 100644 --- a/BlueWest.Api/Program.cs +++ b/BlueWest.Api/Program.cs @@ -9,13 +9,13 @@ using System.Linq; using System.Threading.Tasks; using BlueWest.Core; using BlueWest.Tools; +using BlueWest.WebApi.Interfaces; namespace BlueWest.WebApi { public class Program { - public static readonly EventManager EventManager = - new EventManager(new Dictionary>(10000)); + public static EventManager EventManager { get; set; } private static ThreadServer _threadServer; @@ -39,11 +39,41 @@ namespace BlueWest.WebApi Host1 = CreateHostBuilder(args) .UseContentRoot(Directory.GetCurrentDirectory()) .Build(); - Host1.Run(); - // Use RunASync - /*System.Threading.Thread.Sleep(2500); - _threadServer = new ThreadServer(EventManager); - _threadServer.Init();*/ + Host1.RunAsync(); + + + var tryGetEventManager = Host1.Services.GetService(typeof(EventManager)); + + try + { + _ = Host1.Services.GetService(typeof(ExchangeInterface)); + + } + catch (Exception e) + { + if (e is InvalidOperationException exception) + { + if (e.Source == "Pomelo.EntityFrameworkCore.MySql") + { + throw new InvalidOperationException("MySQL Error"); + } + } + + throw; + + } + + if(tryGetEventManager == null) Console.WriteLine($"Failed to get {nameof(EventManager)} Service."); + + if (tryGetEventManager is EventManager eventManager) + { + // Use RunASync + System.Threading.Thread.Sleep(2500); + _threadServer = new ThreadServer(eventManager); + _threadServer.Init(); + } + + } public static IHostBuilder CreateHostBuilder(string[] args) => diff --git a/BlueWest.Api/Startup.cs b/BlueWest.Api/Startup.cs index 0e514c8..d045d06 100644 --- a/BlueWest.Api/Startup.cs +++ b/BlueWest.Api/Startup.cs @@ -13,6 +13,8 @@ using System.Linq; using System.Reflection; using System.Text.Json.Serialization; using System.Threading.Tasks; +using BlueWest.Tools; +using BlueWest.WebApi.Interfaces; using BlueWest.WebApi.MySQL; using BlueWest.WebApi.Tools; using Microsoft.EntityFrameworkCore; @@ -22,19 +24,28 @@ namespace BlueWest.WebApi { public class Startup { + + public IConfiguration Configuration { get; } + + private readonly IWebHostEnvironment _environment; + + private readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; + + /// /// Startup configuration of the API /// - /// Accessible configuration information - public Startup(IConfiguration configuration) + public Startup(IConfiguration configuration, IWebHostEnvironment hostEnvironment) { Configuration = configuration; + _environment = hostEnvironment; } - - readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; - public IConfiguration Configuration { get; } + - // This method gets called by the runtime. Use this method to add services to the container. + /// + /// Configure Services + /// + /// Dependency injection public void ConfigureServices(IServiceCollection services) { services.AddCors(options => @@ -88,11 +99,10 @@ namespace BlueWest.WebApi services - .AddDbContextPool(options => options.GetSqlSettings(Configuration)) - .AddDbContextPool(options => options.GetSqlSettings(Configuration)) - .AddDbContextPool(options => options.GetSqlSettings(Configuration)) - ; - + .AddSingleton() + .PrepareDatabasePool(Configuration, _environment) + .AddSingleton(); + // services.AddGrpc(); } @@ -120,7 +130,6 @@ namespace BlueWest.WebApi app.UseAuthorization(); - app.UseEndpoints(endpoints => { endpoints.MapControllers(); diff --git a/BlueWest.Api/StartupExtensions.cs b/BlueWest.Api/StartupExtensions.cs index 947141f..c886303 100644 --- a/BlueWest.Api/StartupExtensions.cs +++ b/BlueWest.Api/StartupExtensions.cs @@ -1,20 +1,55 @@ using System; +using BlueWest.WebApi.MySQL; +using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace BlueWest.WebApi; - -public static class StartupExtensions +namespace BlueWest.WebApi { - public static void GetSqlSettings(this DbContextOptionsBuilder optionsBuilder, IConfiguration configuration) + /// + /// Startup Extensions + /// + public static class StartupExtensions { - optionsBuilder.UseMySql(configuration.GetConnectionString("LocalMySQL"), - new MySqlServerVersion(new Version(8, 0, 11))) + /// + /// Get MYSQL Connection String + /// + /// + /// + public static void GetMySqlSettings( + this DbContextOptionsBuilder optionsBuilder, + IConfiguration configuration, + IWebHostEnvironment environment) + { + var optionsBuilderRef = optionsBuilder.UseMySql(configuration.GetConnectionString("LocalMySQL"), + new MySqlServerVersion(new Version(8, 0, 11))); // The following three options help with debugging, but should // be changed or removed for production. - .LogTo(Console.WriteLine, LogLevel.Information) - .EnableSensitiveDataLogging() - .EnableDetailedErrors(); + if (environment.IsDevelopment()) + { + optionsBuilderRef + .LogTo(Console.WriteLine, LogLevel.Information) + .EnableSensitiveDataLogging() + .EnableDetailedErrors(); + } + } + + /// + /// Setup database Contexts + /// + /// + /// + /// + public static IServiceCollection PrepareDatabasePool(this IServiceCollection serviceCollection, + IConfiguration configuration, IWebHostEnvironment environment) + { + return serviceCollection + .AddDbContextPool(options => options.GetMySqlSettings(configuration, environment)) + .AddDbContextPool(options => options.GetMySqlSettings(configuration, environment)) + .AddDbContextPool(options => options.GetMySqlSettings(configuration, environment)); + } } } \ No newline at end of file diff --git a/BlueWest.Data/Transaction/FinanceOp.cs b/BlueWest.Data/Transaction/FinanceOp.cs index 4b1f182..a4a8147 100644 --- a/BlueWest.Data/Transaction/FinanceOp.cs +++ b/BlueWest.Data/Transaction/FinanceOp.cs @@ -7,8 +7,7 @@ namespace BlueWest.Data [MapFrom(typeof(FinanceOpCreate))] public partial class FinanceOp { - - public int UserId { get; set; } + public int UserId { get; set; } [Key] public TimeSpan CreationDate { get; set; } diff --git a/BlueWest.Data/Transaction/TransactionAmount.cs b/BlueWest.Data/Transaction/TransactionAmount.cs new file mode 100644 index 0000000..b9c24e2 --- /dev/null +++ b/BlueWest.Data/Transaction/TransactionAmount.cs @@ -0,0 +1,8 @@ +namespace BlueWest.Data +{ + public class TransactionAmount + { + public Currency Currency { get; set; } + } +} + diff --git a/BlueWest.Data/User/User.cs b/BlueWest.Data/User/User.cs index 8decbdd..3e61a87 100644 --- a/BlueWest.Data/User/User.cs +++ b/BlueWest.Data/User/User.cs @@ -12,11 +12,15 @@ namespace BlueWest.Data */ public partial class User { - public int Id { get; set; } + public int Id { get; set; } public string Name { get; set; } public List FinanceTransactions { get; set; } + public Country Country { get; set; } + + [ForeignKey("Country")] + public int CountryId { get; set; } public User(int id, string name) { diff --git a/BlueWest.Data/User/UserUnique.cs b/BlueWest.Data/User/UserUnique.cs new file mode 100644 index 0000000..369d07f --- /dev/null +++ b/BlueWest.Data/User/UserUnique.cs @@ -0,0 +1,6 @@ +namespace BlueWest.Data; + +public class UserUnique +{ + +} \ No newline at end of file diff --git a/BlueWest.sln b/BlueWest.sln index 5b7e3ec..08b662a 100644 --- a/BlueWest.sln +++ b/BlueWest.sln @@ -30,6 +30,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "README", "README", "{E9E3CE README.md = README.md EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{552B9217-4BB2-432A-B1B5-45E9B1AB13BC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlueWest.Api.Gateway", "BlueWest.Api.Gateway\BlueWest.Api.Gateway.csproj", "{A78343AF-77C6-48FD-A9C4-F8B7CBA56212}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -64,6 +68,10 @@ Global {5BE0A68C-B3ED-4FA1-B74B-3E857504899B}.Debug|Any CPU.Build.0 = Debug|Any CPU {5BE0A68C-B3ED-4FA1-B74B-3E857504899B}.Release|Any CPU.ActiveCfg = Release|Any CPU {5BE0A68C-B3ED-4FA1-B74B-3E857504899B}.Release|Any CPU.Build.0 = Release|Any CPU + {A78343AF-77C6-48FD-A9C4-F8B7CBA56212}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A78343AF-77C6-48FD-A9C4-F8B7CBA56212}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A78343AF-77C6-48FD-A9C4-F8B7CBA56212}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A78343AF-77C6-48FD-A9C4-F8B7CBA56212}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -76,5 +84,7 @@ Global {72B37540-A12F-466E-A58F-7BA2B247CB74} = {A1606EEC-6AC5-4779-B140-F57089F5A05F} {08F4484E-5FD8-4590-A8D7-12FBE47120C8} = {A1606EEC-6AC5-4779-B140-F57089F5A05F} {5BE0A68C-B3ED-4FA1-B74B-3E857504899B} = {A1606EEC-6AC5-4779-B140-F57089F5A05F} + {293E7852-8AFD-4EFB-8C2D-F1BBE68AEE78} = {552B9217-4BB2-432A-B1B5-45E9B1AB13BC} + {A78343AF-77C6-48FD-A9C4-F8B7CBA56212} = {552B9217-4BB2-432A-B1B5-45E9B1AB13BC} EndGlobalSection EndGlobal diff --git a/BlueWest/Artefacts/WorldArtefact.cs b/BlueWest/Artefacts/WorldArtefact.cs index 62c1c9f..0b55c35 100644 --- a/BlueWest/Artefacts/WorldArtefact.cs +++ b/BlueWest/Artefacts/WorldArtefact.cs @@ -1,10 +1,11 @@ using System; using BlueWest.Core; using BlueWest.Core.ComponentSystem; +using PerformanceSolution.Core.System; namespace BlueWest.Artefacts { - /*public class WorldArtefact: Artefact + public class WorldArtefact: Artefact { public WorldArtefact() @@ -16,6 +17,7 @@ namespace BlueWest.Artefacts protected override void Start() { AddComponent(); + Console.WriteLine("World Artefact enabled"); //BlueConsole.Log("World Artefact started"); } @@ -33,5 +35,5 @@ namespace BlueWest.Artefacts { base.OnDisable(); } - }*/ + } } \ No newline at end of file diff --git a/BlueWest/Core/Events/EventManager.cs b/BlueWest/Core/Events/EventManager.cs index 4b76e55..fb91693 100644 --- a/BlueWest/Core/Events/EventManager.cs +++ b/BlueWest/Core/Events/EventManager.cs @@ -16,6 +16,12 @@ namespace BlueWest.Tools _instance = this; } + public EventManager() + { + _subscribersList = new Dictionary>(); + _instance = this; + } + /// /// Adds a new subscriber to a certain event. /// diff --git a/BlueWest/Core/System/ThreadServer.cs b/BlueWest/Core/System/ThreadServer.cs index 8835c62..6af1048 100644 --- a/BlueWest/Core/System/ThreadServer.cs +++ b/BlueWest/Core/System/ThreadServer.cs @@ -12,6 +12,8 @@ namespace BlueWest.Core { public bool IsActive { get; private set; } + public EventManager EventManager => _eventManager; + private readonly EventManager _eventManager; public ThreadServer(EventManager eventManager) { @@ -70,6 +72,7 @@ namespace BlueWest.Core { Priority = threadPriority }; + thread.Start(); } }