Browse Source

Merge pull request #1 from colinin/im-notify

合并IM模块到主分支
pull/21/head
cKey 6 years ago
committed by GitHub
parent
commit
6f26dd6e2b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      README.en.md
  2. 14
      README.md
  3. 62
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs
  4. 21
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContext.cs
  5. 29
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/EntityFrameworkCore/MessageServiceHostMigrationsDbContextFactory.cs
  6. 40
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj
  7. 152
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/AbpMessageServiceHttpApiHostModule.cs
  8. 16
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/Utils/SnowflakeIdGenerator.cs
  9. 130
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.Designer.cs
  10. 93
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200601060701_Add-Abp-Message-Service-Module.cs
  11. 494
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.Designer.cs
  12. 281
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.cs
  13. 492
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs
  14. 35
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/MultiTenancy/AuthorizationTenantResolveContributor.cs
  15. 49
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Program.cs
  16. 20
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Properties/launchSettings.json
  17. 18
      aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Startup.cs
  18. 12
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs
  19. 1
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN.Abp.IM.SignalR.csproj
  20. 7
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/AbpIMSignalRModule.cs
  21. 77
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessageHub.cs
  22. 101
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs
  23. 34
      aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/OnlineClientHubBase.cs
  24. 2
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj
  25. 26
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/Group.cs
  26. 40
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs
  27. 13
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs
  28. 29
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs
  29. 9
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageSender.cs
  30. 35
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs
  31. 4
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageSendState.cs
  32. 10
      aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageType.cs
  33. 18
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN.Abp.Notifications.SignalR.csproj
  34. 15
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs
  35. 32
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/NotificationsHub.cs
  36. 78
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/OnlineClientHubBase.cs
  37. 41
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs
  38. 26
      aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/Microsoft/AspNetCore/Builder/SignalRJwtTokenMiddleware.cs
  39. 2
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj
  40. 14
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs
  41. 2
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs
  42. 12
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationSender.cs
  43. 8
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs
  44. 34
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs
  45. 8
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs
  46. 30
      aspnet-core/modules/common/LINGYUN.Abp.Notifications/Newtonsoft/Json/HexLongConverter.cs
  47. 12
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN.Abp.RealTime.csproj
  48. 8
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/AbpRealTimeModule.cs
  49. 6
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClient.cs
  50. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientManager.cs
  51. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/IOnlineClientStore.cs
  52. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/InMemoryOnlineClientStore.cs
  53. 13
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClient.cs
  54. 6
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientContext.cs
  55. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientEventArgs.cs
  56. 4
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientExtensions.cs
  57. 5
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManager.cs
  58. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineClientManagerExtensions.cs
  59. 2
      aspnet-core/modules/common/LINGYUN.Abp.RealTime/LINGYUN/Abp/RealTime/Client/OnlineUserEventArgs.cs
  60. 4
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs
  61. 3
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json
  62. 3
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json
  63. 9
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs
  64. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN.Abp.MessageService.Domain.Shared.csproj
  65. 9
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Localization/MessageServiceResource.cs
  66. 30
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceErrorCodes.cs
  67. 16
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceSettingNames.cs
  68. 15
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/ChatGroupConsts.cs
  69. 10
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/MessageConsts.cs
  70. 16
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/CleanupNotificationJobArgs.cs
  71. 4
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs
  72. 17
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/ReadStatus.cs
  73. 2
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs
  74. 14
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj
  75. 9
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDbProperties.cs
  76. 13
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/AbpMessageServiceDomainModule.cs
  77. 37
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/BackgroundJobs/NotificationExpritionCleanupJob.cs
  78. 48
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/UserCreateEventHandler.cs
  79. 11
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json
  80. 11
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json
  81. 57
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs
  82. 76
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroup.cs
  83. 69
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroupAdmin.cs
  84. 34
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs
  85. 32
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupChatBlack.cs
  86. 24
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupMessage.cs
  87. 22
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IGroupRepository.cs
  88. 24
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IMessageRepository.cs
  89. 25
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatGroupRepository.cs
  90. 20
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatSettingRepository.cs
  91. 50
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/Message.cs
  92. 132
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/MessageStore.cs
  93. 32
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatBlack.cs
  94. 27
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatGroup.cs
  95. 54
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatSetting.cs
  96. 86
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserGroupStore.cs
  97. 25
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserMessage.cs
  98. 32
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserSpecialFocus.cs
  99. 12
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationRepository.cs
  100. 11
      aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/INotificationStore.cs

14
README.en.md

@ -41,7 +41,19 @@ If you want to get started with a minimal template code instead of integration s
## Screenshots ## Screenshots
![dashboard](./demo/dashboard.png) ![Login](./vueJs/images/userLogin.png)
![Tenants](./vueJs/images/tenant.png)
![Roles](./vueJs/images/userRoles.png)
![Permissions](./vueJs/images/userPermissions.png)
![IM](./vueJs/images/im-notifications.png)
![Clients](./vueJs/images/client.png)
![Aggregate route](./vueJs/images/aggregate.png)
## Related Projects ## Related Projects

14
README.md

@ -19,11 +19,19 @@
## 截图 ## 截图
![登录页](./images/userLogin.png) ![登录页](./vueJs/images/userLogin.png)
![角色页](./images/userRoles.png) ![租户管理](./vueJs/images/tenant.png)
![权限页](./images/userPermissions.png) ![角色页](./vueJs/images/userRoles.png)
![权限页](./vueJs/images/userPermissions.png)
![即时通讯](./vueJs/images/im-notifications.png)
![客户端管理](./vueJs/images/client.png)
![聚合路由](./vueJs/images/aggregate.png)
## 相关项目 ## 相关项目

62
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs

@ -0,0 +1,62 @@
using LINGYUN.Abp.Notifications;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.MessageService.Controllers
{
[Route("api/app/notifications")]
public class NotificationController : AbpController
{
private readonly INotificationDispatcher _notificationDispatcher;
public NotificationController(
INotificationDispatcher notificationDispatcher)
{
_notificationDispatcher = notificationDispatcher;
}
[HttpPost]
[Route("Send")]
public async Task SendNofitication([FromForm] SendNotification notification)
{
var notificationInfo = new NotificationInfo
{
TenantId = null,
NotificationSeverity = notification.Severity,
NotificationType = NotificationType.Application,
Id = new Random().Next(int.MinValue, int.MaxValue),
Name = "TestApplicationNotofication",
CreationTime = Clock.Now
};
notificationInfo.Data.Properties["id"] = notificationInfo.Id.ToString();
notificationInfo.Data.Properties["title"] = notification.Title;
notificationInfo.Data.Properties["message"] = notification.Message;
notificationInfo.Data.Properties["datetime"] = Clock.Now;
notificationInfo.Data.Properties["severity"] = notification.Severity;
await _notificationDispatcher.DispatcheAsync(notificationInfo);
}
}
public class SendNotification
{
public Guid UserId { get; set; }
public string Title { get; set; }
public string Message { get; set; }
public NotificationSeverity Severity { get; set; } = NotificationSeverity.Success;
}
public class TestApplicationNotificationData : NotificationData
{
public object Message
{
get { return this[nameof(Message)]; }
set
{
Properties[nameof(Message)] = value;
}
}
}
}

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

@ -0,0 +1,21 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
{
public class MessageServiceHostMigrationsDbContext : AbpDbContext<MessageServiceHostMigrationsDbContext>
{
public MessageServiceHostMigrationsDbContext(DbContextOptions<MessageServiceHostMigrationsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureMessageService();
}
}
}

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

@ -0,0 +1,29 @@
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
namespace LINGYUN.Abp.MessageService.EntityFrameworkCore
{
public class MessageServiceHostMigrationsDbContextFactory : IDesignTimeDbContextFactory<MessageServiceHostMigrationsDbContext>
{
public MessageServiceHostMigrationsDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
var builder = new DbContextOptionsBuilder<MessageServiceHostMigrationsDbContext>()
.UseMySql(configuration.GetConnectionString("Default"));
return new MessageServiceHostMigrationsDbContext(builder.Options);
}
private static IConfigurationRoot BuildConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.Development.json", optional: false);
return builder.Build();
}
}
}

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

@ -0,0 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>LINGYUN.Abp.MessageService</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.1.3" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="3.1.3" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Enrichers.Assembly" Version="2.0.0" />
<PackageReference Include="Serilog.Enrichers.Process" Version="2.0.1" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.4.1" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="2.8.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.8.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="2.8.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" />
<ProjectReference Include="..\modules\common\LINGYUN.Abp.IM.SignalR\LINGYUN.Abp.IM.SignalR.csproj" />
<ProjectReference Include="..\modules\common\LINGYUN.Abp.Notifications.SignalR\LINGYUN.Abp.Notifications.SignalR.csproj" />
<ProjectReference Include="..\modules\message\LINGYUN.Abp.MessageService.EntityFrameworkCore\LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\modules\message\LINGYUN.Abp.MessageService.HttpApi\LINGYUN.Abp.MessageService.HttpApi.csproj" />
</ItemGroup>
</Project>

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

