diff --git a/aspnet-core/database/ApiGateway-Init.sql b/aspnet-core/database/ApiGateway-Init.sql index 2088e26b5..c143190a3 100644 --- a/aspnet-core/database/ApiGateway-Init.sql +++ b/aspnet-core/database/ApiGateway-Init.sql @@ -11,7 +11,7 @@ Target Server Version : 80020 File Encoding : 65001 - Date: 08/09/2020 10:17:07 + Date: 12/09/2020 10:33:17 */ SET NAMES utf8mb4; @@ -54,7 +54,7 @@ CREATE TABLE `appapigatewayaggregate` ( `Priority` int(0) NULL DEFAULT NULL, `UpstreamHttpMethod` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, PRIMARY KEY (`Id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of appapigatewayaggregate @@ -76,7 +76,7 @@ CREATE TABLE `appapigatewayaggregateconfig` ( PRIMARY KEY (`Id`) USING BTREE, INDEX `IX_AppApiGatewayAggregateConfig_AggregateReRouteId`(`AggregateReRouteId`) USING BTREE, CONSTRAINT `FK_AppApiGatewayAggregateConfig_AppApiGatewayAggregate_Aggregat~` FOREIGN KEY (`AggregateReRouteId`) REFERENCES `appapigatewayaggregate` (`Id`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for appapigatewayauthoptions @@ -188,6 +188,7 @@ INSERT INTO `appapigatewayauthoptions` VALUES (121, 1299273770182737920, '', '') INSERT INTO `appapigatewayauthoptions` VALUES (122, 1299273978023084032, '', ''); INSERT INTO `appapigatewayauthoptions` VALUES (123, 1299274123225694208, '', ''); INSERT INTO `appapigatewayauthoptions` VALUES (124, 1299274222299348992, '', ''); +INSERT INTO `appapigatewayauthoptions` VALUES (125, 1304238876758495232, '', ''); -- ---------------------------- -- Table structure for appapigatewaybalanceroptions @@ -304,6 +305,7 @@ INSERT INTO `appapigatewaybalanceroptions` VALUES (124, NULL, 129927377018273792 INSERT INTO `appapigatewaybalanceroptions` VALUES (125, NULL, 1299273978023084032, '', '', 0); INSERT INTO `appapigatewaybalanceroptions` VALUES (126, NULL, 1299274123225694208, '', '', 0); INSERT INTO `appapigatewaybalanceroptions` VALUES (127, NULL, 1299274222299348992, '', '', 0); +INSERT INTO `appapigatewaybalanceroptions` VALUES (128, NULL, 1304238876758495232, '', '', 0); -- ---------------------------- -- Table structure for appapigatewaycacheoptions @@ -415,6 +417,7 @@ INSERT INTO `appapigatewaycacheoptions` VALUES (121, 1299273770182737920, NULL, INSERT INTO `appapigatewaycacheoptions` VALUES (122, 1299273978023084032, NULL, NULL); INSERT INTO `appapigatewaycacheoptions` VALUES (123, 1299274123225694208, NULL, NULL); INSERT INTO `appapigatewaycacheoptions` VALUES (124, 1299274222299348992, NULL, NULL); +INSERT INTO `appapigatewaycacheoptions` VALUES (125, 1304238876758495232, 0, ''); -- ---------------------------- -- Table structure for appapigatewaydiscovery @@ -434,7 +437,7 @@ CREATE TABLE `appapigatewaydiscovery` ( PRIMARY KEY (`Id`) USING BTREE, UNIQUE INDEX `IX_AppApiGatewayDiscovery_ItemId`(`ItemId`) USING BTREE, CONSTRAINT `FK_AppApiGatewayDiscovery_AppApiGatewayGlobalConfiguration_Item~` FOREIGN KEY (`ItemId`) REFERENCES `appapigatewayglobalconfiguration` (`ItemId`) ON DELETE CASCADE ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of appapigatewaydiscovery @@ -455,7 +458,7 @@ CREATE TABLE `appapigatewaydynamicreroute` ( `AppId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (`Id`) USING BTREE, UNIQUE INDEX `AK_AppApiGatewayDynamicReRoute_DynamicReRouteId`(`DynamicReRouteId`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for appapigatewayglobalconfiguration @@ -475,7 +478,7 @@ CREATE TABLE `appapigatewayglobalconfiguration` ( `AppId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (`Id`) USING BTREE, UNIQUE INDEX `AK_AppApiGatewayGlobalConfiguration_ItemId`(`ItemId`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of appapigatewayglobalconfiguration @@ -623,6 +626,7 @@ INSERT INTO `appapigatewayhttpoptions` VALUES (124, NULL, 1299273770182737920, 0 INSERT INTO `appapigatewayhttpoptions` VALUES (125, NULL, 1299273978023084032, 0, 0, 0, 0, 0); INSERT INTO `appapigatewayhttpoptions` VALUES (126, NULL, 1299274123225694208, 0, 0, 0, 0, 0); INSERT INTO `appapigatewayhttpoptions` VALUES (127, NULL, 1299274222299348992, 0, 0, 0, 0, 0); +INSERT INTO `appapigatewayhttpoptions` VALUES (128, NULL, 1304238876758495232, 0, 0, 0, 0, 0); -- ---------------------------- -- Table structure for appapigatewayqosoptions @@ -739,6 +743,7 @@ INSERT INTO `appapigatewayqosoptions` VALUES (124, NULL, 1299273770182737920, 50 INSERT INTO `appapigatewayqosoptions` VALUES (125, NULL, 1299273978023084032, 50, 60000, 30000); INSERT INTO `appapigatewayqosoptions` VALUES (126, NULL, 1299274123225694208, 50, 60000, 30000); INSERT INTO `appapigatewayqosoptions` VALUES (127, NULL, 1299274222299348992, 50, 60000, 30000); +INSERT INTO `appapigatewayqosoptions` VALUES (128, NULL, 1304238876758495232, 50, 60000, 30000); -- ---------------------------- -- Table structure for appapigatewayratelimitoptions @@ -755,7 +760,7 @@ CREATE TABLE `appapigatewayratelimitoptions` ( PRIMARY KEY (`Id`) USING BTREE, UNIQUE INDEX `IX_AppApiGatewayRateLimitOptions_ItemId`(`ItemId`) USING BTREE, CONSTRAINT `FK_AppApiGatewayRateLimitOptions_AppApiGatewayGlobalConfigurati~` FOREIGN KEY (`ItemId`) REFERENCES `appapigatewayglobalconfiguration` (`ItemId`) ON DELETE CASCADE ON UPDATE RESTRICT -) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of appapigatewayratelimitoptions @@ -878,6 +883,7 @@ INSERT INTO `appapigatewayratelimitrule` VALUES (121, 1299273770182737920, NULL, INSERT INTO `appapigatewayratelimitrule` VALUES (122, 1299273978023084032, NULL, '', 0, NULL, NULL, NULL); INSERT INTO `appapigatewayratelimitrule` VALUES (123, 1299274123225694208, NULL, '', 0, NULL, NULL, NULL); INSERT INTO `appapigatewayratelimitrule` VALUES (124, 1299274222299348992, NULL, '', 0, NULL, NULL, NULL); +INSERT INTO `appapigatewayratelimitrule` VALUES (125, 1304238876758495232, NULL, '', 0, NULL, NULL, NULL); -- ---------------------------- -- Table structure for appapigatewayreroute @@ -1015,6 +1021,7 @@ INSERT INTO `appapigatewayreroute` VALUES (128, '{}', 'f8d2b2f0f1d649c2a07eeef23 INSERT INTO `appapigatewayreroute` VALUES (129, '{}', '9785be7a29774b468e271b23009fe115', 1299273978023084032, '【消息服务】- Hangfire仪表板 - 重试', '/hangfire/retries', '', '', '/hangfire/retries', 'GET,POST,PUT,DELETE,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30020,', '', '', '', 0, 30000, 1, '', 'TEST-APP'); INSERT INTO `appapigatewayreroute` VALUES (130, '{}', '9c0c1cd196bb45c0bc03fafb7a1eb8f2', 1299274123225694208, '【消息服务】- Hangfire仪表板 - 周期性作业', '/hangfire/recurring', '', '', '/hangfire/recurring', 'GET,POST,DELETE,PUT,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30020,', '', '', '', 0, 30000, 1, '', 'TEST-APP'); INSERT INTO `appapigatewayreroute` VALUES (131, '{}', '243bafe828be463ea63a3e2b521f9923', 1299274222299348992, '【消息服务】- Hangfire仪表板 - 服务器列表', '/hangfire/servers', '', '', '/hangfire/servers', 'GET,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30020,', '', '', '', 0, 30000, 1, '', 'TEST-APP'); +INSERT INTO `appapigatewayreroute` VALUES (132, '{}', '57a8ac1b41bb434cad38fbde0e2ba2f0', 1304238876758495232, '【后台管理】- 管理功能', '/api/feature-management/features', '', '', '/api/feature-management/features', 'GET,PUT,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30010,', '', '', '', 0, 30000, 1, '', 'TEST-APP'); -- ---------------------------- -- Table structure for appapigatewayroutegroup @@ -1156,6 +1163,7 @@ INSERT INTO `appapigatewaysecurityoptions` VALUES (121, 1299273770182737920, '12 INSERT INTO `appapigatewaysecurityoptions` VALUES (122, 1299273978023084032, '127.0.0.1', ''); INSERT INTO `appapigatewaysecurityoptions` VALUES (123, 1299274123225694208, '127.0.0.1', ''); INSERT INTO `appapigatewaysecurityoptions` VALUES (124, 1299274222299348992, '127.0.0.1', ''); +INSERT INTO `appapigatewaysecurityoptions` VALUES (125, 1304238876758495232, '', ''); -- ---------------------------- -- Table structure for cap.published @@ -1174,6 +1182,11 @@ CREATE TABLE `cap.published` ( INDEX `IX_ExpiresAt`(`ExpiresAt`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; +-- ---------------------------- +-- Records of cap.published +-- ---------------------------- +INSERT INTO `cap.published` VALUES (1304238878134226944, 'v1', 'LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData', '{\"Headers\":{\"cap-callback-name\":null,\"cap-msg-id\":\"1304238878134226944\",\"cap-msg-name\":\"LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData\",\"cap-msg-type\":\"Object\",\"cap-senttime\":\"2020/9/11 10:02:34 +08:00\",\"cap-corr-id\":\"1304238878134226944\",\"cap-corr-seq\":\"0\"},\"Value\":{\"DateTime\":\"2020-09-11T10:02:34.7884591+08:00\",\"AppId\":\"TEST-APP\",\"Method\":\"Create\",\"Object\":\"ReRoute\"}}', 0, '2020-09-11 10:02:35', '2020-09-12 10:02:35', 'Succeeded'); + -- ---------------------------- -- Table structure for cap.received -- ---------------------------- diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureDefinitionProvider.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureDefinitionProvider.cs new file mode 100644 index 000000000..57edb92ae --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureDefinitionProvider.cs @@ -0,0 +1,49 @@ +using LINGYUN.Abp.FileManagement.Localization; +using Volo.Abp.Features; +using Volo.Abp.Localization; +using Volo.Abp.Validation.StringValues; + +namespace LINGYUN.Abp.FileManagement.Features +{ + public class AbpFileManagementFeatureDefinitionProvider : FeatureDefinitionProvider + { + public override void Define(IFeatureDefinitionContext context) + { + var featureGroup = context.AddGroup( + name: AbpFileManagementFeatureNames.GroupName, + displayName: L("Features:FileManagement")); + + var fileSystemFeature = featureGroup.AddFeature( + name: AbpFileManagementFeatureNames.FileSystem.Default, + displayName: L("Features:DisplayName:FileSystem"), + description: L("Features:Description:FileSystem")); + + fileSystemFeature.CreateChild( + name: AbpFileManagementFeatureNames.FileSystem.DownloadFile, + defaultValue: false.ToString(), + displayName: L("Features:DisplayName:DownloadFile"), + description: L("Features:Description:DownloadFile"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + + fileSystemFeature.CreateChild( + name: AbpFileManagementFeatureNames.FileSystem.UploadFile, + defaultValue: true.ToString(), + displayName: L("Features:DisplayName:UploadFile"), + description: L("Features:Description:UploadFile"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + + // TODO: 此功能需要控制器协同,暂时不实现 + fileSystemFeature.CreateChild( + name: AbpFileManagementFeatureNames.FileSystem.MaxUploadFileCount, + defaultValue: 1.ToString(), + displayName: L("Features:DisplayName:MaxUploadFileCount"), + description: L("Features:Description:MaxUploadFileCount"), + valueType: new ToggleStringValueType(new NumericValueValidator(1, 10))); + } + + protected ILocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureNames.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureNames.cs new file mode 100644 index 000000000..328d66946 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureNames.cs @@ -0,0 +1,23 @@ +namespace LINGYUN.Abp.FileManagement.Features +{ + public class AbpFileManagementFeatureNames + { + public const string GroupName = "Abp.FileManagement"; + public class FileSystem + { + public const string Default = GroupName + ".FileSystem"; + /// + /// 下载文件功能 + /// + public const string DownloadFile = Default + ".DownloadFile"; + /// + /// 上传文件功能 + /// + public const string UploadFile = Default + ".UploadFile"; + /// + /// 最大上传文件 + /// + public const string MaxUploadFileCount = Default + ".MaxUploadFileCount"; + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs index 7e54afc81..ed08e336b 100644 --- a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs @@ -53,12 +53,12 @@ namespace LINGYUN.Abp.FileManagement string fileSystemPath = GetFileSystemPath(path); if (!Directory.Exists(fileSystemPath)) { - throw new UserFriendlyException("指定目录不存在!"); + throw new UserFriendlyException(L["PathNotFound"]); } var copyToFilePath = GetFileSystemPath(input.CopyToPath); if (Directory.Exists(copyToFilePath)) { - throw new UserFriendlyException("指定的路径中已经有同名的目录存在!"); + throw new UserFriendlyException(L["FilePathAlreadyExists"]); } CopyDirectory(fileSystemPath, copyToFilePath); diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json index 1d0e12ffd..f6fc9c7a4 100644 --- a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json @@ -26,6 +26,14 @@ "DisplayName:FileLimitLength": "File limit size", "Description:FileLimitLength": "Limit size of uploaded file in MB", "DisplayName:AllowFileExtensions": "File extension", - "Description:AllowFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation" + "Description:AllowFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation", + "Features:FileManagement": "File management", + "Features:DisplayName:FileSystem": "File system", + "Features:DisplayName:DownloadFile": "Download file", + "Features:Description:DownloadFile": "Whether to allow users to download files", + "Features:DisplayName:UploadFile": "Upload file", + "Features:Description:UploadFile": "Whether to allow users to upload files", + "Features:DisplayName:MaxUploadFileCount": "Maximum number of upload files", + "Features:Description:MaxUploadFileCount": "Limit the number of files a user uploads at a time" } } \ No newline at end of file diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json index ff7fc6dcf..8f3fb55e2 100644 --- a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json @@ -26,6 +26,14 @@ "DisplayName:FileLimitLength": "文件限制大小", "Description:FileLimitLength": "上传文件的限制大小,单位(MB)", "DisplayName:AllowFileExtensions": "文件扩展名", - "Description:AllowFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号" + "Description:AllowFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号", + "Features:FileManagement": "文件管理", + "Features:DisplayName:FileSystem": "文件系统", + "Features:DisplayName:DownloadFile": "下载文件", + "Features:Description:DownloadFile": "是否允许用户下载文件", + "Features:DisplayName:UploadFile": "上传文件", + "Features:Description:UploadFile": "是否允许用户上传文件", + "Features:DisplayName:MaxUploadFileCount": "上传文件数量", + "Features:Description:MaxUploadFileCount": "用户单次上传文件的限制数量" } } \ No newline at end of file diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs index 3f4d60836..e155ab1b2 100644 --- a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs @@ -15,6 +15,8 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.IO; using Volo.Abp.Settings; +using Volo.Abp.Features; +using LINGYUN.Abp.FileManagement.Features; namespace LINGYUN.Abp.FileManagement { @@ -52,6 +54,7 @@ namespace LINGYUN.Abp.FileManagement [HttpPost] [Route("files")] + [RequiresFeature(AbpFileManagementFeatureNames.FileSystem.UploadFile)] [Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Create)] public virtual async Task CreateFileAsync([FromForm] FileUploadDto input) { @@ -164,6 +167,7 @@ namespace LINGYUN.Abp.FileManagement [HttpGet] [Route("files")] + [RequiresFeature(AbpFileManagementFeatureNames.FileSystem.DownloadFile)] [Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Download)] public virtual async Task DownloadFileAsync(FileSystemDownloadDto input) { diff --git a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs index e87b8fdc3..0e0288b38 100644 --- a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs +++ b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs @@ -36,6 +36,8 @@ using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.MySQL; +using Volo.Abp.FeatureManagement; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.Identity.Localization; using Volo.Abp.IdentityServer.EntityFrameworkCore; using Volo.Abp.Localization; @@ -75,6 +77,8 @@ namespace LINGYUN.BackendAdmin typeof(AbpSettingManagementHttpApiModule), typeof(AbpPermissionManagementApplicationModule), typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpFeatureManagementApplicationModule), + typeof(AbpFeatureManagementHttpApiModule), typeof(AbpTenantManagementApplicationModule), typeof(AbpTenantManagementHttpApiModule), typeof(AbpEntityFrameworkCoreMySQLModule), @@ -83,6 +87,7 @@ namespace LINGYUN.BackendAdmin typeof(AbpTenantManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpEmailingExceptionHandlingModule), typeof(AbpCAPEventBusModule), diff --git a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/EntityFrameworkCore/BackendAdminHostMigrationsDbContext.cs b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/EntityFrameworkCore/BackendAdminHostMigrationsDbContext.cs index 892dd7d79..8d67e8ae9 100644 --- a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/EntityFrameworkCore/BackendAdminHostMigrationsDbContext.cs +++ b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/EntityFrameworkCore/BackendAdminHostMigrationsDbContext.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore; @@ -18,6 +19,7 @@ namespace LINGYUN.BackendAdmin.EntityFrameworkCore { base.OnModelCreating(modelBuilder); + modelBuilder.ConfigureFeatureManagement(); modelBuilder.ConfigureTenantManagement(); modelBuilder.ConfigureSettingManagement(); modelBuilder.ConfigurePermissionManagement(); diff --git a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/LINGYUN.BackendAdminApp.Host.csproj b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/LINGYUN.BackendAdminApp.Host.csproj index e397fcbc4..d711578fc 100644 --- a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/LINGYUN.BackendAdminApp.Host.csproj +++ b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/LINGYUN.BackendAdminApp.Host.csproj @@ -46,6 +46,9 @@ + + + diff --git a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.Designer.cs b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.Designer.cs new file mode 100644 index 000000000..7b07e4d83 --- /dev/null +++ b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.Designer.cs @@ -0,0 +1,206 @@ +// +using System; +using LINGYUN.BackendAdmin.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.BackendAdmin.Migrations +{ + [DbContext(typeof(BackendAdminHostMigrationsDbContext))] + [Migration("20200910080638_Add-abp-feature-module")] + partial class Addabpfeaturemodule + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("ProviderName") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpPermissionGrants"); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(2048); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpSettings"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnName("ConcurrencyStamp") + .HasColumnType("varchar(40) CHARACTER SET utf8mb4") + .HasMaxLength(40); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("char(36)"); + + b.Property("DeleterId") + .HasColumnName("DeleterId") + .HasColumnType("char(36)"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime(6)"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("AbpTenants"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("varchar(1024) CHARACTER SET utf8mb4") + .HasMaxLength(1024); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.cs b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.cs new file mode 100644 index 000000000..3b8609a2a --- /dev/null +++ b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace LINGYUN.BackendAdmin.Migrations +{ + public partial class Addabpfeaturemodule : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(nullable: false), + Name = table.Column(maxLength: 128, nullable: false), + Value = table.Column(maxLength: 128, nullable: false), + ProviderName = table.Column(maxLength: 64, nullable: true), + ProviderKey = table.Column(maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + } + } +} diff --git a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/BackendAdminHostMigrationsDbContextModelSnapshot.cs b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/BackendAdminHostMigrationsDbContextModelSnapshot.cs index c09b401ef..f98bd7dc8 100644 --- a/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/BackendAdminHostMigrationsDbContextModelSnapshot.cs +++ b/aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/BackendAdminHostMigrationsDbContextModelSnapshot.cs @@ -16,12 +16,43 @@ namespace LINGYUN.BackendAdmin.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) - .HasAnnotation("ProductVersion", "3.1.5") + .HasAnnotation("ProductVersion", "3.1.7") .HasAnnotation("Relational:MaxIdentifierLength", 64); + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpFeatureValues"); + }); + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("char(36)"); @@ -40,7 +71,7 @@ namespace LINGYUN.BackendAdmin.Migrations .HasColumnType("varchar(64) CHARACTER SET utf8mb4") .HasMaxLength(64); - b.Property("TenantId") + b.Property("TenantId") .HasColumnName("TenantId") .HasColumnType("char(36)"); @@ -53,7 +84,7 @@ namespace LINGYUN.BackendAdmin.Migrations modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("char(36)"); @@ -84,7 +115,7 @@ namespace LINGYUN.BackendAdmin.Migrations modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("char(36)"); @@ -98,11 +129,11 @@ namespace LINGYUN.BackendAdmin.Migrations .HasColumnName("CreationTime") .HasColumnType("datetime(6)"); - b.Property("CreatorId") + b.Property("CreatorId") .HasColumnName("CreatorId") .HasColumnType("char(36)"); - b.Property("DeleterId") + b.Property("DeleterId") .HasColumnName("DeleterId") .HasColumnType("char(36)"); @@ -124,7 +155,7 @@ namespace LINGYUN.BackendAdmin.Migrations .HasColumnName("LastModificationTime") .HasColumnType("datetime(6)"); - b.Property("LastModifierId") + b.Property("LastModifierId") .HasColumnName("LastModifierId") .HasColumnType("char(36)"); @@ -142,7 +173,7 @@ namespace LINGYUN.BackendAdmin.Migrations modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => { - b.Property("TenantId") + b.Property("TenantId") .HasColumnType("char(36)"); b.Property("Name") diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db index bcc45da00..821c0270c 100644 Binary files a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db and b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db differ diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs index 30efb1213..f0d093e51 100644 --- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs +++ b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs @@ -31,6 +31,7 @@ using Volo.Abp.BlobStoring.FileSystem; using Volo.Abp.Caching; using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; @@ -50,6 +51,7 @@ namespace LINGYUN.Platform typeof(AppPlatformHttpApiModule), typeof(AppPlatformEntityFrameworkCoreModule), typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule), typeof(AbpTenantManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj index 2bfb4cb7c..38a0cb22c 100644 --- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj +++ b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj @@ -42,6 +42,7 @@ + diff --git a/vueJs/src/api/feature-management.ts b/vueJs/src/api/feature-management.ts new file mode 100644 index 000000000..ca09e24e6 --- /dev/null +++ b/vueJs/src/api/feature-management.ts @@ -0,0 +1,56 @@ +import ApiService from './serviceBase' + +const serviceUrl = process.env.VUE_APP_BASE_API + +export default class FeatureManagementService { + public static getFeatures(providerName: string, providerKey: string) { + let _url = '/api/feature-management/features?' + _url += 'providerName=' + providerName + _url += '&providerKey=' + providerKey + return ApiService.Get(_url, serviceUrl) + } + + public static updateFeatures(providerName: string, providerKey: string, features: Features) { + let _url = '/api/feature-management/features?' + _url += 'providerName=' + providerName + _url += '&providerKey=' + providerKey + return ApiService.Put(_url, features, serviceUrl) + } +} + +export class Provider { + providerName!: string + providerKey!: string +} + +export class ValueType { + name!: string + properties!: any + validator!: any +} + +export class Feature { + name!: string + displayName?: string + value!: string + description?: string + valueType?: ValueType + depth?: number + parentName?: string + + constructor( + name: string, + value: any + ) { + this.name = name + this.value = value + } +} + +export class Features { + features!: Feature[] + + constructor() { + this.features = new Array() + } +} diff --git a/vueJs/src/store/modules/abp.ts b/vueJs/src/store/modules/abp.ts index 332e2cff5..fdd0f105f 100644 --- a/vueJs/src/store/modules/abp.ts +++ b/vueJs/src/store/modules/abp.ts @@ -29,12 +29,12 @@ class AbpConfiguration extends VuexModule implements IAbpState { if (typeof resource !== 'object') return Object.keys(resource).forEach(key2 => { if (/'{|{/g.test(resource[key2])) { - resource[key2] = resource[key2].replace(/'{|{/g, '{{').replace(/}'|}/g, '}}') + resource[key2] = resource[key2].replace(/'{|{/g, '{').replace(/}'|}/g, '}') } }) resources[key] = resource }) - i18n.mergeLocaleMessage(twoLetterIsoLanguageName as string, resources) + i18n.mergeLocaleMessage(twoLetterIsoLanguageName, resources) } @Action({ rawError: true }) diff --git a/vueJs/src/utils/request.ts b/vueJs/src/utils/request.ts index a26207b9f..f26703fd8 100644 --- a/vueJs/src/utils/request.ts +++ b/vueJs/src/utils/request.ts @@ -96,6 +96,7 @@ service.interceptors.response.use( return response }, (error) => { + console.log(error.response) if (error.response.status === 401) { UserModule.RefreshSession().then(token => { const config = error.response.config diff --git a/vueJs/src/views/admin/components/FeatureManagement.vue b/vueJs/src/views/admin/components/FeatureManagement.vue new file mode 100644 index 000000000..eb736c869 --- /dev/null +++ b/vueJs/src/views/admin/components/FeatureManagement.vue @@ -0,0 +1,317 @@ + + + + + diff --git a/vueJs/src/views/admin/tenants/components/TenantFeatureEditForm.vue b/vueJs/src/views/admin/tenants/components/TenantFeatureEditForm.vue new file mode 100644 index 000000000..09ceda3db --- /dev/null +++ b/vueJs/src/views/admin/tenants/components/TenantFeatureEditForm.vue @@ -0,0 +1,41 @@ + + + diff --git a/vueJs/src/views/admin/tenants/index.vue b/vueJs/src/views/admin/tenants/index.vue index 3faf6af09..f527640ae 100644 --- a/vueJs/src/views/admin/tenants/index.vue +++ b/vueJs/src/views/admin/tenants/index.vue @@ -122,6 +122,12 @@ > {{ $t('tenant.connectionOptions') }} + + 管理功能 + + + @@ -184,6 +196,7 @@ import TenantService, { TenantDto, TenantGetByPaged } from '@/api/tenant' import { dateFormat } from '@/utils/index' import { checkPermission } from '@/utils/permission' import Pagination from '@/components/Pagination/index.vue' +import TenantFeatureEditForm from './components/TenantFeatureEditForm.vue' import TenantCreateOrEditForm from './components/TenantCreateOrEditForm.vue' import TenantEditConnectionForm from './components/TenantEditConnectionForm.vue' @@ -191,6 +204,7 @@ import TenantEditConnectionForm from './components/TenantEditConnectionForm.vue' name: 'RoleList', components: { Pagination, + TenantFeatureEditForm, TenantCreateOrEditForm, TenantEditConnectionForm }, @@ -213,6 +227,7 @@ export default class extends Vue { private showEditTenantConnectionDialog: boolean private showCreateOrEditTenantDialog: boolean + private showFeatureEditFormDialog = false constructor() { super() @@ -245,6 +260,10 @@ export default class extends Vue { this.editTenantId = command.row.id this.showEditTenantConnectionDialog = true break + case 'feature' : + this.editTenantId = command.row.id + this.showFeatureEditFormDialog = true + break case 'delete' : this.handleDeleteTenant(command.row.id, command.row.name) break @@ -291,6 +310,11 @@ export default class extends Vue { this.tenantGetPagedFilter.sorting = column.prop } + private onFeatureEditFormClosed() { + this.showFeatureEditFormDialog = false + this.editTenantId = '' + } + private l(name: string, values?: any[] | { [key: string]: any }) { return this.$t(name, values).toString() } diff --git a/vueJs/src/views/file-management/index.vue b/vueJs/src/views/file-management/index.vue index ff0c13ab7..ee0055c48 100644 --- a/vueJs/src/views/file-management/index.vue +++ b/vueJs/src/views/file-management/index.vue @@ -382,6 +382,8 @@ export default class extends Vue { // 下载完成后的回调 callback(size) } + }).catch(() => { + callback(size) }) }