From 61818f5b9cb5c1264bf092d7e167fd5f93700a9c Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Mon, 1 Jun 2020 14:41:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=A8=E4=BA=8E=E5=8D=B3?= =?UTF-8?q?=E6=97=B6=E9=80=9A=E8=AE=AF=E4=B8=8E=E9=80=9A=E7=9F=A5=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=9A=84=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MessageServiceHostMigrationsDbContext.cs | 21 ++ ...geServiceHostMigrationsDbContextFactory.cs | 29 +++ ...YUN.Abp.MessageService.HttpApi.Host.csproj | 38 +++ .../AbpMessageServiceHttpApiHostModule.cs | 143 +++++++++++ ...Add-Abp-Message-Service-Module.Designer.cs | 130 ++++++++++ ...01060701_Add-Abp-Message-Service-Module.cs | 93 +++++++ ...iceHostMigrationsDbContextModelSnapshot.cs | 128 ++++++++++ .../AuthorizationTenantResolveContributor.cs | 35 +++ .../Program.cs | 49 ++++ .../Properties/launchSettings.json | 20 ++ .../Startup.cs | 18 ++ .../LINGYUN.Abp.IM.SignalR.csproj | 1 + .../Abp/IM/SignalR/AbpIMSignalRModule.cs | 7 +- .../Abp/IM/SignalR/Hubs/AbpMessageHub.cs | 78 ++++++ .../SignalR/Messages/SignalRMessageSender.cs | 89 +++++++ .../Abp/IM/SignalR/OnlineClientHubBase.cs | 34 ++- .../LINGYUN/Abp/IM/Group/GroupChat.cs | 8 + .../LINGYUN/Abp/IM/Group/IUserGroupStore.cs | 40 +++ .../LINGYUN/Abp/IM/Group/UserGroup.cs | 11 + .../LINGYUN/Abp/IM/Messages/ChatMessage.cs | 15 ++ .../LINGYUN/Abp/IM/Messages/IMessageSender.cs | 9 + .../LINGYUN/Abp/IM/Messages/IMessageStore.cs | 34 +++ .../LINGYUN/Abp/IM/Messages/MessageType.cs | 10 + .../LINGYUN.Abp.Notifications.SignalR.csproj | 18 ++ .../SignalR/AbpNotificationsSignalRModule.cs | 15 ++ .../SignalR/Hubs/AbpNotificationsHub.cs | 25 ++ .../SignalR/OnlineClientHubBase.cs | 68 +++++ .../SignalR}/SignalRNotificationPublisher.cs | 41 ++- .../Notifications/AbpNotificationModule.cs | 14 + .../Notifications/INotificationPublisher.cs | 2 +- .../Abp/Notifications/INotificationSender.cs | 12 - .../Abp/Notifications/INotificationStore.cs | 6 +- .../Internal/DefaultNotificationDispatcher.cs | 34 +++ .../Abp/Notifications/NotificationInfo.cs | 2 +- .../LINGYUN.Abp.RealTime.csproj | 12 + .../LINGYUN/Abp/RealTime/AbpRealTimeModule.cs | 8 + .../Abp/RealTime/Client}/IOnlineClient.cs | 6 +- .../RealTime/Client}/IOnlineClientManager.cs | 2 +- .../RealTime/Client}/IOnlineClientStore.cs | 2 +- .../Client}/InMemoryOnlineClientStore.cs | 2 +- .../Abp/RealTime/Client}/OnlineClient.cs | 13 +- .../RealTime/Client}/OnlineClientContext.cs | 6 +- .../RealTime/Client}/OnlineClientEventArgs.cs | 2 +- .../Client}/OnlineClientExtensions.cs | 4 +- .../RealTime/Client}/OnlineClientManager.cs | 5 +- .../Client}/OnlineClientManagerExtensions.cs | 2 +- .../RealTime/Client}/OnlineUserEventArgs.cs | 2 +- .../LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs | 4 +- ...UN.Abp.MessageService.Domain.Shared.csproj | 2 +- .../Localization/MessageServiceResource.cs | 9 + .../MessageServiceSettingNames.cs | 16 ++ .../CleanupNotificationJobArgs.cs | 16 ++ .../LINGYUN/Abp/MessageService/ReadStatus.cs | 17 -- .../LINGYUN.Abp.MessageService.Domain.csproj | 3 + .../AbpMessageServiceDbProperties.cs | 9 + .../NotificationExpritionCleanupJob.cs | 37 +++ .../MessageServiceDomainAutoMapperProfile.cs | 35 +++ .../MessageService/Messages/ChatMessage.cs | 4 - .../Notifications/INotificationRepository.cs | 12 + .../Notifications/INotificationStore.cs | 11 - .../IUserNotificationRepository.cs | 17 ++ .../Notifications/Notification.cs | 8 +- .../Notifications/NotificationConsts.cs | 4 +- .../Notifications/NotificationDispatcher.cs | 41 ++- .../Notifications/NotificationStore.cs | 239 ++++++++++++++++++ .../Notifications/UserNotification.cs | 11 +- .../Subscriptions/ISubscribeStore.cs | 13 - ...ository.cs => IUserSubscribeRepository.cs} | 6 +- .../Subscriptions/RoleSubscribe.cs | 17 -- .../MessageService/Subscriptions/Subscribe.cs | 4 +- .../Subscriptions/SubscribeConsts.cs | 2 - .../Subscriptions/SubscribeStore.cs | 41 --- .../Subscriptions/UserSubscribe.cs | 2 - .../Utils/ISnowflakeIdGenerator.cs | 2 +- ....MessageService.EntityFrameworkCore.csproj | 16 ++ ...MessageServiceEntityFrameworkCoreModule.cs | 26 ++ .../MessageServiceDbContext.cs | 26 ++ ...ServiceDbContextModelCreatingExtensions.cs | 62 +++++ ...ServiceModelBuilderConfigurationOptions.cs | 18 ++ .../EfCoreNotificationRepository.cs | 36 +++ .../EfCoreUserNotificationRepository.cs | 53 ++++ .../EfCoreUserSubscribeRepository.cs | 68 +++++ .../LINGYUN.Abp.MessageService.SignalR.csproj | 4 + .../ApiGateway/ApiGatewayHostModule.cs | 2 + 84 files changed, 2027 insertions(+), 209 deletions(-) create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContext.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContextFactory.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/AbpMessageServiceHttpApiHostModule.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.Designer.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/MultiTenancy/AuthorizationTenantResolveContributor.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Program.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Properties/launchSettings.json create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Startup.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/AbpMessageHub.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageSender.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageType.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/AbpNotificationsHub.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs rename aspnet-core/modules/{message/LINGYUN.Abp.MessageService.SignalR/LINGYUN/Abp/MessageService/SignalR/Notifications => common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR}/SignalRNotificationPublisher.cs (55%) create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs delete mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationSender.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/AbpRealTimeModule.cs rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/IOnlineClient.cs (77%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/IOnlineClientManager.cs (94%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/IOnlineClientStore.cs (91%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/InMemoryOnlineClientStore.cs (97%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/OnlineClient.cs (83%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/OnlineClientContext.cs (69%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/OnlineClientEventArgs.cs (86%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/OnlineClientExtensions.cs (67%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/OnlineClientManager.cs (93%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/OnlineClientManagerExtensions.cs (95%) rename aspnet-core/modules/common/{LINGYUN.Abp.IM/LINGYUN/Abp/IM => LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client}/OnlineUserEventArgs.cs (87%) create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Localization/MessageServiceResource.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceSettingNames.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/CleanupNotificationJobArgs.cs delete mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/ReadStatus.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDbProperties.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/BackgroundJobs/NotificationExpritionCleanupJob.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationRepository.cs delete mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationStore.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs delete mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeStore.cs rename aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/{ISubscribeRepository.cs => IUserSubscribeRepository.cs} (66%) delete mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/RoleSubscribe.cs delete mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeStore.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContext.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceModelBuilderConfigurationOptions.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContext.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContext.cs new file mode 100644 index 000000000..20be364d6 --- /dev/null +++ b/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 + { + public MessageServiceHostMigrationsDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureMessageService(); + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContextFactory.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContextFactory.cs new file mode 100644 index 000000000..dc0072ba9 --- /dev/null +++ b/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 + { + public MessageServiceHostMigrationsDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .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(); + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj new file mode 100644 index 000000000..cc942270a --- /dev/null +++ b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj @@ -0,0 +1,38 @@ + + + + netcoreapp3.1 + LINGYUN.Abp.MessageService + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/AbpMessageServiceHttpApiHostModule.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/AbpMessageServiceHttpApiHostModule.cs new file mode 100644 index 000000000..31fa0f95c --- /dev/null +++ b/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(options => + { + options.UseMySQL(); + }); + + Configure(options => + { + options.FileSets.AddEmbedded("LINGYUN.Abp.MessageService"); + }); + + // 多租户 + Configure(options => + { + options.IsEnabled = true; + }); + + Configure(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(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(); + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.Designer.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.Designer.cs new file mode 100644 index 000000000..54ac519b1 --- /dev/null +++ b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.Designer.cs @@ -0,0 +1,130 @@ +// +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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("ExpirationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationData") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("NotificationTypeName") + .IsRequired() + .HasColumnType("varchar(512) CHARACTER SET utf8mb4") + .HasMaxLength(512); + + b.Property("Severity") + .HasColumnType("tinyint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NotificationName"); + + b.ToTable("AppNotifications"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("ReadStatus") + .HasColumnType("tinyint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("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 + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.cs new file mode 100644 index 000000000..4da6c6aef --- /dev/null +++ b/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(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TenantId = table.Column(nullable: true), + Severity = table.Column(nullable: false), + Type = table.Column(nullable: false), + NotificationId = table.Column(nullable: false), + NotificationName = table.Column(maxLength: 100, nullable: false), + NotificationData = table.Column(maxLength: 1048576, nullable: false), + NotificationTypeName = table.Column(maxLength: 512, nullable: false), + ExpirationTime = table.Column(nullable: true), + CreationTime = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppNotifications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserNotifications", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + NotificationId = table.Column(nullable: false), + ReadStatus = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserNotifications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserSubscribes", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TenantId = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + NotificationName = table.Column(maxLength: 100, nullable: false), + UserId = table.Column(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"); + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..8e253493d --- /dev/null +++ b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,128 @@ +// +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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("ExpirationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationData") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("NotificationTypeName") + .IsRequired() + .HasColumnType("varchar(512) CHARACTER SET utf8mb4") + .HasMaxLength(512); + + b.Property("Severity") + .HasColumnType("tinyint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NotificationName"); + + b.ToTable("AppNotifications"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("ReadStatus") + .HasColumnType("tinyint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("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 + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/MultiTenancy/AuthorizationTenantResolveContributor.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/MultiTenancy/AuthorizationTenantResolveContributor.cs new file mode 100644 index 000000000..f0c09657f --- /dev/null +++ b/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; + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Program.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Program.cs new file mode 100644 index 000000000..210cb65f8 --- /dev/null +++ b/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(); + }) + .UseSerilog() + .UseAutofac(); + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 000000000..0e44e51b1 --- /dev/null +++ b/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" + } + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Startup.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Startup.cs new file mode 100644 index 000000000..ad091b0da --- /dev/null +++ b/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(); + } + + public void Configure(IApplicationBuilder app) + { + app.InitializeApplication(); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj index 36bb389f9..7718a5418 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj @@ -11,6 +11,7 @@ + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/AbpIMSignalRModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/AbpIMSignalRModule.cs index 541627145..6d2bcdc75 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/AbpIMSignalRModule.cs +++ b/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 { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/AbpMessageHub.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/AbpMessageHub.cs new file mode 100644 index 000000000..b1155fcb3 --- /dev/null +++ b/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; + } + /// + /// 客户端调用发送消息方法 + /// + /// + /// + [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); + } + } + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs new file mode 100644 index 000000000..65576b017 --- /dev/null +++ b/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 Logger { protected get; set; } + + private readonly IOnlineClientManager _onlineClientManager; + + private readonly IHubContext _hubContext; + + private readonly IMessageStore _messageStore; + + public SignalRMessageSender( + IOnlineClientManager onlineClientManager, + IHubContext hubContext, + IMessageStore messageStore) + { + _hubContext = hubContext; + _messageStore = messageStore; + _onlineClientManager = onlineClientManager; + + Logger = NullLogger.Instance; + } + /// + /// 服务端调用发送消息方法 + /// + /// + /// + 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); + } + } + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/OnlineClientHubBase.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/OnlineClientHubBase.cs index ad432a11e..0d9d2aac9 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/OnlineClientHubBase.cs +++ b/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 }; diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs new file mode 100644 index 000000000..4927ae723 --- /dev/null +++ b/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; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs new file mode 100644 index 000000000..800ca41b6 --- /dev/null +++ b/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 + { + /// + /// 获取用户所在通讯组列表 + /// + /// + /// + /// + Task> GetUserGroupsAsync(Guid? tenantId, Guid userId); + /// + /// 获取通讯组所有用户 + /// + /// + /// + /// + Task> GetGroupUsersAsync(Guid? tenantId, long groupId); + /// + /// 用户加入通讯组 + /// + /// + /// + /// + /// + Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId); + /// + /// 用户退出通讯组 + /// + /// + /// + /// + /// + Task RemoveUserFormGroupAsync(Guid? tenantId, Guid userId, long groupId); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs new file mode 100644 index 000000000..d008896d5 --- /dev/null +++ b/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; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs new file mode 100644 index 000000000..33f9c7624 --- /dev/null +++ b/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; + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageSender.cs new file mode 100644 index 000000000..caea95cb9 --- /dev/null +++ b/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); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs new file mode 100644 index 000000000..7ca433a90 --- /dev/null +++ b/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 + { + /// + /// 存储聊天记录 + /// + /// + /// + /// + /// + Task StoreMessageAsync(ChatMessage chatMessage); + /// + /// 获取群组聊天记录 + /// + /// + /// + /// + /// + Task> GetGroupMessageAsync(Guid tenantId, string groupName, int maxResultCount = 10); + /// + /// 获取与某个用户的聊天记录 + /// + /// + /// + /// + /// + Task> GetChatMessageAsync(Guid tenantId, Guid userId, int maxResultCount = 10); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageType.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageType.cs new file mode 100644 index 000000000..eb9e6fb9f --- /dev/null +++ b/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 + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj new file mode 100644 index 000000000..1d4d15feb --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj @@ -0,0 +1,18 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs new file mode 100644 index 000000000..549f249f8 --- /dev/null +++ b/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 + { + + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/AbpNotificationsHub.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/AbpNotificationsHub.cs new file mode 100644 index 000000000..1f2b9ba6c --- /dev/null +++ b/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> GetNotificationAsync(NotificationReadState readState = NotificationReadState.UnRead) + { + var userNotifications = await NotificationStore.GetUserNotificationsAsync(CurrentTenant.Id, CurrentUser.GetId(), readState); + + return new ListResultDto(userNotifications); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs new file mode 100644 index 000000000..3a942cbc6 --- /dev/null +++ b/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; + } + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN/Abp/MessageService/SignalR/Notifications/SignalRNotificationPublisher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs similarity index 55% rename from aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN/Abp/MessageService/SignalR/Notifications/SignalRNotificationPublisher.cs rename to aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs index 98da317ef..534d88e4f 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN/Abp/MessageService/SignalR/Notifications/SignalRNotificationPublisher.cs +++ b/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 Logger { protected get; set; } private readonly IOnlineClientManager _onlineClientManager; - private readonly IHubContext _hubContext; + private readonly IHubContext _hubContext; public SignalRNotificationPublisher( - IOnlineClientManager onlineClientManager, - IHubContext hubContext) + IOnlineClientManager onlineClientManager, + IHubContext hubContext) { _hubContext = hubContext; _onlineClientManager = onlineClientManager; @@ -30,15 +28,15 @@ namespace LINGYUN.Abp.MessageService.SignalR.Notifications Logger = NullLogger.Instance; } - public async Task PublishAsync(NotificationData data, IEnumerable userIds, Guid? tenantId) + public async Task PublishAsync(NotificationInfo notification, IEnumerable 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); - } } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs new file mode 100644 index 000000000..ec8c315e2 --- /dev/null +++ b/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(); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs index 523856eea..1e8411eb9 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs +++ b/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 userIds, Guid? tenantId); + Task PublishAsync(NotificationInfo notification, IEnumerable userIds); } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationSender.cs deleted file mode 100644 index aed195b60..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationSender.cs +++ /dev/null @@ -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 userIds, Guid? tenantId); - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs index e35c2a4aa..1ca149a17 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs +++ b/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 userIds, string notificationName); + Task DeleteUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName); Task> GetSubscriptionsAsync(Guid? tenantId, string notificationName); @@ -26,6 +28,8 @@ namespace LINGYUN.Abp.Notifications Task GetNotificationOrNullAsync(Guid? tenantId, long notificationId); - Task ChangeUserNotificationReadStateAsync(Guid? tenantId, Guid userId, string notificationName, NotificationReadState readState); + Task> GetUserNotificationsAsync(Guid? tenantId, Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10); + + Task ChangeUserNotificationReadStateAsync(Guid? tenantId, Guid userId, long notificationId, NotificationReadState readState); } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs new file mode 100644 index 000000000..ff03a6478 --- /dev/null +++ b/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); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs index 3f1826be9..e1bdf131b 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs +++ b/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; } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj new file mode 100644 index 000000000..268dae169 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/AbpRealTimeModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/AbpRealTimeModule.cs new file mode 100644 index 000000000..f4282a301 --- /dev/null +++ b/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 + { + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClient.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClient.cs similarity index 77% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClient.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClient.cs index 9106ad1b3..00f465a89 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClient.cs +++ b/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; } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientManager.cs similarity index 94% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientManager.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientManager.cs index 67008fc02..7f83b96bb 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientManager.cs +++ b/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 { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientStore.cs similarity index 91% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientStore.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientStore.cs index ef7e704c8..9affcabbc 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/IOnlineClientStore.cs +++ b/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 { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/InMemoryOnlineClientStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/InMemoryOnlineClientStore.cs similarity index 97% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/InMemoryOnlineClientStore.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/InMemoryOnlineClientStore.cs index 5e93ddfd3..20b8de95c 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/InMemoryOnlineClientStore.cs +++ b/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 { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClient.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClient.cs similarity index 83% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClient.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClient.cs index 0771f485d..43dc48b1c 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClient.cs +++ b/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(); } @@ -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"); } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientContext.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientContext.cs similarity index 69% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientContext.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientContext.cs index e27877c3e..38ef6e05a 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientContext.cs +++ b/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; } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientEventArgs.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientEventArgs.cs similarity index 86% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientEventArgs.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientEventArgs.cs index a2e459529..dffdece95 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientEventArgs.cs +++ b/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 { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientExtensions.cs similarity index 67% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientExtensions.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientExtensions.cs index 6dc956615..6f9acfb3f 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientExtensions.cs +++ b/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; } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManager.cs similarity index 93% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManager.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManager.cs index c82594930..e02405cf4 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManager.cs +++ b/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(); } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManagerExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManagerExtensions.cs similarity index 95% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManagerExtensions.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManagerExtensions.cs index 5a51135b5..ad69bb5cf 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineClientManagerExtensions.cs +++ b/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 { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineUserEventArgs.cs b/aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineUserEventArgs.cs similarity index 87% rename from aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineUserEventArgs.cs rename to aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineUserEventArgs.cs index 4ce24f1a9..1c5708cb4 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/OnlineUserEventArgs.cs +++ b/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 { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs index 5ee48c601..36690094b 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs +++ b/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 diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj index 1cf822808..799cfdfd1 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Localization/MessageServiceResource.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Localization/MessageServiceResource.cs new file mode 100644 index 000000000..6f918bea7 --- /dev/null +++ b/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 + { + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceSettingNames.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceSettingNames.cs new file mode 100644 index 000000000..0b4a121fe --- /dev/null +++ b/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"; + /// + /// 清理过期消息批次 + /// + public const string CleanupExpirationBatchCount = Default + ".CleanupExpirationBatchCount"; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/CleanupNotificationJobArgs.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/CleanupNotificationJobArgs.cs new file mode 100644 index 000000000..03536e0da --- /dev/null +++ b/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 + { + /// + /// 清理大小 + /// + public int Count { get; set; } + /// + /// 清理租户 + /// + public Guid? TenantId { get; set; } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/ReadStatus.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/ReadStatus.cs deleted file mode 100644 index 0fe9e94df..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/ReadStatus.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace LINGYUN.Abp.MessageService -{ - /// - /// 读取状态 - /// - public enum ReadStatus : sbyte - { - /// - /// 已读 - /// - Read = 0, - /// - /// 未读 - /// - UnRead = 10 - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj index cb3747869..4ca8aa840 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj @@ -7,9 +7,12 @@ + + + diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDbProperties.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDbProperties.cs new file mode 100644 index 000000000..6a87fed45 --- /dev/null +++ b/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; + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/BackgroundJobs/NotificationExpritionCleanupJob.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/BackgroundJobs/NotificationExpritionCleanupJob.cs new file mode 100644 index 000000000..7a342922e --- /dev/null +++ b/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 + { + 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(); + } + } + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs new file mode 100644 index 000000000..f49e6d8a3 --- /dev/null +++ b/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() + .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(); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs index 995e5a29a..fb4ac32b3 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs @@ -26,9 +26,5 @@ namespace LINGYUN.Abp.MessageService.Messages /// 发送状态 /// public virtual SendStatus SendStatus { get; protected set; } - /// - /// 阅读状态 - /// - public virtual ReadStatus ReadStatus { get; protected set; } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationRepository.cs new file mode 100644 index 000000000..dc91fff44 --- /dev/null +++ b/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 + { + Task GetByIdAsync(long notificationId); + + Task DeleteExpritionAsync(int batchCount); + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationStore.cs deleted file mode 100644 index 3d6ae41b6..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationStore.cs +++ /dev/null @@ -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); - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/IUserNotificationRepository.cs new file mode 100644 index 000000000..fe5995696 --- /dev/null +++ b/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 + { + Task GetByIdAsync(Guid userId, long notificationId); + + Task> GetNotificationsAsync(Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10); + + Task ChangeUserNotificationReadStateAsync(Guid userId, long notificationId, NotificationReadState readState); + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/Notification.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/Notification.cs index 911511771..329ae9140 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/Notification.cs +++ b/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; } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs index 62b2da9d0..83de31bff 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs +++ b/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; } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs index df76ef4af..a24a3dae8 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs +++ b/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 userIds) + protected virtual async Task NotifyAsync(NotificationInfo notification, IEnumerable userIds) { - await NotificationPublisher.PublishAsync(data, userIds, tenantId); + await NotificationPublisher.PublishAsync(notification, userIds); } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs new file mode 100644 index 000000000..d36d75ff0 --- /dev/null +++ b/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 GetNotificationOrNullAsync(Guid? tenantId, long notificationId) + { + using (CurrentTenant.Change(tenantId)) + { + var notification = await NotificationRepository.GetByIdAsync(notificationId); + + return _objectMapper.Map(notification); + } + } + + public async Task> GetSubscriptionsAsync(Guid? tenantId, string notificationName) + { + using (CurrentTenant.Change(tenantId)) + { + var userSubscriptions = await UserSubscribeRepository.GetSubscribesAsync(notificationName); + + return _objectMapper.Map, List>(userSubscriptions); + } + } + + public async Task> 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>(notifications); + } + } + + public async Task> GetUserSubscriptionsAsync(Guid? tenantId, Guid userId) + { + using (CurrentTenant.Change(tenantId)) + { + var userSubscriptionNames = await UserSubscribeRepository.GetUserSubscribesAsync(userId); + + var userSubscriptions = new List(); + + 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 userIds, string notificationName) + { + using (var unitOfWork = _unitOfWorkManager.Begin()) + { + using (CurrentTenant.Change(tenantId)) + { + var userSubscribes = new List(); + + foreach(var userId in userIds) + { + userSubscribes.Add(new UserSubscribe(notificationName, userId)); + } + + await UserSubscribeRepository.InsertUserSubscriptionAsync(userSubscribes); + + await unitOfWork.SaveChangesAsync(); + } + } + } + + public async Task IsSubscribedAsync(Guid? tenantId, Guid userId, string notificationName) + { + using (CurrentTenant.Change(tenantId)) + return await UserSubscribeRepository.UserSubscribeExistsAysnc(notificationName, userId); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/UserNotification.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/UserNotification.cs index 76741a1b7..2099b4d06 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/UserNotification.cs +++ b/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; } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeStore.cs deleted file mode 100644 index b3a7fef01..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeStore.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace LINGYUN.Abp.MessageService.Subscriptions -{ - public interface ISubscribeStore - { - Task> GetUserSubscribesAsync(string notificationName); - Task UserSubscribeAsync(string notificationName, Guid userId); - Task UserUnSubscribeAsync(string notificationName, Guid userId); - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/IUserSubscribeRepository.cs similarity index 66% rename from aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeRepository.cs rename to aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/IUserSubscribeRepository.cs index 13c264548..0615db628 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/ISubscribeRepository.cs +++ b/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 + public interface IUserSubscribeRepository : IBasicRepository { Task UserSubscribeExistsAysnc(string notificationName, Guid userId); Task GetUserSubscribeAsync(string notificationName, Guid userId); + Task> GetSubscribesAsync(string notificationName); + Task> GetUserSubscribesAsync(Guid userId); Task> GetUserSubscribesAsync(string notificationName); + + Task InsertUserSubscriptionAsync(IEnumerable userSubscribes); } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/RoleSubscribe.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/RoleSubscribe.cs deleted file mode 100644 index 23f052e20..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/RoleSubscribe.cs +++ /dev/null @@ -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; - } - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/Subscribe.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/Subscribe.cs index 2fdc1306d..4fb6dbc1e 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/Subscribe.cs +++ b/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, IMultiTenant + public abstract class Subscribe : Entity, IMultiTenant, IHasCreationTime { public virtual Guid? TenantId { get; protected set; } + public virtual DateTime CreationTime { get; set; } public virtual string NotificationName { get; protected set; } protected Subscribe() { } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs index ad3011801..d7a583b55 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs +++ b/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; } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeStore.cs deleted file mode 100644 index cefc653f6..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeStore.cs +++ /dev/null @@ -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> 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); - } - } - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs index a3012dd17..5c5f03c4c 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs +++ b/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; } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/ISnowflakeIdGenerator.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/ISnowflakeIdGenerator.cs index 22609c5e0..310f419de 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Utils/ISnowflakeIdGenerator.cs +++ b/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(); } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj new file mode 100644 index 000000000..3ce788c0a --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..8fdc82b7d --- /dev/null +++ b/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(options => + { + options.AddRepository(); + options.AddRepository(); + options.AddRepository(); + + options.AddDefaultRepositories(includeAllEntities: true); + }); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContext.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContext.cs new file mode 100644 index 000000000..4f7fbb22d --- /dev/null +++ b/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 + { + public MessageServiceDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ConfigureMessageService(options => + { + options.TablePrefix = AbpMessageServiceDbProperties.DefaultTablePrefix; + options.Schema = AbpMessageServiceDbProperties.DefaultSchema; + }); + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs new file mode 100644 index 000000000..a30c550a8 --- /dev/null +++ b/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 optionsAction = null) + { + Check.NotNull(builder, nameof(builder)); + + var options = new MessageServiceModelBuilderConfigurationOptions(); + + optionsAction?.Invoke(options); + + builder.Entity(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(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(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(); + }); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceModelBuilderConfigurationOptions.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceModelBuilderConfigurationOptions.cs new file mode 100644 index 000000000..049ae7d54 --- /dev/null +++ b/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) + { + + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreNotificationRepository.cs new file mode 100644 index 000000000..f6fd96e39 --- /dev/null +++ b/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, + INotificationRepository, ITransientDependency + { + public EfCoreNotificationRepository( + IDbContextProvider 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 GetByIdAsync(long notificationId) + { + return await DbSet.Where(x => x.NotificationId.Equals(notificationId)).FirstOrDefaultAsync(); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs new file mode 100644 index 000000000..6b3e24fd7 --- /dev/null +++ b/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, + IUserNotificationRepository, ITransientDependency + { + public EfCoreUserNotificationRepository( + IDbContextProvider 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 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> GetNotificationsAsync(Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10) + { + + var userNofitications = await (from un in DbContext.Set() + join n in DbContext.Set() + on un.NotificationId equals n.NotificationId + where un.UserId.Equals(userId) && un.ReadStatus.Equals(readState) + select n) + .Take(maxResultCount) + .ToListAsync(); + return userNofitications; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs new file mode 100644 index 000000000..898701772 --- /dev/null +++ b/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, + IUserSubscribeRepository, ITransientDependency + { + public EfCoreUserSubscribeRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task> GetSubscribesAsync(string notificationName) + { + var userSubscribes = await DbSet.Where(x => x.NotificationName.Equals(notificationName)).ToListAsync(); + + return userSubscribes; + } + + public async Task 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> GetUserSubscribesAsync(Guid userId) + { + var userSubscribeNames = await DbSet + .Where(x => x.UserId.Equals(userId)) + .Select(x => x.NotificationName) + .ToListAsync(); + + return userSubscribeNames; + } + + public async Task> 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 userSubscribes) + { + await DbSet.AddRangeAsync(userSubscribes); + } + + public async Task UserSubscribeExistsAysnc(string notificationName, Guid userId) + { + return await DbSet.AnyAsync(x => x.UserId.Equals(userId) && x.NotificationName.Equals(notificationName)); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN.Abp.MessageService.SignalR.csproj b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN.Abp.MessageService.SignalR.csproj index d014cb2da..ea1854834 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN.Abp.MessageService.SignalR.csproj +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.SignalR/LINGYUN.Abp.MessageService.SignalR.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayHostModule.cs b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayHostModule.cs index 5a5666258..8eb8eae72 100644 --- a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayHostModule.cs +++ b/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(); }