@ -0,0 +1,152 @@
using IdentityModel;
using LINGYUN.Abp.IM.SignalR;
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using LINGYUN.Abp.MessageService.MultiTenancy;
using LINGYUN.Abp.Notifications.SignalR;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.Autofac;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.Security.Claims;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.MessageService
{
[DependsOn(
typeof(AbpMessageServiceHttpApiModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpMessageServiceEntityFrameworkCoreModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpIMSignalRModule),
typeof(AbpNotificationsSignalRModule),
typeof(AbpAutofacModule)
)]
public class AbpMessageServiceHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = hostingEnvironment.BuildConfiguration();
// 配置Ef
Configure<AbpDbContextOptions>(options =>
{
options.UseMySQL();
});
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpMessageServiceHttpApiHostModule>("LINGYUN.Abp.MessageService");
});
// 多租户
Configure<AbpMultiTenancyOptions>(options =>
{
options.IsEnabled = true;
});
Configure<AbpTenantResolveOptions>(options =>
{
options.TenantResolvers.Insert(0, new AuthorizationTenantResolveContributor());
});
// Swagger
context.Services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MessageService API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
});
// 支持本地化语言类型
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
});
context.Services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = false;
options.ApiName = configuration["AuthServer:ApiName"];
AbpClaimTypes.UserId = JwtClaimTypes.Subject;
AbpClaimTypes.UserName = JwtClaimTypes.Name;
AbpClaimTypes.Role = JwtClaimTypes.Role;
AbpClaimTypes.Email = JwtClaimTypes.Email;
});
context.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = configuration["RedisCache:ConnectString"];
var instanceName = configuration["RedisCache:RedisPrefix"];
options.InstanceName = instanceName.IsNullOrEmpty() ? "MessageService_Cache" : instanceName;
});
if (!hostingEnvironment.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(configuration["RedisCache:ConnectString"]);
context.Services
.AddDataProtection()
.PersistKeysToStackExchangeRedis(redis, "MessageService-Protection-Keys");
}
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
// http调用链
app.UseCorrelationId();
// 虚拟文件系统
app.UseVirtualFiles();
// 本地化
app.UseAbpRequestLocalization();
//路由
app.UseRouting();
// 加入自定义中间件
app.UseMiddleware<SignalRJwtTokenMiddleware>();
// 认证
app.UseAuthentication();
// jwt
app.UseJwtTokenMiddleware();
// 授权
app.UseAuthorization();
// 多租户
app.UseMultiTenancy();
// Swagger
app.UseSwagger();
// Swagger可视化界面
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support MessageService API");
});
// 审计日志
app.UseAuditing();
// 路由
app.UseConfiguredEndpoints();
}
}
}

16
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/Utils/SnowflakeIdGenerator.cs

@ -0,0 +1,16 @@
using DotNetCore.CAP.Internal;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.MessageService.Utils
{
[Dependency(ServiceLifetime.Singleton, TryRegister = true)]
[ExposeServices(typeof(ISnowflakeIdGenerator))]
public class SnowflakeIdGenerator : ISnowflakeIdGenerator
{
public long Create()
{
return SnowflakeId.Default().NextId();
}
}
}

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

@ -0,0 +1,130 @@
// <auto-generated />
using System;
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace LINGYUN.Abp.MessageService.Migrations
{
[DbContext(typeof(MessageServiceHostMigrationsDbContext))]
[Migration("20200601060701_Add-Abp-Message-Service-Module")]
partial class AddAbpMessageServiceModule
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.3")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("datetime(6)");
b.Property<string>("NotificationData")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(1048576);
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<string>("NotificationName")
.IsRequired()
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<string>("NotificationTypeName")
.IsRequired()
.HasColumnType("varchar(512) CHARACTER SET utf8mb4")
.HasMaxLength(512);
b.Property<sbyte>("Severity")
.HasColumnType("tinyint");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("NotificationName");
b.ToTable("AppNotifications");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<sbyte>("ReadStatus")
.HasColumnType("tinyint");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationId")
.HasName("IX_Tenant_User_Notification_Id");
b.ToTable("AppUserNotifications");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<string>("NotificationName")
.IsRequired()
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationName")
.IsUnique()
.HasName("IX_Tenant_User_Notification_Name");
b.ToTable("AppUserSubscribes");
});
#pragma warning restore 612, 618
}
}
}

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

@ -0,0 +1,93 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace LINGYUN.Abp.MessageService.Migrations
{
public partial class AddAbpMessageServiceModule : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AppNotifications",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TenantId = table.Column<Guid>(nullable: true),
Severity = table.Column<sbyte>(nullable: false),
Type = table.Column<int>(nullable: false),
NotificationId = table.Column<long>(nullable: false),
NotificationName = table.Column<string>(maxLength: 100, nullable: false),
NotificationData = table.Column<string>(maxLength: 1048576, nullable: false),
NotificationTypeName = table.Column<string>(maxLength: 512, nullable: false),
ExpirationTime = table.Column<DateTime>(nullable: true),
CreationTime = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppNotifications", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUserNotifications",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TenantId = table.Column<Guid>(nullable: true),
UserId = table.Column<Guid>(nullable: false),
NotificationId = table.Column<long>(nullable: false),
ReadStatus = table.Column<sbyte>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUserNotifications", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUserSubscribes",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TenantId = table.Column<Guid>(nullable: true),
CreationTime = table.Column<DateTime>(nullable: false),
NotificationName = table.Column<string>(maxLength: 100, nullable: false),
UserId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUserSubscribes", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_AppNotifications_NotificationName",
table: "AppNotifications",
column: "NotificationName");
migrationBuilder.CreateIndex(
name: "IX_Tenant_User_Notification_Id",
table: "AppUserNotifications",
columns: new[] { "TenantId", "UserId", "NotificationId" });
migrationBuilder.CreateIndex(
name: "IX_Tenant_User_Notification_Name",
table: "AppUserSubscribes",
columns: new[] { "TenantId", "UserId", "NotificationName" },
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AppNotifications");
migrationBuilder.DropTable(
name: "AppUserNotifications");
migrationBuilder.DropTable(
name: "AppUserSubscribes");
}
}
}

494
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.Designer.cs

@ -0,0 +1,494 @@
// <auto-generated />
using System;
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace LINGYUN.Abp.MessageService.Migrations
{
[DbContext(typeof(MessageServiceHostMigrationsDbContext))]
[Migration("20200602134027_Add-Chat-Message-Entites")]
partial class AddChatMessageEntites
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.3")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Address")
.HasColumnType("varchar(256) CHARACTER SET utf8mb4")
.HasMaxLength(256);
b.Property<bool>("AllowAnonymous")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendMessage")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId")
.HasColumnType("char(36)");
b.Property<string>("Description")
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId")
.HasColumnType("char(36)");
b.Property<int>("MaxUserCount")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(20) CHARACTER SET utf8mb4")
.HasMaxLength(20);
b.Property<string>("Notice")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("Tag")
.HasColumnType("varchar(512) CHARACTER SET utf8mb4")
.HasMaxLength(512);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "Name");
b.ToTable("AppChatGroups");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroupAdmin", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool>("AllowAddPeople")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowDissolveGroup")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowKickPeople")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendNotice")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSilence")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<bool>("IsSuperAdmin")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppChatGroupAdmins");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupChatBlack", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<Guid>("ShieldUserId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppGroupChatBlacks");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupMessage", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(1048576);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<long>("MessageId")
.HasColumnType("bigint");
b.Property<sbyte>("SendState")
.HasColumnType("tinyint");
b.Property<string>("SendUserName")
.IsRequired()
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppGroupMessages");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatBlack", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<Guid>("ShieldUserId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserChatBlacks");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatGroup", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId", "UserId");
b.ToTable("AppUserChatGroups");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatSetting", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool>("AllowAddFriend")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowAnonymous")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowReceiveMessage")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendMessage")
.HasColumnType("tinyint(1)");
b.Property<bool>("RequireAddFriendValition")
.HasColumnType("tinyint(1)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserChatSettings");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserMessage", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(1048576);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("MessageId")
.HasColumnType("bigint");
b.Property<Guid>("ReceiveUserId")
.HasColumnType("char(36)");
b.Property<sbyte>("SendState")
.HasColumnType("tinyint");
b.Property<string>("SendUserName")
.IsRequired()
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TenantId", "ReceiveUserId");
b.ToTable("AppUserMessages");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserSpecialFocus", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<Guid>("FocusUserId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserSpecialFocuss");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("datetime(6)");
b.Property<string>("NotificationData")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(1048576);
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<string>("NotificationName")
.IsRequired()
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<string>("NotificationTypeName")
.IsRequired()
.HasColumnType("varchar(512) CHARACTER SET utf8mb4")
.HasMaxLength(512);
b.Property<sbyte>("Severity")
.HasColumnType("tinyint");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("NotificationName");
b.ToTable("AppNotifications");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<int>("ReadStatus")
.HasColumnType("int");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationId")
.HasName("IX_Tenant_User_Notification_Id");
b.ToTable("AppUserNotifications");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<string>("NotificationName")
.IsRequired()
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationName")
.IsUnique()
.HasName("IX_Tenant_User_Notification_Name");
b.ToTable("AppUserSubscribes");
});
#pragma warning restore 612, 618
}
}
}

281
aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.cs

@ -0,0 +1,281 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace LINGYUN.Abp.MessageService.Migrations
{
public partial class AddChatMessageEntites : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "ReadStatus",
table: "AppUserNotifications",
nullable: false,
oldClrType: typeof(sbyte),
oldType: "tinyint");
migrationBuilder.CreateTable(
name: "AppChatGroupAdmins",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
LastModificationTime = table.Column<DateTime>(nullable: true),
LastModifierId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
GroupId = table.Column<long>(nullable: false),
UserId = table.Column<Guid>(nullable: false),
IsSuperAdmin = table.Column<bool>(nullable: false),
AllowSilence = table.Column<bool>(nullable: false),
AllowKickPeople = table.Column<bool>(nullable: false),
AllowAddPeople = table.Column<bool>(nullable: false),
AllowSendNotice = table.Column<bool>(nullable: false),
AllowDissolveGroup = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppChatGroupAdmins", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppChatGroups",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
LastModificationTime = table.Column<DateTime>(nullable: true),
LastModifierId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
GroupId = table.Column<long>(nullable: false),
Name = table.Column<string>(maxLength: 20, nullable: false),
Tag = table.Column<string>(maxLength: 512, nullable: true),
Address = table.Column<string>(maxLength: 256, nullable: true),
Notice = table.Column<string>(maxLength: 64, nullable: true),
MaxUserCount = table.Column<int>(nullable: false),
AllowAnonymous = table.Column<bool>(nullable: false),
AllowSendMessage = table.Column<bool>(nullable: false),
Description = table.Column<string>(maxLength: 128, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AppChatGroups", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppGroupChatBlacks",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
GroupId = table.Column<long>(nullable: false),
ShieldUserId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppGroupChatBlacks", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppGroupMessages",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
MessageId = table.Column<long>(nullable: false),
SendUserName = table.Column<string>(maxLength: 64, nullable: false),
Content = table.Column<string>(maxLength: 1048576, nullable: false),
Type = table.Column<int>(nullable: false),
SendState = table.Column<sbyte>(nullable: false),
GroupId = table.Column<long>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppGroupMessages", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUserChatBlacks",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
UserId = table.Column<Guid>(nullable: false),
ShieldUserId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUserChatBlacks", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUserChatGroups",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
UserId = table.Column<Guid>(nullable: false),
GroupId = table.Column<long>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUserChatGroups", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUserChatSettings",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TenantId = table.Column<Guid>(nullable: true),
UserId = table.Column<Guid>(nullable: false),
AllowAnonymous = table.Column<bool>(nullable: false),
AllowAddFriend = table.Column<bool>(nullable: false),
RequireAddFriendValition = table.Column<bool>(nullable: false),
AllowReceiveMessage = table.Column<bool>(nullable: false),
AllowSendMessage = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUserChatSettings", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUserMessages",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
MessageId = table.Column<long>(nullable: false),
SendUserName = table.Column<string>(maxLength: 64, nullable: false),
Content = table.Column<string>(maxLength: 1048576, nullable: false),
Type = table.Column<int>(nullable: false),
SendState = table.Column<sbyte>(nullable: false),
ReceiveUserId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUserMessages", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUserSpecialFocuss",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
TenantId = table.Column<Guid>(nullable: true),
UserId = table.Column<Guid>(nullable: false),
FocusUserId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUserSpecialFocuss", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_AppChatGroupAdmins_TenantId_GroupId",
table: "AppChatGroupAdmins",
columns: new[] { "TenantId", "GroupId" });
migrationBuilder.CreateIndex(
name: "IX_AppChatGroups_TenantId_Name",
table: "AppChatGroups",
columns: new[] { "TenantId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_AppGroupChatBlacks_TenantId_GroupId",
table: "AppGroupChatBlacks",
columns: new[] { "TenantId", "GroupId" });
migrationBuilder.CreateIndex(
name: "IX_AppGroupMessages_TenantId_GroupId",
table: "AppGroupMessages",
columns: new[] { "TenantId", "GroupId" });
migrationBuilder.CreateIndex(
name: "IX_AppUserChatBlacks_TenantId_UserId",
table: "AppUserChatBlacks",
columns: new[] { "TenantId", "UserId" });
migrationBuilder.CreateIndex(
name: "IX_AppUserChatGroups_TenantId_GroupId_UserId",
table: "AppUserChatGroups",
columns: new[] { "TenantId", "GroupId", "UserId" });
migrationBuilder.CreateIndex(
name: "IX_AppUserChatSettings_TenantId_UserId",
table: "AppUserChatSettings",
columns: new[] { "TenantId", "UserId" });
migrationBuilder.CreateIndex(
name: "IX_AppUserMessages_TenantId_ReceiveUserId",
table: "AppUserMessages",
columns: new[] { "TenantId", "ReceiveUserId" });
migrationBuilder.CreateIndex(
name: "IX_AppUserSpecialFocuss_TenantId_UserId",
table: "AppUserSpecialFocuss",
columns: new[] { "TenantId", "UserId" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AppChatGroupAdmins");
migrationBuilder.DropTable(
name: "AppChatGroups");
migrationBuilder.DropTable(
name: "AppGroupChatBlacks");
migrationBuilder.DropTable(
name: "AppGroupMessages");
migrationBuilder.DropTable(
name: "AppUserChatBlacks");
migrationBuilder.DropTable(
name: "AppUserChatGroups");
migrationBuilder.DropTable(
name: "AppUserChatSettings");
migrationBuilder.DropTable(
name: "AppUserMessages");
migrationBuilder.DropTable(
name: "AppUserSpecialFocuss");
migrationBuilder.AlterColumn<sbyte>(
name: "ReadStatus",
table: "AppUserNotifications",
type: "tinyint",
nullable: false,
oldClrType: typeof(int));
}
}
}

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

@ -0,0 +1,492 @@
// <auto-generated />
using System;
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace LINGYUN.Abp.MessageService.Migrations
{
[DbContext(typeof(MessageServiceHostMigrationsDbContext))]
partial class MessageServiceHostMigrationsDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.3")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Address")
.HasColumnType("varchar(256) CHARACTER SET utf8mb4")
.HasMaxLength(256);
b.Property<bool>("AllowAnonymous")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendMessage")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId")
.HasColumnType("char(36)");
b.Property<string>("Description")
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId")
.HasColumnType("char(36)");
b.Property<int>("MaxUserCount")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(20) CHARACTER SET utf8mb4")
.HasMaxLength(20);
b.Property<string>("Notice")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("Tag")
.HasColumnType("varchar(512) CHARACTER SET utf8mb4")
.HasMaxLength(512);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "Name");
b.ToTable("AppChatGroups");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroupAdmin", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool>("AllowAddPeople")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowDissolveGroup")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowKickPeople")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendNotice")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSilence")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<bool>("IsSuperAdmin")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppChatGroupAdmins");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupChatBlack", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<Guid>("ShieldUserId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppGroupChatBlacks");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupMessage", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(1048576);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<long>("MessageId")
.HasColumnType("bigint");
b.Property<sbyte>("SendState")
.HasColumnType("tinyint");
b.Property<string>("SendUserName")
.IsRequired()
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId");
b.ToTable("AppGroupMessages");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatBlack", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<Guid>("ShieldUserId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserChatBlacks");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatGroup", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("GroupId")
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "GroupId", "UserId");
b.ToTable("AppUserChatGroups");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatSetting", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool>("AllowAddFriend")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowAnonymous")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowReceiveMessage")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowSendMessage")
.HasColumnType("tinyint(1)");
b.Property<bool>("RequireAddFriendValition")
.HasColumnType("tinyint(1)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserChatSettings");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserMessage", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(1048576);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<long>("MessageId")
.HasColumnType("bigint");
b.Property<Guid>("ReceiveUserId")
.HasColumnType("char(36)");
b.Property<sbyte>("SendState")
.HasColumnType("tinyint");
b.Property<string>("SendUserName")
.IsRequired()
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TenantId", "ReceiveUserId");
b.ToTable("AppUserMessages");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserSpecialFocus", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)");
b.Property<Guid>("FocusUserId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId");
b.ToTable("AppUserSpecialFocuss");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("datetime(6)");
b.Property<string>("NotificationData")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(1048576);
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<string>("NotificationName")
.IsRequired()
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<string>("NotificationTypeName")
.IsRequired()
.HasColumnType("varchar(512) CHARACTER SET utf8mb4")
.HasMaxLength(512);
b.Property<sbyte>("Severity")
.HasColumnType("tinyint");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("NotificationName");
b.ToTable("AppNotifications");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<long>("NotificationId")
.HasColumnType("bigint");
b.Property<int>("ReadStatus")
.HasColumnType("int");
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationId")
.HasName("IX_Tenant_User_Notification_Id");
b.ToTable("AppUserNotifications");
});
modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<string>("NotificationName")
.IsRequired()
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId", "UserId", "NotificationName")
.IsUnique()
.HasName("IX_Tenant_User_Notification_Name");
b.ToTable("AppUserSubscribes");
});
#pragma warning restore 612, 618
}
}
}

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

@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Http;
using System.Linq;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Claims;
namespace LINGYUN.Abp.MessageService.MultiTenancy
{
public class AuthorizationTenantResolveContributor : HttpTenantResolveContributorBase
{
public override string Name => "Authorization";
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
if (httpContext.User?.Identity == null)
{
return null;
}
if (!httpContext.User.Identity.IsAuthenticated)
{
return null;
}
var tenantIdKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey;
var tenantClaim = httpContext.User.Claims.FirstOrDefault(x => x.Type.Equals(AbpClaimTypes.TenantId));
if (tenantClaim == null)
{
return null;
}
return tenantClaim.Value;
}
}
}

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

@ -0,0 +1,49 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
using System;
using System.IO;
namespace LINGYUN.Abp.MessageService
{
public class Program
{
public static int Main(string[] args)
{
var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile($"appsettings.{env}.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
try
{
Log.Information("Starting web host.");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly!");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseSerilog()
.UseAutofac();
}
}

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

@ -0,0 +1,20 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:63963",
"sslPort": 0
}
},
"profiles": {
"LINGYUN.Abp.MessageService.HttpApi.Host": {
"commandName": "Project",
"launchBrowser": false,
"applicationUrl": "http://localhost:30020",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

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

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace LINGYUN.Abp.MessageService
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AbpMessageServiceHttpApiHostModule>();
}
public void Configure(IApplicationBuilder app)
{
app.InitializeApplication();
}
}
}

12
aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs

@ -59,13 +59,15 @@ namespace LINGYUN.Abp.Account
var userEmail = input.EmailAddress ?? input.PhoneNumber + "@abp.io"; var userEmail = input.EmailAddress ?? input.PhoneNumber + "@abp.io";
var userName = input.UserName ?? input.PhoneNumber; var userName = input.UserName ?? input.PhoneNumber;
var user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id); var user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id)
user.Name = input.Name ?? input.PhoneNumber; {
Name = input.Name ?? input.PhoneNumber
};
(await UserManager.CreateAsync(user, input.Password)).CheckErrors(); (await UserManager.CreateAsync(user, input.Password)).CheckErrors();
await UserManager.ChangePhoneNumberAsync(user, input.PhoneNumber, input.VerifyCode); (await UserManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors();
await UserManager.SetEmailAsync(user, userEmail); (await UserManager.SetEmailAsync(user, userEmail)).CheckErrors();
await UserManager.AddDefaultRolesAsync(user); (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();
await Cache.RemoveAsync(phoneVerifyCacheKey); await Cache.RemoveAsync(phoneVerifyCacheKey);

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

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

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

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

77
aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessageHub.cs

@ -0,0 +1,77 @@
using LINGYUN.Abp.IM.Messages;
using LINGYUN.Abp.RealTime.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.SignalR;
namespace LINGYUN.Abp.IM.SignalR.Hubs
{
[Authorize]
public class MessageHub : OnlineClientHubBase
{
private readonly IMessageStore _messageStore;
public MessageHub(
IMessageStore messageStore)
{
_messageStore = messageStore;
}
/// <summary>
/// 客户端调用发送消息方法
/// </summary>
/// <param name="chatMessage"></param>
/// <returns></returns>
[HubMethodName("SendMessage")]
public virtual async Task SendMessageAsync(ChatMessage chatMessage)
{
// 持久化
await _messageStore.StoreMessageAsync(chatMessage);
if (!chatMessage.GroupId.IsNullOrWhiteSpace())
{
try
{
var signalRClient = Clients.Group(chatMessage.GroupId);
if (signalRClient == null)
{
Logger.LogDebug("Can not get group " + chatMessage.GroupId + " from SignalR hub!");
return;
}
await signalRClient.SendAsync("getChatMessage", chatMessage);
}
catch (Exception ex)
{
Logger.LogWarning("Could not send message to group: {0}", chatMessage.GroupId);
Logger.LogWarning("Send group message error: {0}", ex.Message);
}
}
else
{
var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId.GetValueOrDefault());
var onlineClients = OnlineClientManager.GetAllByContext(onlineClientContext);
foreach (var onlineClient in onlineClients)
{
try
{
var signalRClient = Clients.Client(onlineClient.ConnectionId);
if (signalRClient == null)
{
Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!");
continue;
}
await signalRClient.SendAsync("getChatMessage", chatMessage);
}
catch (Exception ex)
{
Logger.LogWarning("Could not send message to user: {0}", chatMessage.ToUserId);
Logger.LogWarning("Send to user message error: {0}", ex.Message);
}
}
}
}
}
}

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

@ -0,0 +1,101 @@
using LINGYUN.Abp.IM.Messages;
using LINGYUN.Abp.IM.SignalR.Hubs;
using LINGYUN.Abp.RealTime.Client;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.IM.SignalR.Messages
{
public class SignalRMessageSender : IMessageSender, ITransientDependency
{
public ILogger<SignalRMessageSender> Logger { protected get; set; }
private readonly IOnlineClientManager _onlineClientManager;
private readonly IHubContext<MessageHub> _hubContext;
private readonly IMessageStore _messageStore;
public SignalRMessageSender(
IOnlineClientManager onlineClientManager,
IHubContext<MessageHub> hubContext,
IMessageStore messageStore)
{
_hubContext = hubContext;
_messageStore = messageStore;
_onlineClientManager = onlineClientManager;
Logger = NullLogger<SignalRMessageSender>.Instance;
}
/// <summary>
/// 服务端调用发送消息方法
/// </summary>
/// <param name="chatMessage"></param>
/// <returns></returns>
public async Task SendMessageAsync(ChatMessage chatMessage)
{
// 持久化
await _messageStore.StoreMessageAsync(chatMessage);
try
{
if (!chatMessage.GroupId.IsNullOrWhiteSpace())
{
await SendMessageToGroupAsync(chatMessage);
}
else
{
await SendMessageToUserAsync(chatMessage);
}
}
catch (Exception ex)
{
Logger.LogWarning("Could not send message, group: {0}, formUser: {1}, toUser: {2}",
chatMessage.GroupId, chatMessage.FormUserName,
chatMessage.ToUserId.HasValue ? chatMessage.ToUserId.ToString() : "None");
Logger.LogWarning("Send group message error: {0}", ex.Message);
}
}
protected virtual async Task SendMessageToGroupAsync(ChatMessage chatMessage)
{
var signalRClient = _hubContext.Clients.Group(chatMessage.GroupId);
if (signalRClient == null)
{
Logger.LogDebug("Can not get group " + chatMessage.GroupId + " from SignalR hub!");
return;
}
await signalRClient.SendAsync("getChatMessage", chatMessage);
}
protected virtual async Task SendMessageToUserAsync(ChatMessage chatMessage)
{
var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId.Value);
var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext);
foreach (var onlineClient in onlineClients)
{
try
{
var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId);
if (signalRClient == null)
{
Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!");
continue;
}
await signalRClient.SendAsync("getChatMessage", chatMessage);
}
catch (Exception ex)
{
Logger.LogWarning("Could not send message to user: {0}", chatMessage.ToUserId);
Logger.LogWarning("Send to user message error: {0}", ex.Message);
}
}
}
}
}

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

@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Http; using LINGYUN.Abp.IM.Group;
using LINGYUN.Abp.RealTime.Client;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -8,6 +10,9 @@ namespace LINGYUN.Abp.IM.SignalR
{ {
public abstract class OnlineClientHubBase : AbpHub public abstract class OnlineClientHubBase : AbpHub
{ {
private IUserGroupStore _userGroupStore;
protected IUserGroupStore UserGroupStore => LazyGetRequiredService(ref _userGroupStore);
private IOnlineClientManager _onlineClientManager; private IOnlineClientManager _onlineClientManager;
protected IOnlineClientManager OnlineClientManager => LazyGetRequiredService(ref _onlineClientManager); protected IOnlineClientManager OnlineClientManager => LazyGetRequiredService(ref _onlineClientManager);
@ -18,28 +23,45 @@ namespace LINGYUN.Abp.IM.SignalR
{ {
await base.OnConnectedAsync(); await base.OnConnectedAsync();
IOnlineClient onlineClient = CreateClientForCurrentConnection(); IOnlineClient onlineClient = CreateClientForCurrentConnection();
Logger.LogDebug("A client is connected: " + onlineClient?.ToString()); Logger.LogDebug("A client is connected: " + onlineClient.ToString());
OnlineClientManager.Add(onlineClient); 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) public override async Task OnDisconnectedAsync(Exception exception)
{ {
await base.OnDisconnectedAsync(exception); await base.OnDisconnectedAsync(exception);
Logger.LogDebug("A client is disconnected: " + base.Context.ConnectionId); Logger.LogDebug("A client is disconnected: " + Context.ConnectionId);
try 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) catch (Exception ex)
{ {
base.Logger.LogWarning(ex.ToString(), ex); Logger.LogWarning(ex.ToString(), ex);
} }
} }
protected virtual IOnlineClient CreateClientForCurrentConnection() protected virtual IOnlineClient CreateClientForCurrentConnection()
{ {
return new OnlineClient(Context.ConnectionId, GetClientIpAddress(), return new OnlineClient(Context.ConnectionId, GetClientIpAddress(),
CurrentTenant.Id, CurrentUser.Id, CurrentUser.Roles) CurrentTenant.Id, CurrentUser.Id)
{ {
ConnectTime = Clock.Now ConnectTime = Clock.Now
}; };

2
aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj

@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Core" Version="2.8.0" /> <PackageReference Include="Volo.Abp.Auditing" Version="2.8.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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

@ -0,0 +1,26 @@
namespace LINGYUN.Abp.IM.Group
{
public class Group
{
/// <summary>
/// 群组名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 允许匿名聊天
/// </summary>
public bool AllowAnonymous { get; set; }
/// <summary>
/// 允许发送消息
/// </summary>
public bool AllowSendMessage { get; set; }
/// <summary>
/// 最大用户数
/// </summary>
public int MaxUserLength { get; set; }
/// <summary>
/// 群组用户数
/// </summary>
public int GroupUserCount { get; set; }
}
}

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

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.IM.Group
{
public interface IUserGroupStore
{
/// <summary>
/// 获取用户所在通讯组列表
/// </summary>
/// <param name="tenantId"></param>
/// <param name="userId"></param>
/// <returns></returns>
Task<IEnumerable<Group>> GetUserGroupsAsync(Guid? tenantId, Guid userId);
/// <summary>
/// 获取通讯组所有用户
/// </summary>
/// <param name="tenantId"></param>
/// <param name="groupId"></param>
/// <returns></returns>
Task<IEnumerable<UserGroup>> GetGroupUsersAsync(Guid? tenantId, long groupId);
/// <summary>
/// 用户加入通讯组
/// </summary>
/// <param name="tenantId"></param>
/// <param name="userId"></param>
/// <param name="groupId"></param>
/// <returns></returns>
Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId, Guid acceptUserId);
/// <summary>
/// 用户退出通讯组
/// </summary>
/// <param name="tenantId"></param>
/// <param name="userId"></param>
/// <param name="groupId"></param>
/// <returns></returns>
Task RemoveUserFormGroupAsync(Guid? tenantId, Guid userId, long groupId);
}
}

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

@ -0,0 +1,13 @@
using System;
namespace LINGYUN.Abp.IM.Group
{
public class UserGroup
{
public Guid? TenantId { get; set; }
public Guid UserId { get; set; }
public long GroupId { get; set; }
public bool IsAdmin { get; set; }
public bool IsSuperAdmin { get; set; }
}
}

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

@ -0,0 +1,29 @@
using System;
using Volo.Abp.Auditing;
namespace LINGYUN.Abp.IM.Messages
{
public class ChatMessage
{
public Guid? TenantId { get; set; }
public string GroupId { get; set; }
public string MessageId { get; set; }
public Guid FormUserId { get; set; }
public string FormUserName { get; set; }
public Guid? ToUserId { get; set; }
[DisableAuditing]
public string Content { get; set; }
public DateTime SendTime { get; set; }
public bool IsAnonymous { get; set; } = false;
public MessageType MessageType { get; set; } = MessageType.Text;
}
}

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

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

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

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.IM.Messages
{
public interface IMessageStore
{
/// <summary>
/// 存储聊天记录
/// </summary>
/// <param name="chatMessage"></param>
/// <param name="formUserId"></param>
/// <param name="toUserId"></param>
/// <returns></returns>
Task StoreMessageAsync(ChatMessage chatMessage);
/// <summary>
/// 获取群组聊天记录
/// </summary>
/// <param name="tenantId"></param>
/// <param name="groupName"></param>
/// <param name="maxResultCount"></param>
/// <returns></returns>
Task<List<ChatMessage>> GetGroupMessageAsync(Guid? tenantId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10);
/// <summary>
/// 获取与某个用户的聊天记录
/// </summary>
/// <param name="tenantId"></param>
/// <param name="userId"></param>
/// <param name="maxResultCount"></param>
/// <returns></returns>
Task<List<ChatMessage>> GetChatMessageAsync(Guid? tenantId, Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10);
}
}

4
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/SendStatus.cs → aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageSendState.cs

@ -1,9 +1,9 @@
namespace LINGYUN.Abp.MessageService namespace LINGYUN.Abp.IM.Messages
{ {
/// <summary> /// <summary>
/// 消息状态 /// 消息状态
/// </summary> /// </summary>
public enum SendStatus : sbyte public enum MessageSendState : sbyte
{ {
/// <summary> /// <summary>
/// 已发送 /// 已发送

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

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

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

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.SignalR" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj" />
</ItemGroup>
</Project>

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

@ -0,0 +1,15 @@
using LINGYUN.Abp.RealTime;
using Volo.Abp.AspNetCore.SignalR;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Notifications.SignalR
{
[DependsOn(
typeof(AbpRealTimeModule),
typeof(AbpNotificationModule),
typeof(AbpAspNetCoreSignalRModule))]
public class AbpNotificationsSignalRModule : AbpModule
{
}
}

32
aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/NotificationsHub.cs

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

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

@ -0,0 +1,78 @@
using LINGYUN.Abp.RealTime.Client;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.SignalR;
using Volo.Abp.Security.Claims;
namespace LINGYUN.Abp.Notifications.SignalR
{
public abstract class OnlineClientHubBase : AbpHub
{
private ICurrentPrincipalAccessor _currentPrincipalAccessor;
protected ICurrentPrincipalAccessor CurrentPrincipalAccessor => LazyGetRequiredService(ref _currentPrincipalAccessor);
private IOnlineClientManager _onlineClientManager;
protected IOnlineClientManager OnlineClientManager => LazyGetRequiredService(ref _onlineClientManager);
private IHttpContextAccessor _httpContextAccessor;
protected IHttpContextAccessor HttpContextAccessor => LazyGetRequiredService(ref _httpContextAccessor);
public override async Task OnConnectedAsync()
{
await base.OnConnectedAsync();
IOnlineClient onlineClient = CreateClientForCurrentConnection();
Logger.LogDebug("A client is connected: " + onlineClient.ToString());
OnlineClientManager.Add(onlineClient);
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
Logger.LogDebug("A client is disconnected: " + Context.ConnectionId);
try
{
// 从通讯组移除
var onlineClient = OnlineClientManager.GetByConnectionIdOrNull(Context.ConnectionId);
if(onlineClient != null)
{
// 移除在线客户端
OnlineClientManager.Remove(Context.ConnectionId);
}
}
catch (Exception ex)
{
Logger.LogWarning(ex.ToString(), ex);
}
}
protected virtual IOnlineClient CreateClientForCurrentConnection()
{
// abp框架没有处理,需要切换一下用户身份令牌.否则无法获取用户信息
using (CurrentPrincipalAccessor.Change(Context.User))
{
return new OnlineClient(Context.ConnectionId, GetClientIpAddress(),
CurrentTenant.Id, CurrentUser.Id)
{
ConnectTime = Clock.Now,
UserName = CurrentUser.UserName
};
}
}
protected virtual string GetClientIpAddress()
{
try
{
return HttpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
}
catch (Exception ex)
{
Logger.LogException(ex, LogLevel.Warning);
return null;
}
}
}
}

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

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

26
aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/Microsoft/AspNetCore/Builder/SignalRJwtTokenMiddleware.cs

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Microsoft.AspNetCore.Builder
{
public class SignalRJwtTokenMiddleware : IMiddleware, ITransientDependency
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// 仅针对自定义的SignalR hub
if (context.Request.Path.StartsWithSegments("/signalr-hubs/notifications"))
{
if (context.User.Identity?.IsAuthenticated != true)
{
if (context.Request.Query.TryGetValue("access_token", out var accessToken))
{
context.Request.Headers.Add("Authorization", $"Bearer {accessToken}");
}
}
}
await next(context);
}
}
}

2
aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj

@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Core" Version="2.8.0" /> <PackageReference Include="Volo.Abp.Json" Version="2.8.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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

@ -0,0 +1,14 @@
using LINGYUN.Abp.Notifications.Internal;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Notifications
{
public class AbpNotificationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient<INotificationDispatcher, DefaultNotificationDispatcher>();
}
}
}

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

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

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

@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Notifications
{
public interface INotificationSender
{
Task SendAsync(NotificationData data, Guid userId, Guid? tenantId);
Task SendAsync(NotificationData data, IEnumerable<Guid> userIds, Guid? tenantId);
}
}

8
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, Guid userId, string notificationName);
Task InsertUserSubscriptionAsync(Guid? tenantId, IEnumerable<Guid> userIds, string notificationName);
Task DeleteUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName); Task DeleteUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName);
Task<List<NotificationSubscriptionInfo>> GetSubscriptionsAsync(Guid? tenantId, string notificationName); Task<List<NotificationSubscriptionInfo>> GetSubscriptionsAsync(Guid? tenantId, string notificationName);
@ -22,10 +24,14 @@ namespace LINGYUN.Abp.Notifications
Task InsertUserNotificationAsync(NotificationInfo notification, Guid userId); Task InsertUserNotificationAsync(NotificationInfo notification, Guid userId);
Task InsertUserNotificationsAsync(NotificationInfo notification, IEnumerable<Guid> userIds);
Task DeleteUserNotificationAsync(Guid? tenantId, Guid userId, long notificationId); Task DeleteUserNotificationAsync(Guid? tenantId, Guid userId, long notificationId);
Task<NotificationInfo> GetNotificationOrNullAsync(Guid? tenantId, long notificationId); Task<NotificationInfo> GetNotificationOrNullAsync(Guid? tenantId, long notificationId);
Task ChangeUserNotificationReadStateAsync(Guid? tenantId, Guid userId, string notificationName, NotificationReadState readState); Task<List<NotificationInfo>> GetUserNotificationsAsync(Guid? tenantId, Guid userId, NotificationReadState readState = NotificationReadState.UnRead, int maxResultCount = 10);
Task ChangeUserNotificationReadStateAsync(Guid? tenantId, Guid userId, long notificationId, NotificationReadState readState);
} }
} }

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

@ -0,0 +1,34 @@
using System.Linq;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Notifications.Internal
{
internal class DefaultNotificationDispatcher : INotificationDispatcher
{
private readonly INotificationStore _notificationStore;
private readonly INotificationPublisher _notificationPublisher;
public DefaultNotificationDispatcher(
INotificationStore notificationStore,
INotificationPublisher notificationPublisher)
{
_notificationStore = notificationStore;
_notificationPublisher = notificationPublisher;
}
public async Task DispatcheAsync(NotificationInfo notification)
{
// 持久化通知
await _notificationStore.InsertNotificationAsync(notification);
// 获取用户订阅列表
var userSubscriptions = await _notificationStore.GetSubscriptionsAsync(notification.TenantId, notification.Name);
// 持久化用户通知
var subscriptionUserIds = userSubscriptions.Select(us => us.UserId);
await _notificationStore.InsertUserNotificationsAsync(notification, subscriptionUserIds);
// 发布用户通知
await _notificationPublisher.PublishAsync(notification, subscriptionUserIds);
}
}
}

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

@ -1,4 +1,5 @@
using System; using Newtonsoft.Json;
using System;
namespace LINGYUN.Abp.Notifications namespace LINGYUN.Abp.Notifications
{ {
@ -6,8 +7,9 @@ namespace LINGYUN.Abp.Notifications
{ {
public Guid? TenantId { get; set; } public Guid? TenantId { get; set; }
public string Name { get; set; } public string Name { get; set; }
[JsonConverter(typeof(HexLongConverter))]
public long Id { get; set; }
public NotificationData Data { get; set; } public NotificationData Data { get; set; }
public DateTime? ExpirationTime { get; set; }
public DateTime CreationTime { get; set; } public DateTime CreationTime { get; set; }
public NotificationType NotificationType { get; set; } public NotificationType NotificationType { get; set; }
public NotificationSeverity NotificationSeverity { get; set; } public NotificationSeverity NotificationSeverity { get; set; }
@ -16,6 +18,8 @@ namespace LINGYUN.Abp.Notifications
Data = new NotificationData(); Data = new NotificationData();
NotificationType = NotificationType.Application; NotificationType = NotificationType.Application;
NotificationSeverity = NotificationSeverity.Info; NotificationSeverity = NotificationSeverity.Info;
CreationTime = DateTime.Now;
} }
} }
} }

30
aspnet-core/modules/common/LINGYUN.Abp.Notifications/Newtonsoft/Json/HexLongConverter.cs

@ -0,0 +1,30 @@
using System;
namespace Newtonsoft.Json
{
public class HexLongConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
long v = value is ulong ? (long)(ulong)value : (long)value;
writer.WriteValue(v.ToString());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
string value = reader.Value as string;
long lValue = long.Parse(value);
return typeof(ulong) == objectType ? (object)(ulong)lValue : lValue;
}
public override bool CanConvert(Type objectType)
{
switch (objectType.FullName)
{
case "System.Int64":
case "System.UInt64":
return true;
default:
return false;
}
}
}
}

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

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Core" Version="2.8.0" />
</ItemGroup>
</Project>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -115,7 +115,9 @@ namespace LINYUN.Abp.Sms.Aliyun
{ {
if (Environment.IsDevelopment()) 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); request.AddQueryParameters("PhoneNumbers", Options.DeveloperPhoneNumber);
} }
else else

3
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json

@ -25,6 +25,7 @@
"ClientClaimNotFound": "Client claim: {0} not found!", "ClientClaimNotFound": "Client claim: {0} not found!",
"ClientSecretNotFound": "Client secret: {0} not found!", "ClientSecretNotFound": "Client secret: {0} not found!",
"ClientPropertyNotFound": "Client property: {0} not found!", "ClientPropertyNotFound": "Client property: {0} not found!",
"IdentityResourcePropertyNotFound": "Identity resource property: {0} not found!" "IdentityResourcePropertyNotFound": "Identity resource property: {0} not found!",
"EncryptionNotImplemented": "Encryption type: {0} not implemented!"
} }
} }

3
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json

@ -25,6 +25,7 @@
"ClientClaimNotFound": "客户端声明: {0} 不存在!", "ClientClaimNotFound": "客户端声明: {0} 不存在!",
"ClientSecretNotFound": "客户端密钥: {0} 不存在!", "ClientSecretNotFound": "客户端密钥: {0} 不存在!",
"ClientPropertyNotFound": "客户端属性: {0} 不存在!", "ClientPropertyNotFound": "客户端属性: {0} 不存在!",
"IdentityResourcePropertyNotFound": "身份资源属性: {0} 不存在!" "IdentityResourcePropertyNotFound": "身份资源属性: {0} 不存在!",
"EncryptionNotImplemented": "加密类型: {0} 未实现!"
} }
} }

9
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs

