using System.Security.Cryptography; using MySqlConnector; namespace Rmsys.Infrastructure; /// /// 系统配置读写(直连 MySQL,不依赖 EF)。 /// 为什么不用 EF:JWT 签名密钥必须在 AddAuthentication 之前就拿到, /// 那时 DI 容器还没建好,只能用原始连接读。 /// 表不存在或库连不上时返回 null,由调用方回退到配置文件 —— 不让启动直接崩。 /// public static class SysConfigStore { public static string? Get(string connStr, string key) { try { using var c = new MySqlConnection(connStr); c.Open(); using var cmd = c.CreateCommand(); cmd.CommandText = "select ConfigValue from sysconfigs where ConfigKey=@k limit 1"; cmd.Parameters.AddWithValue("@k", key); var v = cmd.ExecuteScalar(); return v == null || v is DBNull ? null : Convert.ToString(v); } catch { return null; // 表未建 / 库不可达 → 回退 } } public static bool Set(string connStr, string key, string value, string remark, string? by = null) { try { using var c = new MySqlConnection(connStr); c.Open(); using var cmd = c.CreateCommand(); cmd.CommandText = @" insert into sysconfigs(ConfigKey,ConfigValue,Remark,IsSecret,UpdatedAt,UpdatedBy) values(@k,@v,@r,1,@t,@by) on duplicate key update ConfigValue=@v, Remark=@r, UpdatedAt=@t, UpdatedBy=@by"; cmd.Parameters.AddWithValue("@k", key); cmd.Parameters.AddWithValue("@v", value); cmd.Parameters.AddWithValue("@r", remark); cmd.Parameters.AddWithValue("@t", DateTime.Now); cmd.Parameters.AddWithValue("@by", (object?)by ?? DBNull.Value); return cmd.ExecuteNonQuery() > 0; } catch { return false; } } /// 存在就取,不存在就生成并写入;库不可用时返回 null public static string? GetOrCreate(string connStr, string key, Func factory, string remark) { var v = Get(connStr, key); if (!string.IsNullOrWhiteSpace(v)) return v; var created = factory(); return Set(connStr, key, created, remark) ? created : null; } /// 生成 48 字节随机密钥(base64 后 64 字符,够 HMAC-SHA256 用) public static string NewSecret() => Convert.ToBase64String(RandomNumberGenerator.GetBytes(48)); }