diff --git a/LFlow.Base/LFlow.Base.csproj b/LFlow.Base/LFlow.Base.csproj index a868336..f72642b 100644 --- a/LFlow.Base/LFlow.Base.csproj +++ b/LFlow.Base/LFlow.Base.csproj @@ -16,6 +16,8 @@ + + diff --git a/LFlow.Base/Program.cs b/LFlow.Base/Program.cs index c3a8545..13b7716 100644 --- a/LFlow.Base/Program.cs +++ b/LFlow.Base/Program.cs @@ -16,6 +16,7 @@ public static class Program public static void Main(string[] args) { + // 先用Serilog的BootstrapLogger Log.Logger = new LoggerConfiguration() .MinimumLevel.Override("Microsoft", LogEventLevel.Information) @@ -23,6 +24,7 @@ public static class Program .WriteTo.Console() .CreateBootstrapLogger(); + ConfigDllLoader(); var builder = WebApplication.CreateBuilder(args); // 添加到Service中 builder.Services.AddSerilog((services, lc) => lc @@ -31,6 +33,10 @@ public static class Program .Enrich.FromLogContext() // .WriteTo.Console() ); + builder.Services.AddLogging(loggingBuilder => + { + loggingBuilder.AddSerilog(Log.Logger, dispose: true); + }); builder.Services.AddResponseCompression(); builder.Services.AddResponseCaching(); @@ -38,13 +44,6 @@ public static class Program Log.Logger.Information("LoadSubService"); builder.Services.LoadSubService(); - // 注册中间件 - builder.Services.RegisterMiddlewares(App.SubServiceAssembly); - - // 注册内部事件总线 - builder.Services.AddInternalEventBus(App.SubServiceAssembly); - // 注册自身缓存器 - builder.Services.AddSelfCache(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -80,16 +79,25 @@ public static class Program }); }); - // 使用Serilog,此处为了修复 `The logger is already frozen` 的问题,重新配置Serilog - builder.Host.UseSerilog((context, services, config) => - { - config.ReadFrom.Configuration(context.Configuration) - .ReadFrom.Services(services) - .Enrich.FromLogContext(); - // .WriteTo.Console(); - }, true); - // init App.service + //// 使用Serilog,此处为了修复 `The logger is already frozen` 的问题,重新配置Serilog + //builder.Host.UseSerilog((context, services, config) => + //{ + // config.ReadFrom.Configuration(context.Configuration) + // .ReadFrom.Services(services) + // .Enrich.FromLogContext(); + // // .WriteTo.Console(); + //}, true); + builder.Host.UseSerilog(Log.Logger); + // 注册中间件 + builder.Services.RegisterMiddlewares(App.SubServiceAssembly); + // 注册内部事件总线 + builder.Services.AddInternalEventBus(App.SubServiceAssembly); + // 注册自身缓存器 + builder.Services.AddSelfCache(); + + + // init App.service App.services = builder.Services; var app = builder.Build(); app.UseSerilogRequestLogging(options => @@ -118,7 +126,7 @@ public static class Program { Log.Logger.Information("ApplicationStarted"); CodeFirst.InitTable(); - await InternalEventBus.InternalEventBus.Publish("Init", "ApplicationStarted"); + InternalEventBus.InternalEventBus.Publish("Init", "ApplicationStarted"); }); // 启用自定义中间件 app.UseLFlowMiddleware(); @@ -225,5 +233,38 @@ public static class Program } + public static void ConfigDllLoader() + { + AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => + { + var assemblyName = new AssemblyName(args.Name); + // 判断是否已经被加载 + var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies() + .FirstOrDefault(a => a.FullName == assemblyName.FullName); + if (loadedAssembly != null) + { + Log.Logger?.Information($"Assembly {assemblyName.Name} has been loaded."); + return loadedAssembly; + } + + // 从当前路径下加载 + var path = Path.Combine(AppContext.BaseDirectory, $"{assemblyName.Name}.dll"); + if (File.Exists(path)) + { + Log.Logger?.Information($"Assembly {assemblyName.Name} has been loaded for {path}."); + return Assembly.LoadFile(path); + } + + // 从Service文件夹中加载 + path = Path.Combine(AppContext.BaseDirectory, "Service", $"{assemblyName.Name}.dll"); + if (File.Exists(path)) + { + Log.Logger?.Information($"Assembly {assemblyName.Name} has been loaded for {path}."); + return Assembly.LoadFile(path); + } + Log.Logger?.Error($"Assembly {assemblyName.Name} not found."); + return null; + }; + } } diff --git a/LFlow.Base/appsettings.json b/LFlow.Base/appsettings.json index ecc731c..b146ec7 100644 --- a/LFlow.Base/appsettings.json +++ b/LFlow.Base/appsettings.json @@ -4,9 +4,9 @@ "MinimumLevel": { "Default": "Debug", "Override": { - "Microsoft.AspNetCore.Mvc": "Information", - "Microsoft.AspNetCore.Routing": "Information", - "Microsoft.AspNetCore.Hosting": "Information" + "Microsoft.AspNetCore.Mvc": "Debug", + "Microsoft.AspNetCore.Routing": "Debug", + "Microsoft.AspNetCore.Hosting": "Debug" } }, "WriteTo": [ diff --git a/LFlow.Cache/Cacher/SelfSingleCache.cs b/LFlow.Cache/Cacher/SelfSingleCache.cs index b531a8e..ef654d1 100644 --- a/LFlow.Cache/Cacher/SelfSingleCache.cs +++ b/LFlow.Cache/Cacher/SelfSingleCache.cs @@ -34,7 +34,8 @@ namespace LFlow.Cache.Cacher public Task RemoveAsync(string key) { - CacheProvider.Remove(key); + if (CacheProvider.TryGetValue(key, out _)) + CacheProvider.Remove(key); return Task.CompletedTask; } diff --git a/LFlow.Permission/Controller/PermissionController.cs b/LFlow.Permission/Controller/PermissionController.cs new file mode 100644 index 0000000..06d4099 --- /dev/null +++ b/LFlow.Permission/Controller/PermissionController.cs @@ -0,0 +1,45 @@ +using LFlow.Base.Interfaces; +using LFlow.Base.Utils; +using LFlow.Permission.Model; +using LFlow.Permission.Service; +using Microsoft.AspNetCore.Mvc; +using Serilog; + +namespace LFlow.Permission.Controller +{ + /// + /// 权限控制 + /// + /// + /// + public class PermissionController : BaseController + { + private IPermissionService service; + private ILogger logger; + + public PermissionController(IPermissionService service, ILogger logger) + + { + this.service = service; + this.logger = logger; + } + + /// + /// 查询权限 + /// + /// + /// + /// + [HttpGet] + public async Task>> GetAll(int pageSize, int pageIndex) + { + var total = 0; + var list = await service.GetPermissionListAsync(pageIndex, pageSize, ref total); + return new PagedApiResult> + { + Data = list, + TotalCount = total + }; + } + } +} diff --git a/LFlow.Permission/LFlow.Permission.csproj b/LFlow.Permission/LFlow.Permission.csproj new file mode 100644 index 0000000..d04a79d --- /dev/null +++ b/LFlow.Permission/LFlow.Permission.csproj @@ -0,0 +1,18 @@ + + + + + + + + net8.0 + enable + enable + ../LFlow_Bin/Services/ + false + false + true + true + + + \ No newline at end of file diff --git a/LFlow.Permission/Model/PermissionDto.cs b/LFlow.Permission/Model/PermissionDto.cs new file mode 100644 index 0000000..08c8541 --- /dev/null +++ b/LFlow.Permission/Model/PermissionDto.cs @@ -0,0 +1,56 @@ +using LFlow.Base.Interfaces; + +namespace LFlow.Permission.Model +{ + public class PermissionDto : IModel + { + /// + /// ID + /// + public string? ID + { + get; + set; + } + /// + /// 角色ID + /// + public string? RoleId + { + get; + set; + } + /// + /// 权限对应程序ID + /// + public string? PermissionProgID + { + get; + set; + } + /// + /// 权限对应程序名称 + /// + public string? PermissionProgName + { + get; + set; + } + /// + /// 权限名称 + /// + public string? PermissionName + { + get; + set; + } + /// + /// 权限接口 + /// + public string? PermissionAction + { + get; + set; + } + } +} diff --git a/LFlow.Permission/Model/PermissionModel.cs b/LFlow.Permission/Model/PermissionModel.cs new file mode 100644 index 0000000..0df100d --- /dev/null +++ b/LFlow.Permission/Model/PermissionModel.cs @@ -0,0 +1,55 @@ +using LFlow.Base.Interfaces; +using SqlSugar; + +namespace LFlow.Permission.Model +{ + [SugarTable("T_U_USERINFO")] + public class PermissionModel : IDataModel + { + [SugarColumn(IsPrimaryKey = true)] + public string ID + { + get; + set; + } + public string RoleId + { + get; + set; + } + /// + /// 权限对应程序ID + /// + public string PermissionProgID + { + get; + set; + } + /// + /// 权限对应程序名称 + /// + public string PermissionProgName + { + get; + set; + } + /// + /// 权限名称 + /// + public string PermissionName + { + get; + set; + } + /// + /// 权限接口 + /// + public string PermissionAction + { + get; + set; + } + + } + +} diff --git a/LFlow.Permission/PermissionModule.cs b/LFlow.Permission/PermissionModule.cs new file mode 100644 index 0000000..07b6d6a --- /dev/null +++ b/LFlow.Permission/PermissionModule.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using LFlow.Base.Interfaces; +using LFlow.Base.Utils; +using Microsoft.Extensions.DependencyInjection; +using Serilog; + +namespace LFlow.Permission; + +public class PermissionModule : IModule +{ + + public void ConfigureModule(IServiceCollection services) + { + CodeFirst.AddType(typeof(PermissionModule)); + var assembly = Assembly.GetAssembly(typeof(PermissionModule))!; + var types = assembly.GetTypes().ToList(); + RegisterModule.RegisterAllService(types, services); + RegisterModule.RegisterAllRepo(types, services); + //RegisterModule.RegisterAllModel(types, services); + services.AddControllers().AddApplicationPart(assembly); + Log.Logger?.Information("UserManegementModule ConfigureModule done"); + } +} diff --git a/LFlow.Permission/Repository/PermissionRepo.cs b/LFlow.Permission/Repository/PermissionRepo.cs new file mode 100644 index 0000000..1016dc6 --- /dev/null +++ b/LFlow.Permission/Repository/PermissionRepo.cs @@ -0,0 +1,10 @@ +using LFlow.Base.Default; +using LFlow.Permission.Model; +using SqlSugar; + +namespace LFlow.Permission.Repository +{ + internal class RoleRepo(ISqlSugarClient client) : DefaultCurdRepo(client) + { + } +} diff --git a/LFlow.Permission/Service/IPermissionService.cs b/LFlow.Permission/Service/IPermissionService.cs new file mode 100644 index 0000000..0eb7294 --- /dev/null +++ b/LFlow.Permission/Service/IPermissionService.cs @@ -0,0 +1,21 @@ +using LFlow.Base.Interfaces; +using LFlow.Permission.Model; + +namespace LFlow.Permission.Service +{ + public interface IPermissionService : IService// + { + Task> GetPermissionListAsync(int pageIndex, int pageSize, ref int total); + Task GetPermissionAsync(string id); + Task AddPermissionAsync(PermissionDto model); + Task UpdatePermissionAsync(PermissionDto model); + Task DeletePermissionAsync(string id); + /// + /// 获取程序权限列表 + /// + /// + /// + Task> GetProgPerminssionListAsync(string progID); + + } +} diff --git a/LFlow.Permission/Service/PermissionService.cs b/LFlow.Permission/Service/PermissionService.cs new file mode 100644 index 0000000..8506c2f --- /dev/null +++ b/LFlow.Permission/Service/PermissionService.cs @@ -0,0 +1,100 @@ +using LFlow.Base.Interfaces; +using LFlow.Base.Utils; +using LFlow.Cache.Interface; +using LFlow.Permission.Model; +using Mapster; +using SqlSugar; + +namespace LFlow.Permission.Service +{ + /// + /// 角色服务 + /// + public class PermissionService(IRepo repo, ISelfCache cacher) : IPermissionService + { + /// + /// 添加权限项 + /// + /// + /// + public Task AddPermissionAsync(PermissionDto model) + { + var savedModel = repo.SaveOrUpdate(model.Adapt(), isUpdate: false); + var result = savedModel?.MapTo() ?? throw new InvalidOperationException("Failed to add the permission model."); + return Task.FromResult(result); + } + + /// + /// 删除权限项并清理缓存 + /// + /// + /// + public Task DeletePermissionAsync(string id) + { + cacher.RemoveAsync(id); + return Task.FromResult(repo.DeleteById(id)); + } + /// + /// 根据ID获取权限 + /// + /// + /// + public async Task GetPermissionAsync(string id) + { + var cachedPermission = await cacher.GetAsync(id); + if (cachedPermission != null) + { + return cachedPermission!.MapTo()!; + } + var permission = await Task.FromResult(repo.Get(id)); + if (permission != null) + { + await cacher.SetAsync(id, permission); + } + return permission?.MapTo() ?? new PermissionDto(); + } + /// + /// 获取权限列表 + /// + /// + /// + /// + /// + public Task> GetPermissionListAsync(int pageIndex, int pageSize, ref int total) + { + return Task.FromResult(repo.GetAll(pageIndex, pageSize, ref total).Adapt>()); + } + /// + /// 获取程序权限列表 + /// + /// + /// + public Task> GetProgPerminssionListAsync(string progID) + { + return Task.FromResult(repo.Search(new PermissionModel + { + PermissionProgID = progID + }).Adapt>()); + } + + /// + /// 更新权限项 + /// + /// + /// + public Task UpdatePermissionAsync(PermissionDto model) + { + if (model != null && !string.IsNullOrEmpty(model.ID)) + { + cacher.RemoveAsync(model.ID); + } + if (model != null) + { + var permissionModel = model?.Adapt() ?? throw new ArgumentNullException(nameof(model)); + var savedModel = repo.SaveOrUpdate(permissionModel, isUpdate: true); + return Task.FromResult(savedModel?.MapTo() ?? throw new InvalidOperationException("Failed to update the permission model.")); + } + throw new ArgumentNullException(nameof(model)); + } + } +} diff --git a/LFlow.Role/Controller/RoleController.cs b/LFlow.Role/Controller/RoleController.cs new file mode 100644 index 0000000..9fec89b --- /dev/null +++ b/LFlow.Role/Controller/RoleController.cs @@ -0,0 +1,11 @@ +using LFlow.Base.Interfaces; +using LFlow.Role.Service; +using Serilog; + +namespace LFlow.Role.Controller +{ + public class RoleController(IRoleService service, ILogger logger) : BaseController + { + + } +} diff --git a/LFlow.Role/LFlow.Role.csproj b/LFlow.Role/LFlow.Role.csproj new file mode 100644 index 0000000..7a46b84 --- /dev/null +++ b/LFlow.Role/LFlow.Role.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + enable + enable + ../LFlow_Bin/Services/ + false + false + true + true + + + + + + + + \ No newline at end of file diff --git a/LFlow.Role/Model/RoleDto.cs b/LFlow.Role/Model/RoleDto.cs new file mode 100644 index 0000000..44cd554 --- /dev/null +++ b/LFlow.Role/Model/RoleDto.cs @@ -0,0 +1,53 @@ +using LFlow.Base.Interfaces; +using LFlow.Permission.Model; + +namespace LFlow.Role.Model +{ + public class RoleDto : IModel + { + public string? ID + { + get; + set; + } + + public string? RoleName + { + get; + set; + } + + public string? RoleDesc + { + get; + set; + } + + public string? RoleType + { + get; + set; + } + + public string? RoleStatus + { + get; + set; + } + + public bool? IsDefault + { + get; + set; + } + public bool? IsEnable + { + get; + set; + } + /// + /// 权限列表 + /// + public List Permissions { get; set; } = []; + } +} diff --git a/LFlow.Role/Model/RoleModel.cs b/LFlow.Role/Model/RoleModel.cs new file mode 100644 index 0000000..a563802 --- /dev/null +++ b/LFlow.Role/Model/RoleModel.cs @@ -0,0 +1,52 @@ +using LFlow.Base.Interfaces; +using SqlSugar; + +namespace LFlow.Role.Model +{ + [SugarTable("T_U_USERINFO")] + public class RoleModel : IDataModel + { + [SugarColumn(IsPrimaryKey = true)] + public string ID + { + get; + set; + } + + public string RoleName + { + get; + set; + } + + public string RoleDesc + { + get; + set; + } + + public string RoleType + { + get; + set; + } + + public string RoleStatus + { + get; + set; + } + + public bool IsDefault + { + get; + set; + } + public bool IsEnable + { + get; + set; + } + } + +} diff --git a/LFlow.Role/Repository/RoleRepo.cs b/LFlow.Role/Repository/RoleRepo.cs new file mode 100644 index 0000000..cee3453 --- /dev/null +++ b/LFlow.Role/Repository/RoleRepo.cs @@ -0,0 +1,10 @@ +using LFlow.Base.Default; +using LFlow.Role.Model; +using SqlSugar; + +namespace LFlow.Role.Repository +{ + internal class RoleRepo(ISqlSugarClient client) : DefaultCurdRepo(client) + { + } +} diff --git a/LFlow.Role/RoleModule.cs b/LFlow.Role/RoleModule.cs new file mode 100644 index 0000000..c70f2e7 --- /dev/null +++ b/LFlow.Role/RoleModule.cs @@ -0,0 +1,24 @@ +using LFlow.Base.Interfaces; +using LFlow.Base.Utils; +using LFlow.Role.Model; +using Microsoft.Extensions.DependencyInjection; +using Serilog; +using System.Reflection; + +namespace LFlow.Role +{ + public class RoleModule : IModule + { + public void ConfigureModule(IServiceCollection services) + { + CodeFirst.AddType(typeof(RoleModel)); + var assembly = Assembly.GetAssembly(typeof(RoleModule))!; + var types = assembly.GetTypes().ToList(); + RegisterModule.RegisterAllService(types, services); + RegisterModule.RegisterAllRepo(types, services); + //RegisterModule.RegisterAllModel(types, services); + services.AddControllers().AddApplicationPart(assembly); + Log.Logger?.Information("UserManegementModule ConfigureModule done"); + } + } +} diff --git a/LFlow.Role/Service/IRoleService.cs b/LFlow.Role/Service/IRoleService.cs new file mode 100644 index 0000000..054fd7b --- /dev/null +++ b/LFlow.Role/Service/IRoleService.cs @@ -0,0 +1,21 @@ +using LFlow.Base.Interfaces; +using LFlow.Role.Model; + +namespace LFlow.Role.Service +{ + public interface IRoleService : IService// + { + Task> GetRoleListAsync(int pageIndex, int pageSize, ref int total); + Task GetRoleAsync(string id); + Task AddRoleAsync(RoleDto model); + Task UpdateRoleAsync(RoleDto model); + Task DeleteRoleAsync(string id); + /// + /// 获取角色权限列表 + /// + /// + /// + Task GetRolePerminssionListAsync(string roleId); + + } +} diff --git a/LFlow.Role/Service/RoleService.cs b/LFlow.Role/Service/RoleService.cs new file mode 100644 index 0000000..3e4de1f --- /dev/null +++ b/LFlow.Role/Service/RoleService.cs @@ -0,0 +1,103 @@ +using LFlow.Base.Interfaces; +using LFlow.Base.Utils; +using LFlow.Cache.Interface; +using LFlow.Permission.Service; +using LFlow.Role.Model; +using Mapster; + +namespace LFlow.Role.Service +{ + /// + /// 角色服务 + /// + public class RoleService(IRepo repo, IPermissionService permissionService, ISelfCache cacher) : IRoleService + { + /// + /// 添加角色 + /// + /// + /// + public Task AddRoleAsync(RoleDto model) + { + var savedRole = repo.SaveOrUpdate(model.Adapt(), isUpdate: false); + if (savedRole == null) + { + throw new InvalidOperationException("Failed to save or update the role."); + } + var roleDto = savedRole.MapTo(); + if (roleDto == null) + { + throw new InvalidOperationException("Failed to map the saved role to RoleDto."); + } + return Task.FromResult(roleDto); + } + /// + /// 删除角色并清理缓存 + /// + /// + /// + public Task DeleteRoleAsync(string id) + { + cacher.RemoveAsync(id); + return Task.FromResult(repo.DeleteById(id)); + } + + public async Task GetRolePerminssionListAsync(string roleId) + { + var roleDto = GetRoleAsync(roleId).Result; + if (roleDto == null) + { + return new RoleDto(); + } + var permissions = await permissionService.GetProgPerminssionListAsync(roleId); + if (permissions != null && permissions.Count >= 0) + { + roleDto.Permissions = permissions!; + return roleDto; + } + else + { + return new RoleDto(); + } + } + + /// + /// 根据ID获取角色 + /// + /// + /// + public async Task GetRoleAsync(string id) + { + var cachedRole = await cacher.GetAsync(id); + if (cachedRole != null) + { + return cachedRole; + } + var role = await Task.FromResult(repo.Get(id)); + if (role != null) + { + await cacher.SetAsync(id, role); + } + return role?.MapTo() ?? new RoleDto(); + } + /// + /// 获取角色列表 + /// + /// + /// + /// + /// + public Task> GetRoleListAsync(int pageIndex, int pageSize, ref int total) + { + var roleModels = repo.GetAll(pageIndex, pageSize, ref total); + var roleDtos = roleModels?.Select(role => role.MapTo()).ToList() ?? []; + return Task.FromResult(roleDtos ?? [])!; + } + + public Task UpdateRoleAsync(RoleDto model) + { + throw new NotImplementedException(); + } + + } +} diff --git a/LFlow.UserManagement/UserManegementModule.cs b/LFlow.UserManagement/UserManegementModule.cs index d342dbd..0b6f6de 100644 --- a/LFlow.UserManagement/UserManegementModule.cs +++ b/LFlow.UserManagement/UserManegementModule.cs @@ -16,7 +16,7 @@ namespace LFlow.UserManagement var types = assembly.GetTypes().ToList(); RegisterModule.RegisterAllService(types, services); RegisterModule.RegisterAllRepo(types, services); - RegisterModule.RegisterAllModel(types, services); + //RegisterModule.RegisterAllModel(types, services); services.AddControllers().AddApplicationPart(assembly); Log.Logger?.Information("UserManegementModule ConfigureModule done"); } diff --git a/LFlow.sln b/LFlow.sln index 7d7df22..131ae41 100644 --- a/LFlow.sln +++ b/LFlow.sln @@ -11,11 +11,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LFlow.OnlineManegement", "L EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LFlow.UserManagement", "LFlow.UserManagement\LFlow.UserManagement.csproj", "{DA68CE22-AC53-40BD-AB2A-5C52DFDDD548}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LFlow.Middleware", "LFlow.Middleware\LFlow.Middleware.csproj", "{5BFD207E-28B3-40B8-94DF-1723C6A4424B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LFlow.Middleware", "LFlow.Middleware\LFlow.Middleware.csproj", "{5BFD207E-28B3-40B8-94DF-1723C6A4424B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LFlow.InternalEventBus", "LFlow.InternalEventBus\LFlow.InternalEventBus.csproj", "{72CB0C72-9725-43A5-882D-3E93FD1F8706}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LFlow.InternalEventBus", "LFlow.InternalEventBus\LFlow.InternalEventBus.csproj", "{72CB0C72-9725-43A5-882D-3E93FD1F8706}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LFlow.Cache", "LFlow.Cache\LFlow.Cache.csproj", "{97D56496-BE2A-4431-A882-7DEA20B72EB0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LFlow.Cache", "LFlow.Cache\LFlow.Cache.csproj", "{97D56496-BE2A-4431-A882-7DEA20B72EB0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LFlow.Role", "LFlow.Role\LFlow.Role.csproj", "{05CEB068-167F-4B27-A59A-EFBF0A656C43}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LFlow.Permission", "LFlow.Permission\LFlow.Permission.csproj", "{E7C112C2-534C-4212-959F-FBB4E21A41C1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,6 +55,14 @@ Global {97D56496-BE2A-4431-A882-7DEA20B72EB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {97D56496-BE2A-4431-A882-7DEA20B72EB0}.Release|Any CPU.ActiveCfg = Release|Any CPU {97D56496-BE2A-4431-A882-7DEA20B72EB0}.Release|Any CPU.Build.0 = Release|Any CPU + {05CEB068-167F-4B27-A59A-EFBF0A656C43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05CEB068-167F-4B27-A59A-EFBF0A656C43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05CEB068-167F-4B27-A59A-EFBF0A656C43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05CEB068-167F-4B27-A59A-EFBF0A656C43}.Release|Any CPU.Build.0 = Release|Any CPU + {E7C112C2-534C-4212-959F-FBB4E21A41C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7C112C2-534C-4212-959F-FBB4E21A41C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7C112C2-534C-4212-959F-FBB4E21A41C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7C112C2-534C-4212-959F-FBB4E21A41C1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE