committed by
GitHub
146 changed files with 5088 additions and 402 deletions
@ -0,0 +1,62 @@ |
|||||
|
using LINGYUN.Abp.Notifications; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Controllers |
||||
|
{ |
||||
|
[Route("api/app/notifications")] |
||||
|
public class NotificationController : AbpController |
||||
|
{ |
||||
|
private readonly INotificationDispatcher _notificationDispatcher; |
||||
|
public NotificationController( |
||||
|
INotificationDispatcher notificationDispatcher) |
||||
|
{ |
||||
|
_notificationDispatcher = notificationDispatcher; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("Send")] |
||||
|
public async Task SendNofitication([FromForm] SendNotification notification) |
||||
|
{ |
||||
|
var notificationInfo = new NotificationInfo |
||||
|
{ |
||||
|
TenantId = null, |
||||
|
NotificationSeverity = notification.Severity, |
||||
|
NotificationType = NotificationType.Application, |
||||
|
Id = new Random().Next(int.MinValue, int.MaxValue), |
||||
|
Name = "TestApplicationNotofication", |
||||
|
CreationTime = Clock.Now |
||||
|
}; |
||||
|
notificationInfo.Data.Properties["id"] = notificationInfo.Id.ToString(); |
||||
|
notificationInfo.Data.Properties["title"] = notification.Title; |
||||
|
notificationInfo.Data.Properties["message"] = notification.Message; |
||||
|
notificationInfo.Data.Properties["datetime"] = Clock.Now; |
||||
|
notificationInfo.Data.Properties["severity"] = notification.Severity; |
||||
|
|
||||
|
await _notificationDispatcher.DispatcheAsync(notificationInfo); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class SendNotification |
||||
|
{ |
||||
|
public Guid UserId { get; set; } |
||||
|
public string Title { get; set; } |
||||
|
public string Message { get; set; } |
||||
|
public NotificationSeverity Severity { get; set; } = NotificationSeverity.Success; |
||||
|
} |
||||
|
|
||||
|
public class TestApplicationNotificationData : NotificationData |
||||
|
{ |
||||
|
public object Message |
||||
|
{ |
||||
|
get { return this[nameof(Message)]; } |
||||
|
set |
||||
|
{ |
||||
|
Properties[nameof(Message)] = value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore |
||||
|
{ |
||||
|
public class MessageServiceHostMigrationsDbContext : AbpDbContext<MessageServiceHostMigrationsDbContext> |
||||
|
{ |
||||
|
public MessageServiceHostMigrationsDbContext(DbContextOptions<MessageServiceHostMigrationsDbContext> options) |
||||
|
: base(options) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
base.OnModelCreating(modelBuilder); |
||||
|
|
||||
|
modelBuilder.ConfigureMessageService(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
using System.IO; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Design; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore |
||||
|
{ |
||||
|
public class MessageServiceHostMigrationsDbContextFactory : IDesignTimeDbContextFactory<MessageServiceHostMigrationsDbContext> |
||||
|
{ |
||||
|
public MessageServiceHostMigrationsDbContext CreateDbContext(string[] args) |
||||
|
{ |
||||
|
var configuration = BuildConfiguration(); |
||||
|
|
||||
|
var builder = new DbContextOptionsBuilder<MessageServiceHostMigrationsDbContext>() |
||||
|
.UseMySql(configuration.GetConnectionString("Default")); |
||||
|
|
||||
|
return new MessageServiceHostMigrationsDbContext(builder.Options); |
||||
|
} |
||||
|
|
||||
|
private static IConfigurationRoot BuildConfiguration() |
||||
|
{ |
||||
|
var builder = new ConfigurationBuilder() |
||||
|
.SetBasePath(Directory.GetCurrentDirectory()) |
||||
|
.AddJsonFile("appsettings.Development.json", optional: false); |
||||
|
|
||||
|
return builder.Build(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp3.1</TargetFramework> |
||||
|
<RootNamespace>LINGYUN.Abp.MessageService</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3"> |
||||
|
<PrivateAssets>all</PrivateAssets> |
||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> |
||||
|
</PackageReference> |
||||
|
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.1.3" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="3.1.3" /> |
||||
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> |
||||
|
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" /> |
||||
|
<PackageReference Include="Serilog.Enrichers.Assembly" Version="2.0.0" /> |
||||
|
<PackageReference Include="Serilog.Enrichers.Process" Version="2.0.1" /> |
||||
|
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" /> |
||||
|
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" /> |
||||
|
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" /> |
||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.4.1" /> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="2.8.0" /> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="2.8.0" /> |
||||
|
<PackageReference Include="Volo.Abp.Autofac" Version="2.8.0" /> |
||||
|
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="2.8.0" /> |
||||
|
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.8.0" /> |
||||
|
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.8.0" /> |
||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.8.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" /> |
||||
|
<ProjectReference Include="..\modules\common\LINGYUN.Abp.IM.SignalR\LINGYUN.Abp.IM.SignalR.csproj" /> |
||||
|
<ProjectReference Include="..\modules\common\LINGYUN.Abp.Notifications.SignalR\LINGYUN.Abp.Notifications.SignalR.csproj" /> |
||||
|
<ProjectReference Include="..\modules\message\LINGYUN.Abp.MessageService.EntityFrameworkCore\LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj" /> |
||||
|
<ProjectReference Include="..\modules\message\LINGYUN.Abp.MessageService.HttpApi\LINGYUN.Abp.MessageService.HttpApi.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,152 @@ |
|||||
|
using IdentityModel; |
||||
|
using LINGYUN.Abp.IM.SignalR; |
||||
|
using LINGYUN.Abp.MessageService.EntityFrameworkCore; |
||||
|
using LINGYUN.Abp.MessageService.MultiTenancy; |
||||
|
using LINGYUN.Abp.Notifications.SignalR; |
||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.DataProtection; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Hosting; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Microsoft.OpenApi.Models; |
||||
|
using StackExchange.Redis; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Authentication.JwtBearer; |
||||
|
using Volo.Abp.AspNetCore.MultiTenancy; |
||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.PermissionManagement.EntityFrameworkCore; |
||||
|
using Volo.Abp.Security.Claims; |
||||
|
using Volo.Abp.SettingManagement.EntityFrameworkCore; |
||||
|
using Volo.Abp.TenantManagement.EntityFrameworkCore; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpMessageServiceHttpApiModule), |
||||
|
typeof(AbpAspNetCoreMultiTenancyModule), |
||||
|
typeof(AbpMessageServiceEntityFrameworkCoreModule), |
||||
|
typeof(AbpTenantManagementEntityFrameworkCoreModule), |
||||
|
typeof(AbpSettingManagementEntityFrameworkCoreModule), |
||||
|
typeof(AbpPermissionManagementEntityFrameworkCoreModule), |
||||
|
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), |
||||
|
typeof(AbpIMSignalRModule), |
||||
|
typeof(AbpNotificationsSignalRModule), |
||||
|
typeof(AbpAutofacModule) |
||||
|
)] |
||||
|
public class AbpMessageServiceHttpApiHostModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
||||
|
var configuration = hostingEnvironment.BuildConfiguration(); |
||||
|
// 配置Ef
|
||||
|
Configure<AbpDbContextOptions>(options => |
||||
|
{ |
||||
|
options.UseMySQL(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpMessageServiceHttpApiHostModule>("LINGYUN.Abp.MessageService"); |
||||
|
}); |
||||
|
|
||||
|
// 多租户
|
||||
|
Configure<AbpMultiTenancyOptions>(options => |
||||
|
{ |
||||
|
options.IsEnabled = true; |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpTenantResolveOptions>(options => |
||||
|
{ |
||||
|
options.TenantResolvers.Insert(0, new AuthorizationTenantResolveContributor()); |
||||
|
}); |
||||
|
|
||||
|
// Swagger
|
||||
|
context.Services.AddSwaggerGen( |
||||
|
options => |
||||
|
{ |
||||
|
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MessageService API", Version = "v1" }); |
||||
|
options.DocInclusionPredicate((docName, description) => true); |
||||
|
options.CustomSchemaIds(type => type.FullName); |
||||
|
}); |
||||
|
|
||||
|
// 支持本地化语言类型
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Languages.Add(new LanguageInfo("en", "en", "English")); |
||||
|
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); |
||||
|
}); |
||||
|
|
||||
|
context.Services.AddAuthentication("Bearer") |
||||
|
.AddIdentityServerAuthentication(options => |
||||
|
{ |
||||
|
options.Authority = configuration["AuthServer:Authority"]; |
||||
|
options.RequireHttpsMetadata = false; |
||||
|
options.ApiName = configuration["AuthServer:ApiName"]; |
||||
|
AbpClaimTypes.UserId = JwtClaimTypes.Subject; |
||||
|
AbpClaimTypes.UserName = JwtClaimTypes.Name; |
||||
|
AbpClaimTypes.Role = JwtClaimTypes.Role; |
||||
|
AbpClaimTypes.Email = JwtClaimTypes.Email; |
||||
|
}); |
||||
|
|
||||
|
context.Services.AddStackExchangeRedisCache(options => |
||||
|
{ |
||||
|
options.Configuration = configuration["RedisCache:ConnectString"]; |
||||
|
var instanceName = configuration["RedisCache:RedisPrefix"]; |
||||
|
options.InstanceName = instanceName.IsNullOrEmpty() ? "MessageService_Cache" : instanceName; |
||||
|
}); |
||||
|
|
||||
|
if (!hostingEnvironment.IsDevelopment()) |
||||
|
{ |
||||
|
var redis = ConnectionMultiplexer.Connect(configuration["RedisCache:ConnectString"]); |
||||
|
context.Services |
||||
|
.AddDataProtection() |
||||
|
.PersistKeysToStackExchangeRedis(redis, "MessageService-Protection-Keys"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
||||
|
{ |
||||
|
var app = context.GetApplicationBuilder(); |
||||
|
// http调用链
|
||||
|
app.UseCorrelationId(); |
||||
|
// 虚拟文件系统
|
||||
|
app.UseVirtualFiles(); |
||||
|
// 本地化
|
||||
|
app.UseAbpRequestLocalization(); |
||||
|
//路由
|
||||
|
app.UseRouting(); |
||||
|
// 加入自定义中间件
|
||||
|
app.UseMiddleware<SignalRJwtTokenMiddleware>(); |
||||
|
// 认证
|
||||
|
app.UseAuthentication(); |
||||
|
// jwt
|
||||
|
app.UseJwtTokenMiddleware(); |
||||
|
// 授权
|
||||
|
app.UseAuthorization(); |
||||
|
// 多租户
|
||||
|
app.UseMultiTenancy(); |
||||
|
// Swagger
|
||||
|
app.UseSwagger(); |
||||
|
// Swagger可视化界面
|
||||
|
app.UseSwaggerUI(options => |
||||
|
{ |
||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support MessageService API"); |
||||
|
}); |
||||
|
// 审计日志
|
||||
|
app.UseAuditing(); |
||||
|
// 路由
|
||||
|
app.UseConfiguredEndpoints(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using DotNetCore.CAP.Internal; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Utils |
||||
|
{ |
||||
|
[Dependency(ServiceLifetime.Singleton, TryRegister = true)] |
||||
|
[ExposeServices(typeof(ISnowflakeIdGenerator))] |
||||
|
public class SnowflakeIdGenerator : ISnowflakeIdGenerator |
||||
|
{ |
||||
|
public long Create() |
||||
|
{ |
||||
|
return SnowflakeId.Default().NextId(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,130 @@ |
|||||
|
// <auto-generated />
|
||||
|
using System; |
||||
|
using LINGYUN.Abp.MessageService.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Migrations |
||||
|
{ |
||||
|
[DbContext(typeof(MessageServiceHostMigrationsDbContext))] |
||||
|
[Migration("20200601060701_Add-Abp-Message-Service-Module")] |
||||
|
partial class AddAbpMessageServiceModule |
||||
|
{ |
||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
#pragma warning disable 612, 618
|
||||
|
modelBuilder |
||||
|
.HasAnnotation("ProductVersion", "3.1.3") |
||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<DateTime?>("ExpirationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<string>("NotificationData") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(1048576); |
||||
|
|
||||
|
b.Property<long>("NotificationId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("NotificationName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(100) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(100); |
||||
|
|
||||
|
b.Property<string>("NotificationTypeName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(512) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(512); |
||||
|
|
||||
|
b.Property<sbyte>("Severity") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("Type") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("NotificationName"); |
||||
|
|
||||
|
b.ToTable("AppNotifications"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<long>("NotificationId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<sbyte>("ReadStatus") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId", "NotificationId") |
||||
|
.HasName("IX_Tenant_User_Notification_Id"); |
||||
|
|
||||
|
b.ToTable("AppUserNotifications"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<string>("NotificationName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(100) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(100); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId", "NotificationName") |
||||
|
.IsUnique() |
||||
|
.HasName("IX_Tenant_User_Notification_Name"); |
||||
|
|
||||
|
b.ToTable("AppUserSubscribes"); |
||||
|
}); |
||||
|
#pragma warning restore 612, 618
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,93 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Metadata; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Migrations |
||||
|
{ |
||||
|
public partial class AddAbpMessageServiceModule : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppNotifications", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
Severity = table.Column<sbyte>(nullable: false), |
||||
|
Type = table.Column<int>(nullable: false), |
||||
|
NotificationId = table.Column<long>(nullable: false), |
||||
|
NotificationName = table.Column<string>(maxLength: 100, nullable: false), |
||||
|
NotificationData = table.Column<string>(maxLength: 1048576, nullable: false), |
||||
|
NotificationTypeName = table.Column<string>(maxLength: 512, nullable: false), |
||||
|
ExpirationTime = table.Column<DateTime>(nullable: true), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppNotifications", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppUserNotifications", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
UserId = table.Column<Guid>(nullable: false), |
||||
|
NotificationId = table.Column<long>(nullable: false), |
||||
|
ReadStatus = table.Column<sbyte>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppUserNotifications", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppUserSubscribes", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
NotificationName = table.Column<string>(maxLength: 100, nullable: false), |
||||
|
UserId = table.Column<Guid>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppUserSubscribes", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppNotifications_NotificationName", |
||||
|
table: "AppNotifications", |
||||
|
column: "NotificationName"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_Tenant_User_Notification_Id", |
||||
|
table: "AppUserNotifications", |
||||
|
columns: new[] { "TenantId", "UserId", "NotificationId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_Tenant_User_Notification_Name", |
||||
|
table: "AppUserSubscribes", |
||||
|
columns: new[] { "TenantId", "UserId", "NotificationName" }, |
||||
|
unique: true); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppNotifications"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppUserNotifications"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppUserSubscribes"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,494 @@ |
|||||
|
// <auto-generated />
|
||||
|
using System; |
||||
|
using LINGYUN.Abp.MessageService.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Migrations |
||||
|
{ |
||||
|
[DbContext(typeof(MessageServiceHostMigrationsDbContext))] |
||||
|
[Migration("20200602134027_Add-Chat-Message-Entites")] |
||||
|
partial class AddChatMessageEntites |
||||
|
{ |
||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
#pragma warning disable 612, 618
|
||||
|
modelBuilder |
||||
|
.HasAnnotation("ProductVersion", "3.1.3") |
||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("Address") |
||||
|
.HasColumnType("varchar(256) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(256); |
||||
|
|
||||
|
b.Property<bool>("AllowAnonymous") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSendMessage") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnName("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Description") |
||||
|
.HasColumnType("varchar(128) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(128); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnName("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnName("LastModifierId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("MaxUserCount") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(20) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(20); |
||||
|
|
||||
|
b.Property<string>("Notice") |
||||
|
.HasColumnType("varchar(64) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(64); |
||||
|
|
||||
|
b.Property<string>("Tag") |
||||
|
.HasColumnType("varchar(512) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(512); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "Name"); |
||||
|
|
||||
|
b.ToTable("AppChatGroups"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroupAdmin", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<bool>("AllowAddPeople") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowDissolveGroup") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowKickPeople") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSendNotice") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSilence") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<bool>("IsSuperAdmin") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId"); |
||||
|
|
||||
|
b.ToTable("AppChatGroupAdmins"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupChatBlack", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<Guid>("ShieldUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId"); |
||||
|
|
||||
|
b.ToTable("AppGroupChatBlacks"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupMessage", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("Content") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(1048576); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<long>("MessageId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<sbyte>("SendState") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<string>("SendUserName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(64) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(64); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("Type") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId"); |
||||
|
|
||||
|
b.ToTable("AppGroupMessages"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatBlack", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("ShieldUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserChatBlacks"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatGroup", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnName("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserChatGroups"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatSetting", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<bool>("AllowAddFriend") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowAnonymous") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowReceiveMessage") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSendMessage") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("RequireAddFriendValition") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserChatSettings"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserMessage", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("Content") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(1048576); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("MessageId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<Guid>("ReceiveUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<sbyte>("SendState") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<string>("SendUserName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(64) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(64); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("Type") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "ReceiveUserId"); |
||||
|
|
||||
|
b.ToTable("AppUserMessages"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserSpecialFocus", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("FocusUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserSpecialFocuss"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<DateTime?>("ExpirationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<string>("NotificationData") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(1048576); |
||||
|
|
||||
|
b.Property<long>("NotificationId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("NotificationName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(100) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(100); |
||||
|
|
||||
|
b.Property<string>("NotificationTypeName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(512) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(512); |
||||
|
|
||||
|
b.Property<sbyte>("Severity") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("Type") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("NotificationName"); |
||||
|
|
||||
|
b.ToTable("AppNotifications"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<long>("NotificationId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<int>("ReadStatus") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId", "NotificationId") |
||||
|
.HasName("IX_Tenant_User_Notification_Id"); |
||||
|
|
||||
|
b.ToTable("AppUserNotifications"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<string>("NotificationName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(100) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(100); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId", "NotificationName") |
||||
|
.IsUnique() |
||||
|
.HasName("IX_Tenant_User_Notification_Name"); |
||||
|
|
||||
|
b.ToTable("AppUserSubscribes"); |
||||
|
}); |
||||
|
#pragma warning restore 612, 618
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,281 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Metadata; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Migrations |
||||
|
{ |
||||
|
public partial class AddChatMessageEntites : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.AlterColumn<int>( |
||||
|
name: "ReadStatus", |
||||
|
table: "AppUserNotifications", |
||||
|
nullable: false, |
||||
|
oldClrType: typeof(sbyte), |
||||
|
oldType: "tinyint"); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppChatGroupAdmins", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
LastModificationTime = table.Column<DateTime>(nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
GroupId = table.Column<long>(nullable: false), |
||||
|
UserId = table.Column<Guid>(nullable: false), |
||||
|
IsSuperAdmin = table.Column<bool>(nullable: false), |
||||
|
AllowSilence = table.Column<bool>(nullable: false), |
||||
|
AllowKickPeople = table.Column<bool>(nullable: false), |
||||
|
AllowAddPeople = table.Column<bool>(nullable: false), |
||||
|
AllowSendNotice = table.Column<bool>(nullable: false), |
||||
|
AllowDissolveGroup = table.Column<bool>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppChatGroupAdmins", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppChatGroups", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
LastModificationTime = table.Column<DateTime>(nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
GroupId = table.Column<long>(nullable: false), |
||||
|
Name = table.Column<string>(maxLength: 20, nullable: false), |
||||
|
Tag = table.Column<string>(maxLength: 512, nullable: true), |
||||
|
Address = table.Column<string>(maxLength: 256, nullable: true), |
||||
|
Notice = table.Column<string>(maxLength: 64, nullable: true), |
||||
|
MaxUserCount = table.Column<int>(nullable: false), |
||||
|
AllowAnonymous = table.Column<bool>(nullable: false), |
||||
|
AllowSendMessage = table.Column<bool>(nullable: false), |
||||
|
Description = table.Column<string>(maxLength: 128, nullable: true) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppChatGroups", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppGroupChatBlacks", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
GroupId = table.Column<long>(nullable: false), |
||||
|
ShieldUserId = table.Column<Guid>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppGroupChatBlacks", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppGroupMessages", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
MessageId = table.Column<long>(nullable: false), |
||||
|
SendUserName = table.Column<string>(maxLength: 64, nullable: false), |
||||
|
Content = table.Column<string>(maxLength: 1048576, nullable: false), |
||||
|
Type = table.Column<int>(nullable: false), |
||||
|
SendState = table.Column<sbyte>(nullable: false), |
||||
|
GroupId = table.Column<long>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppGroupMessages", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppUserChatBlacks", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
UserId = table.Column<Guid>(nullable: false), |
||||
|
ShieldUserId = table.Column<Guid>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppUserChatBlacks", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppUserChatGroups", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
UserId = table.Column<Guid>(nullable: false), |
||||
|
GroupId = table.Column<long>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppUserChatGroups", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppUserChatSettings", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
UserId = table.Column<Guid>(nullable: false), |
||||
|
AllowAnonymous = table.Column<bool>(nullable: false), |
||||
|
AllowAddFriend = table.Column<bool>(nullable: false), |
||||
|
RequireAddFriendValition = table.Column<bool>(nullable: false), |
||||
|
AllowReceiveMessage = table.Column<bool>(nullable: false), |
||||
|
AllowSendMessage = table.Column<bool>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppUserChatSettings", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppUserMessages", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
MessageId = table.Column<long>(nullable: false), |
||||
|
SendUserName = table.Column<string>(maxLength: 64, nullable: false), |
||||
|
Content = table.Column<string>(maxLength: 1048576, nullable: false), |
||||
|
Type = table.Column<int>(nullable: false), |
||||
|
SendState = table.Column<sbyte>(nullable: false), |
||||
|
ReceiveUserId = table.Column<Guid>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppUserMessages", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AppUserSpecialFocuss", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<long>(nullable: false) |
||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), |
||||
|
CreationTime = table.Column<DateTime>(nullable: false), |
||||
|
CreatorId = table.Column<Guid>(nullable: true), |
||||
|
TenantId = table.Column<Guid>(nullable: true), |
||||
|
UserId = table.Column<Guid>(nullable: false), |
||||
|
FocusUserId = table.Column<Guid>(nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AppUserSpecialFocuss", x => x.Id); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppChatGroupAdmins_TenantId_GroupId", |
||||
|
table: "AppChatGroupAdmins", |
||||
|
columns: new[] { "TenantId", "GroupId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppChatGroups_TenantId_Name", |
||||
|
table: "AppChatGroups", |
||||
|
columns: new[] { "TenantId", "Name" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppGroupChatBlacks_TenantId_GroupId", |
||||
|
table: "AppGroupChatBlacks", |
||||
|
columns: new[] { "TenantId", "GroupId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppGroupMessages_TenantId_GroupId", |
||||
|
table: "AppGroupMessages", |
||||
|
columns: new[] { "TenantId", "GroupId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppUserChatBlacks_TenantId_UserId", |
||||
|
table: "AppUserChatBlacks", |
||||
|
columns: new[] { "TenantId", "UserId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppUserChatGroups_TenantId_GroupId_UserId", |
||||
|
table: "AppUserChatGroups", |
||||
|
columns: new[] { "TenantId", "GroupId", "UserId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppUserChatSettings_TenantId_UserId", |
||||
|
table: "AppUserChatSettings", |
||||
|
columns: new[] { "TenantId", "UserId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppUserMessages_TenantId_ReceiveUserId", |
||||
|
table: "AppUserMessages", |
||||
|
columns: new[] { "TenantId", "ReceiveUserId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AppUserSpecialFocuss_TenantId_UserId", |
||||
|
table: "AppUserSpecialFocuss", |
||||
|
columns: new[] { "TenantId", "UserId" }); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppChatGroupAdmins"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppChatGroups"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppGroupChatBlacks"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppGroupMessages"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppUserChatBlacks"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppUserChatGroups"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppUserChatSettings"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppUserMessages"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AppUserSpecialFocuss"); |
||||
|
|
||||
|
migrationBuilder.AlterColumn<sbyte>( |
||||
|
name: "ReadStatus", |
||||
|
table: "AppUserNotifications", |
||||
|
type: "tinyint", |
||||
|
nullable: false, |
||||
|
oldClrType: typeof(int)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,492 @@ |
|||||
|
// <auto-generated />
|
||||
|
using System; |
||||
|
using LINGYUN.Abp.MessageService.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Migrations |
||||
|
{ |
||||
|
[DbContext(typeof(MessageServiceHostMigrationsDbContext))] |
||||
|
partial class MessageServiceHostMigrationsDbContextModelSnapshot : ModelSnapshot |
||||
|
{ |
||||
|
protected override void BuildModel(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
#pragma warning disable 612, 618
|
||||
|
modelBuilder |
||||
|
.HasAnnotation("ProductVersion", "3.1.3") |
||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("Address") |
||||
|
.HasColumnType("varchar(256) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(256); |
||||
|
|
||||
|
b.Property<bool>("AllowAnonymous") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSendMessage") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnName("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Description") |
||||
|
.HasColumnType("varchar(128) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(128); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnName("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnName("LastModifierId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("MaxUserCount") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(20) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(20); |
||||
|
|
||||
|
b.Property<string>("Notice") |
||||
|
.HasColumnType("varchar(64) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(64); |
||||
|
|
||||
|
b.Property<string>("Tag") |
||||
|
.HasColumnType("varchar(512) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(512); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "Name"); |
||||
|
|
||||
|
b.ToTable("AppChatGroups"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroupAdmin", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<bool>("AllowAddPeople") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowDissolveGroup") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowKickPeople") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSendNotice") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSilence") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<bool>("IsSuperAdmin") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId"); |
||||
|
|
||||
|
b.ToTable("AppChatGroupAdmins"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupChatBlack", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<Guid>("ShieldUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId"); |
||||
|
|
||||
|
b.ToTable("AppGroupChatBlacks"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupMessage", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("Content") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(1048576); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<long>("MessageId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<sbyte>("SendState") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<string>("SendUserName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(64) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(64); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("Type") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId"); |
||||
|
|
||||
|
b.ToTable("AppGroupMessages"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatBlack", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("ShieldUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserChatBlacks"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatGroup", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnName("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("GroupId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "GroupId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserChatGroups"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatSetting", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<bool>("AllowAddFriend") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowAnonymous") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowReceiveMessage") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("AllowSendMessage") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("RequireAddFriendValition") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserChatSettings"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserMessage", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("Content") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(1048576); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<long>("MessageId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<Guid>("ReceiveUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<sbyte>("SendState") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<string>("SendUserName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(64) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(64); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("Type") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "ReceiveUserId"); |
||||
|
|
||||
|
b.ToTable("AppUserMessages"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserSpecialFocus", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("FocusUserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId"); |
||||
|
|
||||
|
b.ToTable("AppUserSpecialFocuss"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<DateTime?>("ExpirationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<string>("NotificationData") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(1048576); |
||||
|
|
||||
|
b.Property<long>("NotificationId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<string>("NotificationName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(100) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(100); |
||||
|
|
||||
|
b.Property<string>("NotificationTypeName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(512) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(512); |
||||
|
|
||||
|
b.Property<sbyte>("Severity") |
||||
|
.HasColumnType("tinyint"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<int>("Type") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("NotificationName"); |
||||
|
|
||||
|
b.ToTable("AppNotifications"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<long>("NotificationId") |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<int>("ReadStatus") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId", "NotificationId") |
||||
|
.HasName("IX_Tenant_User_Notification_Id"); |
||||
|
|
||||
|
b.ToTable("AppUserNotifications"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b => |
||||
|
{ |
||||
|
b.Property<long>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("bigint"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnName("CreationTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<string>("NotificationName") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("varchar(100) CHARACTER SET utf8mb4") |
||||
|
.HasMaxLength(100); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnName("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid>("UserId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "UserId", "NotificationName") |
||||
|
.IsUnique() |
||||
|
.HasName("IX_Tenant_User_Notification_Name"); |
||||
|
|
||||
|
b.ToTable("AppUserSubscribes"); |
||||
|
}); |
||||
|
#pragma warning restore 612, 618
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.AspNetCore.MultiTenancy; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Security.Claims; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.MultiTenancy |
||||
|
{ |
||||
|
public class AuthorizationTenantResolveContributor : HttpTenantResolveContributorBase |
||||
|
{ |
||||
|
public override string Name => "Authorization"; |
||||
|
|
||||
|
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) |
||||
|
{ |
||||
|
if (httpContext.User?.Identity == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
if (!httpContext.User.Identity.IsAuthenticated) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
var tenantIdKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey; |
||||
|
|
||||
|
var tenantClaim = httpContext.User.Claims.FirstOrDefault(x => x.Type.Equals(AbpClaimTypes.TenantId)); |
||||
|
|
||||
|
if (tenantClaim == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return tenantClaim.Value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.Hosting; |
||||
|
using Serilog; |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService |
||||
|
{ |
||||
|
public class Program |
||||
|
{ |
||||
|
public static int Main(string[] args) |
||||
|
{ |
||||
|
var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"; |
||||
|
var configuration = new ConfigurationBuilder() |
||||
|
.SetBasePath(Directory.GetCurrentDirectory()) |
||||
|
.AddJsonFile($"appsettings.{env}.json", optional: false, reloadOnChange: true) |
||||
|
.AddEnvironmentVariables() |
||||
|
.Build(); |
||||
|
Log.Logger = new LoggerConfiguration() |
||||
|
.ReadFrom.Configuration(configuration) |
||||
|
.CreateLogger(); |
||||
|
try |
||||
|
{ |
||||
|
Log.Information("Starting web host."); |
||||
|
CreateHostBuilder(args).Build().Run(); |
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Log.Fatal(ex, "Host terminated unexpectedly!"); |
||||
|
return 1; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
Log.CloseAndFlush(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
internal static IHostBuilder CreateHostBuilder(string[] args) => |
||||
|
Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args) |
||||
|
.ConfigureWebHostDefaults(webBuilder => |
||||
|
{ |
||||
|
webBuilder.UseStartup<Startup>(); |
||||
|
}) |
||||
|
.UseSerilog() |
||||
|
.UseAutofac(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:63963", |
||||
|
"sslPort": 0 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"LINGYUN.Abp.MessageService.HttpApi.Host": { |
||||
|
"commandName": "Project", |
||||
|
"launchBrowser": false, |
||||
|
"applicationUrl": "http://localhost:30020", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService |
||||
|
{ |
||||
|
public class Startup |
||||
|
{ |
||||
|
public void ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
services.AddApplication<AbpMessageServiceHttpApiHostModule>(); |
||||
|
} |
||||
|
|
||||
|
public void Configure(IApplicationBuilder app) |
||||
|
{ |
||||
|
app.InitializeApplication(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,77 @@ |
|||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using LINGYUN.Abp.RealTime.Client; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.SignalR; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IM.SignalR.Hubs |
||||
|
{ |
||||
|
[Authorize] |
||||
|
public class MessageHub : OnlineClientHubBase |
||||
|
{ |
||||
|
private readonly IMessageStore _messageStore; |
||||
|
|
||||
|
public MessageHub( |
||||
|
IMessageStore messageStore) |
||||
|
{ |
||||
|
_messageStore = messageStore; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 客户端调用发送消息方法
|
||||
|
/// </summary>
|
||||
|
/// <param name="chatMessage"></param>
|
||||
|
/// <returns></returns>
|
||||
|
[HubMethodName("SendMessage")] |
||||
|
public virtual async Task SendMessageAsync(ChatMessage chatMessage) |
||||
|
{ |
||||
|
// 持久化
|
||||
|
await _messageStore.StoreMessageAsync(chatMessage); |
||||
|
|
||||
|
if (!chatMessage.GroupId.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
var signalRClient = Clients.Group(chatMessage.GroupId); |
||||
|
if (signalRClient == null) |
||||
|
{ |
||||
|
Logger.LogDebug("Can not get group " + chatMessage.GroupId + " from SignalR hub!"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
await signalRClient.SendAsync("getChatMessage", chatMessage); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Logger.LogWarning("Could not send message to group: {0}", chatMessage.GroupId); |
||||
|
Logger.LogWarning("Send group message error: {0}", ex.Message); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId.GetValueOrDefault()); |
||||
|
var onlineClients = OnlineClientManager.GetAllByContext(onlineClientContext); |
||||
|
foreach (var onlineClient in onlineClients) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
var signalRClient = Clients.Client(onlineClient.ConnectionId); |
||||
|
if (signalRClient == null) |
||||
|
{ |
||||
|
Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!"); |
||||
|
continue; |
||||
|
} |
||||
|
await signalRClient.SendAsync("getChatMessage", chatMessage); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Logger.LogWarning("Could not send message to user: {0}", chatMessage.ToUserId); |
||||
|
Logger.LogWarning("Send to user message error: {0}", ex.Message); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,101 @@ |
|||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using LINGYUN.Abp.IM.SignalR.Hubs; |
||||
|
using LINGYUN.Abp.RealTime.Client; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IM.SignalR.Messages |
||||
|
{ |
||||
|
public class SignalRMessageSender : IMessageSender, ITransientDependency |
||||
|
{ |
||||
|
public ILogger<SignalRMessageSender> Logger { protected get; set; } |
||||
|
|
||||
|
private readonly IOnlineClientManager _onlineClientManager; |
||||
|
|
||||
|
private readonly IHubContext<MessageHub> _hubContext; |
||||
|
|
||||
|
private readonly IMessageStore _messageStore; |
||||
|
|
||||
|
public SignalRMessageSender( |
||||
|
IOnlineClientManager onlineClientManager, |
||||
|
IHubContext<MessageHub> hubContext, |
||||
|
IMessageStore messageStore) |
||||
|
{ |
||||
|
_hubContext = hubContext; |
||||
|
_messageStore = messageStore; |
||||
|
_onlineClientManager = onlineClientManager; |
||||
|
|
||||
|
Logger = NullLogger<SignalRMessageSender>.Instance; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 服务端调用发送消息方法
|
||||
|
/// </summary>
|
||||
|
/// <param name="chatMessage"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public async Task SendMessageAsync(ChatMessage chatMessage) |
||||
|
{ |
||||
|
// 持久化
|
||||
|
await _messageStore.StoreMessageAsync(chatMessage); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
if (!chatMessage.GroupId.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
await SendMessageToGroupAsync(chatMessage); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
await SendMessageToUserAsync(chatMessage); |
||||
|
} |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Logger.LogWarning("Could not send message, group: {0}, formUser: {1}, toUser: {2}", |
||||
|
chatMessage.GroupId, chatMessage.FormUserName, |
||||
|
chatMessage.ToUserId.HasValue ? chatMessage.ToUserId.ToString() : "None"); |
||||
|
Logger.LogWarning("Send group message error: {0}", ex.Message); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task SendMessageToGroupAsync(ChatMessage chatMessage) |
||||
|
{ |
||||
|
var signalRClient = _hubContext.Clients.Group(chatMessage.GroupId); |
||||
|
if (signalRClient == null) |
||||
|
{ |
||||
|
Logger.LogDebug("Can not get group " + chatMessage.GroupId + " from SignalR hub!"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
await signalRClient.SendAsync("getChatMessage", chatMessage); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task SendMessageToUserAsync(ChatMessage chatMessage) |
||||
|
{ |
||||
|
var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId.Value); |
||||
|
var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext); |
||||
|
foreach (var onlineClient in onlineClients) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId); |
||||
|
if (signalRClient == null) |
||||
|
{ |
||||
|
Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!"); |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
await signalRClient.SendAsync("getChatMessage", chatMessage); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Logger.LogWarning("Could not send message to user: {0}", chatMessage.ToUserId); |
||||
|
Logger.LogWarning("Send to user message error: {0}", ex.Message); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
namespace LINGYUN.Abp.IM.Group |
||||
|
{ |
||||
|
public class Group |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 群组名称
|
||||
|
/// </summary>
|
||||
|
public string Name { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许匿名聊天
|
||||
|
/// </summary>
|
||||
|
public bool AllowAnonymous { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许发送消息
|
||||
|
/// </summary>
|
||||
|
public bool AllowSendMessage { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 最大用户数
|
||||
|
/// </summary>
|
||||
|
public int MaxUserLength { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群组用户数
|
||||
|
/// </summary>
|
||||
|
public int GroupUserCount { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IM.Group |
||||
|
{ |
||||
|
public interface IUserGroupStore |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 获取用户所在通讯组列表
|
||||
|
/// </summary>
|
||||
|
/// <param name="tenantId"></param>
|
||||
|
/// <param name="userId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<IEnumerable<Group>> GetUserGroupsAsync(Guid? tenantId, Guid userId); |
||||
|
/// <summary>
|
||||
|
/// 获取通讯组所有用户
|
||||
|
/// </summary>
|
||||
|
/// <param name="tenantId"></param>
|
||||
|
/// <param name="groupId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<IEnumerable<UserGroup>> GetGroupUsersAsync(Guid? tenantId, long groupId); |
||||
|
/// <summary>
|
||||
|
/// 用户加入通讯组
|
||||
|
/// </summary>
|
||||
|
/// <param name="tenantId"></param>
|
||||
|
/// <param name="userId"></param>
|
||||
|
/// <param name="groupId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId, Guid acceptUserId); |
||||
|
/// <summary>
|
||||
|
/// 用户退出通讯组
|
||||
|
/// </summary>
|
||||
|
/// <param name="tenantId"></param>
|
||||
|
/// <param name="userId"></param>
|
||||
|
/// <param name="groupId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task RemoveUserFormGroupAsync(Guid? tenantId, Guid userId, long groupId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IM.Group |
||||
|
{ |
||||
|
public class UserGroup |
||||
|
{ |
||||
|
public Guid? TenantId { get; set; } |
||||
|
public Guid UserId { get; set; } |
||||
|
public long GroupId { get; set; } |
||||
|
public bool IsAdmin { get; set; } |
||||
|
public bool IsSuperAdmin { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Auditing; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IM.Messages |
||||
|
{ |
||||
|
public class ChatMessage |
||||
|
{ |
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
public string GroupId { get; set; } |
||||
|
|
||||
|
public string MessageId { get; set; } |
||||
|
|
||||
|
public Guid FormUserId { get; set; } |
||||
|
|
||||
|
public string FormUserName { get; set; } |
||||
|
|
||||
|
public Guid? ToUserId { get; set; } |
||||
|
|
||||
|
[DisableAuditing] |
||||
|
public string Content { get; set; } |
||||
|
|
||||
|
public DateTime SendTime { get; set; } |
||||
|
|
||||
|
public bool IsAnonymous { get; set; } = false; |
||||
|
|
||||
|
public MessageType MessageType { get; set; } = MessageType.Text; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IM.Messages |
||||
|
{ |
||||
|
public interface IMessageSender |
||||
|
{ |
||||
|
Task SendMessageAsync(ChatMessage chatMessage); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IM.Messages |
||||
|
{ |
||||
|
public interface IMessageStore |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 存储聊天记录
|
||||
|
/// </summary>
|
||||
|
/// <param name="chatMessage"></param>
|
||||
|
/// <param name="formUserId"></param>
|
||||
|
/// <param name="toUserId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task StoreMessageAsync(ChatMessage chatMessage); |
||||
|
/// <summary>
|
||||
|
/// 获取群组聊天记录
|
||||
|
/// </summary>
|
||||
|
/// <param name="tenantId"></param>
|
||||
|
/// <param name="groupName"></param>
|
||||
|
/// <param name="maxResultCount"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<List<ChatMessage>> GetGroupMessageAsync(Guid? tenantId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); |
||||
|
/// <summary>
|
||||
|
/// 获取与某个用户的聊天记录
|
||||
|
/// </summary>
|
||||
|
/// <param name="tenantId"></param>
|
||||
|
/// <param name="userId"></param>
|
||||
|
/// <param name="maxResultCount"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<List<ChatMessage>> GetChatMessageAsync(Guid? tenantId, Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -1,9 +1,9 @@ |
|||||
namespace LINGYUN.Abp.MessageService |
namespace LINGYUN.Abp.IM.Messages |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// 消息状态
|
/// 消息状态
|
||||
/// </summary>
|
/// </summary>
|
||||
public enum SendStatus : sbyte |
public enum MessageSendState : sbyte |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// 已发送
|
/// 已发送
|
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace LINGYUN.Abp.IM.Messages |
||||
|
{ |
||||
|
public enum MessageType |
||||
|
{ |
||||
|
Text = 0, |
||||
|
Image = 10, |
||||
|
Link = 20, |
||||
|
Video = 30 |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp3.1</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.SignalR" Version="2.8.0" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.8.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,15 @@ |
|||||
|
using LINGYUN.Abp.RealTime; |
||||
|
using Volo.Abp.AspNetCore.SignalR; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.SignalR |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpRealTimeModule), |
||||
|
typeof(AbpNotificationModule), |
||||
|
typeof(AbpAspNetCoreSignalRModule))] |
||||
|
public class AbpNotificationsSignalRModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.SignalR.Hubs |
||||
|
{ |
||||
|
[Authorize] |
||||
|
public class NotificationsHub : OnlineClientHubBase |
||||
|
{ |
||||
|
private INotificationStore _notificationStore; |
||||
|
protected INotificationStore NotificationStore => LazyGetRequiredService(ref _notificationStore); |
||||
|
|
||||
|
[HubMethodName("GetNotification")] |
||||
|
public virtual async Task<ListResultDto<NotificationInfo>> GetNotificationAsync( |
||||
|
NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10) |
||||
|
{ |
||||
|
var userNotifications = await NotificationStore.GetUserNotificationsAsync(CurrentTenant.Id, CurrentUser.GetId(), readState, maxResultCount); |
||||
|
|
||||
|
return new ListResultDto<NotificationInfo>(userNotifications); |
||||
|
} |
||||
|
|
||||
|
[HubMethodName("ChangeState")] |
||||
|
public virtual async Task ChangeStateAsync(long id, NotificationReadState readState = NotificationReadState.Read) |
||||
|
{ |
||||
|
await NotificationStore.ChangeUserNotificationReadStateAsync(CurrentTenant.Id, CurrentUser.GetId(), id, readState); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,78 @@ |
|||||
|
using LINGYUN.Abp.RealTime.Client; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.SignalR; |
||||
|
using Volo.Abp.Security.Claims; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.SignalR |
||||
|
{ |
||||
|
public abstract class OnlineClientHubBase : AbpHub |
||||
|
{ |
||||
|
private ICurrentPrincipalAccessor _currentPrincipalAccessor; |
||||
|
protected ICurrentPrincipalAccessor CurrentPrincipalAccessor => LazyGetRequiredService(ref _currentPrincipalAccessor); |
||||
|
|
||||
|
private IOnlineClientManager _onlineClientManager; |
||||
|
protected IOnlineClientManager OnlineClientManager => LazyGetRequiredService(ref _onlineClientManager); |
||||
|
|
||||
|
private IHttpContextAccessor _httpContextAccessor; |
||||
|
protected IHttpContextAccessor HttpContextAccessor => LazyGetRequiredService(ref _httpContextAccessor); |
||||
|
|
||||
|
public override async Task OnConnectedAsync() |
||||
|
{ |
||||
|
await base.OnConnectedAsync(); |
||||
|
IOnlineClient onlineClient = CreateClientForCurrentConnection(); |
||||
|
Logger.LogDebug("A client is connected: " + onlineClient.ToString()); |
||||
|
OnlineClientManager.Add(onlineClient); |
||||
|
} |
||||
|
|
||||
|
public override async Task OnDisconnectedAsync(Exception exception) |
||||
|
{ |
||||
|
await base.OnDisconnectedAsync(exception); |
||||
|
Logger.LogDebug("A client is disconnected: " + Context.ConnectionId); |
||||
|
try |
||||
|
{ |
||||
|
// 从通讯组移除
|
||||
|
var onlineClient = OnlineClientManager.GetByConnectionIdOrNull(Context.ConnectionId); |
||||
|
if(onlineClient != null) |
||||
|
{ |
||||
|
// 移除在线客户端
|
||||
|
OnlineClientManager.Remove(Context.ConnectionId); |
||||
|
} |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Logger.LogWarning(ex.ToString(), ex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual IOnlineClient CreateClientForCurrentConnection() |
||||
|
{ |
||||
|
// abp框架没有处理,需要切换一下用户身份令牌.否则无法获取用户信息
|
||||
|
using (CurrentPrincipalAccessor.Change(Context.User)) |
||||
|
{ |
||||
|
return new OnlineClient(Context.ConnectionId, GetClientIpAddress(), |
||||
|
CurrentTenant.Id, CurrentUser.Id) |
||||
|
{ |
||||
|
ConnectTime = Clock.Now, |
||||
|
UserName = CurrentUser.UserName |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetClientIpAddress() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
return HttpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString(); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Logger.LogException(ex, LogLevel.Warning); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Microsoft.AspNetCore.Builder |
||||
|
{ |
||||
|
public class SignalRJwtTokenMiddleware : IMiddleware, ITransientDependency |
||||
|
{ |
||||
|
public async Task InvokeAsync(HttpContext context, RequestDelegate next) |
||||
|
{ |
||||
|
// 仅针对自定义的SignalR hub
|
||||
|
if (context.Request.Path.StartsWithSegments("/signalr-hubs/notifications")) |
||||
|
{ |
||||
|
if (context.User.Identity?.IsAuthenticated != true) |
||||
|
{ |
||||
|
if (context.Request.Query.TryGetValue("access_token", out var accessToken)) |
||||
|
{ |
||||
|
context.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
await next(context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using LINGYUN.Abp.Notifications.Internal; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications |
||||
|
{ |
||||
|
public class AbpNotificationModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddTransient<INotificationDispatcher, DefaultNotificationDispatcher>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,12 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Notifications |
|
||||
{ |
|
||||
public interface INotificationSender |
|
||||
{ |
|
||||
Task SendAsync(NotificationData data, Guid userId, Guid? tenantId); |
|
||||
Task SendAsync(NotificationData data, IEnumerable<Guid> userIds, Guid? tenantId); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,34 @@ |
|||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.Internal |
||||
|
{ |
||||
|
internal class DefaultNotificationDispatcher : INotificationDispatcher |
||||
|
{ |
||||
|
private readonly INotificationStore _notificationStore; |
||||
|
private readonly INotificationPublisher _notificationPublisher; |
||||
|
public DefaultNotificationDispatcher( |
||||
|
INotificationStore notificationStore, |
||||
|
INotificationPublisher notificationPublisher) |
||||
|
{ |
||||
|
_notificationStore = notificationStore; |
||||
|
_notificationPublisher = notificationPublisher; |
||||
|
} |
||||
|
|
||||
|
public async Task DispatcheAsync(NotificationInfo notification) |
||||
|
{ |
||||
|
// 持久化通知
|
||||
|
await _notificationStore.InsertNotificationAsync(notification); |
||||
|
|
||||
|
// 获取用户订阅列表
|
||||
|
var userSubscriptions = await _notificationStore.GetSubscriptionsAsync(notification.TenantId, notification.Name); |
||||
|
|
||||
|
// 持久化用户通知
|
||||
|
var subscriptionUserIds = userSubscriptions.Select(us => us.UserId); |
||||
|
await _notificationStore.InsertUserNotificationsAsync(notification, subscriptionUserIds); |
||||
|
|
||||
|
// 发布用户通知
|
||||
|
await _notificationPublisher.PublishAsync(notification, subscriptionUserIds); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Newtonsoft.Json |
||||
|
{ |
||||
|
public class HexLongConverter : JsonConverter |
||||
|
{ |
||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
||||
|
{ |
||||
|
long v = value is ulong ? (long)(ulong)value : (long)value; |
||||
|
writer.WriteValue(v.ToString()); |
||||
|
} |
||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
||||
|
{ |
||||
|
string value = reader.Value as string; |
||||
|
long lValue = long.Parse(value); |
||||
|
return typeof(ulong) == objectType ? (object)(ulong)lValue : lValue; |
||||
|
} |
||||
|
public override bool CanConvert(Type objectType) |
||||
|
{ |
||||
|
switch (objectType.FullName) |
||||
|
{ |
||||
|
case "System.Int64": |
||||
|
case "System.UInt64": |
||||
|
return true; |
||||
|
default: |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Core" Version="2.8.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.RealTime |
||||
|
{ |
||||
|
public class AbpRealTimeModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,6 @@ |
|||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
|
|
||||
namespace LINGYUN.Abp.IM |
namespace LINGYUN.Abp.RealTime.Client |
||||
{ |
{ |
||||
public interface IOnlineClientStore |
public interface IOnlineClientStore |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using System; |
using System; |
||||
|
|
||||
namespace LINGYUN.Abp.IM |
namespace LINGYUN.Abp.RealTime.Client |
||||
{ |
{ |
||||
public class OnlineClientEventArgs : EventArgs |
public class OnlineClientEventArgs : EventArgs |
||||
{ |
{ |
||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.IM |
namespace LINGYUN.Abp.RealTime.Client |
||||
{ |
{ |
||||
public class OnlineUserEventArgs : OnlineClientEventArgs |
public class OnlineUserEventArgs : OnlineClientEventArgs |
||||
{ |
{ |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Localization |
||||
|
{ |
||||
|
[LocalizationResourceName("MessageService")] |
||||
|
public class MessageServiceResource |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
namespace LINGYUN.Abp.MessageService |
||||
|
{ |
||||
|
public class MessageServiceErrorCodes |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 管理员已开启全员禁言
|
||||
|
/// </summary>
|
||||
|
public const string GroupNotAllowedToSpeak = "Messages:Group:1001"; |
||||
|
/// <summary>
|
||||
|
/// 管理员不允许匿名发言
|
||||
|
/// </summary>
|
||||
|
public const string GroupNotAllowedToSpeakAnonymously = "Messages:Group:1002"; |
||||
|
/// <summary>
|
||||
|
/// 管理员已禁止用户发言
|
||||
|
/// </summary>
|
||||
|
public const string GroupUserHasBlack = "Messages:Group:1003"; |
||||
|
/// <summary>
|
||||
|
/// 用户已将发信人拉黑
|
||||
|
/// </summary>
|
||||
|
public const string UserHasBlack = "Messages:User:1003"; |
||||
|
/// <summary>
|
||||
|
/// 用户已拒接所有消息
|
||||
|
/// </summary>
|
||||
|
public const string UserHasRejectAllMessage = "Messages:User:1001"; |
||||
|
/// <summary>
|
||||
|
/// 用户不允许匿名发言
|
||||
|
/// </summary>
|
||||
|
public const string UserNotAllowedToSpeakAnonymously = "Messages:User:1002"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
namespace LINGYUN.Abp.MessageService |
||||
|
{ |
||||
|
public class MessageServiceSettingNames |
||||
|
{ |
||||
|
public const string GroupName = "Abp.MessageService"; |
||||
|
|
||||
|
public class Notifications |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Notifications"; |
||||
|
/// <summary>
|
||||
|
/// 清理过期消息批次
|
||||
|
/// </summary>
|
||||
|
public const string CleanupExpirationBatchCount = Default + ".CleanupExpirationBatchCount"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public class ChatGroupConsts |
||||
|
{ |
||||
|
public const int MaxNameLength = 20; |
||||
|
|
||||
|
public const int MaxTagLength = 512; |
||||
|
|
||||
|
public const int MaxAddressLength = 256; |
||||
|
|
||||
|
public const int MaxNoticeLength = 64; |
||||
|
|
||||
|
public const int MaxDescriptionLength = 128; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public class MessageConsts |
||||
|
{ |
||||
|
public const int MaxSendUserNameLength = 64; |
||||
|
|
||||
|
// 1 MB
|
||||
|
public const int MaxContentLength = 1024 * 1024; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Notifications |
||||
|
{ |
||||
|
public class CleanupNotificationJobArgs |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 清理大小
|
||||
|
/// </summary>
|
||||
|
public int Count { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 清理租户
|
||||
|
/// </summary>
|
||||
|
public Guid? TenantId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -1,17 +0,0 @@ |
|||||
namespace LINGYUN.Abp.MessageService |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 读取状态
|
|
||||
/// </summary>
|
|
||||
public enum ReadStatus : sbyte |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 已读
|
|
||||
/// </summary>
|
|
||||
Read = 0, |
|
||||
/// <summary>
|
|
||||
/// 未读
|
|
||||
/// </summary>
|
|
||||
UnRead = 10 |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace LINGYUN.Abp.MessageService |
||||
|
{ |
||||
|
public class AbpMessageServiceDbProperties |
||||
|
{ |
||||
|
public const string DefaultTablePrefix = "App"; |
||||
|
|
||||
|
public const string DefaultSchema = null; |
||||
|
} |
||||
|
} |
||||
@ -1,9 +1,18 @@ |
|||||
using Volo.Abp.Modularity; |
using LINGYUN.Abp.MessageService.Mapper; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
namespace LINGYUN.Abp.MessageService |
namespace LINGYUN.Abp.MessageService |
||||
{ |
{ |
||||
|
[DependsOn(typeof(AbpAutoMapperModule))] |
||||
public class AbpMessageServiceDomainModule : AbpModule |
public class AbpMessageServiceDomainModule : AbpModule |
||||
{ |
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpAutoMapperOptions>(options => |
||||
|
{ |
||||
|
options.AddProfile<MessageServiceDomainAutoMapperProfile>(validate: true); |
||||
|
}); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,37 @@ |
|||||
|
using LINGYUN.Abp.MessageService.Notifications; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.BackgroundJobs; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.BackgroundJobs |
||||
|
{ |
||||
|
public class NotificationExpritionCleanupJob : AsyncBackgroundJob<CleanupNotificationJobArgs> |
||||
|
{ |
||||
|
private readonly ICurrentTenant _currentTenant; |
||||
|
private readonly IUnitOfWorkManager _unitOfWorkManager; |
||||
|
private readonly INotificationRepository _notificationRepository; |
||||
|
public NotificationExpritionCleanupJob( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IUnitOfWorkManager unitOfWorkManager, |
||||
|
INotificationRepository notificationRepository) |
||||
|
{ |
||||
|
_currentTenant = currentTenant; |
||||
|
_unitOfWorkManager = unitOfWorkManager; |
||||
|
_notificationRepository = notificationRepository; |
||||
|
} |
||||
|
|
||||
|
public override async Task ExecuteAsync(CleanupNotificationJobArgs args) |
||||
|
{ |
||||
|
using (var unitOfWork = _unitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
using (_currentTenant.Change(args.TenantId)) |
||||
|
{ |
||||
|
await _notificationRepository.DeleteExpritionAsync(args.Count); |
||||
|
|
||||
|
await unitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
using LINGYUN.Abp.MessageService.Messages; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Entities.Events.Distributed; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Uow; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.EventBus |
||||
|
{ |
||||
|
public class UserCreateEventHandler : IDistributedEventHandler<EntityCreatedEto<UserEto>> |
||||
|
{ |
||||
|
private readonly ICurrentTenant _currentTenant; |
||||
|
private readonly IUnitOfWorkManager _unitOfWorkManager; |
||||
|
private readonly IUserChatSettingRepository _userChatSettingRepository; |
||||
|
public UserCreateEventHandler( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IUnitOfWorkManager unitOfWorkManager, |
||||
|
IUserChatSettingRepository userChatSettingRepository) |
||||
|
{ |
||||
|
_currentTenant = currentTenant; |
||||
|
_unitOfWorkManager = unitOfWorkManager; |
||||
|
_userChatSettingRepository = userChatSettingRepository; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 接收添加用户事件,启用IM模块时增加用户配置
|
||||
|
/// </summary>
|
||||
|
/// <param name="eventData"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public async Task HandleEventAsync(EntityCreatedEto<UserEto> eventData) |
||||
|
{ |
||||
|
using (var unitOfWork = _unitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
using (_currentTenant.Change(eventData.Entity.TenantId)) |
||||
|
{ |
||||
|
var userHasOpendIm = await _userChatSettingRepository.UserHasOpendImAsync(eventData.Entity.Id); |
||||
|
if (!userHasOpendIm) |
||||
|
{ |
||||
|
var userChatSetting = new UserChatSetting(eventData.Entity.Id, eventData.Entity.TenantId); |
||||
|
await _userChatSettingRepository.InsertAsync(userChatSetting); |
||||
|
|
||||
|
await unitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Messages:Group:1001": "The current group is not allowed to speak", |
||||
|
"Messages:Group:1002": "The current group is not allowed to speak anonymously", |
||||
|
"Messages:Group:1003": "The administrator has banned you from speaking!", |
||||
|
"Messages:User:1001": "Users do not receive anonymous comments!", |
||||
|
"Messages:User:1002": "The user has rejected all messages!", |
||||
|
"Messages:User:1003": "The user rejects the message you sent!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Messages:Group:1001": "管理员已开启全员禁言!", |
||||
|
"Messages:Group:1002": "管理员不允许匿名发言!", |
||||
|
"Messages:Group:1003": "管理员已禁止您发言!", |
||||
|
"Messages:User:1001": "用户不接收匿名发言!", |
||||
|
"Messages:User:1002": "用户已拒接所有消息!", |
||||
|
"Messages:User:1003": "用户拒绝您发送的消息!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
using AutoMapper; |
||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using LINGYUN.Abp.MessageService.Messages; |
||||
|
using LINGYUN.Abp.MessageService.Notifications; |
||||
|
using LINGYUN.Abp.MessageService.Subscriptions; |
||||
|
using LINGYUN.Abp.Notifications; |
||||
|
using Newtonsoft.Json; |
||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Mapper |
||||
|
{ |
||||
|
public class MessageServiceDomainAutoMapperProfile : Profile |
||||
|
{ |
||||
|
public MessageServiceDomainAutoMapperProfile() |
||||
|
{ |
||||
|
CreateMap<Notification, NotificationInfo>() |
||||
|
.ForMember(dto => dto.Id, map => map.MapFrom(src => src.NotificationId)) |
||||
|
.ForMember(dto => dto.Name, map => map.MapFrom(src => src.NotificationName)) |
||||
|
.ForMember(dto => dto.NotificationType, map => map.MapFrom(src => src.Type)) |
||||
|
.ForMember(dto => dto.NotificationSeverity, map => map.MapFrom(src => src.Severity)) |
||||
|
.ForMember(dto => dto.Data, map => map.MapFrom((src, nfi) => |
||||
|
{ |
||||
|
var notificationDataType = Type.GetType(src.NotificationTypeName); |
||||
|
var notificationData = JsonConvert.DeserializeObject(src.NotificationData, notificationDataType); |
||||
|
if(notificationData != null) |
||||
|
{ |
||||
|
return notificationData as NotificationData; |
||||
|
} |
||||
|
return new NotificationData(); |
||||
|
})); |
||||
|
|
||||
|
CreateMap<UserSubscribe, NotificationSubscriptionInfo>(); |
||||
|
|
||||
|
CreateMap<GroupMessage, ChatMessage>() |
||||
|
.ForMember(dto => dto.Content, map => map.MapFrom(src => src.Content)) |
||||
|
.ForMember(dto => dto.GroupId, map => map.MapFrom(src => src.GroupId.ToString())) |
||||
|
.ForMember(dto => dto.MessageId, map => map.MapFrom(src => src.MessageId.ToString())) |
||||
|
.ForMember(dto => dto.FormUserId, map => map.MapFrom(src => src.CreatorId)) |
||||
|
.ForMember(dto => dto.FormUserName, map => map.MapFrom(src => src.SendUserName)) |
||||
|
.ForMember(dto => dto.SendTime, map => map.MapFrom(src => src.CreationTime)) |
||||
|
.ForMember(dto => dto.MessageType, map => map.MapFrom(src => src.Type)) |
||||
|
.ForMember(dto => dto.IsAnonymous, map => map.Ignore()) |
||||
|
.ForMember(dto => dto.ToUserId, map => map.Ignore()); |
||||
|
|
||||
|
CreateMap<UserMessage, ChatMessage>() |
||||
|
.ForMember(dto => dto.Content, map => map.MapFrom(src => src.Content)) |
||||
|
.ForMember(dto => dto.ToUserId, map => map.MapFrom(src => src.ReceiveUserId)) |
||||
|
.ForMember(dto => dto.MessageId, map => map.MapFrom(src => src.MessageId.ToString())) |
||||
|
.ForMember(dto => dto.FormUserId, map => map.MapFrom(src => src.CreatorId)) |
||||
|
.ForMember(dto => dto.FormUserName, map => map.MapFrom(src => src.SendUserName)) |
||||
|
.ForMember(dto => dto.SendTime, map => map.MapFrom(src => src.CreationTime)) |
||||
|
.ForMember(dto => dto.MessageType, map => map.MapFrom(src => src.Type)) |
||||
|
.ForMember(dto => dto.IsAnonymous, map => map.Ignore()) |
||||
|
.ForMember(dto => dto.GroupId, map => map.Ignore()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,76 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 聊天群组
|
||||
|
/// </summary>
|
||||
|
public class ChatGroup : AuditedEntity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 群组标识
|
||||
|
/// </summary>
|
||||
|
public virtual long GroupId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 群组名称
|
||||
|
/// </summary>
|
||||
|
public virtual string Name { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 群组标记
|
||||
|
/// </summary>
|
||||
|
public virtual string Tag { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 群组地址
|
||||
|
/// </summary>
|
||||
|
public virtual string Address { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 群组公告
|
||||
|
/// </summary>
|
||||
|
public virtual string Notice { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 最大用户数量
|
||||
|
/// </summary>
|
||||
|
public virtual int MaxUserCount { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 允许匿名聊天
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowAnonymous { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许发送消息
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowSendMessage { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群组说明
|
||||
|
/// </summary>
|
||||
|
public virtual string Description { get; set; } |
||||
|
protected ChatGroup() |
||||
|
{ |
||||
|
} |
||||
|
public ChatGroup(long id, string name, string tag = "", string address = "", int maxUserCount = 200) |
||||
|
{ |
||||
|
GroupId = id; |
||||
|
Name = name; |
||||
|
Tag = tag; |
||||
|
Address = address; |
||||
|
MaxUserCount = maxUserCount; |
||||
|
} |
||||
|
|
||||
|
public void ChangeAddress(string address) |
||||
|
{ |
||||
|
Address = address; |
||||
|
} |
||||
|
|
||||
|
public void SetNotice(string notice) |
||||
|
{ |
||||
|
Notice = notice; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 群管理员
|
||||
|
/// </summary>
|
||||
|
public class ChatGroupAdmin : AuditedEntity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 群组标识
|
||||
|
/// </summary>
|
||||
|
public virtual long GroupId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 管理员用户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid UserId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 是否群主
|
||||
|
/// </summary>
|
||||
|
public virtual bool IsSuperAdmin { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 允许禁言
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowSilence { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许踢人
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowKickPeople { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许加人
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowAddPeople { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许发送群公告
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowSendNotice { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许解散群组
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowDissolveGroup { get; set; } |
||||
|
protected ChatGroupAdmin() { } |
||||
|
public ChatGroupAdmin(long groupId, Guid userId, bool isSuperAdmin = false) |
||||
|
{ |
||||
|
GroupId = groupId; |
||||
|
UserId = userId; |
||||
|
AllowSilence = true; |
||||
|
AllowKickPeople = true; |
||||
|
AllowAddPeople = true; |
||||
|
AllowSendNotice = true; |
||||
|
SetSuperAdmin(isSuperAdmin); |
||||
|
} |
||||
|
|
||||
|
public void SetSuperAdmin(bool isSuperAdmin = false) |
||||
|
{ |
||||
|
IsSuperAdmin = isSuperAdmin; |
||||
|
if (isSuperAdmin) |
||||
|
{ |
||||
|
AllowDissolveGroup = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,34 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp.Domain.Entities; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
|
|
||||
namespace LINGYUN.Abp.MessageService.Messages |
|
||||
{ |
|
||||
public abstract class ChatMessage : Entity<long>, IMultiTenant |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 租户
|
|
||||
/// </summary>
|
|
||||
public virtual Guid? TenantId { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 发送用户标识
|
|
||||
/// </summary>
|
|
||||
public virtual Guid SendUserId { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 接收用户标识
|
|
||||
/// </summary>
|
|
||||
public virtual Guid ReceiveUserId { get; set; } |
|
||||
/// <summary>
|
|
||||
/// 内容
|
|
||||
/// </summary>
|
|
||||
public virtual string Content { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 发送状态
|
|
||||
/// </summary>
|
|
||||
public virtual SendStatus SendStatus { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 阅读状态
|
|
||||
/// </summary>
|
|
||||
public virtual ReadStatus ReadStatus { get; protected set; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户黑名单
|
||||
|
/// </summary>
|
||||
|
public class GroupChatBlack : CreationAuditedEntity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 群组标识
|
||||
|
/// </summary>
|
||||
|
public virtual long GroupId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 拉黑的用户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid ShieldUserId { get; protected set; } |
||||
|
protected GroupChatBlack() { } |
||||
|
public GroupChatBlack(long groupId, Guid shieldUserId, Guid? tenantId) |
||||
|
{ |
||||
|
GroupId = groupId; |
||||
|
ShieldUserId = shieldUserId; |
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public class GroupMessage : Message |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 群组标识
|
||||
|
/// </summary>
|
||||
|
public virtual long GroupId { get; protected set; } |
||||
|
|
||||
|
protected GroupMessage() { } |
||||
|
public GroupMessage(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text) |
||||
|
: base(id, sendUserId, sendUserName, content, type) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
public void SendToGroup(long groupId) |
||||
|
{ |
||||
|
GroupId = groupId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public interface IGroupRepository : IBasicRepository<ChatGroup, long> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户是否已被拉黑
|
||||
|
/// </summary>
|
||||
|
/// <param name="id"></param>
|
||||
|
/// <param name="formUserId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<bool> UserHasBlackedAsync(long id, Guid formUserId); |
||||
|
|
||||
|
Task<ChatGroup> GetByIdAsync(long id); |
||||
|
|
||||
|
Task<List<ChatGroupAdmin>> GetGroupAdminAsync(long id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public interface IMessageRepository |
||||
|
{ |
||||
|
Task<UserMessage> InsertUserMessageAsync(UserMessage userMessage, bool saveChangs = false); |
||||
|
|
||||
|
Task<GroupMessage> InsertGroupMessageAsync(GroupMessage groupMessage, bool saveChangs = false); |
||||
|
|
||||
|
Task<UserMessage> GetUserMessageAsync(long id); |
||||
|
|
||||
|
Task<GroupMessage> GetGroupMessageAsync(long id); |
||||
|
|
||||
|
Task<List<UserMessage>> GetUserMessagesAsync(Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); |
||||
|
|
||||
|
Task<List<GroupMessage>> GetGroupMessagesAsync(long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); |
||||
|
|
||||
|
Task<List<GroupMessage>> GetUserGroupMessagesAsync(Guid sendUserId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using LINGYUN.Abp.IM.Group; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public interface IUserChatGroupRepository : IBasicRepository<UserChatGroup, long> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户是否在组里
|
||||
|
/// </summary>
|
||||
|
/// <param name="id"></param>
|
||||
|
/// <param name="userId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<bool> UserHasInGroupAsync(long groupId, Guid userId); |
||||
|
|
||||
|
Task<UserChatGroup> GetUserGroupAsync(long groupId, Guid userId); |
||||
|
|
||||
|
Task<List<UserGroup>> GetGroupUsersAsync(long groupId); |
||||
|
|
||||
|
Task<List<Group>> GetUserGroupsAsync(Guid userId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public interface IUserChatSettingRepository : IBasicRepository<UserChatSetting, long> |
||||
|
{ |
||||
|
Task<bool> UserHasOpendImAsync(Guid userId); |
||||
|
/// <summary>
|
||||
|
/// 用户是否已被拉黑
|
||||
|
/// </summary>
|
||||
|
/// <param name="formUserId"></param>
|
||||
|
/// <param name="toUserId"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<bool> UserHasBlackedAsync(Guid formUserId, Guid toUserId); |
||||
|
|
||||
|
Task<UserChatSetting> GetByUserIdAsync(Guid userId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public abstract class Message : CreationAuditedEntity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 消息标识
|
||||
|
/// </summary>
|
||||
|
public virtual long MessageId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 发送用户名称
|
||||
|
/// </summary>
|
||||
|
public virtual string SendUserName { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 内容
|
||||
|
/// </summary>
|
||||
|
public virtual string Content { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 消息类型
|
||||
|
/// </summary>
|
||||
|
public virtual MessageType Type { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 发送状态
|
||||
|
/// </summary>
|
||||
|
public virtual MessageSendState SendState { get; protected set; } |
||||
|
protected Message() { } |
||||
|
public Message(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text) |
||||
|
{ |
||||
|
MessageId = id; |
||||
|
CreatorId = sendUserId; |
||||
|
SendUserName = sendUserName; |
||||
|
Content = content; |
||||
|
Type = type; |
||||
|
CreationTime = DateTime.Now; |
||||
|
} |
||||
|
|
||||
|
public void ChangeSendState(MessageSendState state = MessageSendState.Send) |
||||
|
{ |
||||
|
SendState = state; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,132 @@ |
|||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using LINGYUN.Abp.MessageService.Utils; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
using Volo.Abp.ObjectMapping; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public class MessageStore : DomainService, IMessageStore |
||||
|
{ |
||||
|
private IObjectMapper _objectMapper; |
||||
|
protected IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); |
||||
|
|
||||
|
private IUnitOfWorkManager _unitOfWorkManager; |
||||
|
protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); |
||||
|
protected IUserChatSettingRepository UserChatSettingRepository { get; } |
||||
|
protected IMessageRepository MessageRepository { get; } |
||||
|
protected IGroupRepository GroupRepository { get; } |
||||
|
protected ISnowflakeIdGenerator SnowflakeIdGenerator { get; } |
||||
|
public MessageStore( |
||||
|
IGroupRepository groupRepository, |
||||
|
IMessageRepository messageRepository, |
||||
|
ISnowflakeIdGenerator snowflakeIdGenerator, |
||||
|
IUserChatSettingRepository userChatSettingRepository) |
||||
|
{ |
||||
|
GroupRepository = groupRepository; |
||||
|
MessageRepository = messageRepository; |
||||
|
SnowflakeIdGenerator = snowflakeIdGenerator; |
||||
|
UserChatSettingRepository = userChatSettingRepository; |
||||
|
} |
||||
|
|
||||
|
[UnitOfWork] |
||||
|
public async Task StoreMessageAsync(ChatMessage chatMessage) |
||||
|
{ |
||||
|
using (var unitOfWork = UnitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
using (CurrentTenant.Change(chatMessage.TenantId)) |
||||
|
{ |
||||
|
if (!chatMessage.GroupId.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
long groupId = long.Parse(chatMessage.GroupId); |
||||
|
await StoreGroupMessageAsync(chatMessage, groupId); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
await StoreUserMessageAsync(chatMessage); |
||||
|
} |
||||
|
await unitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public async Task<List<ChatMessage>> GetGroupMessageAsync(Guid? tenantId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10) |
||||
|
{ |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
var groupMessages = await MessageRepository.GetGroupMessagesAsync(groupId, filter, type, skipCount, maxResultCount); |
||||
|
var chatMessages = ObjectMapper.Map<List<GroupMessage>, List<ChatMessage>>(groupMessages); |
||||
|
|
||||
|
return chatMessages; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public async Task<List<ChatMessage>> GetChatMessageAsync(Guid? tenantId, Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10) |
||||
|
{ |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
var userMessages = await MessageRepository.GetUserMessagesAsync(sendUserId, receiveUserId, filter, type, skipCount, maxResultCount); |
||||
|
var chatMessages = ObjectMapper.Map<List<UserMessage>, List<ChatMessage>>(userMessages); |
||||
|
|
||||
|
return chatMessages; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task StoreUserMessageAsync(ChatMessage chatMessage) |
||||
|
{ |
||||
|
var userHasBlacked = await UserChatSettingRepository |
||||
|
.UserHasBlackedAsync(chatMessage.ToUserId.Value, chatMessage.FormUserId); |
||||
|
if (userHasBlacked) |
||||
|
{ |
||||
|
// 当前发送的用户已被拉黑
|
||||
|
throw new BusinessException(MessageServiceErrorCodes.UserHasBlack); |
||||
|
} |
||||
|
var userChatSetting = await UserChatSettingRepository.GetByUserIdAsync(chatMessage.ToUserId.Value); |
||||
|
if (!userChatSetting.AllowReceiveMessage) |
||||
|
{ |
||||
|
// 当前发送的用户不接收消息
|
||||
|
throw new BusinessException(MessageServiceErrorCodes.UserHasRejectAllMessage); |
||||
|
} |
||||
|
if (chatMessage.IsAnonymous && !userChatSetting.AllowAnonymous) |
||||
|
{ |
||||
|
// 当前用户不允许匿名发言
|
||||
|
throw new BusinessException(MessageServiceErrorCodes.UserNotAllowedToSpeakAnonymously); |
||||
|
} |
||||
|
var messageId = SnowflakeIdGenerator.Create(); |
||||
|
var message = new UserMessage(messageId, chatMessage.FormUserId, chatMessage.FormUserName, chatMessage.Content, chatMessage.MessageType); |
||||
|
message.SendToUser(chatMessage.ToUserId.Value); |
||||
|
await MessageRepository.InsertUserMessageAsync(message); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task StoreGroupMessageAsync(ChatMessage chatMessage, long groupId) |
||||
|
{ |
||||
|
var userHasBlacked = await GroupRepository |
||||
|
.UserHasBlackedAsync(groupId, chatMessage.FormUserId); |
||||
|
if (userHasBlacked) |
||||
|
{ |
||||
|
// 当前发送的用户已被拉黑
|
||||
|
throw new BusinessException(MessageServiceErrorCodes.GroupUserHasBlack); |
||||
|
} |
||||
|
var group = await GroupRepository.GetByIdAsync(groupId); |
||||
|
if (!group.AllowSendMessage) |
||||
|
{ |
||||
|
// 当前群组不允许发言
|
||||
|
throw new BusinessException(MessageServiceErrorCodes.GroupNotAllowedToSpeak); |
||||
|
} |
||||
|
if (chatMessage.IsAnonymous && !group.AllowAnonymous) |
||||
|
{ |
||||
|
// 当前群组不允许匿名发言
|
||||
|
throw new BusinessException(MessageServiceErrorCodes.GroupNotAllowedToSpeakAnonymously); |
||||
|
} |
||||
|
var messageId = SnowflakeIdGenerator.Create(); |
||||
|
var message = new GroupMessage(messageId, chatMessage.FormUserId, chatMessage.FormUserName, chatMessage.Content, chatMessage.MessageType); |
||||
|
// TODO: 需要压测 高并发场景下的装箱性能影响
|
||||
|
message.SendToGroup(groupId); |
||||
|
await MessageRepository.InsertGroupMessageAsync(message); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户黑名单
|
||||
|
/// </summary>
|
||||
|
public class UserChatBlack : CreationAuditedEntity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 用户标识
|
||||
|
/// </summary>
|
||||
|
public virtual Guid UserId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 拉黑的用户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid ShieldUserId { get; protected set; } |
||||
|
protected UserChatBlack() { } |
||||
|
public UserChatBlack(Guid userId, Guid shieldUserId, Guid? tenantId) |
||||
|
{ |
||||
|
UserId = userId; |
||||
|
ShieldUserId = shieldUserId; |
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户群组
|
||||
|
/// </summary>
|
||||
|
public class UserChatGroup : CreationAuditedEntity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
public virtual Guid UserId { get; protected set; } |
||||
|
public virtual long GroupId { get; protected set; } |
||||
|
protected UserChatGroup() { } |
||||
|
public UserChatGroup(long groupId, Guid userId, Guid acceptUserId, Guid? tenantId = null) |
||||
|
{ |
||||
|
UserId = userId; |
||||
|
GroupId = groupId; |
||||
|
CreatorId = acceptUserId; |
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public class UserChatSetting : Entity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 用户标识
|
||||
|
/// </summary>
|
||||
|
public virtual Guid UserId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 允许匿名聊天
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowAnonymous { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许添加好友
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowAddFriend { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 添加好友需要验证
|
||||
|
/// </summary>
|
||||
|
public virtual bool RequireAddFriendValition { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许接收消息
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowReceiveMessage { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 允许发送消息
|
||||
|
/// </summary>
|
||||
|
public virtual bool AllowSendMessage { get; set; } |
||||
|
protected UserChatSetting() |
||||
|
{ |
||||
|
} |
||||
|
public UserChatSetting(Guid userId, Guid? tenantId) |
||||
|
: this() |
||||
|
{ |
||||
|
UserId = userId; |
||||
|
TenantId = tenantId; |
||||
|
AllowAnonymous = false; |
||||
|
AllowAddFriend = true; |
||||
|
AllowReceiveMessage = true; |
||||
|
AllowSendMessage = true; |
||||
|
RequireAddFriendValition = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
using LINGYUN.Abp.IM.Group; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
using Volo.Abp.ObjectMapping; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public class UserGroupStore : DomainService, IUserGroupStore |
||||
|
{ |
||||
|
private IObjectMapper _objectMapper; |
||||
|
protected IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); |
||||
|
|
||||
|
private IUnitOfWorkManager _unitOfWorkManager; |
||||
|
protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); |
||||
|
|
||||
|
protected IUserChatGroupRepository UserChatGroupRepository { get; } |
||||
|
|
||||
|
public UserGroupStore( |
||||
|
IUserChatGroupRepository userChatGroupRepository) |
||||
|
{ |
||||
|
UserChatGroupRepository = userChatGroupRepository; |
||||
|
} |
||||
|
|
||||
|
[UnitOfWork] |
||||
|
public async Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId, Guid acceptUserId) |
||||
|
{ |
||||
|
using (var unitOfWork = UnitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
var userHasInGroup = await UserChatGroupRepository.UserHasInGroupAsync(groupId, userId); |
||||
|
if (!userHasInGroup) |
||||
|
{ |
||||
|
var userGroup = new UserChatGroup(groupId, userId, acceptUserId, tenantId); |
||||
|
|
||||
|
await UserChatGroupRepository.InsertAsync(userGroup); |
||||
|
|
||||
|
await unitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public async Task<IEnumerable<UserGroup>> GetGroupUsersAsync(Guid? tenantId, long groupId) |
||||
|
{ |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
var userGroups = await UserChatGroupRepository.GetGroupUsersAsync(groupId); |
||||
|
|
||||
|
return userGroups; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public async Task<IEnumerable<Group>> GetUserGroupsAsync(Guid? tenantId, Guid userId) |
||||
|
{ |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
var groups = await UserChatGroupRepository.GetUserGroupsAsync(userId); |
||||
|
|
||||
|
return groups; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[UnitOfWork] |
||||
|
public async Task RemoveUserFormGroupAsync(Guid? tenantId, Guid userId, long groupId) |
||||
|
{ |
||||
|
using (var unitOfWork = UnitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
var userGroup = await UserChatGroupRepository.GetUserGroupAsync(groupId, userId); |
||||
|
|
||||
|
if(userGroup != null) |
||||
|
{ |
||||
|
await UserChatGroupRepository.DeleteAsync(userGroup); |
||||
|
|
||||
|
await unitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using LINGYUN.Abp.IM.Messages; |
||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
public class UserMessage : Message |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 接收用户标识
|
||||
|
/// </summary>
|
||||
|
public virtual Guid ReceiveUserId { get; set; } |
||||
|
|
||||
|
protected UserMessage() { } |
||||
|
public UserMessage(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text) |
||||
|
: base(id, sendUserId, sendUserName, content, type) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public void SendToUser(Guid receiveUserId) |
||||
|
{ |
||||
|
ReceiveUserId = receiveUserId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Messages |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户特别关注
|
||||
|
/// </summary>
|
||||
|
public class UserSpecialFocus : CreationAuditedEntity<long>, IMultiTenant |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 租户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 用户标识
|
||||
|
/// </summary>
|
||||
|
public virtual Guid UserId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 关注的用户
|
||||
|
/// </summary>
|
||||
|
public virtual Guid FocusUserId { get; protected set; } |
||||
|
protected UserSpecialFocus() { } |
||||
|
public UserSpecialFocus(Guid userId, Guid focusUserId, Guid? tenantId) |
||||
|
{ |
||||
|
UserId = userId; |
||||
|
FocusUserId = focusUserId; |
||||
|
TenantId = tenantId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace LINGYUN.Abp.MessageService.Notifications |
||||
|
{ |
||||
|
public interface INotificationRepository : IBasicRepository<Notification, long> |
||||
|
{ |
||||
|
Task<Notification> GetByIdAsync(long notificationId); |
||||
|
|
||||
|
Task DeleteExpritionAsync(int batchCount); |
||||
|
} |
||||
|
} |
||||
@ -1,11 +0,0 @@ |
|||||
using LINGYUN.Abp.Notifications; |
|
||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace LINGYUN.Abp.MessageService.Notifications |
|
||||
{ |
|
||||
public interface INotificationStore |
|
||||
{ |
|
||||
Task InsertUserNotificationAsync(NotificationInfo notification, Guid userId); |
|
||||
} |
|
||||
} |
|
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue