GET /api/public/home
GET /api/public/notices/{id}
SQLite / MySQL 双数据库只读连接
.env 与现有数据库配置兼容
公告 HTML 安全清洗
学校、班级、考试、科目、报名及系统通知聚合
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
namespace Eis.Web.Configuration;
|
||||
|
||||
public static class ApplicationPaths
|
||||
{
|
||||
public static string FindApplicationRoot()
|
||||
{
|
||||
foreach (var start in new[] { Directory.GetCurrentDirectory(), AppContext.BaseDirectory })
|
||||
{
|
||||
var directory = new DirectoryInfo(Path.GetFullPath(start));
|
||||
while (directory is not null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directory.FullName, "Eis.slnx")) ||
|
||||
File.Exists(Path.Combine(directory.FullName, "package.json")))
|
||||
{
|
||||
return directory.FullName;
|
||||
}
|
||||
directory = directory.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
return Path.GetFullPath(Directory.GetCurrentDirectory());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
namespace Eis.Web.Configuration;
|
||||
|
||||
public static class EnvironmentFile
|
||||
{
|
||||
public static void Load(string applicationRoot)
|
||||
{
|
||||
var path = Path.Combine(applicationRoot, ".env");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var rawLine in File.ReadLines(path))
|
||||
{
|
||||
var line = rawLine.Trim();
|
||||
if (line.Length == 0 || line.StartsWith('#'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (line.StartsWith("export ", StringComparison.Ordinal))
|
||||
{
|
||||
line = line[7..].TrimStart();
|
||||
}
|
||||
|
||||
var separator = line.IndexOf('=');
|
||||
if (separator <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var key = line[..separator].Trim();
|
||||
if (Environment.GetEnvironmentVariable(key) is not null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var value = line[(separator + 1)..].Trim();
|
||||
if (value.Length >= 2 && ((value[0] == '"' && value[^1] == '"') || (value[0] == '\'' && value[^1] == '\'')))
|
||||
{
|
||||
value = value[1..^1];
|
||||
}
|
||||
Environment.SetEnvironmentVariable(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Eis.Application.Public;
|
||||
|
||||
namespace Eis.Web.Configuration;
|
||||
|
||||
public sealed class PublicSiteConfiguration : IPublicSiteConfiguration
|
||||
{
|
||||
public PublicSiteConfiguration()
|
||||
{
|
||||
Branding = new PublicSiteBranding(
|
||||
new PublicOrganization(
|
||||
Read("PUBLIC_SITE_NAME", "考试服务平台"),
|
||||
Read("PUBLIC_SITE_CODE", "EXAM-SERVICE"),
|
||||
Read("PUBLIC_SITE_PHONE", string.Empty),
|
||||
Read("PUBLIC_SITE_ADDRESS", string.Empty),
|
||||
Read("PUBLIC_SITE_EMAIL", string.Empty)),
|
||||
new PublicSiteCopy(
|
||||
Read("PUBLIC_SITE_HERO_EYEBROW", "EXAMINATION SERVICE"),
|
||||
Read("PUBLIC_SITE_HERO_TITLE", "一个报名号,"),
|
||||
Read("PUBLIC_SITE_HERO_HIGHLIGHT", "贯穿每一次考试。"),
|
||||
Read("PUBLIC_SITE_HERO_DESCRIPTION", "使用学校下发的报名号登录,完成密码更新和个人信息核验后,即可办理所有考试事项。"),
|
||||
Read("PUBLIC_SITE_FOOTER_NOTICE", string.Empty)));
|
||||
}
|
||||
|
||||
public PublicSiteBranding Branding { get; }
|
||||
|
||||
private static string Read(string name, string fallback) =>
|
||||
Environment.GetEnvironmentVariable(name) ?? fallback;
|
||||
}
|
||||
@@ -1,8 +1,15 @@
|
||||
using System.Net;
|
||||
using Eis.Application.Public;
|
||||
using Eis.Infrastructure;
|
||||
using Eis.Infrastructure.Data;
|
||||
using Eis.Infrastructure.Migration;
|
||||
using Eis.Web.Configuration;
|
||||
using Eis.Web.Frontend;
|
||||
using Eis.Web.Legacy;
|
||||
using Eis.Web.Public;
|
||||
|
||||
var applicationRoot = ApplicationPaths.FindApplicationRoot();
|
||||
EnvironmentFile.Load(applicationRoot);
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.WebHost.ConfigureKestrel(options => options.AddServerHeader = false);
|
||||
@@ -20,6 +27,8 @@ builder.Services.AddHttpClient<LegacyApiProxy>((services, client) =>
|
||||
UseCookies = false
|
||||
});
|
||||
builder.Services.AddProblemDetails();
|
||||
builder.Services.AddSingleton<IPublicSiteConfiguration, PublicSiteConfiguration>();
|
||||
builder.Services.AddEisInfrastructure(DatabaseOptions.FromEnvironment(applicationRoot, builder.Environment.IsProduction()));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@@ -51,6 +60,8 @@ app.MapGet("/health/migration", async (LegacyApiProxy proxy, CancellationToken c
|
||||
}, statusCode: statusCode);
|
||||
});
|
||||
|
||||
app.MapNativePublicEndpoints();
|
||||
|
||||
string[] methods =
|
||||
[
|
||||
HttpMethods.Get,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using Eis.Application.Public;
|
||||
|
||||
namespace Eis.Web.Public;
|
||||
|
||||
public static class PublicEndpoints
|
||||
{
|
||||
public static IEndpointRouteBuilder MapNativePublicEndpoints(this IEndpointRouteBuilder endpoints)
|
||||
{
|
||||
endpoints.MapGet("/api/public/home", async (
|
||||
HttpContext context,
|
||||
IPublicQueryService queries,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
context.Response.Headers["X-EIS-Implementation"] = "aspnet-core";
|
||||
return Results.Json(await queries.GetHomeAsync(cancellationToken));
|
||||
});
|
||||
|
||||
endpoints.MapGet("/api/public/notices/{id}", async (
|
||||
string id,
|
||||
HttpContext context,
|
||||
IPublicQueryService queries,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
context.Response.Headers["X-EIS-Implementation"] = "aspnet-core";
|
||||
var notice = await queries.GetNoticeAsync(id, cancellationToken);
|
||||
return notice is null
|
||||
? Results.Json(new { ok = false, message = "通知不存在或尚未发布" }, statusCode: StatusCodes.Status404NotFound)
|
||||
: Results.Json(new { ok = true, notice });
|
||||
});
|
||||
|
||||
return endpoints;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user