云库增加 AI识图,缓存,我的云库收藏增加安全标志

调用外部API 扣费
This commit is contained in:
chfei committed 2026-11-06 19:25:36 +08:00
1 parent 7c29e57623
commit 150e8644b7
49 files changed
+1069 -28

No files matched your search

@@ -260,6 +260,10 @@ namespace MAX.Framework.DependencyInjection
provider.GetRequiredService<PluginRuntime>();
return context;
});
var typedContext = typeof(PluginContext<>).MakeGenericType(plugin.GetType());
host.Services.AddSingleton(typedContext, provider =>
// 复用键名注册,确保仅解析泛型上下文时也由容器管理配置的释放。
Activator.CreateInstance(typedContext, provider.GetRequiredKeyedService<PluginContext>(plugin.Id))!);
RunDebugStep("Plugin", $"注册 {plugin.Id} ({plugin.GetType().FullName}),Priority={plugin.Priority}",
() => plugin.ConfigureServices(host.Services, context));
}
+1
View File
@@ -15,6 +15,7 @@
设备数为 0 时无限制,为 1 时单点登录,为 N 时保留最多 N 个有效会话,超限撤销最早的会话。
签发在事务中锁定现有用户行,使多实例的并发登录也遵守数量限制。MySQL 业务用户表需使用 InnoDB。
退出当前会话、修改密码后的全部会话撤销以及设备替换统一更新 Revoked 并清除当前实例缓存。
宿主注册 Hangfire 任务 `token-cleanup`,每天北京时间 03:00(UTC 19:00)删除已撤销、闲置到期或达到绝对期限的记录;可在 `/hangfire` 查看执行结果。任务执行需要宿主运行。
多实例下其他实例最多延迟 CacheSeconds 秒获知撤销;要求每次查库时设置 CacheSeconds=0。
用户信息在缓存未命中时从实际 `wxxd.user` 表读取 id/user_name/nick_name;当前用户表没有 IsEnabled 或 Role 字段,因此未假设这些字段或新增角色策略。
@@ -131,6 +131,20 @@ public sealed class TokenService(IFreeSql db, IOptions<TokenAuthOptions> options
}
}
/// <summary>清理已撤销或已到期的会话,返回删除数量,供每日后台任务调用。</summary>
public int CleanupExpiredTokens()
{
lock (Gate)
{
var now = Now;
var cutoff = now.AddDays(-settings.AbsoluteMaxDays);
// 与认证的到期边界一致;直接条件删除,避免先查询再删除时误删已续期的会话。
return db.Delete<UserToken>()
.Where(t => t.Revoked || t.ExpiresAt <= now || t.CreatedAt <= cutoff)
.ExecuteAffrows();
}
}
internal void Revoke(string userName, string? sessionId = null)
{
lock (Gate)
+17
View File
@@ -37,3 +37,20 @@ public sealed class PluginContext : IDisposable
(Configuration as IDisposable)?.Dispose();
}
}
/// <summary>按插件类型注入的上下文视图,配置及其生命周期由宿主的 PluginContext 统一管理。</summary>
public sealed class PluginContext<TPlugin>(PluginContext context) where TPlugin : IPlugin
{
/// <summary>插件唯一标识。</summary>
public string Id => context.Id;
/// <summary>插件程序集和配置所在目录。</summary>
public string DirectoryPath => context.DirectoryPath;
/// <summary>当前宿主环境。</summary>
public IHostEnvironment Environment => context.Environment;
/// <summary>与插件入口共享的独立配置实例。</summary>
public IConfigurationRoot Configuration => context.Configuration;
/// <summary>读取必填配置,缺失时沿用插件上下文的错误说明。</summary>
public string RequireConfiguration(string key) => context.RequireConfiguration(key);
}