@ -7,7 +7,6 @@ using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.Security.Encryption;
using Client = Volo.Abp.IdentityServer.Clients.Client; using Client = Volo.Abp.IdentityServer.Clients.Client;
namespace LINGYUN.Abp.IdentityServer.Clients namespace LINGYUN.Abp.IdentityServer.Clients
@ -15,9 +14,6 @@ namespace LINGYUN.Abp.IdentityServer.Clients
[Authorize(AbpIdentityServerPermissions.Clients.Default)] [Authorize(AbpIdentityServerPermissions.Clients.Default)]
public class ClientAppService : AbpIdentityServerAppServiceBase, IClientAppService public class ClientAppService : AbpIdentityServerAppServiceBase, IClientAppService
{ {
private IStringEncryptionService _encryptionService;
protected IStringEncryptionService EncryptionService => LazyGetRequiredService(ref _encryptionService);
protected IClientRepository ClientRepository { get; } protected IClientRepository ClientRepository { get; }
public ClientAppService(IClientRepository clientRepository) public ClientAppService(IClientRepository clientRepository)
@ -69,7 +65,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients
} }
else else
{ {
clientSecretValue = EncryptionService.Encrypt(clientSecretCreate.Value); // 其他类型的服务器加密方式暂时不提供
throw new UserFriendlyException(L["EncryptionNotImplemented", clientSecretCreate.Type]);
} }
client.AddSecret(clientSecretValue, clientSecretCreate.Expiration, client.AddSecret(clientSecretValue, clientSecretCreate.Expiration,
clientSecretCreate.Type, clientSecretCreate.Description); clientSecretCreate.Type, clientSecretCreate.Description);
@ -461,7 +458,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
} }
else else
{ {
clientSecretValue = EncryptionService.Encrypt(clientSecretUpdate.Value); throw new UserFriendlyException(L["EncryptionNotImplemented", clientSecretUpdate.Type]);
} }
clientSecret.Value = clientSecretValue; clientSecret.Value = clientSecretValue;

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

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

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

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

30
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceErrorCodes.cs

@ -0,0 +1,30 @@
namespace LINGYUN.Abp.MessageService
{
public class MessageServiceErrorCodes
{
/// <summary>
/// 管理员已开启全员禁言
/// </summary>
public const string GroupNotAllowedToSpeak = "Messages:Group:1001";
/// <summary>
/// 管理员不允许匿名发言
/// </summary>
public const string GroupNotAllowedToSpeakAnonymously = "Messages:Group:1002";
/// <summary>
/// 管理员已禁止用户发言
/// </summary>
public const string GroupUserHasBlack = "Messages:Group:1003";
/// <summary>
/// 用户已将发信人拉黑
/// </summary>
public const string UserHasBlack = "Messages:User:1003";
/// <summary>
/// 用户已拒接所有消息
/// </summary>
public const string UserHasRejectAllMessage = "Messages:User:1001";
/// <summary>
/// 用户不允许匿名发言
/// </summary>
public const string UserNotAllowedToSpeakAnonymously = "Messages:User:1002";
}
}

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

@ -0,0 +1,16 @@
namespace LINGYUN.Abp.MessageService
{
public class MessageServiceSettingNames
{
public const string GroupName = "Abp.MessageService";
public class Notifications
{
public const string Default = GroupName + ".Notifications";
/// <summary>
/// 清理过期消息批次
/// </summary>
public const string CleanupExpirationBatchCount = Default + ".CleanupExpirationBatchCount";
}
}
}

15
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/ChatGroupConsts.cs

@ -0,0 +1,15 @@
namespace LINGYUN.Abp.MessageService.Messages
{
public class ChatGroupConsts
{
public const int MaxNameLength = 20;
public const int MaxTagLength = 512;
public const int MaxAddressLength = 256;
public const int MaxNoticeLength = 64;
public const int MaxDescriptionLength = 128;
}
}

10
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/MessageConsts.cs

@ -0,0 +1,10 @@
namespace LINGYUN.Abp.MessageService.Messages
{
public class MessageConsts
{
public const int MaxSendUserNameLength = 64;
// 1 MB
public const int MaxContentLength = 1024 * 1024;
}
}

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

@ -0,0 +1,16 @@
using System;
namespace LINGYUN.Abp.MessageService.Notifications
{
public class CleanupNotificationJobArgs
{
/// <summary>
/// 清理大小
/// </summary>
public int Count { get; set; }
/// <summary>
/// 清理租户
/// </summary>
public Guid? TenantId { get; set; }
}
}

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

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

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

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

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

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

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

@ -5,11 +5,25 @@
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\MessageService\Localization\Resources\en.json" />
<None Remove="LINGYUN\Abp\MessageService\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\MessageService\Localization\Resources\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\MessageService\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="2.8.0" /> <PackageReference Include="Volo.Abp.Ddd.Domain" Version="2.8.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="2.8.0" />
<PackageReference Include="Volo.Abp.BackgroundJobs" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Users.Abstractions" Version="2.8.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj" />
<ProjectReference Include="..\..\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" /> <ProjectReference Include="..\..\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.MessageService.Domain.Shared\LINGYUN.Abp.MessageService.Domain.Shared.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.MessageService.Domain.Shared\LINGYUN.Abp.MessageService.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

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

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

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

@ -1,9 +1,18 @@
using Volo.Abp.Modularity; using LINGYUN.Abp.MessageService.Mapper;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.MessageService namespace LINGYUN.Abp.MessageService
{ {
[DependsOn(typeof(AbpAutoMapperModule))]
public class AbpMessageServiceDomainModule : AbpModule public class AbpMessageServiceDomainModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<MessageServiceDomainAutoMapperProfile>(validate: true);
});
}
} }
} }

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

@ -0,0 +1,37 @@
using LINGYUN.Abp.MessageService.Notifications;
using System.Threading.Tasks;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.MessageService.BackgroundJobs
{
public class NotificationExpritionCleanupJob : AsyncBackgroundJob<CleanupNotificationJobArgs>
{
private readonly ICurrentTenant _currentTenant;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly INotificationRepository _notificationRepository;
public NotificationExpritionCleanupJob(
ICurrentTenant currentTenant,
IUnitOfWorkManager unitOfWorkManager,
INotificationRepository notificationRepository)
{
_currentTenant = currentTenant;
_unitOfWorkManager = unitOfWorkManager;
_notificationRepository = notificationRepository;
}
public override async Task ExecuteAsync(CleanupNotificationJobArgs args)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (_currentTenant.Change(args.TenantId))
{
await _notificationRepository.DeleteExpritionAsync(args.Count);
await unitOfWork.SaveChangesAsync();
}
}
}
}
}

48
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/UserCreateEventHandler.cs

@ -0,0 +1,48 @@
using LINGYUN.Abp.MessageService.Messages;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using Volo.Abp.Users;
namespace LINGYUN.Abp.MessageService.EventBus
{
public class UserCreateEventHandler : IDistributedEventHandler<EntityCreatedEto<UserEto>>
{
private readonly ICurrentTenant _currentTenant;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IUserChatSettingRepository _userChatSettingRepository;
public UserCreateEventHandler(
ICurrentTenant currentTenant,
IUnitOfWorkManager unitOfWorkManager,
IUserChatSettingRepository userChatSettingRepository)
{
_currentTenant = currentTenant;
_unitOfWorkManager = unitOfWorkManager;
_userChatSettingRepository = userChatSettingRepository;
}
/// <summary>
/// 接收添加用户事件,启用IM模块时增加用户配置
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public async Task HandleEventAsync(EntityCreatedEto<UserEto> eventData)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
using (_currentTenant.Change(eventData.Entity.TenantId))
{
var userHasOpendIm = await _userChatSettingRepository.UserHasOpendImAsync(eventData.Entity.Id);
if (!userHasOpendIm)
{
var userChatSetting = new UserChatSetting(eventData.Entity.Id, eventData.Entity.TenantId);
await _userChatSettingRepository.InsertAsync(userChatSetting);
await unitOfWork.SaveChangesAsync();
}
}
}
}
}
}

11
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json

@ -0,0 +1,11 @@
{
"culture": "en",
"texts": {
"Messages:Group:1001": "The current group is not allowed to speak",
"Messages:Group:1002": "The current group is not allowed to speak anonymously",
"Messages:Group:1003": "The administrator has banned you from speaking!",
"Messages:User:1001": "Users do not receive anonymous comments!",
"Messages:User:1002": "The user has rejected all messages!",
"Messages:User:1003": "The user rejects the message you sent!"
}
}

11
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json

@ -0,0 +1,11 @@
{
"culture": "zh-Hans",
"texts": {
"Messages:Group:1001": "管理员已开启全员禁言!",
"Messages:Group:1002": "管理员不允许匿名发言!",
"Messages:Group:1003": "管理员已禁止您发言!",
"Messages:User:1001": "用户不接收匿名发言!",
"Messages:User:1002": "用户已拒接所有消息!",
"Messages:User:1003": "用户拒绝您发送的消息!"
}
}

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

@ -0,0 +1,57 @@
using AutoMapper;
using LINGYUN.Abp.IM.Messages;
using LINGYUN.Abp.MessageService.Messages;
using LINGYUN.Abp.MessageService.Notifications;
using LINGYUN.Abp.MessageService.Subscriptions;
using LINGYUN.Abp.Notifications;
using Newtonsoft.Json;
using System;
namespace LINGYUN.Abp.MessageService.Mapper
{
public class MessageServiceDomainAutoMapperProfile : Profile
{
public MessageServiceDomainAutoMapperProfile()
{
CreateMap<Notification, NotificationInfo>()
.ForMember(dto => dto.Id, map => map.MapFrom(src => src.NotificationId))
.ForMember(dto => dto.Name, map => map.MapFrom(src => src.NotificationName))
.ForMember(dto => dto.NotificationType, map => map.MapFrom(src => src.Type))
.ForMember(dto => dto.NotificationSeverity, map => map.MapFrom(src => src.Severity))
.ForMember(dto => dto.Data, map => map.MapFrom((src, nfi) =>
{
var notificationDataType = Type.GetType(src.NotificationTypeName);
var notificationData = JsonConvert.DeserializeObject(src.NotificationData, notificationDataType);
if(notificationData != null)
{
return notificationData as NotificationData;
}
return new NotificationData();
}));
CreateMap<UserSubscribe, NotificationSubscriptionInfo>();
CreateMap<GroupMessage, ChatMessage>()
.ForMember(dto => dto.Content, map => map.MapFrom(src => src.Content))
.ForMember(dto => dto.GroupId, map => map.MapFrom(src => src.GroupId.ToString()))
.ForMember(dto => dto.MessageId, map => map.MapFrom(src => src.MessageId.ToString()))
.ForMember(dto => dto.FormUserId, map => map.MapFrom(src => src.CreatorId))
.ForMember(dto => dto.FormUserName, map => map.MapFrom(src => src.SendUserName))
.ForMember(dto => dto.SendTime, map => map.MapFrom(src => src.CreationTime))
.ForMember(dto => dto.MessageType, map => map.MapFrom(src => src.Type))
.ForMember(dto => dto.IsAnonymous, map => map.Ignore())
.ForMember(dto => dto.ToUserId, map => map.Ignore());
CreateMap<UserMessage, ChatMessage>()
.ForMember(dto => dto.Content, map => map.MapFrom(src => src.Content))
.ForMember(dto => dto.ToUserId, map => map.MapFrom(src => src.ReceiveUserId))
.ForMember(dto => dto.MessageId, map => map.MapFrom(src => src.MessageId.ToString()))
.ForMember(dto => dto.FormUserId, map => map.MapFrom(src => src.CreatorId))
.ForMember(dto => dto.FormUserName, map => map.MapFrom(src => src.SendUserName))
.ForMember(dto => dto.SendTime, map => map.MapFrom(src => src.CreationTime))
.ForMember(dto => dto.MessageType, map => map.MapFrom(src => src.Type))
.ForMember(dto => dto.IsAnonymous, map => map.Ignore())
.ForMember(dto => dto.GroupId, map => map.Ignore());
}
}
}

