diff --git a/Bootstrap.Admin/Bootstrap.Admin.csproj b/Bootstrap.Admin/Bootstrap.Admin.csproj index 58ccde44..28aa4d1f 100644 --- a/Bootstrap.Admin/Bootstrap.Admin.csproj +++ b/Bootstrap.Admin/Bootstrap.Admin.csproj @@ -12,7 +12,7 @@ - + diff --git a/Bootstrap.Admin/appsettings.json b/Bootstrap.Admin/appsettings.json index e35f4879..1a3979c6 100644 --- a/Bootstrap.Admin/appsettings.json +++ b/Bootstrap.Admin/appsettings.json @@ -15,7 +15,6 @@ "ConnectionStrings": { "ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa" }, - "MongoDB": "BootstrapAdmin", "DB": [ { "Enabled": false @@ -28,25 +27,25 @@ } }, { - "Enabled": true, + "Enabled": false, "ProviderName": "MySql", "ConnectionStrings": { "ba": "Server=localhost;Database=BA;Uid=argozhang;Pwd=argo@163.com;SslMode=none;" } }, { - "Enabled": true, + "Enabled": false, "ProviderName": "Npgsql", "ConnectionStrings": { "ba": "Server=localhost;Database=BootstrapAdmin;User ID=argozhang;Password=argo@163.com;" } }, { - "Enabled": true, + "Enabled": false, "Widget": "Bootstrap.DataAccess.MongoDB", "ProviderName": "MongoDB", "ConnectionStrings": { - "ba": "mongodb://localhost:27017" + "ba": "mongodb://localhost:27017;Database=BootstrapAdmin" } } ], @@ -244,4 +243,4 @@ } ] } -} +} \ No newline at end of file diff --git a/Bootstrap.Client.DataAccess.MongoDB/App.cs b/Bootstrap.Client.DataAccess.MongoDB/App.cs new file mode 100644 index 00000000..1d2d9075 --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/App.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + /// + /// + /// + public class App : DataAccess.App + { + /// + /// 根据指定用户名获得授权应用程序集合 + /// + /// + /// + public override IEnumerable RetrievesByUserName(string userName) + { + var ret = new List(); + var roles = RoleHelper.RetrievesByUserName(userName); + if (roles.Contains("Administrators", StringComparer.OrdinalIgnoreCase)) + { + ret.AddRange(DictHelper.RetrieveApps().Select(kv => kv.Key)); + } + else + { + RoleHelper.Retrieves().Cast().Where(r => roles.Any(rn => rn == r.RoleName)).ToList().ForEach(r => ret.AddRange(r.Apps)); + } + return ret; + } + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Bootstrap.Client.DataAccess.MongoDB.csproj b/Bootstrap.Client.DataAccess.MongoDB/Bootstrap.Client.DataAccess.MongoDB.csproj new file mode 100644 index 00000000..334ed7ec --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Bootstrap.Client.DataAccess.MongoDB.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/Bootstrap.Client.DataAccess.MongoDB/DbManager.cs b/Bootstrap.Client.DataAccess.MongoDB/DbManager.cs new file mode 100644 index 00000000..70d0414a --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/DbManager.cs @@ -0,0 +1,171 @@ +using Bootstrap.Security; +using Longbow.Configuration; +using Microsoft.Extensions.Primitives; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; +using MongoDB.Driver; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + /// + /// 数据库操作类 + /// + internal static class DbManager + { + private static IMongoDatabase _db = null; + private static bool _register = false; + private static readonly object _locker = new object(); + + /// + /// + /// + private static IMongoDatabase BADatabase + { + get + { + if (_db == null) + { + lock (_locker) + { + if (!_register) + { + _register = true; + ChangeToken.OnChange(() => ConfigurationManager.AppSettings.GetReloadToken(), () => _db = null); + InitClassMap(); + } + if (_db == null) + InitDb("ba"); + } + } + return _db; + } + } + + #region Collections + /// + /// Dicts 集合 + /// + public static IMongoCollection Dicts + { + get + { + return BADatabase.GetCollection("Dicts"); + } + } + + /// + /// Users 集合 + /// + public static IMongoCollection Users + { + get + { + return BADatabase.GetCollection("Users"); + } + } + + /// + /// Roles 集合 + /// + public static IMongoCollection Roles + { + get + { + return BADatabase.GetCollection("Roles"); + } + } + + /// + /// Groups 集合 + /// + public static IMongoCollection Groups + { + get + { + return BADatabase.GetCollection("Groups"); + } + } + + /// + /// Menus 集合 + /// + public static IMongoCollection Menus + { + get + { + return BADatabase.GetCollection("Navigations"); + } + } + #endregion + + private static void InitDb(string name = null) + { + var (connectString, databaseName) = Longbow.Data.DbManager.GetMongoDB(name); + var client = new MongoClient(connectString); + _db = client.GetDatabase(databaseName); + } + + private static void InitClassMap() + { + BsonSerializer.RegisterSerializer(DateTimeSerializer.LocalInstance); + + if (!BsonClassMap.IsClassMapRegistered(typeof(BootstrapDict))) + { + BsonClassMap.RegisterClassMap(md => + { + md.AutoMap(); + md.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId)); + md.IdMemberMap.SetIgnoreIfDefault(true); + }); + } + if (!BsonClassMap.IsClassMapRegistered(typeof(User))) + { + BsonClassMap.RegisterClassMap(md => + { + md.AutoMap(); + md.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId)); + md.IdMemberMap.SetIgnoreIfDefault(true); + }); + } + if (!BsonClassMap.IsClassMapRegistered(typeof(BootstrapMenu))) + { + BsonClassMap.RegisterClassMap(md => + { + md.AutoMap(); + md.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId)); + md.IdMemberMap.SetIgnoreIfDefault(true); + md.UnmapMember(m => m.CategoryName); + md.UnmapMember(m => m.Active); + md.UnmapMember(m => m.ParentName); + md.UnmapMember(m => m.Menus); + }); + } + if (!BsonClassMap.IsClassMapRegistered(typeof(BootstrapGroup))) + { + BsonClassMap.RegisterClassMap(md => + { + md.AutoMap(); + md.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId)); + md.IdMemberMap.SetIgnoreIfDefault(true); + }); + } + if (!BsonClassMap.IsClassMapRegistered(typeof(Group))) + { + BsonClassMap.RegisterClassMap(md => + { + md.AutoMap(); + }); + } + if (!BsonClassMap.IsClassMapRegistered(typeof(Role))) + { + BsonClassMap.RegisterClassMap(md => + { + md.AutoMap(); + md.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId)); + md.IdMemberMap.SetIgnoreIfDefault(true); + }); + } + } + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Dict.cs b/Bootstrap.Client.DataAccess.MongoDB/Dict.cs new file mode 100644 index 00000000..31a62315 --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Dict.cs @@ -0,0 +1,45 @@ +using Bootstrap.Security; +using Longbow.Configuration; +using MongoDB.Driver; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + /// + /// + /// + public class Dict : DataAccess.Dict + { + /// + /// + /// + /// + public override IEnumerable RetrieveDicts() => DbManager.Dicts.Find(FilterDefinition.Empty).ToList(); + + private static string RetrieveAppName(string name, string defaultValue = "未设置") + { + var dicts = DictHelper.RetrieveDicts(); + var platName = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == ConfigurationManager.AppSettings["AppId"])?.Name; + return dicts.FirstOrDefault(d => d.Category == platName && d.Name == name)?.Code ?? $"{name}{defaultValue}"; + } + + /// + /// 获得系统设置地址 + /// + /// + public override string RetrieveSettingsUrl() => RetrieveAppName("系统设置地址"); + + /// + /// 获得系统个人中心地址 + /// + /// + public override string RetrieveProfilesUrl() => RetrieveAppName("个人中心地址"); + + /// + /// 获得系统通知地址地址 + /// + /// + public override string RetrieveNotisUrl() => RetrieveAppName("系统通知地址"); + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Group.cs b/Bootstrap.Client.DataAccess.MongoDB/Group.cs new file mode 100644 index 00000000..cc0b1da9 --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Group.cs @@ -0,0 +1,28 @@ +using Bootstrap.Security; +using MongoDB.Driver; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + class Group : BootstrapGroup + { + /// + /// 获得/设置 群组描述 + /// + public string Description { get; set; } + + /// + /// + /// + public IEnumerable Roles { get; set; } + + /// + /// + /// + /// + public IEnumerable Retrieves() + { + return DbManager.Groups.Find(FilterDefinition.Empty).ToList(); + } + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Helper/GroupHelper.cs b/Bootstrap.Client.DataAccess.MongoDB/Helper/GroupHelper.cs new file mode 100644 index 00000000..a5ce787a --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Helper/GroupHelper.cs @@ -0,0 +1,24 @@ +using Longbow.Cache; +using MongoDB.Driver; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + class GroupHelper + { + /// + /// + /// + public const string RetrieveGroupsDataKey = "GroupHelper-RetrieveGroups"; + + /// + /// + /// + /// + public static IEnumerable Retrieves() + { + return CacheManager.GetOrAdd(RetrieveGroupsDataKey, key => DbManager.Groups.Find(FilterDefinition.Empty).ToList()); + } + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Helper/RoleHelper.cs b/Bootstrap.Client.DataAccess.MongoDB/Helper/RoleHelper.cs new file mode 100644 index 00000000..978200ff --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Helper/RoleHelper.cs @@ -0,0 +1,39 @@ +using Longbow.Cache; +using MongoDB.Driver; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + class RoleHelper + { + /// + /// + /// + public const string RetrieveRolesDataKey = "RoleHelper-RetrieveRoles"; + + /// + /// 查询所有角色 + /// + /// + public static IEnumerable Retrieves() => CacheManager.GetOrAdd(RetrieveRolesDataKey, key => DbManager.Roles.Find(FilterDefinition.Empty).ToList()); + + /// + /// + /// + /// + /// + public static IEnumerable RetrievesByUserName(string userName) + { + var roles = new List(); + var user = UserHelper.Retrieves().FirstOrDefault(u => u.UserName.ToLowerInvariant() == userName.ToLowerInvariant()); + if (user != null) + { + var role = Retrieves(); + roles.AddRange(role.Where(r => user.Roles.Any(rl => rl == r.Id)).Select(r => r.RoleName)); + if (roles.Count == 0) roles.Add("Default"); + } + return roles; + } + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Helper/UserHelper.cs b/Bootstrap.Client.DataAccess.MongoDB/Helper/UserHelper.cs new file mode 100644 index 00000000..76f4df24 --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Helper/UserHelper.cs @@ -0,0 +1,30 @@ +using Longbow.Cache; +using MongoDB.Driver; +using System; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + class UserHelper + { + /// + /// 获取所有用户缓存数据键值 + /// + public const string RetrieveUsersDataKey = "UserHelper-RetrieveUsers"; + + /// + /// 查询所有用户 + /// + /// + public static IEnumerable Retrieves() => CacheManager.GetOrAdd(RetrieveUsersDataKey, key => + { + var project = Builders.Projection.Include(u => u.Id) + .Include(u => u.UserName) + .Include(u => u.DisplayName) + .Include(u => u.Groups) + .Include(u => u.Roles) + .Include(u => u.ApprovedTime); + return DbManager.Users.Find(user => user.ApprovedTime != DateTime.MinValue).Project(project).ToList(); + }); + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Menu.cs b/Bootstrap.Client.DataAccess.MongoDB/Menu.cs new file mode 100644 index 00000000..1e4a4874 --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Menu.cs @@ -0,0 +1,50 @@ +using Bootstrap.Security; +using MongoDB.Driver; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + /// + /// 菜单实体类 + /// + public class Menu : DataAccess.Menu + { + /// + /// 通过当前用户名获得所有菜单 + /// + /// 当前登录的用户名 + /// + public override IEnumerable RetrieveAllMenus(string userName) + { + var user = UserHelper.Retrieves().Cast().FirstOrDefault(u => u.UserName.ToLowerInvariant() == userName.ToLowerInvariant()); + if (user == null) return Enumerable.Empty(); + + var roles = RoleHelper.Retrieves().Cast(); + var groups = GroupHelper.Retrieves().Cast(); + + // 通过用户获取 组列表相关联的角色列表 + var userRoles = user.Groups.Aggregate(user.Roles.ToList(), (r, g) => + { + var groupRoles = groups.Where(group => group.Id == g).FirstOrDefault()?.Roles; + if (groupRoles != null) r.AddRange(groupRoles); + return r; + }).Distinct().ToList(); + + var allRoles = roles.Where(r => userRoles.Any(rl => rl == r.Id)).ToList(); + var menus = DbManager.Menus.Find(FilterDefinition.Empty).ToList() + .Where(m => allRoles.Any(r => r.RoleName.Equals("Administrators", StringComparison.OrdinalIgnoreCase) || r.Menus.Any(rm => rm.Equals(m.Id, StringComparison.OrdinalIgnoreCase)))) + .ToList(); + + var dicts = DictHelper.RetrieveDicts().Where(m => m.Category == "菜单"); + menus.ForEach(m => + { + m.CategoryName = dicts.FirstOrDefault(d => d.Code == m.Category)?.Name; + if (m.ParentId != "0") m.ParentName = menus.FirstOrDefault(p => p.Id == m.ParentId)?.Name; + }); + + return menus; + } + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/Role.cs b/Bootstrap.Client.DataAccess.MongoDB/Role.cs new file mode 100644 index 00000000..cbe02dad --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Role.cs @@ -0,0 +1,69 @@ +using MongoDB.Driver; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + /// + /// + /// + public class Role : DataAccess.Role + { + /// + /// 此角色关联的所有菜单 + /// + public IEnumerable Menus { get; set; } + + /// + /// 此角色关联的所有应用程序 + /// + public IEnumerable Apps { get; set; } + + /// + /// 获得/设置 角色主键ID + /// + public string Id { get; set; } + + /// + /// 获得/设置 角色名称 + /// + public string RoleName { get; set; } + + /// + /// 获得/设置 角色描述 + /// + public string Description { get; set; } + + /// + /// + /// + /// + /// + public override IEnumerable RetrievesByUserName(string userName) + { + var roles = new List(); + var user = UserHelper.Retrieves().Cast().FirstOrDefault(u => u.UserName.ToLowerInvariant() == userName.ToLowerInvariant()); + if (user != null) + { + var role = RoleHelper.Retrieves(); + roles.AddRange(role.Where(r => user.Roles.Any(rl => rl == r.Id)).Select(r => r.RoleName)); + if (roles.Count == 0) roles.Add("Default"); + } + return roles; + } + + /// + /// 根据菜单url查询某个所拥有的角色 + /// 从NavigatorRole表查 + /// 从Navigators -> GroupNavigatorRole -> Role查查询某个用户所拥有的角色 + /// + /// + public override IEnumerable RetrievesByUrl(string url) + { + var menu = DbManager.Menus.Find(md => md.Url.StartsWith(url)).FirstOrDefault(); + var ret = RoleHelper.Retrieves().Cast().Where(md => md.Menus != null && md.Menus.Contains(menu.Id)).Select(m => m.RoleName).ToList(); + if (!ret.Contains("Administrators")) ret.Add("Administrators"); + return ret; + } + } +} diff --git a/Bootstrap.Client.DataAccess.MongoDB/User.cs b/Bootstrap.Client.DataAccess.MongoDB/User.cs new file mode 100644 index 00000000..cd0d1f5b --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/User.cs @@ -0,0 +1,55 @@ +using Bootstrap.Security; +using MongoDB.Driver; +using System; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + /// + /// 用户表实体类 + /// + public class User : DataAccess.User + { + /// + /// 获得/设置 用户主键ID + /// + public string Id { get; set; } + + /// + /// 获得/设置 用户被批复时间 + /// + public DateTime? ApprovedTime { get; set; } + + /// + /// + /// + public IEnumerable Roles { get; set; } + + /// + /// + /// + public IEnumerable Groups { get; set; } + + /// + /// + /// + /// + /// + public override BootstrapUser RetrieveUserByUserName(string userName) + { + var project = Builders.Projection.Include(u => u.Id) + .Include(u => u.UserName) + .Include(u => u.DisplayName) + .Include(u => u.Icon) + .Include(u => u.Css) + .Include(u => u.App); + var ret = DbManager.Users.Find(user => user.UserName.ToLowerInvariant() == userName.ToLowerInvariant()).Project(project).FirstOrDefault(); + if (ret != null) + { + if (string.IsNullOrEmpty(ret.Icon)) ret.Icon = "default.jpg"; + if (string.IsNullOrEmpty(ret.App)) ret.App = "0"; + } + return ret; + } + } +} diff --git a/Bootstrap.Client.DataAccess/App.cs b/Bootstrap.Client.DataAccess/App.cs new file mode 100644 index 00000000..f404aaed --- /dev/null +++ b/Bootstrap.Client.DataAccess/App.cs @@ -0,0 +1,18 @@ +using Bootstrap.Security.DataAccess; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// + /// + public class App + { + /// + /// 根据指定用户名获得授权应用程序集合 + /// + /// + /// + public virtual IEnumerable RetrievesByUserName(string userName) => DbHelper.RetrieveAppsByUserName(userName); + } +} diff --git a/Bootstrap.Client.DataAccess/Bootstrap.Client.DataAccess.csproj b/Bootstrap.Client.DataAccess/Bootstrap.Client.DataAccess.csproj new file mode 100644 index 00000000..612bfef5 --- /dev/null +++ b/Bootstrap.Client.DataAccess/Bootstrap.Client.DataAccess.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.0 + + + + + + + + + diff --git a/Bootstrap.Client.DataAccess/DbManager.cs b/Bootstrap.Client.DataAccess/DbManager.cs new file mode 100644 index 00000000..d05f747f --- /dev/null +++ b/Bootstrap.Client.DataAccess/DbManager.cs @@ -0,0 +1,25 @@ +using PetaPoco; +using System; +using System.Collections.Specialized; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// 数据库连接操作类 + /// + internal static class DbManager + { + /// + /// 创建 IDatabase 实例方法 + /// + /// 配置文件中配置的数据库连接字符串名称 + /// 是否保持连接,默认为 false + /// + public static IDatabase Create(string connectionName = null, bool keepAlive = false) + { + var db = Longbow.Data.DbManager.Create(connectionName, keepAlive); + db.ExceptionThrown += (sender, args) => args.Exception.Log(new NameValueCollection() { ["LastCmd"] = db.LastCommand }); + return db; + } + } +} diff --git a/Bootstrap.Client.DataAccess/Dict.cs b/Bootstrap.Client.DataAccess/Dict.cs new file mode 100644 index 00000000..cb30da6c --- /dev/null +++ b/Bootstrap.Client.DataAccess/Dict.cs @@ -0,0 +1,116 @@ +using Bootstrap.Security; +using Bootstrap.Security.DataAccess; +using Longbow; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// + /// + public class Dict : BootstrapDict + { + /// + /// 获取系统网站标题 + /// + /// + public virtual string RetrieveWebTitle() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站标题" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "后台管理系统" }).Code; + + /// + /// 获取系统网站页脚 + /// + /// + public virtual string RetrieveWebFooter() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站页脚" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "2016 © 通用后台管理系统" }).Code; + + /// + /// 获得网站设置中的当前样式 + /// + /// + public virtual string RetrieveActiveTheme() + { + var theme = DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "使用样式" && d.Category == "当前样式" && d.Define == 0); + return theme == null ? string.Empty : (theme.Code.Equals("site.css", StringComparison.OrdinalIgnoreCase) ? string.Empty : theme.Code); + } + + /// + /// 通过数据库获得所有字典表配置信息,缓存Key=DictHelper-RetrieveDicts + /// + /// + public virtual IEnumerable RetrieveDicts() => DbHelper.RetrieveDicts(); + + /// + /// 获得 IP地理位置 + /// + /// + public string RetrieveLocaleIPSvr() => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "IP地理位置接口" && d.Define == 0)?.Code; + + /// + /// + /// + /// + public string RetrieveLocaleIPSvrCachePeriod() => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "IP请求缓存时长" && d.Define == 0)?.Code; + + /// + /// 获得 项目是否获取登录地点 默认为false + /// + /// 服务提供名称 + /// + public string RetrieveLocaleIPSvrUrl(string ipSvr) => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == ipSvr && d.Define == 0)?.Code; + + /// + /// 获得 是否为演示系统 默认为 false 不是演示系统 + /// + /// + public bool RetrieveSystemModel() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "演示系统" && d.Define == 0)?.Code, "0") == "1"; + + /// + /// 获得 验证码图床地址 + /// + /// + public string RetrieveImagesLibUrl() => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "验证码图床" && d.Define == 0)?.Code ?? "http://images.sdgxgz.com/"; + + /// + /// 获得 数据库标题是否显示 + /// + /// + public bool RetrieveCardTitleStatus() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "网站设置" && d.Name == "卡片标题状态" && d.Define == 0)?.Code ?? "1") == "1"; + + /// + /// 获得 是否显示侧边栏 为真时显示 + /// + /// + public bool RetrieveSidebarStatus() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "网站设置" && d.Name == "侧边栏状态" && d.Define == 0)?.Code ?? "1") == "1"; + + /// + /// + /// + /// + public virtual IEnumerable> RetrieveApps() => DictHelper.RetrieveDicts().Where(d => d.Category == "应用程序" && d.Define == 0).Select(d => new KeyValuePair(d.Code, d.Name)).OrderBy(d => d.Key); + + /// + /// 获取头像路径 + /// + /// + public virtual string RetrieveIconFolderPath() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == 0) ?? new BootstrapDict { Code = "~/images/uploader/" }).Code; + + /// + /// 获得系统设置地址 + /// + /// + public virtual string RetrieveSettingsUrl() => DbHelper.RetrieveSettingsUrl(); + + /// + /// 获得系统个人中心地址 + /// + /// + public virtual string RetrieveProfilesUrl() => DbHelper.RetrieveProfilesUrl(); + + /// + /// 获得系统通知地址地址 + /// + /// + public virtual string RetrieveNotisUrl() => DbHelper.RetrieveNotisUrl(); + } +} diff --git a/Bootstrap.Client.DataAccess/Helper/AppHelper.cs b/Bootstrap.Client.DataAccess/Helper/AppHelper.cs new file mode 100644 index 00000000..afad18ef --- /dev/null +++ b/Bootstrap.Client.DataAccess/Helper/AppHelper.cs @@ -0,0 +1,20 @@ +using Bootstrap.Security.DataAccess; +using Longbow.Cache; +using Longbow.Data; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// + /// + public static class AppHelper + { + /// + /// 根据指定用户名获得授权应用程序集合 + /// + /// + /// + public static IEnumerable RetrievesByUserName(string userName) => CacheManager.GetOrAdd($"{DbHelper.RetrieveAppsByUserNameDataKey}-{userName}", key => DbContextManager.Create().RetrievesByUserName(userName), DbHelper.RetrieveAppsByUserNameDataKey); + } +} diff --git a/Bootstrap.Client.DataAccess/Helper/DictHelper.cs b/Bootstrap.Client.DataAccess/Helper/DictHelper.cs new file mode 100644 index 00000000..1aa2d4a7 --- /dev/null +++ b/Bootstrap.Client.DataAccess/Helper/DictHelper.cs @@ -0,0 +1,119 @@ +using Bootstrap.Security; +using Bootstrap.Security.DataAccess; +using Longbow.Cache; +using Longbow.Data; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// + /// + public static class DictHelper + { + /// + /// + /// + /// + /// 缓存索引,BootstrapAdmin后台清理缓存时使用 + /// + public const string RetrieveDictsDataKey = DbHelper.RetrieveDictsDataKey; + + /// + /// + /// + /// + public static IEnumerable RetrieveDicts() => CacheManager.GetOrAdd(RetrieveDictsDataKey, key => DbContextManager.Create().RetrieveDicts()); + + /// + /// + /// + /// + public static IEnumerable> RetrieveApps() => DbContextManager.Create().RetrieveApps(); + + /// + /// + /// + /// + public static string RetrieveWebTitle() => DbContextManager.Create().RetrieveWebTitle(); + + /// + /// + /// + /// + public static string RetrieveWebFooter() => DbContextManager.Create().RetrieveWebFooter(); + + /// + /// 获得网站设置中的当前样式 + /// + /// + public static string RetrieveActiveTheme() => DbContextManager.Create().RetrieveActiveTheme(); + + /// + /// + /// + /// + public static string RetrieveLocaleIPSvr() => DbContextManager.Create().RetrieveLocaleIPSvr(); + + /// + /// + /// + /// ip地址请求服务名称 + /// + public static string RetrieveLocaleIPSvrUrl(string ipSvr) => DbContextManager.Create().RetrieveLocaleIPSvrUrl(ipSvr); + + /// + /// + /// + /// + public static string RetrieveLocaleIPSvrCachePeriod() => DbContextManager.Create().RetrieveLocaleIPSvrCachePeriod(); + + /// + /// 获得 是否为演示系统 默认为 false 不是演示系统 + /// + /// + public static bool RetrieveSystemModel() => DbContextManager.Create().RetrieveSystemModel(); + + /// + /// 获得验证码图床地址 + /// + /// + public static string RetrieveImagesLibUrl() => DbContextManager.Create().RetrieveImagesLibUrl(); + + /// + /// 获取头像路径 + /// + /// + public static string RetrieveIconFolderPath() => DbContextManager.Create().RetrieveIconFolderPath(); + + /// + /// 获得数据区卡片标题是否显示 + /// + /// + public static bool RetrieveCardTitleStatus() => DbContextManager.Create().RetrieveCardTitleStatus(); + + /// + /// 获得侧边栏状态 未真时显示 + /// + /// + public static bool RetrieveSidebarStatus() => DbContextManager.Create().RetrieveSidebarStatus(); + + /// + /// 获得系统设置地址 + /// + /// + public static string RetrieveSettingsUrl() => DbContextManager.Create().RetrieveSettingsUrl(); + + /// + /// 获得系统个人中心地址 + /// + /// + public static string RetrieveProfilesUrl() => DbContextManager.Create().RetrieveProfilesUrl(); + + /// + /// 获得系统通知地址地址 + /// + /// + public static string RetrieveNotisUrl() => DbContextManager.Create().RetrieveNotisUrl(); + } +} diff --git a/Bootstrap.Client.DataAccess/Helper/MenuHelper.cs b/Bootstrap.Client.DataAccess/Helper/MenuHelper.cs new file mode 100644 index 00000000..4b6460ac --- /dev/null +++ b/Bootstrap.Client.DataAccess/Helper/MenuHelper.cs @@ -0,0 +1,41 @@ +using Bootstrap.Security; +using Bootstrap.Security.DataAccess; +using Longbow.Cache; +using Longbow.Configuration; +using Longbow.Data; +using System.Collections.Generic; +using System.Linq; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// 菜单操作类 + /// + public static class MenuHelper + { + /// + /// 通过当前用户获取所有菜单数据缓存键名称 "BootstrapMenu-RetrieveMenus" + /// + public const string RetrieveMenusAll = DbHelper.RetrieveMenusAll; + + /// + /// 获取指定用户的应用程序菜单 + /// + /// + /// + /// + public static IEnumerable RetrieveAppMenus(string userName, string activeUrl) + { + var appId = ConfigurationManager.GetValue("AppId", ""); + var menus = RetrieveAllMenus(userName).Where(m => m.Category == "1" && m.IsResource == 0 && m.Application == appId); + return DbHelper.CascadeMenus(menus, activeUrl); + } + + /// + /// 通过用户获得所有菜单 + /// + /// + /// + public static IEnumerable RetrieveAllMenus(string userName) => CacheManager.GetOrAdd($"{RetrieveMenusAll}-{userName}", key => DbContextManager.Create().RetrieveAllMenus(userName), RetrieveMenusAll); + } +} diff --git a/Bootstrap.Client.DataAccess/Helper/RoleHelper.cs b/Bootstrap.Client.DataAccess/Helper/RoleHelper.cs new file mode 100644 index 00000000..dda5bceb --- /dev/null +++ b/Bootstrap.Client.DataAccess/Helper/RoleHelper.cs @@ -0,0 +1,27 @@ +using Bootstrap.Security.DataAccess; +using Longbow.Cache; +using Longbow.Data; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// + /// + public static class RoleHelper + { + /// + /// + /// + /// + /// + public static IEnumerable RetrievesByUserName(string userName) => CacheManager.GetOrAdd(string.Format("{0}-{1}", DbHelper.RetrieveRolesByUserNameDataKey, userName), key => DbContextManager.Create().RetrievesByUserName(userName), DbHelper.RetrieveRolesByUserNameDataKey); + + /// + /// + /// + /// + /// + public static IEnumerable RetrievesByUrl(string url) => CacheManager.GetOrAdd(string.Format("{0}-{1}", DbHelper.RetrieveRolesByUrlDataKey, url), key => DbContextManager.Create().RetrievesByUrl(url), DbHelper.RetrieveRolesByUrlDataKey); + } +} diff --git a/Bootstrap.Client.DataAccess/Helper/UserHelper.cs b/Bootstrap.Client.DataAccess/Helper/UserHelper.cs new file mode 100644 index 00000000..0fc42939 --- /dev/null +++ b/Bootstrap.Client.DataAccess/Helper/UserHelper.cs @@ -0,0 +1,20 @@ +using Bootstrap.Security; +using Bootstrap.Security.DataAccess; +using Longbow.Cache; +using Longbow.Data; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// 用户表相关操作类 + /// + public static class UserHelper + { + /// + /// 通过登录名获取登录用户方法 + /// + /// + /// + public static BootstrapUser RetrieveUserByUserName(string userName) => CacheManager.GetOrAdd(string.Format("{0}-{1}", DbHelper.RetrieveUsersByNameDataKey, userName), k => DbContextManager.Create().RetrieveUserByUserName(userName), DbHelper.RetrieveUsersByNameDataKey); + } +} diff --git a/Bootstrap.Client.DataAccess/Menu.cs b/Bootstrap.Client.DataAccess/Menu.cs new file mode 100644 index 00000000..4290212a --- /dev/null +++ b/Bootstrap.Client.DataAccess/Menu.cs @@ -0,0 +1,19 @@ +using Bootstrap.Security; +using Bootstrap.Security.DataAccess; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// 菜单实体类 + /// + public class Menu : BootstrapMenu + { + /// + /// 通过当前用户名获得所有菜单 + /// + /// 当前登录的用户名 + /// + public virtual IEnumerable RetrieveAllMenus(string userName) => DbHelper.RetrieveAllMenus(userName); + } +} diff --git a/Bootstrap.Client.DataAccess/Role.cs b/Bootstrap.Client.DataAccess/Role.cs new file mode 100644 index 00000000..12639782 --- /dev/null +++ b/Bootstrap.Client.DataAccess/Role.cs @@ -0,0 +1,26 @@ +using Bootstrap.Security.DataAccess; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// + /// + public class Role + { + /// + /// + /// + /// + /// + public virtual IEnumerable RetrievesByUserName(string userName) => DbHelper.RetrieveRolesByUserName(userName); + + /// + /// 根据菜单url查询某个所拥有的角色 + /// 从NavigatorRole表查 + /// 从Navigators -> GroupNavigatorRole -> Role查查询某个用户所拥有的角色 + /// + /// + public virtual IEnumerable RetrievesByUrl(string url) => DbHelper.RetrieveRolesByUrl(url); + } +} diff --git a/Bootstrap.Client.DataAccess/User.cs b/Bootstrap.Client.DataAccess/User.cs new file mode 100644 index 00000000..e684385b --- /dev/null +++ b/Bootstrap.Client.DataAccess/User.cs @@ -0,0 +1,18 @@ +using Bootstrap.Security; +using Bootstrap.Security.DataAccess; + +namespace Bootstrap.Client.DataAccess +{ + /// + /// 用户表实体类 + /// + public class User : BootstrapUser + { + /// + /// + /// + /// + /// + public virtual BootstrapUser RetrieveUserByUserName(string userName) => DbHelper.RetrieveUserByUserName(userName); + } +} diff --git a/Bootstrap.Client/Bootstrap.Client.csproj b/Bootstrap.Client/Bootstrap.Client.csproj index 5cc1f32f..6bd315f0 100644 --- a/Bootstrap.Client/Bootstrap.Client.csproj +++ b/Bootstrap.Client/Bootstrap.Client.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/Bootstrap.Client/Models/HeaderBarModel.cs b/Bootstrap.Client/Models/HeaderBarModel.cs index f6edd291..85540636 100644 --- a/Bootstrap.Client/Models/HeaderBarModel.cs +++ b/Bootstrap.Client/Models/HeaderBarModel.cs @@ -1,4 +1,5 @@ -using Bootstrap.Security.DataAccess; +using Bootstrap.Client.DataAccess; +using Bootstrap.Security.DataAccess; using Longbow.Configuration; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Authentication.Cookies; @@ -18,12 +19,12 @@ namespace Bootstrap.Client.Models /// public HeaderBarModel(IIdentity identity) { - var user = DbHelper.RetrieveUserByUserNameWithCache(identity.Name); + var user = UserHelper.RetrieveUserByUserName(identity.Name); DisplayName = user.DisplayName; UserName = user.UserName; - SettingsUrl = DbHelper.RetrieveSettingsUrl(); - ProfilesUrl = DbHelper.RetrieveProfilesUrl(); - NotisUrl = DbHelper.RetrieveNotisUrl(); + SettingsUrl = DictHelper.RetrieveSettingsUrl(); + ProfilesUrl = DictHelper.RetrieveProfilesUrl(); + NotisUrl = DictHelper.RetrieveNotisUrl(); // set LogoutUrl var authHost = ConfigurationManager.Get().AuthHost; @@ -32,7 +33,7 @@ namespace Bootstrap.Client.Models LogoutUrl = uriBuilder.ToString(); // set Icon - var icon = $"/{DbHelper.RetrieveIconFolderPath().Trim('~', '/')}/{user.Icon}"; + var icon = $"/{DictHelper.RetrieveIconFolderPath().Trim('~', '/')}/{user.Icon}"; Icon = string.IsNullOrEmpty(ConfigurationManager.GetValue("SimulateUserName", string.Empty)) ? $"{authHost.TrimEnd('/')}{icon}" : "/images/admin.jpg"; if (!string.IsNullOrEmpty(user.Css)) Theme = user.Css; } diff --git a/Bootstrap.Client/Models/ModelBase.cs b/Bootstrap.Client/Models/ModelBase.cs index a628a623..72a8c8c2 100644 --- a/Bootstrap.Client/Models/ModelBase.cs +++ b/Bootstrap.Client/Models/ModelBase.cs @@ -1,4 +1,4 @@ -using Bootstrap.Security.DataAccess; +using Bootstrap.Client.DataAccess; namespace Bootstrap.Client.Models { @@ -12,9 +12,9 @@ namespace Bootstrap.Client.Models /// public ModelBase() { - Title = DbHelper.RetrieveTitle(); - Footer = DbHelper.RetrieveFooter(); - Theme = DbHelper.RetrieveActiveTheme(); + Title = DictHelper.RetrieveWebTitle(); + Footer = DictHelper.RetrieveWebFooter(); + Theme = DictHelper.RetrieveActiveTheme(); } /// diff --git a/Bootstrap.Client/Models/NavigatorBarModel.cs b/Bootstrap.Client/Models/NavigatorBarModel.cs index 3cc0341e..244818d5 100644 --- a/Bootstrap.Client/Models/NavigatorBarModel.cs +++ b/Bootstrap.Client/Models/NavigatorBarModel.cs @@ -1,5 +1,6 @@ -using Bootstrap.Security; -using Bootstrap.Security.DataAccess; +using Bootstrap.Client.DataAccess; +using Bootstrap.Security; +using Longbow.Configuration; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; @@ -16,8 +17,8 @@ namespace Bootstrap.Client.Models /// public NavigatorBarModel(ControllerBase controller) : base(controller.User.Identity) { - Navigations = DbHelper.RetrieveAppCascadeMenus(UserName, $"~/{controller.ControllerContext.ActionDescriptor.ControllerName}/{controller.ControllerContext.ActionDescriptor.ActionName}"); - ImageLibUrl = DbHelper.RetrieveImagesLibUrl(); + Navigations = MenuHelper.RetrieveAppMenus(UserName, $"~/{controller.ControllerContext.ActionDescriptor.ControllerName}/{controller.ControllerContext.ActionDescriptor.ActionName}"); + ImageLibUrl = DictHelper.RetrieveImagesLibUrl(); } /// diff --git a/Bootstrap.Client/Startup.cs b/Bootstrap.Client/Startup.cs index c558aa90..5073f336 100644 --- a/Bootstrap.Client/Startup.cs +++ b/Bootstrap.Client/Startup.cs @@ -1,4 +1,5 @@ -using Longbow.Web; +using Bootstrap.Client.DataAccess; +using Longbow.Web; using Longbow.Web.SignalR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -88,7 +89,7 @@ namespace Bootstrap.Client app.UseResponseCompression(); app.UseStaticFiles(); app.UseCookiePolicy(); - app.UseBootstrapAdminAuthentication(); + app.UseBootstrapAdminAuthentication(RoleHelper.RetrievesByUserName, RoleHelper.RetrievesByUrl, AppHelper.RetrievesByUserName); app.UseCacheManager(); app.UseSignalR(routes => { routes.MapHub("/NotiHub"); }); app.UseMvc(routes => diff --git a/Bootstrap.Client/appsettings.Development.json b/Bootstrap.Client/appsettings.Development.json index d91cc053..9d06767e 100644 --- a/Bootstrap.Client/appsettings.Development.json +++ b/Bootstrap.Client/appsettings.Development.json @@ -16,7 +16,8 @@ } }, "ConnectionStrings": { - "ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa" + "ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa", + "client": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa" }, "DB": [ { @@ -26,7 +27,17 @@ "Enabled": true, "ProviderName": "Sqlite", "ConnectionStrings": { - "ba": "Data Source=..\\Bootstrap.Admin\\BootstrapAdmin.db;" + "ba": "Data Source=..\\Bootstrap.Admin\\BootstrapAdmin.db;", + "client": "Data Source=Client.db;" + } + }, + { + "Enabled": false, + "Widget": "Bootstrap.Client.DataAccess.MongoDB", + "ProviderName": "MongoDB", + "ConnectionStrings": { + "ba": "mongodb://localhost:27017;Database=BootstrapAdmin", + "client": "mongodb://localhost:27017;Database=BootstrapClient" } } ], diff --git a/Bootstrap.Client/appsettings.json b/Bootstrap.Client/appsettings.json index 6738d6ee..b7bd59de 100644 --- a/Bootstrap.Client/appsettings.json +++ b/Bootstrap.Client/appsettings.json @@ -13,8 +13,8 @@ } }, "ConnectionStrings": { - "sql": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa", - "ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa" + "ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa", + "client": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa" }, "DB": [ { @@ -24,7 +24,16 @@ "Enabled": true, "ProviderName": "Sqlite", "ConnectionStrings": { - "ba": "Data Source=..\\BA\\BootstrapAdmin.db;" + "ba": "Data Source=..\\BA\\BootstrapAdmin.db;", + "client": "Data Source=Client.db;" + } + }, + { + "Enabled": false, + "Widget": "Bootstrap.Client.DataAccess.MongoDB", + "ProviderName": "MongoDB", + "ConnectionStrings": { + "ba": "mongodb://localhost:27017;Database=BootstrapAdmin" } } ], @@ -78,6 +87,27 @@ "SlidingExpiration": true, "Desc": "用户所有菜单数据缓存" }, + { + "Enabled": true, + "Key": "RoleHelper-RetrieveRoles", + "Interval": 600000, + "SlidingExpiration": true, + "Desc": "所有角色数据" + }, + { + "Enabled": true, + "Key": "GroupHelper-RetrieveGroups", + "Interval": 600000, + "SlidingExpiration": true, + "Desc": "所有部门数据" + }, + { + "Enabled": true, + "Key": "UserHelper-RetrieveUsers", + "Interval": 600000, + "SlidingExpiration": true, + "Desc": "所有用户数据" + }, { "Enabled": true, "Key": "GroupHelper-RetrieveGroupsByUserName", @@ -87,4 +117,4 @@ } ] } -} +} \ No newline at end of file diff --git a/Bootstrap.DataAccess.MongoDB/DbManager.cs b/Bootstrap.DataAccess.MongoDB/DbManager.cs index bfb1bb8d..b529215b 100644 --- a/Bootstrap.DataAccess.MongoDB/DbManager.cs +++ b/Bootstrap.DataAccess.MongoDB/DbManager.cs @@ -9,7 +9,7 @@ using MongoDB.Driver; namespace Bootstrap.DataAccess.MongoDB { /// - /// + /// 数据库操作类 /// internal static class DbManager { @@ -18,7 +18,7 @@ namespace Bootstrap.DataAccess.MongoDB private static readonly object _locker = new object(); /// - /// + /// IMongoDatabase 实例 /// private static IMongoDatabase DBAccess { @@ -34,7 +34,8 @@ namespace Bootstrap.DataAccess.MongoDB ChangeToken.OnChange(() => ConfigurationManager.AppSettings.GetReloadToken(), () => _db = null); InitClassMap(); } - InitDb(); + if (_db == null) + InitDb(); } } return _db; @@ -43,7 +44,7 @@ namespace Bootstrap.DataAccess.MongoDB #region Collections /// - /// + /// Logs 集合 /// public static IMongoCollection Logs { @@ -54,7 +55,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Exceptions 集合 /// public static IMongoCollection Exceptions { @@ -64,7 +65,7 @@ namespace Bootstrap.DataAccess.MongoDB } } /// - /// + /// Dicts 集合 /// public static IMongoCollection Dicts { @@ -75,7 +76,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Users 集合 /// public static IMongoCollection Users { @@ -86,7 +87,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Groups 集合 /// public static IMongoCollection Groups { @@ -97,7 +98,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Roles 集合 /// public static IMongoCollection Roles { @@ -108,7 +109,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Menus 集合 /// public static IMongoCollection Menus { @@ -119,7 +120,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// LoginUsers 集合 /// public static IMongoCollection LoginUsers { @@ -130,7 +131,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// ResetUsers 集合 /// public static IMongoCollection ResetUsers { @@ -141,7 +142,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Traces 集合 /// public static IMongoCollection Traces { @@ -152,7 +153,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// RejectUsers 集合 /// public static IMongoCollection RejectUsers { @@ -163,7 +164,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Messages 集合 /// public static IMongoCollection Messages { @@ -174,7 +175,7 @@ namespace Bootstrap.DataAccess.MongoDB } /// - /// + /// Tasks 集合 /// public static IMongoCollection Tasks { @@ -187,8 +188,9 @@ namespace Bootstrap.DataAccess.MongoDB private static void InitDb() { - var client = new MongoClient(Longbow.Data.DbManager.GetConnectionString()); - _db = client.GetDatabase(ConfigurationManager.AppSettings["MongoDB"]); + var (connectString, databaseName) = Longbow.Data.DbManager.GetMongoDB(); + var client = new MongoClient(connectString); + _db = client.GetDatabase(databaseName); } private static void InitClassMap() diff --git a/Bootstrap.DataAccess.MongoDB/Menu.cs b/Bootstrap.DataAccess.MongoDB/Menu.cs index f2adccc6..c920679e 100644 --- a/Bootstrap.DataAccess.MongoDB/Menu.cs +++ b/Bootstrap.DataAccess.MongoDB/Menu.cs @@ -21,21 +21,23 @@ namespace Bootstrap.DataAccess.MongoDB var user = UserHelper.Retrieves().Cast().FirstOrDefault(u => u.UserName.ToLowerInvariant() == userName.ToLowerInvariant()); if (user == null) return Enumerable.Empty(); - var dicts = DictHelper.RetrieveDicts().Where(m => m.Category == "菜单"); - - // 通过用户获取 角色列表 - var roles = RoleHelper.Retrieves().Cast().Where(r => user.Roles.Any(rl => rl == r.Id)).ToList(); + var roles = RoleHelper.Retrieves().Cast(); + var groups = GroupHelper.Retrieves().Cast(); // 通过用户获取 组列表相关联的角色列表 - roles = GroupHelper.RetrievesByUserName(userName).Aggregate(roles, (r, g) => + var userRoles = user.Groups.Aggregate(user.Roles.ToList(), (r, g) => { - r.AddRange(RoleHelper.RetrievesByGroupId(g.Id).Cast()); + var groupRoles = groups.Where(group => group.Id == g).FirstOrDefault()?.Roles; + if (groupRoles != null) r.AddRange(groupRoles); return r; }).Distinct().ToList(); + var allRoles = roles.Where(r => userRoles.Any(rl => rl == r.Id)).ToList(); var menus = DbManager.Menus.Find(FilterDefinition.Empty).ToList() - .Where(m => roles.Any(r => r.RoleName.Equals("Administrators", StringComparison.OrdinalIgnoreCase) || r.Menus.Any(rm => rm.Equals(m.Id, StringComparison.OrdinalIgnoreCase)))) + .Where(m => allRoles.Any(r => r.RoleName.Equals("Administrators", StringComparison.OrdinalIgnoreCase) || r.Menus.Any(rm => rm.Equals(m.Id, StringComparison.OrdinalIgnoreCase)))) .ToList(); + + var dicts = DictHelper.RetrieveDicts().Where(m => m.Category == "菜单"); menus.ForEach(m => { m.CategoryName = dicts.FirstOrDefault(d => d.Code == m.Category)?.Name; diff --git a/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj b/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj index 8919646e..e5f02365 100644 --- a/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj +++ b/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj @@ -6,7 +6,7 @@ - + diff --git a/Bootstrap.DataAccess/CacheCleanUtility.cs b/Bootstrap.DataAccess/CacheCleanUtility.cs index 3790696d..30530b79 100644 --- a/Bootstrap.DataAccess/CacheCleanUtility.cs +++ b/Bootstrap.DataAccess/CacheCleanUtility.cs @@ -35,6 +35,8 @@ namespace Bootstrap.DataAccess cacheKeys.Add(RoleHelper.RetrieveRolesDataKey + "*"); cacheKeys.Add(MenuHelper.RetrieveMenusAll + "*"); cacheKeys.Add(RetrieveAllRolesDataKey + "*"); + corsKeys.Add(RoleHelper.RetrieveRolesDataKey + "*"); + corsKeys.Add(GroupHelper.RetrieveGroupsDataKey + "*"); corsKeys.Add(MenuHelper.RetrieveMenusAll + "*"); } if (userIds != null) @@ -59,8 +61,10 @@ namespace Bootstrap.DataAccess }); cacheKeys.Add(GroupHelper.RetrieveGroupsDataKey + "*"); cacheKeys.Add(MenuHelper.RetrieveMenusAll + "*"); - corsKeys.Add(MenuHelper.RetrieveMenusAll + "*"); cacheKeys.Add(RetrieveAllRolesDataKey + "*"); + corsKeys.Add(RoleHelper.RetrieveRolesDataKey + "*"); + corsKeys.Add(GroupHelper.RetrieveGroupsDataKey + "*"); + corsKeys.Add(MenuHelper.RetrieveMenusAll + "*"); } if (menuIds != null) { @@ -70,6 +74,8 @@ namespace Bootstrap.DataAccess }); cacheKeys.Add(MenuHelper.RetrieveMenusByRoleIdDataKey + "*"); cacheKeys.Add(MenuHelper.RetrieveMenusAll + "*"); + corsKeys.Add(RoleHelper.RetrieveRolesDataKey + "*"); + corsKeys.Add(GroupHelper.RetrieveGroupsDataKey + "*"); corsKeys.Add(MenuHelper.RetrieveMenusAll + "*"); } if (appIds != null) diff --git a/Bootstrap.DataAccess/Dict.cs b/Bootstrap.DataAccess/Dict.cs index 1a0d34a9..be552c65 100644 --- a/Bootstrap.DataAccess/Dict.cs +++ b/Bootstrap.DataAccess/Dict.cs @@ -61,13 +61,13 @@ namespace Bootstrap.DataAccess public virtual IEnumerable RetrieveCategories() => DictHelper.RetrieveDicts().OrderBy(d => d.Category).Select(d => d.Category).Distinct(); /// - /// + /// 获取系统网站标题 /// /// public virtual string RetrieveWebTitle() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站标题" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "后台管理系统" }).Code; /// - /// + /// 获取系统网站页脚 /// /// public virtual string RetrieveWebFooter() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站页脚" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "2016 © 通用后台管理系统" }).Code; diff --git a/Bootstrap.DataAccess/Helper/RoleHelper.cs b/Bootstrap.DataAccess/Helper/RoleHelper.cs index c18ba877..c6b08065 100644 --- a/Bootstrap.DataAccess/Helper/RoleHelper.cs +++ b/Bootstrap.DataAccess/Helper/RoleHelper.cs @@ -28,6 +28,7 @@ namespace Bootstrap.DataAccess /// /// public const string RetrieveRolesByGroupIdDataKey = "RoleHelper-RetrieveRolesByGroupId"; + /// /// 查询所有角色 /// diff --git a/BootstrapAdmin.sln b/BootstrapAdmin.sln index 6952fa89..f4e40d35 100644 --- a/BootstrapAdmin.sln +++ b/BootstrapAdmin.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.705 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29215.179 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLServer", "SQLServer", "{87319AF5-7C40-4362-B67C-35F9DD737DB4}" ProjectSection(SolutionItems) = preProject @@ -64,6 +64,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Postgresql", "Postgresql", DatabaseScripts\Postgresql\install.sql = DatabaseScripts\Postgresql\install.sql EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bootstrap.Client.DataAccess", "Bootstrap.Client.DataAccess\Bootstrap.Client.DataAccess.csproj", "{843811A2-FE49-410F-BF9F-9F1FB14A1DEE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bootstrap.Client.DataAccess.MongoDB", "Bootstrap.Client.DataAccess.MongoDB\Bootstrap.Client.DataAccess.MongoDB.csproj", "{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -90,6 +94,14 @@ Global {CFE75C48-F9D5-403A-8419-D07939BBD769}.Debug|Any CPU.Build.0 = Debug|Any CPU {CFE75C48-F9D5-403A-8419-D07939BBD769}.Release|Any CPU.ActiveCfg = Release|Any CPU {CFE75C48-F9D5-403A-8419-D07939BBD769}.Release|Any CPU.Build.0 = Release|Any CPU + {843811A2-FE49-410F-BF9F-9F1FB14A1DEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {843811A2-FE49-410F-BF9F-9F1FB14A1DEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {843811A2-FE49-410F-BF9F-9F1FB14A1DEE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {843811A2-FE49-410F-BF9F-9F1FB14A1DEE}.Release|Any CPU.Build.0 = Release|Any CPU + {BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -101,6 +113,8 @@ Global {A06A0AD8-A246-4329-B024-7174AE4A3EDE} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8} {084E2E94-6B7D-4D3E-9BF1-6972427FBF80} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8} {6F61C2AC-84D4-48A9-8A48-680657CC8175} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8} + {843811A2-FE49-410F-BF9F-9F1FB14A1DEE} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} + {BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {221EAE38-5F75-4391-9A48-E462A9F3B8FC}