🎉 Initial commit for the Zone project
This commit is contained in:
4
.github/workflows/docker-build.yml
vendored
4
.github/workflows/docker-build.yml
vendored
@@ -27,8 +27,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
files="${{ steps.changed-files.outputs.files }}"
|
files="${{ steps.changed-files.outputs.files }}"
|
||||||
matrix="{\"include\":[]}"
|
matrix="{\"include\":[]}"
|
||||||
services=("Sphere" "Pass" "Ring" "Drive" "Develop" "Gateway" "Insight")
|
services=("Sphere" "Pass" "Ring" "Drive" "Develop" "Gateway" "Insight" "Zone")
|
||||||
images=("sphere" "pass" "ring" "drive" "develop" "gateway" "insight")
|
images=("sphere" "pass" "ring" "drive" "develop" "gateway" "insight" "zone")
|
||||||
changed_services=()
|
changed_services=()
|
||||||
|
|
||||||
for file in $files; do
|
for file in $files; do
|
||||||
|
|||||||
@@ -50,14 +50,6 @@ public static class ServiceCollectionExtensions
|
|||||||
{
|
{
|
||||||
options.DataAnnotationLocalizerProvider = (type, factory) =>
|
options.DataAnnotationLocalizerProvider = (type, factory) =>
|
||||||
factory.Create(typeof(SharedResource));
|
factory.Create(typeof(SharedResource));
|
||||||
})
|
|
||||||
.ConfigureApplicationPartManager(opts =>
|
|
||||||
{
|
|
||||||
var mockingPart = opts.ApplicationParts.FirstOrDefault(a =>
|
|
||||||
a.Name == "DysonNetwork.Pass"
|
|
||||||
);
|
|
||||||
if (mockingPart != null)
|
|
||||||
opts.ApplicationParts.Remove(mockingPart);
|
|
||||||
});
|
});
|
||||||
services.AddRazorPages();
|
services.AddRazorPages();
|
||||||
|
|
||||||
|
|||||||
47
DysonNetwork.Zone/AppDatabase.cs
Normal file
47
DysonNetwork.Zone/AppDatabase.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using DysonNetwork.Shared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Zone;
|
||||||
|
|
||||||
|
public class AppDatabase(DbContextOptions<AppDatabase> options, IConfiguration configuration) : DbContext(options)
|
||||||
|
{
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
optionsBuilder.UseNpgsql(
|
||||||
|
configuration.GetConnectionString("App"),
|
||||||
|
opt => opt
|
||||||
|
.ConfigureDataSource(optSource => optSource.EnableDynamicJson())
|
||||||
|
.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)
|
||||||
|
.UseNodaTime()
|
||||||
|
).UseSnakeCaseNamingConvention();
|
||||||
|
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
this.ApplyAuditableAndSoftDelete();
|
||||||
|
return await base.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
modelBuilder.ApplySoftDeleteFilters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppDatabaseFactory : IDesignTimeDbContextFactory<AppDatabase>
|
||||||
|
{
|
||||||
|
public AppDatabase CreateDbContext(string[] args)
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("appsettings.json")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var optionsBuilder = new DbContextOptionsBuilder<AppDatabase>();
|
||||||
|
return new AppDatabase(optionsBuilder.Options, configuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
27
DysonNetwork.Zone/Dockerfile
Normal file
27
DysonNetwork.Zone/Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
|
||||||
|
USER app
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 8080
|
||||||
|
EXPOSE 8081
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["DysonNetwork.Zone/DysonNetwork.Zone.csproj", "DysonNetwork.Zone/"]
|
||||||
|
COPY ["DysonNetwork.Shared/DysonNetwork.Shared.csproj", "DysonNetwork.Shared/"]
|
||||||
|
COPY ["DysonNetwork.Develop/DysonNetwork.Develop.csproj", "DysonNetwork.Develop/"]
|
||||||
|
RUN dotnet restore "DysonNetwork.Zone/DysonNetwork.Zone.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/DysonNetwork.Zone"
|
||||||
|
RUN dotnet build "DysonNetwork.Zone.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
RUN dotnet publish "DysonNetwork.Zone.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "DysonNetwork.Zone.dll"]
|
||||||
34
DysonNetwork.Zone/DysonNetwork.Zone.csproj
Normal file
34
DysonNetwork.Zone/DysonNetwork.Zone.csproj
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DysonNetwork.Shared\DysonNetwork.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.11">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="NodaTime.Serialization.Protobuf" Version="2.0.2" />
|
||||||
|
<PackageReference Include="NodaTime" Version="3.2.2"/>
|
||||||
|
<PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.3.0"/>
|
||||||
|
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.71.0"/>
|
||||||
|
<PackageReference Include="Quartz" Version="3.15.1" />
|
||||||
|
<PackageReference Include="Quartz.AspNetCore" Version="3.15.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="..\.dockerignore">
|
||||||
|
<Link>.dockerignore</Link>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
26
DysonNetwork.Zone/Pages/Error.cshtml
Normal file
26
DysonNetwork.Zone/Pages/Error.cshtml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@page
|
||||||
|
@model ErrorModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Error";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1 class="text-danger">Error.</h1>
|
||||||
|
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||||
|
|
||||||
|
@if (Model.ShowRequestId)
|
||||||
|
{
|
||||||
|
<p>
|
||||||
|
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
<h3>Development Mode</h3>
|
||||||
|
<p>
|
||||||
|
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||||
|
It can result in displaying sensitive information from exceptions to end users.
|
||||||
|
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||||
|
and restarting the app.
|
||||||
|
</p>
|
||||||
19
DysonNetwork.Zone/Pages/Error.cshtml.cs
Normal file
19
DysonNetwork.Zone/Pages/Error.cshtml.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Zone.Pages;
|
||||||
|
|
||||||
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
|
[IgnoreAntiforgeryToken]
|
||||||
|
public class ErrorModel : PageModel
|
||||||
|
{
|
||||||
|
public string? RequestId { get; set; }
|
||||||
|
|
||||||
|
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||||
|
|
||||||
|
public void OnGet()
|
||||||
|
{
|
||||||
|
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
DysonNetwork.Zone/Pages/Privacy.cshtml
Normal file
8
DysonNetwork.Zone/Pages/Privacy.cshtml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
@page
|
||||||
|
@model PrivacyModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Privacy Policy";
|
||||||
|
}
|
||||||
|
<h1>@ViewData["Title"]</h1>
|
||||||
|
|
||||||
|
<p>Use this page to detail your site's privacy policy.</p>
|
||||||
11
DysonNetwork.Zone/Pages/Privacy.cshtml.cs
Normal file
11
DysonNetwork.Zone/Pages/Privacy.cshtml.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Zone.Pages;
|
||||||
|
|
||||||
|
public class PrivacyModel : PageModel
|
||||||
|
{
|
||||||
|
public void OnGet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
52
DysonNetwork.Zone/Pages/Shared/_Layout.cshtml
Normal file
52
DysonNetwork.Zone/Pages/Shared/_Layout.cshtml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<title>@ViewData["Title"] - DysonNetwork.Zone</title>
|
||||||
|
<script type="importmap"></script>
|
||||||
|
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/>
|
||||||
|
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true"/>
|
||||||
|
<link rel="stylesheet" href="~/DysonNetwork.Zone.styles.css" asp-append-version="true"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" asp-area="" asp-page="/Index">DysonNetwork.Zone</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
|
||||||
|
aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
|
||||||
|
<ul class="navbar-nav flex-grow-1">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container">
|
||||||
|
<main role="main" class="pb-3">
|
||||||
|
@RenderBody()
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="border-top footer text-muted">
|
||||||
|
<div class="container">
|
||||||
|
© 2025 - DysonNetwork.Zone - <a asp-area="" asp-page="/Privacy">Privacy</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||||
|
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||||
|
|
||||||
|
@await RenderSectionAsync("Scripts", required: false)
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
|
||||||
|
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"></script>
|
||||||
3
DysonNetwork.Zone/Pages/_ViewImports.cshtml
Normal file
3
DysonNetwork.Zone/Pages/_ViewImports.cshtml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@using DysonNetwork.Zone
|
||||||
|
@namespace DysonNetwork.Zone.Pages
|
||||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
3
DysonNetwork.Zone/Pages/_ViewStart.cshtml
Normal file
3
DysonNetwork.Zone/Pages/_ViewStart.cshtml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@{
|
||||||
|
Layout = "_Layout";
|
||||||
|
}
|
||||||
57
DysonNetwork.Zone/Program.cs
Normal file
57
DysonNetwork.Zone/Program.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using DysonNetwork.Zone;
|
||||||
|
using DysonNetwork.Zone.Startup;
|
||||||
|
using DysonNetwork.Shared.Auth;
|
||||||
|
using DysonNetwork.Shared.Http;
|
||||||
|
using DysonNetwork.Shared.Registry;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.AddServiceDefaults();
|
||||||
|
|
||||||
|
builder.ConfigureAppKestrel(builder.Configuration);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
builder.Services.AddRazorPages();
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
|
builder.Services.AddAppServices();
|
||||||
|
builder.Services.AddAppAuthentication();
|
||||||
|
builder.Services.AddAppFlushHandlers();
|
||||||
|
builder.Services.AddAppBusinessServices(builder.Configuration);
|
||||||
|
builder.Services.AddAppScheduledJobs();
|
||||||
|
|
||||||
|
builder.Services.AddDysonAuth();
|
||||||
|
builder.Services.AddAccountService();
|
||||||
|
builder.Services.AddSphereService();
|
||||||
|
|
||||||
|
builder.AddSwaggerManifest(
|
||||||
|
"DysonNetwork.Zone",
|
||||||
|
"The zone service in the Solar Network."
|
||||||
|
);
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
app.MapDefaultEndpoints();
|
||||||
|
|
||||||
|
// Run database migrations
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<AppDatabase>();
|
||||||
|
await db.Database.MigrateAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (!app.Environment.IsDevelopment())
|
||||||
|
app.UseExceptionHandler("/Error");
|
||||||
|
|
||||||
|
app.ConfigureAppMiddleware(builder.Configuration);
|
||||||
|
|
||||||
|
app.UseStaticFiles();
|
||||||
|
app.UseRouting();
|
||||||
|
app.MapRazorPages();
|
||||||
|
|
||||||
|
app.UseSwaggerManifest("DysonNetwork.Zone");
|
||||||
|
|
||||||
|
app.Run();
|
||||||
26
DysonNetwork.Zone/Startup/ApplicationConfiguration.cs
Normal file
26
DysonNetwork.Zone/Startup/ApplicationConfiguration.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using DysonNetwork.Shared.Auth;
|
||||||
|
using DysonNetwork.Shared.Http;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Zone.Startup;
|
||||||
|
|
||||||
|
public static class ApplicationConfiguration
|
||||||
|
{
|
||||||
|
public static WebApplication ConfigureAppMiddleware(this WebApplication app, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
app.UseRequestLocalization();
|
||||||
|
|
||||||
|
app.ConfigureForwardedHeaders(configuration);
|
||||||
|
|
||||||
|
app.UseWebSockets();
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
app.UseMiddleware<PermissionMiddleware>();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
// Map gRPC services
|
||||||
|
app.MapGrpcReflectionService();
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
}
|
||||||
61
DysonNetwork.Zone/Startup/BroadcastEventHandler.cs
Normal file
61
DysonNetwork.Zone/Startup/BroadcastEventHandler.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using DysonNetwork.Shared.Proto;
|
||||||
|
using DysonNetwork.Shared.Stream;
|
||||||
|
using NATS.Client.Core;
|
||||||
|
using NATS.Client.JetStream.Models;
|
||||||
|
using NATS.Net;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Zone.Startup;
|
||||||
|
|
||||||
|
public class BroadcastEventHandler(
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
ILogger<BroadcastEventHandler> logger,
|
||||||
|
INatsConnection nats,
|
||||||
|
RingService.RingServiceClient pusher
|
||||||
|
) : BackgroundService
|
||||||
|
{
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
var accountTask = HandleAccountDeletions(stoppingToken);
|
||||||
|
|
||||||
|
await Task.WhenAll(accountTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleAccountDeletions(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
var js = nats.CreateJetStreamContext();
|
||||||
|
|
||||||
|
await js.EnsureStreamCreated("account_events", [AccountDeletedEvent.Type]);
|
||||||
|
|
||||||
|
var consumer = await js.CreateOrUpdateConsumerAsync("account_events",
|
||||||
|
new ConsumerConfig("sphere_account_deleted_handler"), cancellationToken: stoppingToken);
|
||||||
|
|
||||||
|
await foreach (var msg in consumer.ConsumeAsync<byte[]>(cancellationToken: stoppingToken))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var evt = JsonSerializer.Deserialize<AccountDeletedEvent>(msg.Data, GrpcTypeHelper.SerializerOptions);
|
||||||
|
if (evt == null)
|
||||||
|
{
|
||||||
|
await msg.AckAsync(cancellationToken: stoppingToken);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation("Account deleted: {AccountId}", evt.AccountId);
|
||||||
|
|
||||||
|
using var scope = serviceProvider.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<AppDatabase>();
|
||||||
|
|
||||||
|
// TODO clean up data
|
||||||
|
|
||||||
|
await msg.AckAsync(cancellationToken: stoppingToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Error processing AccountDeleted");
|
||||||
|
await msg.NakAsync(cancellationToken: stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
DysonNetwork.Zone/Startup/ScheduledJobsConfiguration.cs
Normal file
17
DysonNetwork.Zone/Startup/ScheduledJobsConfiguration.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Quartz;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Zone.Startup;
|
||||||
|
|
||||||
|
public static class ScheduledJobsConfiguration
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddAppScheduledJobs(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddQuartz(q =>
|
||||||
|
{
|
||||||
|
|
||||||
|
});
|
||||||
|
services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
79
DysonNetwork.Zone/Startup/ServiceCollectionExtensions.cs
Normal file
79
DysonNetwork.Zone/Startup/ServiceCollectionExtensions.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using DysonNetwork.Shared.Cache;
|
||||||
|
using DysonNetwork.Shared.GeoIp;
|
||||||
|
using NodaTime;
|
||||||
|
using NodaTime.Serialization.SystemTextJson;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Zone.Startup;
|
||||||
|
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddAppServices(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||||
|
|
||||||
|
services.AddDbContext<AppDatabase>();
|
||||||
|
services.AddSingleton<IClock>(SystemClock.Instance);
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
services.AddSingleton<ICacheService, CacheServiceRedis>();
|
||||||
|
|
||||||
|
services.AddHttpClient();
|
||||||
|
|
||||||
|
services
|
||||||
|
.AddControllers()
|
||||||
|
.AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
options.JsonSerializerOptions.NumberHandling =
|
||||||
|
JsonNumberHandling.AllowNamedFloatingPointLiterals;
|
||||||
|
options.JsonSerializerOptions.PropertyNamingPolicy =
|
||||||
|
JsonNamingPolicy.SnakeCaseLower;
|
||||||
|
|
||||||
|
options.JsonSerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
|
||||||
|
});
|
||||||
|
services.AddRazorPages();
|
||||||
|
|
||||||
|
services.AddGrpc(options =>
|
||||||
|
{
|
||||||
|
options.EnableDetailedErrors = true;
|
||||||
|
});
|
||||||
|
services.AddGrpcReflection();
|
||||||
|
|
||||||
|
services.Configure<RequestLocalizationOptions>(options =>
|
||||||
|
{
|
||||||
|
var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("zh-Hans") };
|
||||||
|
|
||||||
|
options.SupportedCultures = supportedCultures;
|
||||||
|
options.SupportedUICultures = supportedCultures;
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddHostedService<BroadcastEventHandler>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddAppAuthentication(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddAuthorization();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddAppFlushHandlers(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<FlushBufferService>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddAppBusinessServices(
|
||||||
|
this IServiceCollection services,
|
||||||
|
IConfiguration configuration
|
||||||
|
)
|
||||||
|
{
|
||||||
|
services.Configure<GeoIpOptions>(configuration.GetSection("GeoIP"));
|
||||||
|
services.AddScoped<GeoIpService>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
DysonNetwork.Zone/appsettings.json
Normal file
17
DysonNetwork.Zone/appsettings.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"DetailedErrors": true,
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"App": "Host=localhost;Port=5432;Database=dyson_zone;Username=postgres;Password=postgres;Include Error Detail=True;Maximum Pool Size=20;Connection Idle Lifetime=60"
|
||||||
|
},
|
||||||
|
"KnownProxies": ["127.0.0.1", "::1"],
|
||||||
|
"Swagger": {
|
||||||
|
"PublicBasePath": "/zone"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DysonNetwork.Gateway", "Dys
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DysonNetwork.Insight", "DysonNetwork.Insight\DysonNetwork.Insight.csproj", "{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DysonNetwork.Insight", "DysonNetwork.Insight\DysonNetwork.Insight.csproj", "{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DysonNetwork.Zone", "DysonNetwork.Zone\DysonNetwork.Zone.csproj", "{E255B723-CAC9-4AC8-AA3B-116CC256E63C}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -141,6 +143,18 @@ Global
|
|||||||
{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}.Release|x64.Build.0 = Release|Any CPU
|
{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}.Release|x86.ActiveCfg = Release|Any CPU
|
{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}.Release|x86.Build.0 = Release|Any CPU
|
{E603CDF2-8BA0-49AE-A1F9-BD2DA5CB983D}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{E255B723-CAC9-4AC8-AA3B-116CC256E63C}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
Reference in New Issue
Block a user