76
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroup.cs

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
/// <summary>
/// 聊天群组
/// </summary>
public class ChatGroup : AuditedEntity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 群组标识
/// </summary>
public virtual long GroupId { get; protected set; }
/// <summary>
/// 群组名称
/// </summary>
public virtual string Name { get; protected set; }
/// <summary>
/// 群组标记
/// </summary>
public virtual string Tag { get; protected set; }
/// <summary>
/// 群组地址
/// </summary>
public virtual string Address { get; protected set; }
/// <summary>
/// 群组公告
/// </summary>
public virtual string Notice { get; protected set; }
/// <summary>
/// 最大用户数量
/// </summary>
public virtual int MaxUserCount { get; protected set; }
/// <summary>
/// 允许匿名聊天
/// </summary>
public virtual bool AllowAnonymous { get; set; }
/// <summary>
/// 允许发送消息
/// </summary>
public virtual bool AllowSendMessage { get; set; }
/// <summary>
/// 群组说明
/// </summary>
public virtual string Description { get; set; }
protected ChatGroup()
{
}
public ChatGroup(long id, string name, string tag = "", string address = "", int maxUserCount = 200)
{
GroupId = id;
Name = name;
Tag = tag;
Address = address;
MaxUserCount = maxUserCount;
}
public void ChangeAddress(string address)
{
Address = address;
}
public void SetNotice(string notice)
{
Notice = notice;
}
}
}

69
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroupAdmin.cs

@ -0,0 +1,69 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
/// <summary>
/// 群管理员
/// </summary>
public class ChatGroupAdmin : AuditedEntity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 群组标识
/// </summary>
public virtual long GroupId { get; protected set; }
/// <summary>
/// 管理员用户
/// </summary>
public virtual Guid UserId { get; protected set; }
/// <summary>
/// 是否群主
/// </summary>
public virtual bool IsSuperAdmin { get; protected set; }
/// <summary>
/// 允许禁言
/// </summary>
public virtual bool AllowSilence { get; set; }
/// <summary>
/// 允许踢人
/// </summary>
public virtual bool AllowKickPeople { get; set; }
/// <summary>
/// 允许加人
/// </summary>
public virtual bool AllowAddPeople { get; set; }
/// <summary>
/// 允许发送群公告
/// </summary>
public virtual bool AllowSendNotice { get; set; }
/// <summary>
/// 允许解散群组
/// </summary>
public virtual bool AllowDissolveGroup { get; set; }
protected ChatGroupAdmin() { }
public ChatGroupAdmin(long groupId, Guid userId, bool isSuperAdmin = false)
{
GroupId = groupId;
UserId = userId;
AllowSilence = true;
AllowKickPeople = true;
AllowAddPeople = true;
AllowSendNotice = true;
SetSuperAdmin(isSuperAdmin);
}
public void SetSuperAdmin(bool isSuperAdmin = false)
{
IsSuperAdmin = isSuperAdmin;
if (isSuperAdmin)
{
AllowDissolveGroup = true;
}
}
}
}

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

@ -1,34 +0,0 @@
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
public abstract class ChatMessage : Entity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 发送用户标识
/// </summary>
public virtual Guid SendUserId { get; protected set; }
/// <summary>
/// 接收用户标识
/// </summary>
public virtual Guid ReceiveUserId { get; set; }
/// <summary>
/// 内容
/// </summary>
public virtual string Content { get; protected set; }
/// <summary>
/// 发送状态
/// </summary>
public virtual SendStatus SendStatus { get; protected set; }
/// <summary>
/// 阅读状态
/// </summary>
public virtual ReadStatus ReadStatus { get; protected set; }
}
}

32
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupChatBlack.cs

@ -0,0 +1,32 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
/// <summary>
/// 用户黑名单
/// </summary>
public class GroupChatBlack : CreationAuditedEntity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 群组标识
/// </summary>
public virtual long GroupId { get; protected set; }
/// <summary>
/// 拉黑的用户
/// </summary>
public virtual Guid ShieldUserId { get; protected set; }
protected GroupChatBlack() { }
public GroupChatBlack(long groupId, Guid shieldUserId, Guid? tenantId)
{
GroupId = groupId;
ShieldUserId = shieldUserId;
TenantId = tenantId;
}
}
}

24
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupMessage.cs

@ -0,0 +1,24 @@
using LINGYUN.Abp.IM.Messages;
using System;
namespace LINGYUN.Abp.MessageService.Messages
{
public class GroupMessage : Message
{
/// <summary>
/// 群组标识
/// </summary>
public virtual long GroupId { get; protected set; }
protected GroupMessage() { }
public GroupMessage(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text)
: base(id, sendUserId, sendUserName, content, type)
{
}
public void SendToGroup(long groupId)
{
GroupId = groupId;
}
}
}

22
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IGroupRepository.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Messages
{
public interface IGroupRepository : IBasicRepository<ChatGroup, long>
{
/// <summary>
/// 用户是否已被拉黑
/// </summary>
/// <param name="id"></param>
/// <param name="formUserId"></param>
/// <returns></returns>
Task<bool> UserHasBlackedAsync(long id, Guid formUserId);
Task<ChatGroup> GetByIdAsync(long id);
Task<List<ChatGroupAdmin>> GetGroupAdminAsync(long id);
}
}

24
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IMessageRepository.cs

@ -0,0 +1,24 @@
using LINGYUN.Abp.IM.Messages;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.MessageService.Messages
{
public interface IMessageRepository
{
Task<UserMessage> InsertUserMessageAsync(UserMessage userMessage, bool saveChangs = false);
Task<GroupMessage> InsertGroupMessageAsync(GroupMessage groupMessage, bool saveChangs = false);
Task<UserMessage> GetUserMessageAsync(long id);
Task<GroupMessage> GetGroupMessageAsync(long id);
Task<List<UserMessage>> GetUserMessagesAsync(Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10);
Task<List<GroupMessage>> GetGroupMessagesAsync(long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10);
Task<List<GroupMessage>> GetUserGroupMessagesAsync(Guid sendUserId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10);
}
}

25
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatGroupRepository.cs

@ -0,0 +1,25 @@
using LINGYUN.Abp.IM.Group;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Messages
{
public interface IUserChatGroupRepository : IBasicRepository<UserChatGroup, long>
{
/// <summary>
/// 用户是否在组里
/// </summary>
/// <param name="id"></param>
/// <param name="userId"></param>
/// <returns></returns>
Task<bool> UserHasInGroupAsync(long groupId, Guid userId);
Task<UserChatGroup> GetUserGroupAsync(long groupId, Guid userId);
Task<List<UserGroup>> GetGroupUsersAsync(long groupId);
Task<List<Group>> GetUserGroupsAsync(Guid userId);
}
}

20
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatSettingRepository.cs

@ -0,0 +1,20 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Messages
{
public interface IUserChatSettingRepository : IBasicRepository<UserChatSetting, long>
{
Task<bool> UserHasOpendImAsync(Guid userId);
/// <summary>
/// 用户是否已被拉黑
/// </summary>
/// <param name="formUserId"></param>
/// <param name="toUserId"></param>
/// <returns></returns>
Task<bool> UserHasBlackedAsync(Guid formUserId, Guid toUserId);
Task<UserChatSetting> GetByUserIdAsync(Guid userId);
}
}

50
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/Message.cs

@ -0,0 +1,50 @@
using LINGYUN.Abp.IM.Messages;
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
public abstract class Message : CreationAuditedEntity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 消息标识
/// </summary>
public virtual long MessageId { get; protected set; }
/// <summary>
/// 发送用户名称
/// </summary>
public virtual string SendUserName { get; protected set; }
/// <summary>
/// 内容
/// </summary>
public virtual string Content { get; protected set; }
/// <summary>
/// 消息类型
/// </summary>
public virtual MessageType Type { get; protected set; }
/// <summary>
/// 发送状态
/// </summary>
public virtual MessageSendState SendState { get; protected set; }
protected Message() { }
public Message(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text)
{
MessageId = id;
CreatorId = sendUserId;
SendUserName = sendUserName;
Content = content;
Type = type;
CreationTime = DateTime.Now;
}
public void ChangeSendState(MessageSendState state = MessageSendState.Send)
{
SendState = state;
}
}
}

132
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/MessageStore.cs

