mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-09-05 23:57:19 +08:00
feat: implement database initialization and admin user setup
This commit is contained in:
@@ -101,7 +101,7 @@ public class AuthController(IUserService userService, IConfigService configServi
|
|||||||
public IActionResult GitHubLogin()
|
public IActionResult GitHubLogin()
|
||||||
{
|
{
|
||||||
string githubClientId = configService["Authentication:GitHubClientId"];
|
string githubClientId = configService["Authentication:GitHubClientId"];
|
||||||
string githubCallback = configService["Authentication:GitHubRedirectUri"];
|
string githubCallback = configService["Authentication:GitHubCallbackUrl"];
|
||||||
string githubAuthorizeUrl =
|
string githubAuthorizeUrl =
|
||||||
$"https://github.com/login/oauth/authorize?client_id={Uri.EscapeDataString(githubClientId)}&redirect_uri={Uri.EscapeDataString(githubCallback)}";
|
$"https://github.com/login/oauth/authorize?client_id={Uri.EscapeDataString(githubClientId)}&redirect_uri={Uri.EscapeDataString(githubCallback)}";
|
||||||
return Redirect(githubAuthorizeUrl);
|
return Redirect(githubAuthorizeUrl);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ RUN dotnet publish "./Foxel.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:U
|
|||||||
|
|
||||||
FROM base AS final
|
FROM base AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
# Format: Host=yourhost;Username=foxel;Password=foxel;Database=foxel
|
||||||
ENV DEFAULT_CONNECTION="YourDefaultConnectionStringHere"
|
ENV DEFAULT_CONNECTION="YourDefaultConnectionStringHere"
|
||||||
COPY --from=publish /app/publish .
|
COPY --from=publish /app/publish .
|
||||||
RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/*
|
||||||
|
|||||||
@@ -52,8 +52,22 @@
|
|||||||
|
|
||||||
打开浏览器访问您的域名或者IP 即可使用 Foxel。
|
打开浏览器访问您的域名或者IP 即可使用 Foxel。
|
||||||
|
|
||||||
> 如需自定义数据库等配置,可通过修改 `Dockerfile` 或挂载配置文件实现。
|
4. **获取管理员账号信息**
|
||||||
|
|
||||||
|
容器启动后,可通过以下命令查看日志,获取管理员邮箱和初始密码:
|
||||||
|
```bash
|
||||||
|
docker logs foxel
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ **注意:**
|
||||||
|
> Foxel 依赖 PostgreSQL 数据库,并需要在数据库中启用 [vector 扩展](https://github.com/pgvector/pgvector)。
|
||||||
|
> 请确保您的 PostgreSQL 实例已正确安装并启用 `vector` 扩展,否则图像检索功能无法正常使用。
|
||||||
|
> 可通过如下命令在数据库中启用扩展:
|
||||||
|
> ```sql
|
||||||
|
> CREATE EXTENSION IF NOT EXISTS vector;
|
||||||
|
> ```
|
||||||
|
|
||||||
|
> 如需自定义数据库等配置,可通过修改 `Dockerfile` 或挂载配置文件实现。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Foxel.Models.DataBase;
|
using Foxel.Models.DataBase;
|
||||||
using Foxel.Services.Interface;
|
using Foxel.Services.Interface;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Foxel.Services;
|
namespace Foxel.Services;
|
||||||
|
|
||||||
@@ -10,16 +12,28 @@ public class DatabaseInitializer(
|
|||||||
ILogger<DatabaseInitializer> logger)
|
ILogger<DatabaseInitializer> logger)
|
||||||
: IDatabaseInitializer
|
: IDatabaseInitializer
|
||||||
{
|
{
|
||||||
|
private const string InitializationFlag = "System:InitializationCompleted";
|
||||||
|
|
||||||
public async Task InitializeAsync()
|
public async Task InitializeAsync()
|
||||||
{
|
{
|
||||||
|
logger.LogInformation("开始检查数据库初始化状态...");
|
||||||
|
|
||||||
|
// 检查是否已经完成初始化
|
||||||
|
if (await configService.ExistsAsync(InitializationFlag) &&
|
||||||
|
configService[InitializationFlag] == "true")
|
||||||
|
{
|
||||||
|
logger.LogInformation("数据库已完成初始化,跳过初始化步骤");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
logger.LogInformation("开始初始化数据库配置...");
|
logger.LogInformation("开始初始化数据库配置...");
|
||||||
|
|
||||||
using var context = await contextFactory.CreateDbContextAsync();
|
await using var context = await contextFactory.CreateDbContextAsync();
|
||||||
|
|
||||||
// 确保数据库已创建
|
// 确保数据库已创建
|
||||||
await context.Database.EnsureCreatedAsync();
|
await context.Database.EnsureCreatedAsync();
|
||||||
|
|
||||||
// 初始化JWT配置 -
|
// 初始化JWT配置
|
||||||
await EnsureConfigExistsAsync("Jwt:SecretKey", "ChAtPiCdEfAuLtSeCrEtKeY2023_Extended_Secure_Key");
|
await EnsureConfigExistsAsync("Jwt:SecretKey", "ChAtPiCdEfAuLtSeCrEtKeY2023_Extended_Secure_Key");
|
||||||
await EnsureConfigExistsAsync("Jwt:Issuer", "Foxel");
|
await EnsureConfigExistsAsync("Jwt:Issuer", "Foxel");
|
||||||
await EnsureConfigExistsAsync("Jwt:Audience", "FoxelUsers");
|
await EnsureConfigExistsAsync("Jwt:Audience", "FoxelUsers");
|
||||||
@@ -27,6 +41,24 @@ public class DatabaseInitializer(
|
|||||||
// 初始化GitHub认证配置
|
// 初始化GitHub认证配置
|
||||||
await EnsureConfigExistsAsync("Authentication:GitHubClientId", "placeholder_replace_with_actual_github_client_id");
|
await EnsureConfigExistsAsync("Authentication:GitHubClientId", "placeholder_replace_with_actual_github_client_id");
|
||||||
await EnsureConfigExistsAsync("Authentication:GitHubClientSecret", "placeholder_replace_with_actual_github_client_secret");
|
await EnsureConfigExistsAsync("Authentication:GitHubClientSecret", "placeholder_replace_with_actual_github_client_secret");
|
||||||
|
await EnsureConfigExistsAsync("Authentication:GitHubClientSecret", "");
|
||||||
|
// 初始化AI相关配置
|
||||||
|
await EnsureConfigExistsAsync("AI:ApiEndpoint", "");
|
||||||
|
await EnsureConfigExistsAsync("AI:ApiKey", "");
|
||||||
|
await EnsureConfigExistsAsync("AI:Model", "");
|
||||||
|
await EnsureConfigExistsAsync("AI:EmbeddingModel", "");
|
||||||
|
// 初始化存储配置
|
||||||
|
await EnsureConfigExistsAsync("Storage:TelegramStorageBotToken", "");
|
||||||
|
await EnsureConfigExistsAsync("Storage:TelegramStorageChatId", "");
|
||||||
|
await EnsureConfigExistsAsync("Storage:DefaultStorage", "Local");
|
||||||
|
// 初始化其他配置
|
||||||
|
await EnsureConfigExistsAsync("AppSettings:ServerUrl", "");
|
||||||
|
|
||||||
|
// 初始化管理员角色和用户
|
||||||
|
await InitializeAdminRoleAndUserAsync();
|
||||||
|
|
||||||
|
// 标记初始化已完成
|
||||||
|
await configService.SetConfigAsync(InitializationFlag, "true", "系统初始化完成标志");
|
||||||
|
|
||||||
logger.LogInformation("数据库配置初始化完成");
|
logger.LogInformation("数据库配置初始化完成");
|
||||||
}
|
}
|
||||||
@@ -39,4 +71,73 @@ public class DatabaseInitializer(
|
|||||||
await configService.SetConfigAsync(key, value, $"自动创建的{key}配置");
|
await configService.SetConfigAsync(key, value, $"自动创建的{key}配置");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task InitializeAdminRoleAndUserAsync()
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync();
|
||||||
|
|
||||||
|
// 检查并创建管理员角色
|
||||||
|
var adminRole = await context.Roles.FirstOrDefaultAsync(r => r.Name == "Administrator");
|
||||||
|
if (adminRole == null)
|
||||||
|
{
|
||||||
|
logger.LogInformation("创建管理员角色");
|
||||||
|
adminRole = new Role
|
||||||
|
{
|
||||||
|
Name = "Administrator",
|
||||||
|
Description = "系统管理员角色",
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
UpdatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
await context.Roles.AddAsync(adminRole);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查并创建管理员用户
|
||||||
|
var adminUser = await context.Users.FirstOrDefaultAsync(u => u.UserName == "Admin");
|
||||||
|
if (adminUser == null)
|
||||||
|
{
|
||||||
|
// 生成随机6位密码
|
||||||
|
string password = GenerateRandomPassword(6);
|
||||||
|
string passwordHash = HashPassword(password);
|
||||||
|
|
||||||
|
logger.LogInformation("创建管理员用户,用户名: Admin,密码: {Password}", password);
|
||||||
|
adminUser = new User
|
||||||
|
{
|
||||||
|
UserName = "Admin",
|
||||||
|
Email = "you@foxel.cc",
|
||||||
|
PasswordHash = passwordHash,
|
||||||
|
RoleId = adminRole.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
UpdatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
await context.Users.AddAsync(adminUser);
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine($"[重要] 管理员账户初始密码: {password},请及时修改");
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateRandomPassword(int length)
|
||||||
|
{
|
||||||
|
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
var random = new Random();
|
||||||
|
var password = new StringBuilder(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
password.Append(chars[random.Next(chars.Length)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return password.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string HashPassword(string password)
|
||||||
|
{
|
||||||
|
using var sha256 = SHA256.Create();
|
||||||
|
var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
|
||||||
|
return Convert.ToBase64String(hashedBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user