云库增加 AI识图,缓存,我的云库收藏增加安全标志
调用外部API 扣费
This commit is contained in:
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));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user