mirror of https://github.com/abpframework/abp.git
228 changed files with 11031 additions and 2525 deletions
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
@ -1,3 +1,153 @@ |
|||
# RabbitMQ Background Job Manager |
|||
# RabbitMQ 后台作业管理 |
|||
|
|||
待添加 |
|||
RabbitMQ 是一个标准的消息队列中间件,虽然它常用于消息传递/分布式事件,但也非常适合存储 FIFO(先进先出) 顺序的后台作业. |
|||
|
|||
ABP Framework 提供了 [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) 包,将使用 RabbitMQ 来执行后台作业. |
|||
|
|||
> 参阅 [后台作业文档](Background-Jobs.md) 学习如何使用后台作业系统,本文只介绍了如何安装和配置 RabbitMQ 集成. |
|||
|
|||
## 安装 |
|||
|
|||
使用 ABP CLI 将 [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) 包添加到你的项目: |
|||
|
|||
- 如果之前没有安装过 [ABP CLI](https://docs.abp.io/en/abp/latest/CLI),请先安装它. |
|||
- 跳转到待安装后台作业管理的项目目录中(包含 `.csproj` 文件的目录),打开终端管理器. |
|||
- 执行 `abp add-package Volo.Abp.BackgroundJobs.RabbitMQ` 命令. |
|||
|
|||
如果你想要手动安装,请先用 NuGet 包管理器安装 [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) 包到指定项目,之后使在你的 [模块](Module-Development-Basics.md) 上面添加 `[DependsOn(typeof(AbpBackgroundJobsRabbitMqModule))]` 配置依赖. |
|||
|
|||
## 配置 |
|||
|
|||
### 默认配置 |
|||
|
|||
默认配置将会使用标准端口和主机名(localhost)连接到 RabbitMQ 服务,**你不需要进行额外配置**. |
|||
|
|||
### RabbitMQ 连接 |
|||
|
|||
你可以使用 ASP.NET Core 的 [标准配置系统](Configuration.md) 对 RabbitMQ 进行详细配置,比如 `appsettings.json` 或者是 [选项类](Options.md). |
|||
|
|||
#### 通过 `appsettings.json` 文件配置 |
|||
|
|||
这种方式是配置 RabbitMQ 连接最简单的方式,你可以使用其他的配置源(例如环境变量).这些强大的功能都是由 [ASP.NET Core](https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/) 提供的支持. |
|||
|
|||
**示例: 配置默认的 RabbitMQ 连接** |
|||
|
|||
```json |
|||
{ |
|||
"RabbitMQ": { |
|||
"Connections": { |
|||
"Default": { |
|||
"HostName": "123.123.123.123", |
|||
"Port": "5672" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
你可以在配置文件使用所有 [ConnectionFactry](http://rabbitmq.github.io/rabbitmq-dotnet-client/api/RabbitMQ.Client.ConnectionFactory.html#properties) 的属性,关于这些属性的具体含义,可以查看 RabbitMQ 的 [官方文档](https://www.rabbitmq.com/dotnet-api-guide.html#exchanges-and-queues). |
|||
|
|||
目前我们允许定义多个连接,多连接的情况适用于不同的后台作业,具体配置信息可以参考下面的 RabbitMQ 后台作业配置说明. |
|||
|
|||
**示例: 定义两个 RabbitMQ 连接** |
|||
|
|||
```json |
|||
{ |
|||
"RabbitMQ": { |
|||
"Connections": { |
|||
"Default": { |
|||
"HostName": "123.123.123.123" |
|||
}, |
|||
"SecondConnection": { |
|||
"HostName": "321.321.321.321" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
如果需要连接到 RabbitMQ 集群,你可以指定多个 HostName. |
|||
|
|||
**示例: 连接到 RabbitMQ 集群** |
|||
|
|||
```json |
|||
{ |
|||
"RabbitMQ": { |
|||
"Connections": { |
|||
"Default": { |
|||
"HostName": "123.123.123.123;234.234.234.234" |
|||
} |
|||
}, |
|||
"EventBus": { |
|||
"ClientName": "MyClientName", |
|||
"ExchangeName": "MyExchangeName" |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
#### 使用选项类 |
|||
|
|||
`AbpRabbitMqOptions` 类型用于配置 RabbitMQ 的连接字符串,你可以在 [模块](Module-Development-Basics.md) 的 `ConfigureService` 方法中进行配置. |
|||
|
|||
**示例: 配置 RabbitMQ 连接** |
|||
|
|||
```csharp |
|||
Configure<AbpRabbitMqOptions>(options => |
|||
{ |
|||
options.Connections.Default.UserName = "user"; |
|||
options.Connections.Default.Password = "pass"; |
|||
options.Connections.Default.HostName = "123.123.123.123"; |
|||
options.Connections.Default.Port = 5672; |
|||
}); |
|||
``` |
|||
|
|||
关于选项类,可以结合 `appsettings.json` 文件一起使用.针对同一个属性,在选项类里面对该值进行了设定,会覆盖掉 `appsettings.json` 的值. |
|||
|
|||
### RabbitMQ 后台作业配置说明 |
|||
|
|||
#### 后台作业队列的名称 |
|||
|
|||
默认情况下,每个后台作业都会使用一个单独的队列,结合标准前缀和作业名称来构造一个完整的队列名称.默认的前缀为 `AbpBackgroundJobs`,所以有一个作业的名称是 `EmailSending` 的话,在 RabbitMQ 的队列名称就是 `AbpBackgroundJobs.EmailSending`. |
|||
|
|||
> 在后台作业的参数类上,可以使用 `BackgroundJobName` 特性指定后台作业的名称.否则的话,后台作业的名称将会是后台作业类的全名(也包含命名空间). |
|||
|
|||
#### 后台作业使用的连接 |
|||
|
|||
默认情况下,后台作业都会使用 `Default` 作为默认连接. |
|||
|
|||
#### 自定义 |
|||
|
|||
`AbpRabbitMqBackgroundJobOptions` 可以自定义队列名和作业使用的 RabbitMQ 连接. |
|||
|
|||
**示例: ** |
|||
|
|||
```csharp |
|||
Configure<AbpRabbitMqBackgroundJobOptions>(options => |
|||
{ |
|||
options.DefaultQueueNamePrefix = "my_app_jobs."; |
|||
options.JobQueues[typeof(EmailSendingArgs)] = |
|||
new JobQueueConfiguration( |
|||
typeof(EmailSendingArgs), |
|||
queueName: "my_app_jobs.emails", |
|||
connectionName: "SecondConnection" |
|||
); |
|||
}); |
|||
``` |
|||
|
|||
- 这个示例将默认的队列名前缀设置为 `my_app_jobs.`,如果多个项目都使用的同一个 RabbitMQ 服务,设置不同的前缀可以避免执行其他项目的后台作业. |
|||
- 这里还设置了 `EmailSendingArgs` 绑定的 RabbitMQ 连接. |
|||
|
|||
`JobQueueConfiguration` 类的构造函数中,还有一些其他的可选参数. |
|||
|
|||
- `queueName`: 指定后台作业对应的队列名称(全名). |
|||
- `connectionName`: 后台作业对应的 RabbitMQ 连接名称,默认是 `Default`. |
|||
- `durable`: 可选参数,默认为 `true`. |
|||
- `exclusive`: 可选参数,默认为 `false`. |
|||
- `autoDelete`: 可选参数,默认为 `false`. |
|||
|
|||
如果你想要更多地了解 `durable`,`exclusive`,`autoDelete` 的用法,请阅读 RabbitMQ 提供的文档. |
|||
|
|||
## 另请参阅 |
|||
|
|||
- [后台作业](Background-Jobs.md) |
|||
|
|||
@ -0,0 +1,78 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using Volo.Abp.Cli.Commands; |
|||
|
|||
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
|||
{ |
|||
public class MicroserviceServiceRandomPortStep : ProjectBuildPipelineStep |
|||
{ |
|||
private readonly string _defaultPort = string.Empty; |
|||
private string _tyeFileContent = null; |
|||
|
|||
public MicroserviceServiceRandomPortStep(string defaultPort) |
|||
{ |
|||
_defaultPort = defaultPort; |
|||
} |
|||
|
|||
public override void Execute(ProjectBuildContext context) |
|||
{ |
|||
var newPort = GetNewRandomPort(context); |
|||
|
|||
var targetFiles = context.Files.Where(f=> f.Name.EndsWith("launchSettings.json") || f.Name.EndsWith("appsettings.json")).ToList(); |
|||
|
|||
foreach (var file in targetFiles) |
|||
{ |
|||
file.SetContent(file.Content.Replace(_defaultPort, newPort)); |
|||
} |
|||
} |
|||
|
|||
private string GetNewRandomPort(ProjectBuildContext context) |
|||
{ |
|||
string newPort; |
|||
var rnd = new Random(); |
|||
var tryCount = 0; |
|||
|
|||
do |
|||
{ |
|||
newPort = rnd.Next(44350, 45350).ToString(); |
|||
|
|||
if (tryCount++ > 2000) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
} while (PortExistsForAnotherService(context, newPort)); |
|||
|
|||
return newPort; |
|||
} |
|||
|
|||
private bool PortExistsForAnotherService(ProjectBuildContext context, string newPort) |
|||
{ |
|||
return ReadTyeFileContent(context).SplitToLines().Any(l => l.Contains("port") && l.Contains(newPort)); |
|||
} |
|||
|
|||
private string ReadTyeFileContent(ProjectBuildContext context) |
|||
{ |
|||
if (_tyeFileContent != null) |
|||
{ |
|||
return _tyeFileContent; |
|||
} |
|||
|
|||
var solutionFolderPath = context.BuildArgs.ExtraProperties[NewCommand.Options.OutputFolder.Short] ?? |
|||
context.BuildArgs.ExtraProperties[NewCommand.Options.OutputFolder.Long] ?? |
|||
Directory.GetCurrentDirectory(); |
|||
|
|||
var tyeFilePath = Path.Combine(solutionFolderPath, "tye.yaml"); |
|||
|
|||
if (!File.Exists(tyeFilePath)) |
|||
{ |
|||
return String.Empty; |
|||
} |
|||
|
|||
_tyeFileContent = File.ReadAllText(tyeFilePath); |
|||
|
|||
return _tyeFileContent; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
|||
{ |
|||
public class RemoveProjectFromTyeStep : ProjectBuildPipelineStep |
|||
{ |
|||
private readonly string _name; |
|||
|
|||
public RemoveProjectFromTyeStep(string name) |
|||
{ |
|||
_name = name; |
|||
} |
|||
|
|||
public override void Execute(ProjectBuildContext context) |
|||
{ |
|||
var tyeFile = context.Files.FirstOrDefault(f => f.Name == "/tye.yaml"); |
|||
|
|||
if (tyeFile == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var lines = tyeFile.GetLines(); |
|||
var newLines = new List<string>(); |
|||
|
|||
var nameLine = $"- name:"; |
|||
var isOneOfTargetLines = false; |
|||
|
|||
foreach (var line in lines) |
|||
{ |
|||
if (line.Equals($"{nameLine} {_name}")) |
|||
{ |
|||
isOneOfTargetLines = true; |
|||
continue; |
|||
} |
|||
|
|||
if (line.StartsWith(nameLine)) |
|||
{ |
|||
isOneOfTargetLines = false; |
|||
} |
|||
|
|||
if (!isOneOfTargetLines) |
|||
{ |
|||
newLines.Add(line); |
|||
} |
|||
} |
|||
|
|||
tyeFile.SetContent(String.Join(Environment.NewLine, newLines)); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using Microsoft.Extensions.Logging; |
|||
using Volo.Abp.Logging; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class ServiceCollectionLoggingExtensions |
|||
{ |
|||
public static ILogger<T> GetInitLogger<T>(this IServiceCollection services) |
|||
{ |
|||
return services.GetSingletonInstance<IInitLoggerFactory>().Create<T>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace Volo.Abp.Logging |
|||
{ |
|||
public class AbpInitLogEntry |
|||
{ |
|||
public LogLevel LogLevel { get; set; } |
|||
|
|||
public EventId EventId { get; set; } |
|||
|
|||
public object State { get; set; } |
|||
|
|||
public Exception Exception { get; set; } |
|||
|
|||
public Func<object, Exception, string> Formatter { get; set; } |
|||
|
|||
public string Message => Formatter(State, Exception); |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace Volo.Abp.Logging |
|||
{ |
|||
public class DefaultInitLogger<T> : IInitLogger<T> |
|||
{ |
|||
public List<AbpInitLogEntry> Entries { get; } |
|||
|
|||
public DefaultInitLogger() |
|||
{ |
|||
Entries = new List<AbpInitLogEntry>(); |
|||
} |
|||
|
|||
public virtual void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) |
|||
{ |
|||
Entries.Add(new AbpInitLogEntry |
|||
{ |
|||
LogLevel = logLevel, |
|||
EventId = eventId, |
|||
State = state, |
|||
Exception = exception, |
|||
Formatter = (s, e) => formatter((TState)s, e), |
|||
}); |
|||
} |
|||
|
|||
public virtual bool IsEnabled(LogLevel logLevel) |
|||
{ |
|||
return logLevel != LogLevel.None; |
|||
} |
|||
|
|||
public virtual IDisposable BeginScope<TState>(TState state) |
|||
{ |
|||
return NullDisposable.Instance; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.Logging |
|||
{ |
|||
public class DefaultInitLoggerFactory : IInitLoggerFactory |
|||
{ |
|||
private readonly Dictionary<Type, object> _cache = new Dictionary<Type, object>(); |
|||
|
|||
public virtual IInitLogger<T> Create<T>() |
|||
{ |
|||
return (IInitLogger<T>)_cache.GetOrAdd(typeof(T), () => new DefaultInitLogger<T>());; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace Volo.Abp.Logging |
|||
{ |
|||
public interface IInitLogger<out T> : ILogger<T> |
|||
{ |
|||
public List<AbpInitLogEntry> Entries { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.Logging |
|||
{ |
|||
public interface IInitLoggerFactory |
|||
{ |
|||
IInitLogger<T> Create<T>(); |
|||
} |
|||
} |
|||
@ -1,21 +1,23 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Logging; |
|||
using Volo.Abp.Logging; |
|||
|
|||
namespace Volo.Abp.Modularity.PlugIns |
|||
{ |
|||
public static class PlugInSourceExtensions |
|||
{ |
|||
[NotNull] |
|||
public static Type[] GetModulesWithAllDependencies([NotNull] this IPlugInSource plugInSource) |
|||
public static Type[] GetModulesWithAllDependencies([NotNull] this IPlugInSource plugInSource, ILogger logger) |
|||
{ |
|||
Check.NotNull(plugInSource, nameof(plugInSource)); |
|||
|
|||
return plugInSource |
|||
.GetModules() |
|||
.SelectMany(AbpModuleHelper.FindAllModuleTypes) |
|||
.SelectMany(type => AbpModuleHelper.FindAllModuleTypes(type, logger)) |
|||
.Distinct() |
|||
.ToArray(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,15 @@ |
|||
using System; |
|||
using Volo.Abp.Domain.Entities.Events.Distributed; |
|||
using Volo.Abp.EventBus; |
|||
|
|||
namespace Volo.Abp.Data |
|||
{ |
|||
[Serializable] |
|||
[EventName("abp.data.apply_database_migrations")] |
|||
public class ApplyDatabaseMigrationsEto : EtoBase |
|||
{ |
|||
public Guid? TenantId { get; set; } |
|||
|
|||
public string DatabaseName { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.Http.ProxyScripting.Configuration |
|||
{ |
|||
public static class AbpApiProxyScriptingConfiguration |
|||
{ |
|||
public static Func<PropertyInfo, string> PropertyNameGenerator { get; set; } |
|||
|
|||
static AbpApiProxyScriptingConfiguration() |
|||
{ |
|||
PropertyNameGenerator = propertyInfo => |
|||
{ |
|||
var jsonPropertyNameAttribute = propertyInfo.GetSingleAttributeOrNull<System.Text.Json.Serialization.JsonPropertyNameAttribute>(true); |
|||
|
|||
if (jsonPropertyNameAttribute != null) |
|||
{ |
|||
return jsonPropertyNameAttribute.Name; |
|||
} |
|||
|
|||
var jsonPropertyAttribute = propertyInfo.GetSingleAttributeOrNull<Newtonsoft.Json.JsonPropertyAttribute>(true); |
|||
|
|||
if (jsonPropertyAttribute != null) |
|||
{ |
|||
return jsonPropertyAttribute.PropertyName; |
|||
} |
|||
|
|||
return null; |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,25 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Added_EntityType_to_Media : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "EntityType", |
|||
table: "CmsMediaDescriptors", |
|||
type: "nvarchar(64)", |
|||
maxLength: 64, |
|||
nullable: false, |
|||
defaultValue: ""); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "EntityType", |
|||
table: "CmsMediaDescriptors"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Added_Content_To_BlogPost : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "Content", |
|||
table: "CmsBlogPosts", |
|||
type: "nvarchar(max)", |
|||
maxLength: 2147483647, |
|||
nullable: true); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "Content", |
|||
table: "CmsBlogPosts"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Added_Content_To_Page : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "Content", |
|||
table: "CmsPages", |
|||
type: "nvarchar(max)", |
|||
maxLength: 2147483647, |
|||
nullable: true); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "Content", |
|||
table: "CmsPages"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,56 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class BlogPost_CoverImage : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "CmsContents"); |
|||
|
|||
migrationBuilder.AddColumn<Guid>( |
|||
name: "CoverImageMediaId", |
|||
table: "CmsBlogPosts", |
|||
type: "uniqueidentifier", |
|||
nullable: true); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "CoverImageMediaId", |
|||
table: "CmsBlogPosts"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "CmsContents", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
EntityId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
|||
EntityType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
|||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Value = table.Column<string>(type: "nvarchar(max)", maxLength: 2147483647, nullable: false) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_CmsContents", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_CmsContents_TenantId_EntityType_EntityId", |
|||
table: "CmsContents", |
|||
columns: new[] { "TenantId", "EntityType", "EntityId" }); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
/* |
|||
https://jquery.com/upgrade-guide/3.5/#jquery-htmlprefilter-changes
|
|||
*/ |
|||
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi; |
|||
jQuery.htmlPrefilter = function (html) { |
|||
return html.replace(rxhtmlTag, "<$1></$2>"); |
|||
}; |
|||
@ -1,23 +0,0 @@ |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Validation; |
|||
using Volo.CmsKit.Contents; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
[Serializable] |
|||
public class ContentCreateDto |
|||
{ |
|||
[Required] |
|||
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxEntityTypeLength))] |
|||
public string EntityType { get; set; } |
|||
|
|||
[Required] |
|||
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxEntityIdLength))] |
|||
public string EntityId { get; set; } |
|||
|
|||
[Required] |
|||
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxValueLength))] |
|||
public string Value { get; set; } |
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
[Serializable] |
|||
public class ContentDto : EntityDto<Guid> |
|||
{ |
|||
public string EntityType { get; set; } |
|||
|
|||
public string EntityId { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
} |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
[Serializable] |
|||
public class ContentGetListDto : EntityDto<Guid> |
|||
{ |
|||
public string EntityType { get; set; } |
|||
|
|||
public string EntityId { get; set; } |
|||
} |
|||
} |
|||
@ -1,10 +0,0 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
[Serializable] |
|||
public class ContentGetListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Validation; |
|||
using Volo.CmsKit.Contents; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
[Serializable] |
|||
public class ContentUpdateDto |
|||
{ |
|||
[Required] |
|||
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxValueLength))] |
|||
public string Value { get; set; } |
|||
} |
|||
} |
|||
@ -1,19 +0,0 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.CmsKit.Admin.Contents; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
public interface IContentAdminAppService |
|||
: ICrudAppService< |
|||
ContentDto, |
|||
ContentGetListDto, |
|||
Guid, |
|||
ContentGetListInput, |
|||
ContentCreateDto, |
|||
ContentUpdateDto> |
|||
{ |
|||
Task<ContentDto> GetAsync(string entityType, string entityId); |
|||
} |
|||
} |
|||
@ -1,71 +0,0 @@ |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.CmsKit.Contents; |
|||
using Volo.CmsKit.Permissions; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
|||
public class ContentAdminAppService : |
|||
CrudAppService< |
|||
Content, |
|||
ContentDto, |
|||
ContentGetListDto, |
|||
Guid, |
|||
ContentGetListInput, |
|||
ContentCreateDto, |
|||
ContentUpdateDto |
|||
>, IContentAdminAppService |
|||
{ |
|||
protected IContentManager ContentManager { get; } |
|||
|
|||
protected IContentRepository ContentRepository { get; } |
|||
|
|||
public ContentAdminAppService( |
|||
IRepository<Content, Guid> repository, |
|||
IContentManager contentManager, |
|||
IContentRepository contentRepository) : base(repository) |
|||
{ |
|||
ContentManager = contentManager; |
|||
ContentRepository = contentRepository; |
|||
|
|||
GetListPolicyName = CmsKitAdminPermissions.Contents.Default; |
|||
GetPolicyName = CmsKitAdminPermissions.Contents.Default; |
|||
CreatePolicyName = CmsKitAdminPermissions.Contents.Create; |
|||
UpdatePolicyName = CmsKitAdminPermissions.Contents.Update; |
|||
DeletePolicyName = CmsKitAdminPermissions.Contents.Delete; |
|||
} |
|||
|
|||
[Authorize(CmsKitAdminPermissions.Contents.Create)] |
|||
public override async Task<ContentDto> CreateAsync(ContentCreateDto input) |
|||
{ |
|||
var entity = new Content( |
|||
GuidGenerator.Create(), |
|||
input.EntityType, |
|||
input.EntityId, |
|||
input.Value, |
|||
CurrentTenant?.Id); |
|||
|
|||
await ContentManager.InsertAsync(entity); |
|||
|
|||
return await MapToGetOutputDtoAsync(entity); |
|||
} |
|||
|
|||
public virtual async Task<ContentDto> GetAsync( |
|||
[NotNull] string entityType, |
|||
[NotNull] string entityId) |
|||
{ |
|||
Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); |
|||
Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); |
|||
|
|||
var content = await ContentRepository.GetAsync(entityType, entityId, CurrentTenant?.Id); |
|||
|
|||
return ObjectMapper.Map<Content, ContentDto>(content); |
|||
} |
|||
} |
|||
} |
|||
@ -1,71 +0,0 @@ |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.CmsKit.Admin.Contents; |
|||
using Volo.CmsKit.GlobalFeatures; |
|||
using Volo.CmsKit.Permissions; |
|||
|
|||
namespace Volo.CmsKit.Admin.Contents |
|||
{ |
|||
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
|||
[RequiresGlobalFeature(typeof(ContentsFeature))] |
|||
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
|||
[Area("cms-kit")] |
|||
[Route("api/cms-kit-admin/contents")] |
|||
public class ContentAdminController : CmsKitAdminController, IContentAdminAppService |
|||
{ |
|||
protected IContentAdminAppService ContentAdminAppService { get; } |
|||
|
|||
public ContentAdminController(IContentAdminAppService contentAdminAppService) |
|||
{ |
|||
ContentAdminAppService = contentAdminAppService; |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Authorize(CmsKitAdminPermissions.Contents.Create)] |
|||
public Task<ContentDto> CreateAsync(ContentCreateDto input) |
|||
{ |
|||
return ContentAdminAppService.CreateAsync(input); |
|||
} |
|||
|
|||
[HttpDelete("{id}")] |
|||
[Authorize(CmsKitAdminPermissions.Contents.Delete)] |
|||
public Task DeleteAsync(Guid id) |
|||
{ |
|||
return ContentAdminAppService.DeleteAsync(id); |
|||
} |
|||
|
|||
[HttpGet("{id}")] |
|||
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
|||
public Task<ContentDto> GetAsync(Guid id) |
|||
{ |
|||
return ContentAdminAppService.GetAsync(id); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
|||
public Task<PagedResultDto<ContentGetListDto>> GetListAsync(ContentGetListInput input) |
|||
{ |
|||
return ContentAdminAppService.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Authorize(CmsKitAdminPermissions.Contents.Update)] |
|||
public Task<ContentDto> UpdateAsync(Guid id, ContentUpdateDto input) |
|||
{ |
|||
return ContentAdminAppService.UpdateAsync(id, input); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("{entityType}/{entityId}")] |
|||
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
|||
public Task<ContentDto> GetAsync(string entityType, string entityId) |
|||
{ |
|||
return ContentAdminAppService.GetAsync(entityType, entityId); |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue