Browse Source

添加用于即时通讯与通知系统的分支

pull/1/head
cKey 6 years ago
parent
commit
61818f5b9c
  1. 21
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContext.cs
  2. 29
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContextFactory.cs
  3. 38
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj
  4. 143
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/AbpMessageServiceHttpApiHostModule.cs
  5. 130
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.Designer.cs
  6. 93
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.cs
  7. 128
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs
  8. 35
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/MultiTenancy/AuthorizationTenantResolveContributor.cs
  9. 49
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Program.cs
  10. 20
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Properties/launchSettings.json
  11. 18
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Startup.cs
  12. 1
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj
  13. 7
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/AbpIMSignalRModule.cs
  14. 78
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/AbpMessageHub.cs
  15. 89
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs
  16. 34
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/OnlineClientHubBase.cs
  17. 8
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs
  18. 40
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs
  19. 11
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs
  20. 15
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs
  21. 9
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageSender.cs
  22. 34
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs
  23. 10
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageType.cs
  24. 18
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj
  25. 15
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs
  26. 25
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/AbpNotificationsHub.cs
  27. 68
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs
  28. 41
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs
  29. 14
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs
  30. 2
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs
  31. 12
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationSender.cs
  32. 6
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs
  33. 34
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs
  34. 2
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs
  35. 12
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj
  36. 8
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/AbpRealTimeModule.cs
  37. 6
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClient.cs
  38. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientManager.cs
  39. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientStore.cs
  40. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/InMemoryOnlineClientStore.cs
  41. 13
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClient.cs
  42. 6
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientContext.cs
  43. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientEventArgs.cs
  44. 4
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientExtensions.cs
  45. 5
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManager.cs
  46. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManagerExtensions.cs
  47. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineUserEventArgs.cs
  48. 4
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs
  49. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj
  50. 9
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Localization/MessageServiceResource.cs
  51. 16
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceSettingNames.cs
  52. 16
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/CleanupNotificationJobArgs.cs
  53. 17
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/ReadStatus.cs
  54. 3
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj
  55. 9
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDbProperties.cs
  56. 37
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/BackgroundJobs/NotificationExpritionCleanupJob.cs
  57. 35
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs
  58. 4
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs
  59. 12
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationRepository.cs
  60. 11
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationStore.cs
  61. 17
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs
  62. 8
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/Notification.cs
  63. 4
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs
  64. 41
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs
  65. 239
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs
  66. 11
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/UserNotification.cs
  67. 13
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeStore.cs
  68. 6
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/IUserSubscribeRepository.cs
  69. 17
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/RoleSubscribe.cs
  70. 4
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/Subscribe.cs
  71. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs
  72. 41
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeStore.cs
  73. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs
  74. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/ISnowflakeIdGenerator.cs
  75. 16
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj
  76. 26
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs
  77. 26
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContext.cs
  78. 62
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs
  79. 18
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceModelBuilderConfigurationOptions.cs
  80. 36
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationRepository.cs
  81. 53
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs
  82. 68
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs
  83. 4
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN.Abp.MessageService.SignalR.csproj
  84. 2
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayHostModule.cs

21
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContext.cs

@ -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();
}
}
}

29
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContextFactory.cs

@ -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();
}
}
}

38
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj

@ -0,0 +1,38 @@
<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.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" />
</ItemGroup>
</Project>

143
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/AbpMessageServiceHttpApiHostModule.cs

@ -0,0 +1,143 @@
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.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System;
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(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() ? "Platform_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.UseAuthentication();
// jwt
app.UseJwtTokenMiddleware();
// 多租户
app.UseMultiTenancy();
// Swagger
app.UseSwagger();
// Swagger可视化界面
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support MessageService API");
});
// 审计日志
app.UseAuditing();
// 路由
app.UseConfiguredEndpoints();
}
}
}

130
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.Designer.cs

@ -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
}
}
}

93
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.cs

@ -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");
}
}
}

128
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs

@ -0,0 +1,128 @@
// <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.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
}
}
}

35
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/MultiTenancy/AuthorizationTenantResolveContributor.cs

@ -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;
}
}
}

49
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Program.cs

@ -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();
}
}

20
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Properties/launchSettings.json

@ -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"
}
}
}
}

18
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Startup.cs

@ -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();
}
}
}

1
aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj

@ -11,6 +11,7 @@
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj" />
</ItemGroup>
</Project>

7
aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/AbpIMSignalRModule.cs

@ -1,9 +1,12 @@
using Volo.Abp.AspNetCore.SignalR;
using LINGYUN.Abp.RealTime;
using Volo.Abp.AspNetCore.SignalR;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.IM.SignalR
{
[DependsOn(typeof(AbpAspNetCoreSignalRModule))]
[DependsOn(
typeof(AbpRealTimeModule),
typeof(AbpAspNetCoreSignalRModule))]
public class AbpIMSignalRModule : AbpModule
{

78
aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/AbpMessageHub.cs

@ -0,0 +1,78 @@
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]
[HubRoute("messages")]
public class AbpMessageHub : OnlineClientHubBase
{
private readonly IMessageStore _messageStore;
public AbpMessageHub(
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.GroupName.IsNullOrWhiteSpace())
{
try
{
var signalRClient = Clients.Group(chatMessage.GroupName);
if (signalRClient == null)
{
Logger.LogDebug("Can not get group " + chatMessage.GroupName + " from SignalR hub!");
return;
}
await signalRClient.SendAsync("getChatMessage", chatMessage);
}
catch (Exception ex)
{
Logger.LogWarning("Could not send message to group: {0}", chatMessage.GroupName);
Logger.LogWarning("Send group message error: {0}", ex.Message);
}
}
else
{
var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId);
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);
}
}
}
}
}
}

89
aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs

@ -0,0 +1,89 @@
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<AbpMessageHub> _hubContext;
private readonly IMessageStore _messageStore;
public SignalRMessageSender(
IOnlineClientManager onlineClientManager,
IHubContext<AbpMessageHub> 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);
if (!chatMessage.GroupName.IsNullOrWhiteSpace())
{
try
{
var signalRClient = _hubContext.Clients.Group(chatMessage.GroupName);
if (signalRClient == null)
{
Logger.LogDebug("Can not get group " + chatMessage.GroupName + " from SignalR hub!");
return;
}
await signalRClient.SendAsync("getChatMessage", chatMessage);
}
catch (Exception ex)
{
Logger.LogWarning("Could not send message to group: {0}", chatMessage.GroupName);
Logger.LogWarning("Send group message error: {0}", ex.Message);
}
}
else
{
var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId);
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);
}
}
}
}
}
}

34
aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/OnlineClientHubBase.cs

@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Http;
using LINGYUN.Abp.IM.Group;
using LINGYUN.Abp.RealTime.Client;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
@ -8,6 +10,9 @@ namespace LINGYUN.Abp.IM.SignalR
{
public abstract class OnlineClientHubBase : AbpHub
{
private IUserGroupStore _userGroupStore;
protected IUserGroupStore UserGroupStore => LazyGetRequiredService(ref _userGroupStore);
private IOnlineClientManager _onlineClientManager;
protected IOnlineClientManager OnlineClientManager => LazyGetRequiredService(ref _onlineClientManager);
@ -18,28 +23,45 @@ namespace LINGYUN.Abp.IM.SignalR
{
await base.OnConnectedAsync();
IOnlineClient onlineClient = CreateClientForCurrentConnection();
Logger.LogDebug("A client is connected: " + onlineClient?.ToString());
Logger.LogDebug("A client is connected: " + onlineClient.ToString());
OnlineClientManager.Add(onlineClient);
// 加入通讯组
var userGroups = await UserGroupStore.GetUserGroupsAsync(onlineClient.TenantId, onlineClient.UserId.Value);
foreach(var group in userGroups)
{
await Groups.AddToGroupAsync(onlineClient.ConnectionId, group.Name);
}
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
Logger.LogDebug("A client is disconnected: " + base.Context.ConnectionId);
Logger.LogDebug("A client is disconnected: " + Context.ConnectionId);
try
{
OnlineClientManager.Remove(Context.ConnectionId);
// 从通讯组移除
var onlineClient = OnlineClientManager.GetByConnectionIdOrNull(Context.ConnectionId);
if(onlineClient != null)
{
var userGroups = await UserGroupStore.GetUserGroupsAsync(onlineClient.TenantId, onlineClient.UserId.Value);
foreach (var group in userGroups)
{
await Groups.RemoveFromGroupAsync(onlineClient.ConnectionId, group.Name);
}
// 移除在线客户端
OnlineClientManager.Remove(Context.ConnectionId);
}
}
catch (Exception ex)
{
base.Logger.LogWarning(ex.ToString(), ex);
Logger.LogWarning(ex.ToString(), ex);
}
}
protected virtual IOnlineClient CreateClientForCurrentConnection()
{
return new OnlineClient(Context.ConnectionId, GetClientIpAddress(),
CurrentTenant.Id, CurrentUser.Id, CurrentUser.Roles)
CurrentTenant.Id, CurrentUser.Id)
{
ConnectTime = Clock.Now
};

8
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs

@ -0,0 +1,8 @@
namespace LINGYUN.Abp.IM.Group
{
public class GroupChat
{
public string Name { get; set; }
public int MaxUserLength { get; set; }
}
}

40
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs

@ -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<GroupChat>> 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);
/// <summary>
/// 用户退出通讯组
/// </summary>
/// <param name="tenantId"></param>
/// <param name="userId"></param>
/// <param name="groupId"></param>
/// <returns></returns>
Task RemoveUserFormGroupAsync(Guid? tenantId, Guid userId, long groupId);
}
}

11
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs

@ -0,0 +1,11 @@
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; }
}
}

15
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs

@ -0,0 +1,15 @@
using System;
namespace LINGYUN.Abp.IM.Messages
{
public class ChatMessage
{
public Guid? TenantId { get; set; }
public string GroupName { get; set; }
public Guid FormUserId { get; set; }
public Guid ToUserId { get; set; }
public string Content { get; set; }
public DateTime SendTime { get; set; }
public MessageType MessageType { get; set; } = MessageType.Text;
}
}

9
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageSender.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.IM.Messages
{
public interface IMessageSender
{
Task SendMessageAsync(ChatMessage chatMessage);
}
}

34
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs

@ -0,0 +1,34 @@
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, string groupName, 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 userId, int maxResultCount = 10);
}
}

10
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageType.cs

@ -0,0 +1,10 @@
namespace LINGYUN.Abp.IM.Messages
{
public enum MessageType
{
Text = 0,
Image = 10,
Link = 20,
Video = 30
}
}

18
aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj

@ -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>

15
aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs

@ -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
{
}
}

25
aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/AbpNotificationsHub.cs

@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.SignalR;
using Volo.Abp.Users;
namespace LINGYUN.Abp.Notifications.SignalR.Hubs
{
[Authorize]
[HubRoute("notifications")]
public class AbpNotificationsHub : OnlineClientHubBase
{
private INotificationStore _notificationStore;
protected INotificationStore NotificationStore => LazyGetRequiredService(ref _notificationStore);
[HubMethodName("GetNotification")]
public virtual async Task<ListResultDto<NotificationInfo>> GetNotificationAsync(NotificationReadState readState = NotificationReadState.UnRead)
{
var userNotifications = await NotificationStore.GetUserNotificationsAsync(CurrentTenant.Id, CurrentUser.GetId(), readState);
return new ListResultDto<NotificationInfo>(userNotifications);
}
}
}

68
aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs

@ -0,0 +1,68 @@
using LINGYUN.Abp.RealTime.Client;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.SignalR;
namespace LINGYUN.Abp.Notifications.SignalR
{
public abstract class OnlineClientHubBase : AbpHub
{
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()
{
return new OnlineClient(Context.ConnectionId, GetClientIpAddress(),
CurrentTenant.Id, CurrentUser.Id)
{
ConnectTime = Clock.Now
};
}
protected virtual string GetClientIpAddress()
{
try
{
return HttpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
}
catch (Exception ex)
{
Logger.LogException(ex, LogLevel.Warning);
return null;
}
}
}
}

41
aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN/Abp/MessageService/SignalR/Notifications/SignalRNotificationPublisher.cs → aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs

@ -1,7 +1,5 @@
using LINGYUN.Abp.IM;
using LINGYUN.Abp.MessageService.Notifications;
using LINGYUN.Abp.MessageService.SignalR.Hubs;
using LINGYUN.Abp.Notifications;
using LINGYUN.Abp.Notifications.SignalR.Hubs;
using LINGYUN.Abp.RealTime.Client;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@ -10,19 +8,19 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.MessageService.SignalR.Notifications
namespace LINGYUN.Abp.Notifications.SignalR
{
public class SignalRNotificationPublisher : INotificationPublisher, ITransientDependency
public class SignalRNotificationPublisher : INotificationPublisher, ISingletonDependency
{
public ILogger<SignalRNotificationPublisher> Logger { protected get; set; }
private readonly IOnlineClientManager _onlineClientManager;
private readonly IHubContext<AbpMessageHub> _hubContext;
private readonly IHubContext<AbpNotificationsHub> _hubContext;
public SignalRNotificationPublisher(
IOnlineClientManager onlineClientManager,
IHubContext<AbpMessageHub> hubContext)
IOnlineClientManager onlineClientManager,
IHubContext<AbpNotificationsHub> hubContext)
{
_hubContext = hubContext;
_onlineClientManager = onlineClientManager;
@ -30,15 +28,15 @@ namespace LINGYUN.Abp.MessageService.SignalR.Notifications
Logger = NullLogger<SignalRNotificationPublisher>.Instance;
}
public async Task PublishAsync(NotificationData data, IEnumerable<Guid> userIds, Guid? tenantId)
public async Task PublishAsync(NotificationInfo notification, IEnumerable<Guid> userIds)
{
try
foreach(var userId in userIds)
{
foreach(var userId in userIds)
var onlineClientContext = new OnlineClientContext(notification.TenantId, userId);
var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext);
foreach (var onlineClient in onlineClients)
{
var onlineClientContext = new OnlineClientContext(userId, tenantId);
var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext);
foreach (var onlineClient in onlineClients)
try
{
var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId);
if (signalRClient == null)
@ -46,15 +44,16 @@ namespace LINGYUN.Abp.MessageService.SignalR.Notifications
Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!");
continue;
}
await signalRClient.SendAsync("getNotification", data);
await signalRClient.SendAsync("getNotification", notification);
}
catch (Exception ex)
{
Logger.LogWarning("Could not send notifications to user: {0}", userId);
Logger.LogWarning("Send to user notifications error: {0}", ex.Message);
}
}
}
catch(Exception ex)
{
//Logger.LogWarning("Could not send notification to user: " + userId);
Logger.LogWarning(ex.ToString(), ex);
}
}
}
}

14
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs

@ -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>();
}
}
}

2
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs

@ -6,6 +6,6 @@ namespace LINGYUN.Abp.Notifications
{
public interface INotificationPublisher
{
Task PublishAsync(NotificationData data, IEnumerable<Guid> userIds, Guid? tenantId);
Task PublishAsync(NotificationInfo notification, IEnumerable<Guid> userIds);
}
}

12
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationSender.cs

@ -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);
}
}

6
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs

@ -8,6 +8,8 @@ namespace LINGYUN.Abp.Notifications
{
Task InsertUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName);
Task InsertUserSubscriptionAsync(Guid? tenantId, IEnumerable<Guid> userIds, string notificationName);
Task DeleteUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName);
Task<List<NotificationSubscriptionInfo>> GetSubscriptionsAsync(Guid? tenantId, string notificationName);
@ -26,6 +28,8 @@ namespace LINGYUN.Abp.Notifications
Task<NotificationInfo> GetNotificationOrNullAsync(Guid? tenantId, long notificationId);
Task ChangeUserNotificationReadStateAsync(Guid? tenantId, Guid userId, string notificationName, NotificationReadState readState);
Task<List<NotificationInfo>> GetUserNotificationsAsync(Guid? tenantId, Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10);
Task ChangeUserNotificationReadStateAsync(Guid? tenantId, Guid userId, long notificationId, NotificationReadState readState);
}
}

34
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs

@ -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.InsertUserSubscriptionAsync(notification.TenantId, subscriptionUserIds, notification.Name);
// 发布用户通知
await _notificationPublisher.PublishAsync(notification, subscriptionUserIds);
}
}
}

2
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs

@ -6,8 +6,8 @@ namespace LINGYUN.Abp.Notifications
{
public Guid? TenantId { get; set; }
public string Name { get; set; }
public long Id { get; set; }
public NotificationData Data { get; set; }
public DateTime? ExpirationTime { get; set; }
public DateTime CreationTime { get; set; }
public NotificationType NotificationType { get; set; }
public NotificationSeverity NotificationSeverity { get; set; }

12
aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj

@ -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>

8
aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/AbpRealTimeModule.cs

@ -0,0 +1,8 @@
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.RealTime
{
public class AbpRealTimeModule : AbpModule
{
}
}

6
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClient.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClient.cs

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public interface IOnlineClient
{
@ -13,7 +13,9 @@ namespace LINGYUN.Abp.IM
Guid? UserId { get; }
string[] Roles { get; }
string UserAccount { get; }
string UserName { get; }
DateTime ConnectTime { get; }

2
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientManager.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientManager.cs

@ -2,7 +2,7 @@
using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public interface IOnlineClientManager
{

2
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientStore.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientStore.cs

@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public interface IOnlineClientStore
{

2
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/InMemoryOnlineClientStore.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/InMemoryOnlineClientStore.cs

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public class InMemoryOnlineClientStore : IOnlineClientStore, ISingletonDependency
{

13
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClient.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClient.cs

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
[Serializable]
public class OnlineClient : IOnlineClient
@ -18,9 +18,10 @@ namespace LINGYUN.Abp.IM
public Guid? TenantId { get; set; }
public Guid? UserId { get; set; }
public Guid? UserId { get; }
public string UserAccount { get; set; }
public string[] Roles { get; set; }
public string UserName { get; set; }
public DateTime ConnectTime { get; set; }
@ -41,18 +42,16 @@ namespace LINGYUN.Abp.IM
public OnlineClient()
{
Roles = new string[0];
ConnectTime = DateTime.Now;
}
public OnlineClient(string connectionId, string ipAddress, Guid? tenantId, Guid? userId, params string[] roles)
public OnlineClient(string connectionId, string ipAddress, Guid? tenantId, Guid? userId)
: this()
{
ConnectionId = connectionId;
IpAddress = ipAddress;
TenantId = tenantId;
UserId = userId;
Roles = roles;
Properties = new Dictionary<string, object>();
}
@ -63,7 +62,7 @@ namespace LINGYUN.Abp.IM
"-- ConnectionId:", ConnectionId,
"-- Connection Time:", ConnectTime,
"-- IpAddress:", IpAddress ?? "::1",
"-- UserId:", UserId.HasValue ? UserId.Value.ToString() : "None",
"-- UserName:", UserName,
"-- TenantId:", TenantId.HasValue ? TenantId.Value.ToString() : "None");
}
}

6
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientContext.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientContext.cs

@ -1,6 +1,6 @@
using System;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public class OnlineClientContext
{
@ -8,10 +8,10 @@ namespace LINGYUN.Abp.IM
public Guid UserId { get; }
public OnlineClientContext(Guid userId, Guid? tenantId)
public OnlineClientContext(Guid? tenantId, Guid userId)
{
UserId = userId;
TenantId = tenantId;
UserId = userId;
}
}
}

2
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientEventArgs.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientEventArgs.cs

@ -1,6 +1,6 @@
using System;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public class OnlineClientEventArgs : EventArgs
{

4
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientExtensions.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientExtensions.cs

@ -1,6 +1,6 @@
using JetBrains.Annotations;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public static class OnlineClientExtensions
{
@ -8,7 +8,7 @@ namespace LINGYUN.Abp.IM
public static OnlineClientContext ToClientContextOrNull(this IOnlineClient onlineClient)
{
return onlineClient.UserId.HasValue
? new OnlineClientContext(onlineClient.ConnectionId, onlineClient.UserId.Value, onlineClient.TenantId)
? new OnlineClientContext(onlineClient.TenantId, onlineClient.UserId.Value)
: null;
}
}

5
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManager.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManager.cs

@ -6,7 +6,7 @@ using System.Linq;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public class OnlineClientManager : IOnlineClientManager, ISingletonDependency
{
@ -101,8 +101,7 @@ namespace LINGYUN.Abp.IM
Check.NotNull(context, nameof(context));
return GetAllClients()
.Where(c => c.UserId == context.UserId && c.TenantId == context.TenantId)
.WhereIf(context.Roles.Length > 0, c => c.Roles.Any(role => context.Roles.Contains(role)))
.Where(c => c.TenantId == context.TenantId && c.UserId.Equals(context.UserId))
.ToImmutableList();
}
}

2
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManagerExtensions.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManagerExtensions.cs

@ -2,7 +2,7 @@
using System.Linq;
using Volo.Abp;
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public static class OnlineClientManagerExtensions
{

2
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineUserEventArgs.cs → aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineUserEventArgs.cs

@ -1,4 +1,4 @@
namespace LINGYUN.Abp.IM
namespace LINGYUN.Abp.RealTime.Client
{
public class OnlineUserEventArgs : OnlineClientEventArgs
{

4
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs

@ -115,7 +115,9 @@ namespace LINYUN.Abp.Sms.Aliyun
{
if (Environment.IsDevelopment())
{
Check.NotNullOrWhiteSpace(Options.DeveloperPhoneNumber, nameof(Options.DeveloperPhoneNumber));
// check phone number length...
Check.NotNullOrWhiteSpace(Options.DeveloperPhoneNumber, nameof(Options.DeveloperPhoneNumber),
maxLength: 11, minLength: 11);
request.AddQueryParameters("PhoneNumbers", Options.DeveloperPhoneNumber);
}
else

2
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<Folder Include="LINGYUN\Abp\MessageService\Notifications\" />
<PackageReference Include="Volo.Abp.Localization" Version="2.8.0" />
</ItemGroup>
</Project>

9
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Localization/MessageServiceResource.cs

@ -0,0 +1,9 @@
using Volo.Abp.Localization;
namespace LINGYUN.Abp.MessageService.Localization
{
[LocalizationResourceName("MessageService")]
public class MessageServiceResource
{
}
}

16
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceSettingNames.cs

@ -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";
}
}
}

16
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/CleanupNotificationJobArgs.cs

@ -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; }
}
}

17
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/ReadStatus.cs

@ -1,17 +0,0 @@
namespace LINGYUN.Abp.MessageService
{
/// <summary>
/// 读取状态
/// </summary>
public enum ReadStatus : sbyte
{
/// <summary>
/// 已读
/// </summary>
Read = 0,
/// <summary>
/// 未读
/// </summary>
UnRead = 10
}
}

3
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj

@ -7,9 +7,12 @@
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="2.8.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="2.8.0" />
<PackageReference Include="Volo.Abp.BackgroundJobs" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj" />
<ProjectReference Include="..\..\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.MessageService.Domain.Shared\LINGYUN.Abp.MessageService.Domain.Shared.csproj" />
</ItemGroup>

9
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDbProperties.cs

@ -0,0 +1,9 @@
namespace LINGYUN.Abp.MessageService
{
public class AbpMessageServiceDbProperties
{
public const string DefaultTablePrefix = "App";
public const string DefaultSchema = null;
}
}

37
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/BackgroundJobs/NotificationExpritionCleanupJob.cs

@ -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();
}
}
}
}
}

35
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs

@ -0,0 +1,35 @@
using AutoMapper;
using LINGYUN.Abp.MessageService.Notifications;
using LINGYUN.Abp.MessageService.Subscriptions;
using LINGYUN.Abp.Notifications;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
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>();
}
}
}

4
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs

@ -26,9 +26,5 @@ namespace LINGYUN.Abp.MessageService.Messages
/// 发送状态
/// </summary>
public virtual SendStatus SendStatus { get; protected set; }
/// <summary>
/// 阅读状态
/// </summary>
public virtual ReadStatus ReadStatus { get; protected set; }
}
}

12
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationRepository.cs

@ -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);
}
}

11
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationStore.cs

@ -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);
}
}

17
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs

@ -0,0 +1,17 @@
using LINGYUN.Abp.Notifications;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Notifications
{
public interface IUserNotificationRepository : IBasicRepository<UserNotification, long>
{
Task<UserNotification> GetByIdAsync(Guid userId, long notificationId);
Task<List<Notification>> GetNotificationsAsync(Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10);
Task ChangeUserNotificationReadStateAsync(Guid userId, long notificationId, NotificationReadState readState);
}
}

8
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/Notification.cs

@ -10,6 +10,7 @@ namespace LINGYUN.Abp.MessageService.Notifications
{
public virtual Guid? TenantId { get; protected set; }
public virtual NotificationSeverity Severity { get; protected set; }
public virtual NotificationType Type { get; set; }
public virtual long NotificationId { get; protected set; }
public virtual string NotificationName { get; protected set; }
public virtual string NotificationData { get; protected set; }
@ -24,7 +25,12 @@ namespace LINGYUN.Abp.MessageService.Notifications
NotificationName = name;
NotificationData = data;
NotificationTypeName = dataType;
CreationTime = DateTime.Now;
Type = NotificationType.Application;
}
public void SetTenantId(Guid? tenantId)
{
TenantId = tenantId;
}
}
}

4
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs

@ -6,8 +6,6 @@
public const int MaxDataLength = 1024 * 1024;
public const int MaxTypeNameLength = 256;
public const int MaxAssemblyQualifiedNameLength = 512;
public const int MaxTypeNameLength = 512;
}
}

41
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs

@ -1,47 +1,40 @@
using LINGYUN.Abp.MessageService.Subscriptions;
using LINGYUN.Abp.MessageService.Utils;
using LINGYUN.Abp.Notifications;
using LINGYUN.Abp.Notifications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.MessageService.Notifications
{
public class NotificationDispatcher : INotificationDispatcher, ITransientDependency
{
protected IJsonSerializer JsonSerializer { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ISubscribeStore SubscribeStore { get; }
protected INotificationStore NotificationStore { get; }
protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager.Current;
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected INotificationPublisher NotificationPublisher { get; }
protected ISnowflakeIdGenerator SnowflakeIdGenerator { get; }
public NotificationDispatcher(
INotificationStore notificationStore,
INotificationPublisher notificationPublisher)
{
NotificationStore = notificationStore;
NotificationPublisher = notificationPublisher;
}
[UnitOfWork]
public virtual async Task DispatcheAsync(NotificationInfo notification)
{
using (CurrentTenant.Change(notification.TenantId))
var subscribes = await NotificationStore.GetSubscriptionsAsync(notification.TenantId, notification.Name);
foreach (var subscribe in subscribes)
{
var subscribeUsers = await SubscribeStore.GetUserSubscribesAsync(notification.Name);
foreach(var userId in subscribeUsers)
{
await NotificationStore.InsertUserNotificationAsync(notification, userId);
}
await CurrentUnitOfWork.SaveChangesAsync();
await NotifyAsync(notification.Data, notification.TenantId, subscribeUsers);
await NotificationStore.InsertUserNotificationAsync(notification, subscribe.UserId);
}
var subscribeUsers = subscribes.Select(s => s.UserId);
await NotifyAsync(notification, subscribeUsers);
}
protected virtual async Task NotifyAsync(NotificationData data, Guid? tenantId, IEnumerable<Guid> userIds)
protected virtual async Task NotifyAsync(NotificationInfo notification, IEnumerable<Guid> userIds)
{
await NotificationPublisher.PublishAsync(data, userIds, tenantId);
await NotificationPublisher.PublishAsync(notification, userIds);
}
}
}

239
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs

@ -0,0 +1,239 @@
using LINGYUN.Abp.MessageService.Subscriptions;
using LINGYUN.Abp.MessageService.Utils;
using LINGYUN.Abp.Notifications;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.Abp.Json;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.MessageService.Notifications
{
public class NotificationStore : DomainService, INotificationStore
{
private readonly IObjectMapper _objectMapper;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private IJsonSerializer _jsonSerializer;
protected IJsonSerializer JsonSerializer => LazyGetRequiredService(ref _jsonSerializer);
private ISnowflakeIdGenerator _snowflakeIdGenerator;
protected ISnowflakeIdGenerator SnowflakeIdGenerator => LazyGetRequiredService(ref _snowflakeIdGenerator);
private INotificationRepository _notificationRepository;
protected INotificationRepository NotificationRepository => LazyGetRequiredService(ref _notificationRepository);
private IUserNotificationRepository _userNotificationRepository;
protected IUserNotificationRepository UserNotificationRepository => LazyGetRequiredService(ref _userNotificationRepository);
private IUserSubscribeRepository _userSubscribeRepository;
protected IUserSubscribeRepository UserSubscribeRepository => LazyGetRequiredService(ref _userSubscribeRepository);
public NotificationStore(
IObjectMapper objectMapper,
IUnitOfWorkManager unitOfWorkManager)
{
_objectMapper = objectMapper;
_unitOfWorkManager = unitOfWorkManager;
}
[UnitOfWork]
public async Task ChangeUserNotificationReadStateAsync(Guid? tenantId, Guid userId, long notificationId, NotificationReadState readState)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(tenantId))
{
await UserNotificationRepository.ChangeUserNotificationReadStateAsync(userId, notificationId, readState);
await unitOfWork.SaveChangesAsync();
}
}
}
[UnitOfWork]
public async Task DeleteNotificationAsync(NotificationInfo notification)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(notification.TenantId))
{
var notify = await NotificationRepository.GetByIdAsync(notification.Id);
await NotificationRepository.DeleteAsync(notify.Id);
await unitOfWork.SaveChangesAsync();
}
}
}
[UnitOfWork]
public async Task DeleteUserNotificationAsync(Guid? tenantId, Guid userId, long notificationId)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(tenantId))
{
var notify = await UserNotificationRepository.GetByIdAsync(userId, notificationId);
await UserNotificationRepository.DeleteAsync(notify.Id);
await unitOfWork.SaveChangesAsync();
}
}
}
[UnitOfWork]
public async Task DeleteUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(tenantId))
{
var userSubscribe = await UserSubscribeRepository.GetUserSubscribeAsync(notificationName, userId);
await UserSubscribeRepository.DeleteAsync(userSubscribe.Id);
await unitOfWork.SaveChangesAsync();
}
}
}
public async Task<NotificationInfo> GetNotificationOrNullAsync(Guid? tenantId, long notificationId)
{
using (CurrentTenant.Change(tenantId))
{
var notification = await NotificationRepository.GetByIdAsync(notificationId);
return _objectMapper.Map<Notification, NotificationInfo>(notification);
}
}
public async Task<List<NotificationSubscriptionInfo>> GetSubscriptionsAsync(Guid? tenantId, string notificationName)
{
using (CurrentTenant.Change(tenantId))
{
var userSubscriptions = await UserSubscribeRepository.GetSubscribesAsync(notificationName);
return _objectMapper.Map<List<UserSubscribe>, List<NotificationSubscriptionInfo>>(userSubscriptions);
}
}
public async Task<List<NotificationInfo>> GetUserNotificationsAsync(Guid? tenantId, Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10)
{
using (CurrentTenant.Change(tenantId))
{
var notifications = await UserNotificationRepository.GetNotificationsAsync(userId, readState, maxResultCount);
return _objectMapper.Map<List<Notification>, List<NotificationInfo>>(notifications);
}
}
public async Task<List<NotificationSubscriptionInfo>> GetUserSubscriptionsAsync(Guid? tenantId, Guid userId)
{
using (CurrentTenant.Change(tenantId))
{
var userSubscriptionNames = await UserSubscribeRepository.GetUserSubscribesAsync(userId);
var userSubscriptions = new List<NotificationSubscriptionInfo>();
userSubscriptionNames.ForEach(name => userSubscriptions.Add(
new NotificationSubscriptionInfo
{
UserId = userId,
TenantId = tenantId,
NotificationName = name
}));
return userSubscriptions;
}
}
[UnitOfWork]
public async Task InsertNotificationAsync(NotificationInfo notification)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(notification.TenantId))
{
var notify = new Notification(SnowflakeIdGenerator.Create(), notification.Name,
notification.Data.GetType().AssemblyQualifiedName,
JsonSerializer.Serialize(notification.Data), notification.NotificationSeverity)
{
CreationTime = Clock.Now,
Type = notification.NotificationType,
ExpirationTime = Clock.Now.AddDays(60)
};
notify.SetTenantId(notification.TenantId);
await NotificationRepository.InsertAsync(notify);
notification.Id = notify.NotificationId;
await unitOfWork.SaveChangesAsync();
}
}
}
[UnitOfWork]
public async Task InsertUserNotificationAsync(NotificationInfo notification, Guid userId)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(notification.TenantId))
{
var userNotification = new UserNotification(notification.Id, userId);
await UserNotificationRepository.InsertAsync(userNotification);
await unitOfWork.SaveChangesAsync();
}
}
}
[UnitOfWork]
public async Task InsertUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(tenantId))
{
var userSubscription = new UserSubscribe(notificationName, userId)
{
CreationTime = Clock.Now
};
await UserSubscribeRepository.InsertAsync(userSubscription);
await unitOfWork.SaveChangesAsync();
}
}
}
[UnitOfWork]
public async Task InsertUserSubscriptionAsync(Guid? tenantId, IEnumerable<Guid> userIds, string notificationName)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (CurrentTenant.Change(tenantId))
{
var userSubscribes = new List<UserSubscribe>();
foreach(var userId in userIds)
{
userSubscribes.Add(new UserSubscribe(notificationName, userId));
}
await UserSubscribeRepository.InsertUserSubscriptionAsync(userSubscribes);
await unitOfWork.SaveChangesAsync();
}
}
}
public async Task<bool> IsSubscribedAsync(Guid? tenantId, Guid userId, string notificationName)
{
using (CurrentTenant.Change(tenantId))
return await UserSubscribeRepository.UserSubscribeExistsAysnc(notificationName, userId);
}
}
}

11
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/UserNotification.cs

@ -1,4 +1,5 @@
using System;
using LINGYUN.Abp.Notifications;
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
@ -9,12 +10,18 @@ namespace LINGYUN.Abp.MessageService.Notifications
public virtual Guid? TenantId { get; protected set; }
public virtual Guid UserId { get; protected set; }
public virtual long NotificationId { get; protected set; }
public virtual ReadStatus ReadStatus { get; protected set; }
public virtual NotificationReadState ReadStatus { get; protected set; }
protected UserNotification() { }
public UserNotification(long notificationId, Guid userId)
{
UserId = userId;
NotificationId = notificationId;
ReadStatus = NotificationReadState.UnRead;
}
public void ChangeReadState(NotificationReadState readStatus)
{
ReadStatus = readStatus;
}
}
}

13
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeStore.cs

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.MessageService.Subscriptions
{
public interface ISubscribeStore
{
Task<List<Guid>> GetUserSubscribesAsync(string notificationName);
Task UserSubscribeAsync(string notificationName, Guid userId);
Task UserUnSubscribeAsync(string notificationName, Guid userId);
}
}

6
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeRepository.cs → aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/IUserSubscribeRepository.cs

@ -5,14 +5,18 @@ using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Subscriptions
{
public interface ISubscribeRepository : IBasicRepository<Subscribe, long>
public interface IUserSubscribeRepository : IBasicRepository<UserSubscribe, long>
{
Task<bool> UserSubscribeExistsAysnc(string notificationName, Guid userId);
Task<UserSubscribe> GetUserSubscribeAsync(string notificationName, Guid userId);
Task<List<UserSubscribe>> GetSubscribesAsync(string notificationName);
Task<List<string>> GetUserSubscribesAsync(Guid userId);
Task<List<Guid>> GetUserSubscribesAsync(string notificationName);
Task InsertUserSubscriptionAsync(IEnumerable<UserSubscribe> userSubscribes);
}
}

17
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/RoleSubscribe.cs

@ -1,17 +0,0 @@
using System;
using Volo.Abp.Auditing;
namespace LINGYUN.Abp.MessageService.Subscriptions
{
public class RoleSubscribe : Subscribe, IHasCreationTime
{
public virtual string RoleName { get; set; }
public virtual DateTime CreationTime { get; set; }
protected RoleSubscribe() { }
public RoleSubscribe(string notificationName, string roleName) : base(notificationName)
{
RoleName = roleName;
CreationTime = DateTime.Now;
}
}
}

4
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/Subscribe.cs

@ -1,12 +1,14 @@
using System;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Subscriptions
{
public abstract class Subscribe : Entity<long>, IMultiTenant
public abstract class Subscribe : Entity<long>, IMultiTenant, IHasCreationTime
{
public virtual Guid? TenantId { get; protected set; }
public virtual DateTime CreationTime { get; set; }
public virtual string NotificationName { get; protected set; }
protected Subscribe() { }

2
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs

@ -3,7 +3,5 @@
public class SubscribeConsts
{
public const int MaxNotificationNameLength = 100;
public const int MaxRoleNameLength = 64;
}
}

41
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeStore.cs

@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.MessageService.Subscriptions
{
public class SubscribeStore : ISubscribeStore, ITransientDependency
{
protected ISubscribeRepository SubscribeRepository { get; }
public SubscribeStore(ISubscribeRepository subscribeRepository)
{
SubscribeRepository = subscribeRepository;
}
public virtual async Task<List<Guid>> GetUserSubscribesAsync(string notificationName)
{
return await SubscribeRepository.GetUserSubscribesAsync(notificationName);
}
public virtual async Task UserSubscribeAsync(string notificationName, Guid userId)
{
var userSubscribeExists = await SubscribeRepository.UserSubscribeExistsAysnc(notificationName, userId);
if (!userSubscribeExists)
{
var userSbuscribe = new UserSubscribe(notificationName, userId);
await SubscribeRepository.InsertAsync(userSbuscribe);
}
}
public virtual async Task UserUnSubscribeAsync(string notificationName, Guid userId)
{
var userSubscribe = await SubscribeRepository.GetUserSubscribeAsync(notificationName, userId);
if (userSubscribe != null)
{
await SubscribeRepository.DeleteAsync(userSubscribe);
}
}
}
}

2
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs

@ -5,12 +5,10 @@ namespace LINGYUN.Abp.MessageService.Subscriptions
{
public class UserSubscribe : Subscribe, IHasCreationTime
{
public virtual DateTime CreationTime { get; set; }
public virtual Guid UserId { get; set; }
protected UserSubscribe() { }
public UserSubscribe(string notificationName, Guid userId) : base(notificationName)
{
CreationTime = DateTime.Now;
UserId = userId;
}
}

2
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/ISnowflakeIdGenerator.cs

@ -2,6 +2,6 @@
{
public interface ISnowflakeIdGenerator
{
long NextId();
long Create();
}
}

16
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.MessageService.Domain\LINGYUN.Abp.MessageService.Domain.csproj" />
</ItemGroup>
</Project>

26
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs

@ -0,0 +1,26 @@
using LINGYUN.Abp.MessageService.Notifications;
using LINGYUN.Abp.MessageService.Subscriptions;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
{
[DependsOn(
typeof(AbpMessageServiceDomainModule),
typeof(AbpEntityFrameworkCoreModule))]
public class AbpMessageServiceEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<MessageServiceDbContext>(options =>
{
options.AddRepository<Notification, INotificationRepository>();
options.AddRepository<UserNotification, IUserNotificationRepository>();
options.AddRepository<UserSubscribe, IUserSubscribeRepository>();
options.AddDefaultRepositories(includeAllEntities: true);
});
}
}
}

26
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContext.cs

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
{
[ConnectionStringName("MessageService")]
public class MessageServiceDbContext : AbpDbContext<MessageServiceDbContext>
{
public MessageServiceDbContext(DbContextOptions<MessageServiceDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ConfigureMessageService(options =>
{
options.TablePrefix = AbpMessageServiceDbProperties.DefaultTablePrefix;
options.Schema = AbpMessageServiceDbProperties.DefaultSchema;
});
base.OnModelCreating(modelBuilder);
}
}
}

62
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs

@ -0,0 +1,62 @@
using LINGYUN.Abp.MessageService.Notifications;
using LINGYUN.Abp.MessageService.Subscriptions;
using Microsoft.EntityFrameworkCore;
using System;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
{
public static class MessageServiceDbContextModelCreatingExtensions
{
public static void ConfigureMessageService(
this ModelBuilder builder,
Action<MessageServiceModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new MessageServiceModelBuilderConfigurationOptions();
optionsAction?.Invoke(options);
builder.Entity<Notification>(b =>
{
b.ToTable(options.TablePrefix + "Notifications", options.Schema);
b.Property(p => p.NotificationName).HasMaxLength(NotificationConsts.MaxNameLength).IsRequired();
b.Property(p => p.NotificationTypeName).HasMaxLength(NotificationConsts.MaxTypeNameLength).IsRequired();
b.Property(p => p.NotificationData).HasMaxLength(NotificationConsts.MaxDataLength).IsRequired();
b.ConfigureMultiTenant();
b.ConfigureCreationTime();
b.HasIndex(p => p.NotificationName);
});
builder.Entity<UserNotification>(b =>
{
b.ToTable(options.TablePrefix + "UserNotifications", options.Schema);
b.ConfigureMultiTenant();
b.HasIndex(p => new { p.TenantId, p.UserId, p.NotificationId })
.HasName("IX_Tenant_User_Notification_Id");
});
builder.Entity<UserSubscribe>(b =>
{
b.ToTable(options.TablePrefix + "UserSubscribes", options.Schema);
b.Property(p => p.NotificationName).HasMaxLength(SubscribeConsts.MaxNotificationNameLength).IsRequired();
b.ConfigureCreationTime();
b.ConfigureMultiTenant();
b.ConfigureMultiTenant();
b.HasIndex(p => new { p.TenantId, p.UserId, p.NotificationName })
.HasName("IX_Tenant_User_Notification_Name")
.IsUnique();
});
}
}
}

18
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceModelBuilderConfigurationOptions.cs

@ -0,0 +1,18 @@
using JetBrains.Annotations;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
{
public class MessageServiceModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
{
public MessageServiceModelBuilderConfigurationOptions(
[NotNull] string tablePrefix = AbpMessageServiceDbProperties.DefaultTablePrefix,
[CanBeNull] string schema = AbpMessageServiceDbProperties.DefaultSchema)
: base(
tablePrefix,
schema)
{
}
}
}

36
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationRepository.cs

@ -0,0 +1,36 @@
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService.Notifications
{
public class EfCoreNotificationRepository : EfCoreRepository<MessageServiceDbContext, Notification, long>,
INotificationRepository, ITransientDependency
{
public EfCoreNotificationRepository(
IDbContextProvider<MessageServiceDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task DeleteExpritionAsync(int batchCount)
{
var notifications = await DbSet
.Where(x => x.ExpirationTime <= DateTime.Now)
.Take(batchCount)
.ToArrayAsync();
DbSet.RemoveRange(notifications);
}
public async Task<Notification> GetByIdAsync(long notificationId)
{
return await DbSet.Where(x => x.NotificationId.Equals(notificationId)).FirstOrDefaultAsync();
}
}
}

53
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs

@ -0,0 +1,53 @@
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using LINGYUN.Abp.Notifications;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService.Notifications
{
public class EfCoreUserNotificationRepository : EfCoreRepository<MessageServiceDbContext, UserNotification, long>,
IUserNotificationRepository, ITransientDependency
{
public EfCoreUserNotificationRepository(
IDbContextProvider<MessageServiceDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task ChangeUserNotificationReadStateAsync(Guid userId, long notificationId, NotificationReadState readState)
{
var userNofitication = await GetByIdAsync(userId, notificationId);
userNofitication.ChangeReadState(readState);
DbSet.Update(userNofitication);
}
public async Task<UserNotification> GetByIdAsync(Guid userId, long notificationId)
{
var userNofitication = await DbSet
.Where(x => x.NotificationId.Equals(notificationId) && x.UserId.Equals(userId))
.FirstOrDefaultAsync();
return userNofitication;
}
public async Task<List<Notification>> GetNotificationsAsync(Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10)
{
var userNofitications = await (from un in DbContext.Set<UserNotification>()
join n in DbContext.Set<Notification>()
on un.NotificationId equals n.NotificationId
where un.UserId.Equals(userId) && un.ReadStatus.Equals(readState)
select n)
.Take(maxResultCount)
.ToListAsync();
return userNofitications;
}
}
}

68
aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs

@ -0,0 +1,68 @@
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService.Subscriptions
{
public class EfCoreUserSubscribeRepository : EfCoreRepository<MessageServiceDbContext, UserSubscribe, long>,
IUserSubscribeRepository, ITransientDependency
{
public EfCoreUserSubscribeRepository(
IDbContextProvider<MessageServiceDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<List<UserSubscribe>> GetSubscribesAsync(string notificationName)
{
var userSubscribes = await DbSet.Where(x => x.NotificationName.Equals(notificationName)).ToListAsync();
return userSubscribes;
}
public async Task<UserSubscribe> GetUserSubscribeAsync(string notificationName, Guid userId)
{
var userSubscribe = await DbSet
.Where(x => x.UserId.Equals(userId) && x.NotificationName.Equals(notificationName))
.FirstOrDefaultAsync();
return userSubscribe;
}
public async Task<List<string>> GetUserSubscribesAsync(Guid userId)
{
var userSubscribeNames = await DbSet
.Where(x => x.UserId.Equals(userId))
.Select(x => x.NotificationName)
.ToListAsync();
return userSubscribeNames;
}
public async Task<List<Guid>> GetUserSubscribesAsync(string notificationName)
{
var subscribeUsers = await DbSet
.Where(x => x.NotificationName.Equals(notificationName))
.Select(x => x.UserId)
.ToListAsync();
return subscribeUsers;
}
public async Task InsertUserSubscriptionAsync(IEnumerable<UserSubscribe> userSubscribes)
{
await DbSet.AddRangeAsync(userSubscribes);
}
public async Task<bool> UserSubscribeExistsAysnc(string notificationName, Guid userId)
{
return await DbSet.AnyAsync(x => x.UserId.Equals(userId) && x.NotificationName.Equals(notificationName));
}
}
}

4
aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN.Abp.MessageService.SignalR.csproj

@ -10,4 +10,8 @@
<ProjectReference Include="..\LINGYUN.Abp.MessageService.Domain\LINGYUN.Abp.MessageService.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="LINGYUN\Abp\MessageService\SignalR\Notifications\" />
</ItemGroup>
</Project>

2
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayHostModule.cs

@ -67,6 +67,8 @@ namespace LINGYUN.ApiGateway
var env = context.GetEnvironment();
app.UseAuditing();
// 启用ws协议
app.UseWebSockets();
app.UseOcelot().Wait();
}

Loading…
Cancel
Save