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.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..d1c95972 --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/DbManager.cs @@ -0,0 +1,169 @@ +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 DBAccess + { + get + { + if (_db == null) + { + lock (_locker) + { + if (!_register) + { + _register = true; + ChangeToken.OnChange(() => ConfigurationManager.AppSettings.GetReloadToken(), () => _db = null); + InitClassMap(); + } + InitDb(); + } + } + return _db; + } + } + + #region Collections + /// + /// + /// + public static IMongoCollection Dicts + { + get + { + return DBAccess.GetCollection("Dicts"); + } + } + + /// + /// + /// + public static IMongoCollection Users + { + get + { + return DBAccess.GetCollection("Users"); + } + } + + /// + /// + /// + public static IMongoCollection Roles + { + get + { + return DBAccess.GetCollection("Roles"); + } + } + + /// + /// + /// + public static IMongoCollection Groups + { + get + { + return DBAccess.GetCollection("Groups"); + } + } + + /// + /// + /// + public static IMongoCollection Menus + { + get + { + return DBAccess.GetCollection("Navigations"); + } + } + #endregion + + private static void InitDb() + { + var client = new MongoClient(Longbow.Data.DbManager.GetConnectionString("ba")); + _db = client.GetDatabase(ConfigurationManager.AppSettings["MongoDB"]); + } + + 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..8d119b2c --- /dev/null +++ b/Bootstrap.Client.DataAccess.MongoDB/Helper/UserHelper.cs @@ -0,0 +1,24 @@ +using MongoDB.Driver; +using System; +using System.Collections.Generic; + +namespace Bootstrap.Client.DataAccess.MongoDB +{ + class UserHelper + { + /// + /// + /// + /// + public static IEnumerable Retrieves() + { + 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..5d003875 --- /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..9ddc6e49 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,16 @@ "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" } } ], diff --git a/Bootstrap.Client/appsettings.json b/Bootstrap.Client/appsettings.json index 6738d6ee..4df83da3 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": true, + "Widget": "Bootstrap.Client.DataAccess.MongoDB", + "ProviderName": "MongoDB", + "ConnectionStrings": { + "ba": "mongodb://localhost:27017" } } ], 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/DbManager.cs b/Bootstrap.DataAccess/DbManager.cs index b63ea92b..7ba531a6 100644 --- a/Bootstrap.DataAccess/DbManager.cs +++ b/Bootstrap.DataAccess/DbManager.cs @@ -7,7 +7,7 @@ namespace Bootstrap.DataAccess /// /// /// - public static class DbManager + internal static class DbManager { /// /// 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}