@ -0,0 +1,132 @@
using LINGYUN.Abp.IM.Messages;
using LINGYUN.Abp.MessageService.Utils;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.MessageService.Messages
{
public class MessageStore : DomainService, IMessageStore
{
private IObjectMapper _objectMapper;
protected IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper);
private IUnitOfWorkManager _unitOfWorkManager;
protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager);
protected IUserChatSettingRepository UserChatSettingRepository { get; }
protected IMessageRepository MessageRepository { get; }
protected IGroupRepository GroupRepository { get; }
protected ISnowflakeIdGenerator SnowflakeIdGenerator { get; }
public MessageStore(
IGroupRepository groupRepository,
IMessageRepository messageRepository,
ISnowflakeIdGenerator snowflakeIdGenerator,
IUserChatSettingRepository userChatSettingRepository)
{
GroupRepository = groupRepository;
MessageRepository = messageRepository;
SnowflakeIdGenerator = snowflakeIdGenerator;
UserChatSettingRepository = userChatSettingRepository;
}
[UnitOfWork]
public async Task StoreMessageAsync(ChatMessage chatMessage)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
using (CurrentTenant.Change(chatMessage.TenantId))
{
if (!chatMessage.GroupId.IsNullOrWhiteSpace())
{
long groupId = long.Parse(chatMessage.GroupId);
await StoreGroupMessageAsync(chatMessage, groupId);
}
else
{
await StoreUserMessageAsync(chatMessage);
}
await unitOfWork.SaveChangesAsync();
}
}
}
public async Task<List<ChatMessage>> GetGroupMessageAsync(Guid? tenantId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10)
{
using (CurrentTenant.Change(tenantId))
{
var groupMessages = await MessageRepository.GetGroupMessagesAsync(groupId, filter, type, skipCount, maxResultCount);
var chatMessages = ObjectMapper.Map<List<GroupMessage>, List<ChatMessage>>(groupMessages);
return chatMessages;
}
}
public async Task<List<ChatMessage>> GetChatMessageAsync(Guid? tenantId, Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10)
{
using (CurrentTenant.Change(tenantId))
{
var userMessages = await MessageRepository.GetUserMessagesAsync(sendUserId, receiveUserId, filter, type, skipCount, maxResultCount);
var chatMessages = ObjectMapper.Map<List<UserMessage>, List<ChatMessage>>(userMessages);
return chatMessages;
}
}
protected virtual async Task StoreUserMessageAsync(ChatMessage chatMessage)
{
var userHasBlacked = await UserChatSettingRepository
.UserHasBlackedAsync(chatMessage.ToUserId.Value, chatMessage.FormUserId);
if (userHasBlacked)
{
// 当前发送的用户已被拉黑
throw new BusinessException(MessageServiceErrorCodes.UserHasBlack);
}
var userChatSetting = await UserChatSettingRepository.GetByUserIdAsync(chatMessage.ToUserId.Value);
if (!userChatSetting.AllowReceiveMessage)
{
// 当前发送的用户不接收消息
throw new BusinessException(MessageServiceErrorCodes.UserHasRejectAllMessage);
}
if (chatMessage.IsAnonymous && !userChatSetting.AllowAnonymous)
{
// 当前用户不允许匿名发言
throw new BusinessException(MessageServiceErrorCodes.UserNotAllowedToSpeakAnonymously);
}
var messageId = SnowflakeIdGenerator.Create();
var message = new UserMessage(messageId, chatMessage.FormUserId, chatMessage.FormUserName, chatMessage.Content, chatMessage.MessageType);
message.SendToUser(chatMessage.ToUserId.Value);
await MessageRepository.InsertUserMessageAsync(message);
}
protected virtual async Task StoreGroupMessageAsync(ChatMessage chatMessage, long groupId)
{
var userHasBlacked = await GroupRepository
.UserHasBlackedAsync(groupId, chatMessage.FormUserId);
if (userHasBlacked)
{
// 当前发送的用户已被拉黑
throw new BusinessException(MessageServiceErrorCodes.GroupUserHasBlack);
}
var group = await GroupRepository.GetByIdAsync(groupId);
if (!group.AllowSendMessage)
{
// 当前群组不允许发言
throw new BusinessException(MessageServiceErrorCodes.GroupNotAllowedToSpeak);
}
if (chatMessage.IsAnonymous && !group.AllowAnonymous)
{
// 当前群组不允许匿名发言
throw new BusinessException(MessageServiceErrorCodes.GroupNotAllowedToSpeakAnonymously);
}
var messageId = SnowflakeIdGenerator.Create();
var message = new GroupMessage(messageId, chatMessage.FormUserId, chatMessage.FormUserName, chatMessage.Content, chatMessage.MessageType);
// TODO: 需要压测 高并发场景下的装箱性能影响
message.SendToGroup(groupId);
await MessageRepository.InsertGroupMessageAsync(message);
}
}
}

32
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatBlack.cs

@ -0,0 +1,32 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
/// <summary>
/// 用户黑名单
/// </summary>
public class UserChatBlack : CreationAuditedEntity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 用户标识
/// </summary>
public virtual Guid UserId { get; protected set; }
/// <summary>
/// 拉黑的用户
/// </summary>
public virtual Guid ShieldUserId { get; protected set; }
protected UserChatBlack() { }
public UserChatBlack(Guid userId, Guid shieldUserId, Guid? tenantId)
{
UserId = userId;
ShieldUserId = shieldUserId;
TenantId = tenantId;
}
}
}

27
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatGroup.cs

@ -0,0 +1,27 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
/// <summary>
/// 用户群组
/// </summary>
public class UserChatGroup : CreationAuditedEntity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
public virtual Guid UserId { get; protected set; }
public virtual long GroupId { get; protected set; }
protected UserChatGroup() { }
public UserChatGroup(long groupId, Guid userId, Guid acceptUserId, Guid? tenantId = null)
{
UserId = userId;
GroupId = groupId;
CreatorId = acceptUserId;
TenantId = tenantId;
}
}
}

54
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatSetting.cs

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
public class UserChatSetting : Entity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 用户标识
/// </summary>
public virtual Guid UserId { get; protected set; }
/// <summary>
/// 允许匿名聊天
/// </summary>
public virtual bool AllowAnonymous { get; set; }
/// <summary>
/// 允许添加好友
/// </summary>
public virtual bool AllowAddFriend { get; set; }
/// <summary>
/// 添加好友需要验证
/// </summary>
public virtual bool RequireAddFriendValition { get; set; }
/// <summary>
/// 允许接收消息
/// </summary>
public virtual bool AllowReceiveMessage { get; set; }
/// <summary>
/// 允许发送消息
/// </summary>
public virtual bool AllowSendMessage { get; set; }
protected UserChatSetting()
{
}
public UserChatSetting(Guid userId, Guid? tenantId)
: this()
{
UserId = userId;
TenantId = tenantId;
AllowAnonymous = false;
AllowAddFriend = true;
AllowReceiveMessage = true;
AllowSendMessage = true;
RequireAddFriendValition = true;
}
}
}

86
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserGroupStore.cs

@ -0,0 +1,86 @@
using LINGYUN.Abp.IM.Group;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.MessageService.Messages
{
public class UserGroupStore : DomainService, IUserGroupStore
{
private IObjectMapper _objectMapper;
protected IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper);
private IUnitOfWorkManager _unitOfWorkManager;
protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager);
protected IUserChatGroupRepository UserChatGroupRepository { get; }
public UserGroupStore(
IUserChatGroupRepository userChatGroupRepository)
{
UserChatGroupRepository = userChatGroupRepository;
}
[UnitOfWork]
public async Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId, Guid acceptUserId)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
using (CurrentTenant.Change(tenantId))
{
var userHasInGroup = await UserChatGroupRepository.UserHasInGroupAsync(groupId, userId);
if (!userHasInGroup)
{
var userGroup = new UserChatGroup(groupId, userId, acceptUserId, tenantId);
await UserChatGroupRepository.InsertAsync(userGroup);
await unitOfWork.SaveChangesAsync();
}
}
}
}
public async Task<IEnumerable<UserGroup>> GetGroupUsersAsync(Guid? tenantId, long groupId)
{
using (CurrentTenant.Change(tenantId))
{
var userGroups = await UserChatGroupRepository.GetGroupUsersAsync(groupId);
return userGroups;
}
}
public async Task<IEnumerable<Group>> GetUserGroupsAsync(Guid? tenantId, Guid userId)
{
using (CurrentTenant.Change(tenantId))
{
var groups = await UserChatGroupRepository.GetUserGroupsAsync(userId);
return groups;
}
}
[UnitOfWork]
public async Task RemoveUserFormGroupAsync(Guid? tenantId, Guid userId, long groupId)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
using (CurrentTenant.Change(tenantId))
{
var userGroup = await UserChatGroupRepository.GetUserGroupAsync(groupId, userId);
if(userGroup != null)
{
await UserChatGroupRepository.DeleteAsync(userGroup);
await unitOfWork.SaveChangesAsync();
}
}
}
}
}
}

25
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserMessage.cs

@ -0,0 +1,25 @@
using LINGYUN.Abp.IM.Messages;
using System;
namespace LINGYUN.Abp.MessageService.Messages
{
public class UserMessage : Message
{
/// <summary>
/// 接收用户标识
/// </summary>
public virtual Guid ReceiveUserId { get; set; }
protected UserMessage() { }
public UserMessage(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text)
: base(id, sendUserId, sendUserName, content, type)
{
}
public void SendToUser(Guid receiveUserId)
{
ReceiveUserId = receiveUserId;
}
}
}

32
aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserSpecialFocus.cs

@ -0,0 +1,32 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.MessageService.Messages
{
/// <summary>
/// 用户特别关注
/// </summary>
public class UserSpecialFocus : CreationAuditedEntity<long>, IMultiTenant
{
/// <summary>
/// 租户
/// </summary>
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// 用户标识
/// </summary>
public virtual Guid UserId { get; protected set; }
/// <summary>
/// 关注的用户
/// </summary>
public virtual Guid FocusUserId { get; protected set; }
protected UserSpecialFocus() { }
public UserSpecialFocus(Guid userId, Guid focusUserId, Guid? tenantId)
{
UserId = userId;
FocusUserId = focusUserId;
TenantId = tenantId;
}
}
}

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

@ -0,0 +1,12 @@
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.MessageService.Notifications
{
public interface INotificationRepository : IBasicRepository<Notification, long>
{
Task<Notification> GetByIdAsync(long notificationId);
Task DeleteExpritionAsync(int batchCount);
}
}

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

@ -1,11 +0,0 @@
using LINGYUN.Abp.Notifications;
using System;
using System.Threading.Tasks;
namespace LINGYUN.Abp.MessageService.Notifications
{
public interface INotificationStore
{
Task InsertUserNotificationAsync(NotificationInfo notification, Guid userId);
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save