diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs index 861de3343..31a2237b4 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs @@ -35,7 +35,9 @@ namespace Microsoft.AspNetCore.Identity var phoneNumber = await manager.GetPhoneNumberAsync(user); if (phoneNumber.IsNullOrWhiteSpace()) { - throw new UserFriendlyException(_stringLocalizer["InvalidPhoneNumber"].Value, "InvalidPhoneNumber"); + return; + // 如果用户没有手机号,不验证 + //throw new UserFriendlyException(_stringLocalizer["InvalidPhoneNumber"].Value, "InvalidPhoneNumber"); } var phoneNumberHasRegisted = await _identityUserRepository.PhoneNumberHasRegistedAsync(phoneNumber); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Class1.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Class1.cs deleted file mode 100644 index ea63efae8..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Class1.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace LINGYUN.Abp.IdentityServer.WeChatValidator -{ - public class Class1 - { - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj index c15204a42..307851aa6 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj @@ -5,6 +5,16 @@ + + + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs new file mode 100644 index 000000000..97a959382 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs @@ -0,0 +1,47 @@ +using LINGYUN.Abp.IdentityServer.WeChatValidator; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.IdentityServer; +using Volo.Abp.IdentityServer.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.IdentityServer +{ + [DependsOn(typeof(AbpIdentityServerDomainModule))] + public class AbpIdentityServerWeChatValidatorModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(builder => + { + builder.AddExtensionGrantValidator(); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + Configure(configuration.GetSection("AuthServer:WeChat")); + Configure(configuration.GetSection("WeChat:Signature")); + + context.Services.AddHttpClient(WeChatValidatorConsts.WeChatValidatorClientName, options => + { + options.BaseAddress = new System.Uri("https://api.weixin.qq.com/sns/jscode2session"); + }); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Get() + .AddVirtualJson("/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator"); + }); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpWeChatValidatorOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpWeChatValidatorOptions.cs new file mode 100644 index 000000000..32cf49f46 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpWeChatValidatorOptions.cs @@ -0,0 +1,8 @@ +namespace LINGYUN.Abp.IdentityServer +{ + public class AbpWeChatValidatorOptions + { + public string AppId { get; set; } + public string AppSecret { get; set; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/en.json b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/en.json new file mode 100644 index 000000000..054ab3e9a --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/en.json @@ -0,0 +1,9 @@ +{ + "culture": "en", + "texts": { + "InvalidGrant:GrantTypeInvalid": "The type of authorization that is not allowed!", + "InvalidGrant:WeChatTokenInvalid": "WeChat authentication failed!", + "InvalidGrant:WeChatCodeNotFound": "The code obtained when WeChat is logged in is empty or does not exist!", + "InvalidGrant:WeChatNotRegister": "User WeChat account not registed!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/zh-Hans.json b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/zh-Hans.json new file mode 100644 index 000000000..cb5482df5 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hans", + "texts": { + "InvalidGrant:GrantTypeInvalid": "不被允许的授权类型!", + "InvalidGrant:WeChatTokenInvalid": "微信认证失败!", + "InvalidGrant:WeChatCodeNotFound": "微信登录时获取的 code 为空或不存在!", + "InvalidGrant:WeChatNotRegister": "用户微信账号未绑定!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs new file mode 100644 index 000000000..65a3a53aa --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs @@ -0,0 +1,69 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; +using System; +using System.Collections; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.IdentityServer +{ + public class WeChatSignatureMiddleware : IMiddleware, ITransientDependency + { + protected WeChatSignatureOptions Options { get; } + public WeChatSignatureMiddleware(IOptions options) + { + Options = options.Value; + } + + public async Task InvokeAsync(HttpContext context, RequestDelegate next) + { + if (context.Request.Path.HasValue) + { + var requestPath = context.Request.Path.Value; + if (requestPath.Equals(Options.RequestPath)) + { + var timestamp = context.Request.Query["timestamp"]; + var nonce = context.Request.Query["nonce"]; + var signature = context.Request.Query["signature"]; + var echostr = context.Request.Query["echostr"]; + var check = CheckWeChatSignature(Options.Token, timestamp, nonce, signature); + if (check) + { + await context.Response.WriteAsync(echostr); + return; + } + throw new AbpException("微信验证不通过"); + } + } + await next(context); + } + + protected bool CheckWeChatSignature(string token, string timestamp, string nonce, string signature) + { + var al = new ArrayList(); + al.Add(token); + al.Add(timestamp); + al.Add(nonce); + al.Sort(); + string signatureStr = string.Empty; + for(int i = 0; i < al.Count; i++) + { + signatureStr += al[i]; + } + using (var sha1 = new SHA1CryptoServiceProvider()) + { + byte[] bytes_in = Encoding.ASCII.GetBytes(signatureStr); + byte[] bytes_out = sha1.ComputeHash(bytes_in); + string result = BitConverter.ToString(bytes_out).Replace("-", ""); + if (result.Equals(signature, StringComparison.CurrentCultureIgnoreCase)) + { + return true; + } + return false; + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs new file mode 100644 index 000000000..76a6f1c8e --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs @@ -0,0 +1,8 @@ +namespace LINGYUN.Abp.IdentityServer +{ + public class WeChatSignatureOptions + { + public string RequestPath { get; set; } + public string Token { get; set; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs new file mode 100644 index 000000000..c4583857e --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs @@ -0,0 +1,119 @@ +using IdentityModel; +using IdentityServer4.Events; +using IdentityServer4.Models; +using IdentityServer4.Services; +using IdentityServer4.Validation; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Security.Claims; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.IdentityServer.Localization; +using Volo.Abp.Security.Claims; +using IdentityUser = Volo.Abp.Identity.IdentityUser; + +namespace LINGYUN.Abp.IdentityServer.WeChatValidator +{ + public class WeChatTokenGrantValidator : IExtensionGrantValidator + { + protected ILogger Logger { get; } + protected AbpWeChatValidatorOptions Options { get; } + protected IHttpClientFactory HttpClientFactory{ get; } + protected IEventService EventService { get; } + protected IIdentityUserRepository UserRepository { get; } + protected UserManager UserManager { get; } + protected SignInManager SignInManager { get; } + protected IStringLocalizer Localizer { get; } + protected PhoneNumberTokenProvider PhoneNumberTokenProvider { get; } + + + public WeChatTokenGrantValidator( + IEventService eventService, + IHttpClientFactory httpClientFactory, + UserManager userManager, + IIdentityUserRepository userRepository, + SignInManager signInManager, + IStringLocalizer stringLocalizer, + PhoneNumberTokenProvider phoneNumberTokenProvider, + IOptionsSnapshot options, + ILogger logger) + { + Logger = logger; + Options = options.Value; + + EventService = eventService; + UserManager = userManager; + SignInManager = signInManager; + Localizer = stringLocalizer; + UserRepository = userRepository; + HttpClientFactory = httpClientFactory; + PhoneNumberTokenProvider = phoneNumberTokenProvider; + } + + public string GrantType => WeChatValidatorConsts.WeChatValidatorGrantTypeName; + + public async Task ValidateAsync(ExtensionGrantValidationContext context) + { + var raw = context.Request.Raw; + var credential = raw.Get(OidcConstants.TokenRequest.GrantType); + if (credential == null || !credential.Equals(GrantType)) + { + Logger.LogWarning("Invalid grant type: not allowed"); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, + Localizer["InvalidGrant:GrantTypeInvalid"]); + return; + } + var wechatCode = raw.Get(WeChatValidatorConsts.WeChatValidatorTokenName); + if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) + { + Logger.LogWarning("Invalid grant type: wechat code not found"); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, + Localizer["InvalidGrant:WeChatCodeNotFound"]); + return; + } + var httpClient = HttpClientFactory.CreateClient(WeChatValidatorConsts.WeChatValidatorClientName); + var httpRequest = new WeChatTokenRequest + { + Code = wechatCode, + AppId = Options.AppId, + Secret = Options.AppSecret, + BaseUrl = httpClient.BaseAddress.AbsoluteUri + }; + + var wechatTokenResponse = await httpClient.RequestWeChatCodeTokenAsync(httpRequest); + if (wechatTokenResponse.IsError) + { + Logger.LogWarning("Authentication failed for token: {0}, reason: invalid token", wechatCode); + Logger.LogWarning("WeChat auth failed, error: {0}", wechatTokenResponse.ErrorMessage); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, + Localizer["InvalidGrant:WeChatTokenInvalid"]); + return; + } + var currentUser = await UserManager.FindByNameAsync(wechatTokenResponse.OpenId); + if(currentUser == null) + { + Logger.LogWarning("Invalid grant type: wechat openid: {0} not register", wechatTokenResponse.OpenId); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, + Localizer["InvalidGrant:WeChatNotRegister"]); + return; + } + var sub = await UserManager.GetUserIdAsync(currentUser); + + var additionalClaims = new List(); + if (currentUser.TenantId.HasValue) + { + additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString())); + } + additionalClaims.Add(new Claim(WeChatValidatorConsts.ClaimTypes.OpenId, wechatTokenResponse.OpenId)); + + await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatTokenResponse.OpenId, null)); + context.Result = new GrantValidationResult(sub, + WeChatValidatorConsts.AuthenticationMethods.BasedWeChatAuthentication, additionalClaims.ToArray()); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatValidatorConsts.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatValidatorConsts.cs new file mode 100644 index 000000000..bc86ed61e --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatValidatorConsts.cs @@ -0,0 +1,21 @@ +namespace LINGYUN.Abp.IdentityServer.WeChatValidator +{ + public class WeChatValidatorConsts + { + public const string WeChatValidatorClientName = "WeChatValidator"; + + public const string WeChatValidatorGrantTypeName = "wechat"; + + public const string WeChatValidatorTokenName = "code"; + + public class ClaimTypes + { + public const string OpenId = "wechat-id"; + } + + public class AuthenticationMethods + { + public const string BasedWeChatAuthentication = "wca"; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs new file mode 100644 index 000000000..91d411491 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs @@ -0,0 +1,13 @@ +using LINGYUN.Abp.IdentityServer; + +namespace Microsoft.AspNetCore.Builder +{ + public static class IdentityServerApplicationBuilderExtensions + { + public static IApplicationBuilder UseWeChatSignature(this IApplicationBuilder builder) + { + builder.UseMiddleware(); + return builder; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/HttpClientTokenRequestExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/HttpClientTokenRequestExtensions.cs new file mode 100644 index 000000000..169520000 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/HttpClientTokenRequestExtensions.cs @@ -0,0 +1,32 @@ +using IdentityModel.Client; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + public static class HttpClientTokenRequestExtensions + { + public static async Task RequestWeChatCodeTokenAsync(this HttpMessageInvoker client, WeChatTokenRequest request, CancellationToken cancellationToken = default) + { + var getResuestUrlBuiilder = new StringBuilder(); + getResuestUrlBuiilder.Append(request.BaseUrl); + getResuestUrlBuiilder.AppendFormat("?appid={0}", request.AppId); + getResuestUrlBuiilder.AppendFormat("&secret={0}", request.Secret); + getResuestUrlBuiilder.AppendFormat("&js_code={0}", request.Code); + getResuestUrlBuiilder.Append("&grant_type=authorization_code"); + + var getRequest = new HttpRequestMessage(HttpMethod.Get, getResuestUrlBuiilder.ToString()); + HttpResponseMessage httpResponse; + try + { + httpResponse = await client.SendAsync(getRequest, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + return ProtocolResponse.FromException(ex); + } + return await ProtocolResponse.FromHttpResponseAsync(httpResponse).ConfigureAwait(false); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/WeChatTokenRequest.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/WeChatTokenRequest.cs new file mode 100644 index 000000000..14088f187 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/WeChatTokenRequest.cs @@ -0,0 +1,10 @@ +namespace System.Net.Http +{ + public class WeChatTokenRequest + { + public string BaseUrl { get; set; } + public string AppId { get; set; } + public string Secret { get; set; } + public string Code { get; set; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/WeChatTokenResponse.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/WeChatTokenResponse.cs new file mode 100644 index 000000000..983a0bc4b --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Net/Http/WeChatTokenResponse.cs @@ -0,0 +1,48 @@ +using IdentityModel.Client; + +namespace System.Net.Http +{ + public class WeChatTokenResponse : ProtocolResponse + { + /// + /// 用户唯一标识 + /// + public string OpenId => TryGet("openid"); + /// + /// 会话密钥 + /// + /// + /// 仅仅只是要一个openid,这个没多大用吧 + /// + public string SessionKey => TryGet("session_key"); + /// + /// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回 + /// + public string UnionId => TryGet("unionid"); + /// + /// 微信认证成功没有errorcode或者errorcode为0 + /// + public new bool IsError => !ErrorCode.IsNullOrWhiteSpace() && !"0".Equals(ErrorCode); + /// + /// 错误码 + /// + public string ErrorCode => TryGet("errcode"); + /// + /// 错误信息 + /// + public new string ErrorMessage + { + get + { + return ErrorCode switch + { + "-1" => "系统繁忙,此时请开发者稍候再试", + "0" => string.Empty, + "40029" => "code 无效", + "45011" => "频率限制,每个用户每分钟100次", + _ => "未知的异常", + }; + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs index 549f249f8..572ab75c3 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/AbpNotificationsSignalRModule.cs @@ -10,6 +10,12 @@ namespace LINGYUN.Abp.Notifications.SignalR typeof(AbpAspNetCoreSignalRModule))] public class AbpNotificationsSignalRModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.PublishProviders.Add(); + }); + } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs similarity index 70% rename from aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs rename to aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs index 8130a659e..79263e96f 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublisher.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/SignalRNotificationPublishProvider.cs @@ -6,33 +6,36 @@ using Microsoft.Extensions.Logging.Abstractions; using System; using System.Collections.Generic; using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; namespace LINGYUN.Abp.Notifications.SignalR { - public class SignalRNotificationPublisher : INotificationPublisher, ISingletonDependency + public class SignalRNotificationPublishProvider : NotificationPublishProvider { - public ILogger Logger { protected get; set; } + public ILogger Logger { protected get; set; } + + public override string Name => "SignalR"; private readonly IOnlineClientManager _onlineClientManager; private readonly IHubContext _hubContext; - public SignalRNotificationPublisher( + public SignalRNotificationPublishProvider( IOnlineClientManager onlineClientManager, - IHubContext hubContext) + IHubContext hubContext, + IServiceProvider serviceProvider) + : base(serviceProvider) { _hubContext = hubContext; _onlineClientManager = onlineClientManager; - Logger = NullLogger.Instance; + Logger = NullLogger.Instance; } - public async Task PublishAsync(NotificationInfo notification, IEnumerable userIds) + public override async Task PublishAsync(NotificationInfo notification, IEnumerable identifiers) { - foreach(var userId in userIds) + foreach(var identifier in identifiers) { - var onlineClientContext = new OnlineClientContext(notification.TenantId, userId); + var onlineClientContext = new OnlineClientContext(notification.TenantId, identifier.UserId); var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext); foreach (var onlineClient in onlineClients) { @@ -49,7 +52,7 @@ namespace LINGYUN.Abp.Notifications.SignalR } catch (Exception ex) { - Logger.LogWarning("Could not send notifications to user: {0}", userId); + Logger.LogWarning("Could not send notifications to user: {0}", identifier.UserId); Logger.LogWarning("Send to user notifications error: {0}", ex.Message); } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN.Abp.Notifications.WeChat.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN.Abp.Notifications.WeChat.csproj new file mode 100644 index 000000000..4ed83b791 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN.Abp.Notifications.WeChat.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeChatNotificationPublishProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeChatNotificationPublishProvider.cs new file mode 100644 index 000000000..f98ddfcc6 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeChatNotificationPublishProvider.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Notifications.WeChat +{ + public class WeChatNotificationPublishProvider : NotificationPublishProvider + { + public override string Name => "WeChat"; + + public WeChatNotificationPublishProvider( + IServiceProvider serviceProvider) + : base(serviceProvider) + { + + } + + public override async Task PublishAsync(NotificationInfo notification, IEnumerable identifiers) + { + // step1 默认微信openid绑定的就是username,如果不是,那就根据userid去获取 + + // step2 调用微信消息推送接口 + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs index ec8c315e2..bc983485c 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs @@ -1,14 +1,40 @@ using LINGYUN.Abp.Notifications.Internal; using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; using Volo.Abp.Modularity; namespace LINGYUN.Abp.Notifications { public class AbpNotificationModule : AbpModule { + + public override void PreConfigureServices(ServiceConfigurationContext context) + { + AutoAddDefinitionProviders(context.Services); + } + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddTransient(); } + + private static void AutoAddDefinitionProviders(IServiceCollection services) + { + var definitionProviders = new List(); + + services.OnRegistred(context => + { + if (typeof(INotificationDefinitionProvider).IsAssignableFrom(context.ImplementationType)) + { + definitionProviders.Add(context.ImplementationType); + } + }); + + services.Configure(options => + { + options.DefinitionProviders.AddIfNotContains(definitionProviders); + }); + } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationOptions.cs new file mode 100644 index 000000000..dffacc0bf --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationOptions.cs @@ -0,0 +1,17 @@ +using Volo.Abp.Collections; + +namespace LINGYUN.Abp.Notifications +{ + public class AbpNotificationOptions + { + public ITypeList DefinitionProviders { get; } + + public ITypeList PublishProviders { get; } + + public AbpNotificationOptions() + { + PublishProviders = new TypeList(); + DefinitionProviders = new TypeList(); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionContext.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionContext.cs new file mode 100644 index 000000000..d46ea70ef --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionContext.cs @@ -0,0 +1,9 @@ +namespace LINGYUN.Abp.Notifications +{ + public interface INotificationDefinitionContext + { + NotificationDefinition GetOrNull(string name); + + void Add(params NotificationDefinition[] definitions); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionManager.cs new file mode 100644 index 000000000..87829d683 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionManager.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; +using System.Collections.Generic; + +namespace LINGYUN.Abp.Notifications +{ + public interface INotificationDefinitionManager + { + [NotNull] + NotificationDefinition Get([NotNull] string name); + + IReadOnlyList GetAll(); + + NotificationDefinition GetOrNull(string name); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionProvider.cs new file mode 100644 index 000000000..7c86ddda0 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDefinitionProvider.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.Notifications +{ + public interface INotificationDefinitionProvider + { + void Define(INotificationDefinitionContext context); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDispatcher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDispatcher.cs index 180f82d59..2ed1301db 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDispatcher.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationDispatcher.cs @@ -1,9 +1,27 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; namespace LINGYUN.Abp.Notifications { public interface INotificationDispatcher { - Task DispatcheAsync(NotificationInfo notification); + /// + /// 发送通知 + /// + /// + /// + [Obsolete("Api已过时,请调用 DispatcheAsync(string notificationName, NotificationData data, Guid? tenantId = null)")] + Task DispatchAsync(NotificationInfo notification); + + /// + /// 发送通知 + /// + /// 通知名称 + /// 数据 + /// 租户 + /// 级别 + /// + Task DispatchAsync(string notificationName, NotificationData data, Guid? tenantId = null, + NotificationSeverity notificationSeverity = NotificationSeverity.Info); } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishProvider.cs new file mode 100644 index 000000000..2819d5a28 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishProvider.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Notifications +{ + public interface INotificationPublishProvider + { + string Name { get; } + + Task PublishAsync(NotificationInfo notification, IEnumerable identifiers); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishProviderManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishProviderManager.cs new file mode 100644 index 000000000..630b932c9 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishProviderManager.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace LINGYUN.Abp.Notifications +{ + public interface INotificationPublishProviderManager + { + List Providers { get; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs deleted file mode 100644 index 1e8411eb9..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublisher.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace LINGYUN.Abp.Notifications -{ - public interface INotificationPublisher - { - Task PublishAsync(NotificationInfo notification, IEnumerable userIds); - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs index e7d0074e5..dc9f81ca9 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationStore.cs @@ -6,9 +6,9 @@ namespace LINGYUN.Abp.Notifications { public interface INotificationStore { - Task InsertUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName); + Task InsertUserSubscriptionAsync(Guid? tenantId, UserIdentifier identifier, string notificationName); - Task InsertUserSubscriptionAsync(Guid? tenantId, IEnumerable userIds, string notificationName); + Task InsertUserSubscriptionAsync(Guid? tenantId, IEnumerable identifiers, string notificationName); Task DeleteUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs index 1e470ee39..6b5bfa6e0 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs @@ -1,34 +1,107 @@ -using System.Linq; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace LINGYUN.Abp.Notifications.Internal { internal class DefaultNotificationDispatcher : INotificationDispatcher { + public ILogger Logger { get; set; } + private readonly INotificationStore _notificationStore; - private readonly INotificationPublisher _notificationPublisher; + private readonly INotificationDefinitionManager _notificationDefinitionManager; + private readonly INotificationPublishProviderManager _notificationPublishProviderManager; public DefaultNotificationDispatcher( INotificationStore notificationStore, - INotificationPublisher notificationPublisher) + INotificationDefinitionManager notificationDefinitionManager, + INotificationPublishProviderManager notificationPublishProviderManager) { _notificationStore = notificationStore; - _notificationPublisher = notificationPublisher; + _notificationDefinitionManager = notificationDefinitionManager; + _notificationPublishProviderManager = notificationPublishProviderManager; + + Logger = NullLogger.Instance; + } + + public virtual async Task DispatchAsync(string notificationName, NotificationData data, Guid? tenantId = null, + NotificationSeverity notificationSeverity = NotificationSeverity.Info) + { + // 获取自定义的通知 + var defineNotification = _notificationDefinitionManager.Get(notificationName); + + var notificationInfo = new NotificationInfo + { + Name = defineNotification.Name, + CreationTime = DateTime.Now, + NotificationSeverity = notificationSeverity, + NotificationType = defineNotification.NotificationType, + TenantId = tenantId, + Data = data + }; + + var providers = Enumerable + .Reverse(_notificationPublishProviderManager.Providers); + + if (defineNotification.Providers.Any()) + { + providers = providers.Where(p => defineNotification.Providers.Contains(p.Name)); + } + + await PublishFromProvidersAsync(providers, notificationInfo); } - public async Task DispatcheAsync(NotificationInfo notification) + public virtual async Task DispatchAsync(NotificationInfo notification) + { + // 获取自定义的通知 + var defineNotification = _notificationDefinitionManager.Get(notification.Name); + + notification.NotificationType = defineNotification.NotificationType; + notification.Name = defineNotification.Name; + + var providers = Enumerable + .Reverse(_notificationPublishProviderManager.Providers); + + if (defineNotification.Providers.Any()) + { + providers = providers.Where(p => defineNotification.Providers.Contains(p.Name)); + } + + await PublishFromProvidersAsync(providers, notification); + } + + protected async Task PublishFromProvidersAsync(IEnumerable providers, + NotificationInfo notificationInfo) { // 持久化通知 - await _notificationStore.InsertNotificationAsync(notification); + await _notificationStore.InsertNotificationAsync(notificationInfo); // 获取用户订阅列表 - var userSubscriptions = await _notificationStore.GetSubscriptionsAsync(notification.TenantId, notification.Name); + var userSubscriptions = await _notificationStore.GetSubscriptionsAsync(notificationInfo.TenantId, notificationInfo.Name); // 持久化用户通知 - var subscriptionUserIds = userSubscriptions.Select(us => us.UserId); - await _notificationStore.InsertUserNotificationsAsync(notification, subscriptionUserIds); + var subscriptionUserIdentifiers = userSubscriptions.Select(us => new UserIdentifier(us.UserId, us.UserName)); + + await _notificationStore.InsertUserNotificationsAsync(notificationInfo, + subscriptionUserIdentifiers.Select(u => u.UserId)); + + // 发送通知 + foreach (var provider in providers) + { + try + { + await provider.PublishAsync(notificationInfo, subscriptionUserIdentifiers); + } + catch(Exception ex) + { + Logger.LogWarning("Send notification error with provider {0}", provider.Name); + Logger.LogWarning("Error message:{0}", ex.Message); - // 发布用户通知 - await _notificationPublisher.PublishAsync(notification, subscriptionUserIds); + Logger.LogTrace(ex, "Send notification error with provider {0}", provider.Name); + } + } } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs new file mode 100644 index 000000000..3ccfd9534 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinition.cs @@ -0,0 +1,70 @@ +using JetBrains.Annotations; +using System; +using System.Collections.Generic; +using Volo.Abp; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Notifications +{ + public class NotificationDefinition + { + /// + /// 通知名称 + /// + [NotNull] + public string Name { get; set; } + /// + /// 通知显示名称 + /// + [NotNull] + public ILocalizableString DisplayName + { + get => _displayName; + set => _displayName = Check.NotNull(value, nameof(value)); + } + private ILocalizableString _displayName; + /// + /// 通知说明 + /// + [CanBeNull] + public ILocalizableString Description { get; set; } + /// + /// 允许客户端显示订阅 + /// + public bool AllowSubscriptionToClients { get; set; } + /// + /// 通知类型 + /// + public NotificationType NotificationType { get; set; } + /// + /// 通知提供者 + /// + public List Providers { get; } + + public NotificationDefinition( + string name, + ILocalizableString displayName = null, + ILocalizableString description = null, + NotificationType notificationType = NotificationType.Application, + bool allowSubscriptionToClients = false) + { + Name = name; + DisplayName = displayName ?? new FixedLocalizableString(name); + Description = description; + NotificationType = notificationType; + AllowSubscriptionToClients = allowSubscriptionToClients; + + Providers = new List(); + } + + public virtual NotificationDefinition WithProviders(params string[] providers) + { + if (!providers.IsNullOrEmpty()) + { + Providers.AddRange(providers); + } + + return this; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionContext.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionContext.cs new file mode 100644 index 000000000..9edf15535 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionContext.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace LINGYUN.Abp.Notifications +{ + public class NotificationDefinitionContext : INotificationDefinitionContext + { + protected Dictionary Notifications { get; } + + public NotificationDefinitionContext(Dictionary notifications) + { + Notifications = notifications; + } + + public void Add(params NotificationDefinition[] definitions) + { + if (definitions.IsNullOrEmpty()) + { + return; + } + + foreach (var definition in definitions) + { + Notifications[definition.Name] = definition; + } + } + + public NotificationDefinition GetOrNull(string name) + { + return Notifications.GetOrDefault(name); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionManager.cs new file mode 100644 index 000000000..3dde7bc3c --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionManager.cs @@ -0,0 +1,75 @@ +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Volo.Abp; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Notifications +{ + public class NotificationDefinitionManager : INotificationDefinitionManager, ISingletonDependency + { + protected Lazy> NotificationDefinitions { get; } + + protected AbpNotificationOptions Options { get; } + + protected IServiceProvider ServiceProvider { get; } + + public NotificationDefinitionManager( + IOptions options, + IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + Options = options.Value; + + NotificationDefinitions = new Lazy>(CreateNotificationDefinitions, true); + } + + public virtual NotificationDefinition Get([NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + var notification = GetOrNull(name); + + if (notification == null) + { + throw new AbpException("Undefined notification: " + name); + } + + return notification; + } + + public virtual IReadOnlyList GetAll() + { + return NotificationDefinitions.Value.Values.ToImmutableList(); + } + + public virtual NotificationDefinition GetOrNull(string name) + { + return NotificationDefinitions.Value.GetOrDefault(name); + } + + protected virtual IDictionary CreateNotificationDefinitions() + { + var notifications = new Dictionary(); + + using (var scope = ServiceProvider.CreateScope()) + { + var providers = Options + .DefinitionProviders + .Select(p => scope.ServiceProvider.GetRequiredService(p) as INotificationDefinitionProvider) + .ToList(); + + foreach (var provider in providers) + { + provider.Define(new NotificationDefinitionContext(notifications)); + } + } + + return notifications; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionProvider.cs new file mode 100644 index 000000000..f921ae5f4 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationDefinitionProvider.cs @@ -0,0 +1,9 @@ +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Notifications +{ + public abstract class NotificationDefinitionProvider : INotificationDefinitionProvider, ITransientDependency + { + public abstract void Define(INotificationDefinitionContext context); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProvider.cs new file mode 100644 index 000000000..1f8a7a6a0 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProvider.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Notifications +{ + public abstract class NotificationPublishProvider : INotificationPublishProvider, ITransientDependency + { + public abstract string Name { get; } + + protected IServiceProvider ServiceProvider { get; } + + protected NotificationPublishProvider(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public abstract Task PublishAsync(NotificationInfo notification, IEnumerable identifiers); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProviderManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProviderManager.cs new file mode 100644 index 000000000..669f3b678 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProviderManager.cs @@ -0,0 +1,33 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Notifications +{ + public class NotificationPublishProviderManager : INotificationPublishProviderManager, ISingletonDependency + { + public List Providers => _lazyProviders.Value; + + protected AbpNotificationOptions Options { get; } + + private readonly Lazy> _lazyProviders; + + public NotificationPublishProviderManager( + IServiceProvider serviceProvider, + IOptions options) + { + Options = options.Value; + + _lazyProviders = new Lazy>( + () => Options + .PublishProviders + .Select(type => serviceProvider.GetRequiredService(type) as INotificationPublishProvider) + .ToList(), + true + ); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationSubscriptionInfo.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationSubscriptionInfo.cs index 0122731fc..b4bcb5f79 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationSubscriptionInfo.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationSubscriptionInfo.cs @@ -6,6 +6,7 @@ namespace LINGYUN.Abp.Notifications { public Guid? TenantId { get; set; } public Guid UserId { get; set; } + public string UserName { get; set; } public string NotificationName { get; set; } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/UserIdentifier.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/UserIdentifier.cs new file mode 100644 index 000000000..a6717897f --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/UserIdentifier.cs @@ -0,0 +1,16 @@ +using System; + +namespace LINGYUN.Abp.Notifications +{ + public class UserIdentifier + { + public Guid UserId { get; set; } + public string UserName { get; set; } + + public UserIdentifier(Guid userId, string userName) + { + UserId = userId; + UserName = userName; + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj index 9eb0d5c96..04ede37ff 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj @@ -6,13 +6,13 @@ - - + + - - + + diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmsValidatorModule.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmsValidatorModule.cs index 0a3d1975c..9c628fe08 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmsValidatorModule.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmsValidatorModule.cs @@ -30,7 +30,7 @@ namespace LINGYUN.Abp.IdentityServer { options.Resources .Get() - .AddVirtualJson("/LINGYUN/Abp/IdentityServer/Localization/Resources"); + .AddVirtualJson("/LINGYUN/Abp/IdentityServer/Localization/SmsValidator"); }); } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/SmsValidator/en.json similarity index 100% rename from aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json rename to aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/SmsValidator/en.json diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/SmsValidator/zh-Hans.json similarity index 100% rename from aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json rename to aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/SmsValidator/zh-Hans.json diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs index d7a583b55..3a70048aa 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs @@ -3,5 +3,7 @@ public class SubscribeConsts { public const int MaxNotificationNameLength = 100; + + public const int MaxUserNameLength = 128; } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs index 0b2cb061e..63fef383c 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/Local/UserCreateSendWelcomeEventHandler.cs @@ -51,21 +51,18 @@ namespace LINGYUN.Abp.MessageService.EventBus } using (CultureHelper.Use(userDefaultCultureName, userDefaultCultureName)) { + var userIdentifer = new UserIdentifier(eventData.Entity.Id, eventData.Entity.UserName); // 订阅用户欢迎消息 await _notificationStore.InsertUserSubscriptionAsync(eventData.Entity.TenantId, - eventData.Entity.Id, UserNotificationNames.WelcomeToApplication); + userIdentifer, UserNotificationNames.WelcomeToApplication); - var userWelcomeNotifiction = new NotificationInfo - { - CreationTime = DateTime.Now, - Name = UserNotificationNames.WelcomeToApplication, - NotificationSeverity = NotificationSeverity.Info, - NotificationType = NotificationType.System, - TenantId = eventData.Entity.TenantId - }; - userWelcomeNotifiction.Data.Properties["message"] = L("WelcomeToApplicationFormUser", eventData.Entity.UserName); + var userWelcomeNotifictionData = new NotificationData(); - await _notificationDispatcher.DispatcheAsync(userWelcomeNotifiction); + // 换成用户名称,而不是用户名 + userWelcomeNotifictionData.Properties["message"] = L("WelcomeToApplicationFormUser", eventData.Entity.Name); + + await _notificationDispatcher.DispatchAsync(UserNotificationNames.WelcomeToApplication, + userWelcomeNotifictionData, eventData.Entity.TenantId); } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json index c39859059..f44750a3b 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json @@ -7,6 +7,7 @@ "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!", + "WelcomeToApplicationNotification": "User Welcome Notice", "WelcomeToApplicationFormUser": "User :{0} welcome to join us!" } } \ No newline at end of file diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json index 9a326307b..cf9f546ac 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json @@ -7,6 +7,7 @@ "Messages:User:1001": "用户不接收匿名发言!", "Messages:User:1002": "用户已拒接所有消息!", "Messages:User:1003": "用户拒绝您发送的消息!", + "WelcomeToApplicationNotification": "用户欢迎通知", "WelcomeToApplicationFormUser": "用户:{0} 欢迎您的加入!" } } \ No newline at end of file diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/AbpMessageServiceNotificationDefinitionProvider.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/AbpMessageServiceNotificationDefinitionProvider.cs new file mode 100644 index 000000000..c2c37f881 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/AbpMessageServiceNotificationDefinitionProvider.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.MessageService.Localization; +using LINGYUN.Abp.Notifications; +using Volo.Abp.Localization; +using Volo.Abp.Users.Notifications; + +namespace LINGYUN.Abp.MessageService.Notifications +{ + public class AbpMessageServiceNotificationDefinitionProvider : NotificationDefinitionProvider + { + public override void Define(INotificationDefinitionContext context) + { + context.Add(new NotificationDefinition( + UserNotificationNames.WelcomeToApplication, + L("WelcomeToApplicationNotification"), + L("WelcomeToApplicationNotification"), + allowSubscriptionToClients: true)); + } + + protected LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs deleted file mode 100644 index a24a3dae8..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationDispatcher.cs +++ /dev/null @@ -1,40 +0,0 @@ -using LINGYUN.Abp.Notifications; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; - -namespace LINGYUN.Abp.MessageService.Notifications -{ - public class NotificationDispatcher : INotificationDispatcher, ITransientDependency - { - protected INotificationStore NotificationStore { get; } - protected INotificationPublisher NotificationPublisher { get; } - - public NotificationDispatcher( - INotificationStore notificationStore, - INotificationPublisher notificationPublisher) - { - NotificationStore = notificationStore; - NotificationPublisher = notificationPublisher; - } - - public virtual async Task DispatcheAsync(NotificationInfo notification) - { - var subscribes = await NotificationStore.GetSubscriptionsAsync(notification.TenantId, notification.Name); - foreach (var subscribe in subscribes) - { - await NotificationStore.InsertUserNotificationAsync(notification, subscribe.UserId); - } - - var subscribeUsers = subscribes.Select(s => s.UserId); - await NotifyAsync(notification, subscribeUsers); - } - - protected virtual async Task NotifyAsync(NotificationInfo notification, IEnumerable userIds) - { - await NotificationPublisher.PublishAsync(notification, userIds); - } - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationPublisher.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationPublisher.cs deleted file mode 100644 index 2288cf3b6..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationPublisher.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace LINGYUN.Abp.MessageService.Notifications -{ - class NotificationPublisher - { - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs index c9de3a3c0..238131f83 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationStore.cs @@ -194,14 +194,14 @@ namespace LINGYUN.Abp.MessageService.Notifications } [UnitOfWork] - public async Task InsertUserSubscriptionAsync(Guid? tenantId, Guid userId, string notificationName) + public async Task InsertUserSubscriptionAsync(Guid? tenantId, UserIdentifier identifier, string notificationName) { using (var unitOfWork = _unitOfWorkManager.Begin()) { using (CurrentTenant.Change(tenantId)) { - var userSubscription = new UserSubscribe(notificationName, userId) + var userSubscription = new UserSubscribe(notificationName, identifier.UserId, identifier.UserName) { CreationTime = Clock.Now }; @@ -214,7 +214,7 @@ namespace LINGYUN.Abp.MessageService.Notifications } [UnitOfWork] - public async Task InsertUserSubscriptionAsync(Guid? tenantId, IEnumerable userIds, string notificationName) + public async Task InsertUserSubscriptionAsync(Guid? tenantId, IEnumerable identifiers, string notificationName) { using (var unitOfWork = _unitOfWorkManager.Begin()) { @@ -222,9 +222,9 @@ namespace LINGYUN.Abp.MessageService.Notifications { var userSubscribes = new List(); - foreach(var userId in userIds) + foreach(var identifier in identifiers) { - userSubscribes.Add(new UserSubscribe(notificationName, userId)); + userSubscribes.Add(new UserSubscribe(notificationName, identifier.UserId, identifier.UserName)); } await UserSubscribeRepository.InsertUserSubscriptionAsync(userSubscribes); diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs index 5c5f03c4c..08ad897e2 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/UserSubscribe.cs @@ -6,10 +6,12 @@ namespace LINGYUN.Abp.MessageService.Subscriptions public class UserSubscribe : Subscribe, IHasCreationTime { public virtual Guid UserId { get; set; } + public virtual string UserName { get; set; } protected UserSubscribe() { } - public UserSubscribe(string notificationName, Guid userId) : base(notificationName) + public UserSubscribe(string notificationName, Guid userId, string userName) : base(notificationName) { UserId = userId; + UserName = userName; } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs index 71e42ab07..d93b8a5fd 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs @@ -49,6 +49,10 @@ namespace LINGYUN.Abp.MessageService.EntityFrameworkCore b.ToTable(options.TablePrefix + "UserSubscribes", options.Schema); b.Property(p => p.NotificationName).HasMaxLength(SubscribeConsts.MaxNotificationNameLength).IsRequired(); + b.Property(p => p.UserName) + .HasMaxLength(SubscribeConsts.MaxUserNameLength) + .HasDefaultValue("/")// 不是必须的 + .IsRequired(); b.ConfigureCreationTime(); b.ConfigureMultiTenant(); diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs index 1b1b1e653..e5a674b4c 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs @@ -29,7 +29,9 @@ namespace LINGYUN.Abp.MessageService.Messages var groupAdmins = await (from gp in DbContext.Set() join gpa in DbContext.Set() on gp.GroupId equals gpa.GroupId - select gpa).ToListAsync(); + select gpa) + .Distinct() + .ToListAsync(); return groupAdmins; } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs index 6508e1a83..f0e1b29d7 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs @@ -35,6 +35,7 @@ namespace LINGYUN.Abp.MessageService.Messages skipCount -= 1; } var groupMessages = await DbContext.Set() + .Distinct() .Where(x => x.GroupId.Equals(groupId) && x.Type.Equals(type)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) .OrderByDescending(x => x.MessageId) @@ -52,6 +53,7 @@ namespace LINGYUN.Abp.MessageService.Messages skipCount -= 1; } var groupMessages = await DbContext.Set() + .Distinct() .Where(x => x.GroupId.Equals(groupId) && x.CreatorId.Equals(sendUserId) && x.Type.Equals(type)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) .OrderByDescending(x => x.MessageId) @@ -77,6 +79,7 @@ namespace LINGYUN.Abp.MessageService.Messages skipCount -= 1; } var userMessages = await DbContext.Set() + .Distinct() .Where(x => x.CreatorId.Equals(sendUserId) && x.ReceiveUserId.Equals(receiveUserId) && x.Type.Equals(type)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) .OrderByDescending(x => x.MessageId) diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs index 95cfec605..de852f05c 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs @@ -38,6 +38,7 @@ namespace LINGYUN.Abp.MessageService.Messages TenantId = ug.TenantId, UserId = ug.UserId }) + .Distinct() .AsNoTracking() .ToListAsync(); return groupUsers; @@ -73,7 +74,9 @@ namespace LINGYUN.Abp.MessageService.Messages GroupUserCount = ug.Count(), MaxUserLength = ug.Key.MaxUserCount, Name = ug.Key.Name - }).ToListAsync(); + }) + .Distinct() + .ToListAsync(); return userGroups; } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs index 41d5a37b7..c743dee86 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Notifications/EfCoreUserNotificationRepository.cs @@ -51,8 +51,9 @@ namespace LINGYUN.Abp.MessageService.Notifications where un.UserId.Equals(userId) && un.ReadStatus.Equals(readState) orderby n.NotificationId descending select n) - .Take(maxResultCount) - .ToListAsync(); + .Distinct() + .Take(maxResultCount) + .ToListAsync(); return userNofitications; } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs index 898701772..66fe146e3 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Subscriptions/EfCoreUserSubscribeRepository.cs @@ -21,7 +21,10 @@ namespace LINGYUN.Abp.MessageService.Subscriptions public async Task> GetSubscribesAsync(string notificationName) { - var userSubscribes = await DbSet.Where(x => x.NotificationName.Equals(notificationName)).ToListAsync(); + var userSubscribes = await DbSet + .Distinct() + .Where(x => x.NotificationName.Equals(notificationName)) + .ToListAsync(); return userSubscribes; } @@ -38,6 +41,7 @@ namespace LINGYUN.Abp.MessageService.Subscriptions public async Task> GetUserSubscribesAsync(Guid userId) { var userSubscribeNames = await DbSet + .Distinct() .Where(x => x.UserId.Equals(userId)) .Select(x => x.NotificationName) .ToListAsync(); @@ -48,6 +52,7 @@ namespace LINGYUN.Abp.MessageService.Subscriptions public async Task> GetUserSubscribesAsync(string notificationName) { var subscribeUsers = await DbSet + .Distinct() .Where(x => x.NotificationName.Equals(notificationName)) .Select(x => x.UserId) .ToListAsync(); diff --git a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs index 2e9890ec2..b6736cfe2 100644 --- a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs +++ b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs @@ -40,6 +40,7 @@ namespace AuthServer.Host typeof(AbpCAPEventBusModule), typeof(AbpIdentityAspNetCoreModule), typeof(AbpIdentityServerSmsValidatorModule), + typeof(AbpIdentityServerWeChatValidatorModule), typeof(AbpEntityFrameworkCoreMySQLModule), typeof(AbpIdentityEntityFrameworkCoreModule), typeof(AbpIdentityServerEntityFrameworkCoreModule), @@ -149,6 +150,7 @@ namespace AuthServer.Host app.UseMultiTenancy(); app.UseIdentityServer(); app.UseAuditing(); + //app.UseWeChatSignature(); SeedData(context); } diff --git a/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj b/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj index 9259faeec..9c6ba8c5e 100644 --- a/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj +++ b/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj @@ -34,6 +34,7 @@ + diff --git a/aspnet-core/services/account/AuthServer.Host/Properties/launchSettings.json b/aspnet-core/services/account/AuthServer.Host/Properties/launchSettings.json index 581e8d94f..3e2911416 100644 --- a/aspnet-core/services/account/AuthServer.Host/Properties/launchSettings.json +++ b/aspnet-core/services/account/AuthServer.Host/Properties/launchSettings.json @@ -11,7 +11,7 @@ "AuthServer.Host": { "commandName": "Project", "launchBrowser": false, - "applicationUrl": "http://localhost:44385", + "applicationUrl": "https://localhost:44386;http://localhost:44385", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs index 200f1be92..ab30847b9 100644 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs @@ -1,7 +1,6 @@ using LINGYUN.Abp.Notifications; using Microsoft.AspNetCore.Mvc; using System; -using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc; @@ -21,20 +20,16 @@ namespace LINGYUN.Abp.MessageService.Controllers [Route("Send")] public async Task SendNofitication([FromForm] SendNotification notification) { - var notificationInfo = new NotificationInfo - { - TenantId = null, - NotificationSeverity = notification.Severity, - NotificationType = NotificationType.Application, - Name = "TestApplicationNotofication", - CreationTime = Clock.Now - }; - notificationInfo.Data.Properties["title"] = notification.Title; - notificationInfo.Data.Properties["message"] = notification.Message; - notificationInfo.Data.Properties["datetime"] = Clock.Now; - notificationInfo.Data.Properties["severity"] = notification.Severity; + var notificationData = new NotificationData(); + notificationData.Properties["title"] = notification.Title; + notificationData.Properties["message"] = notification.Message; + notificationData.Properties["datetime"] = Clock.Now; + notificationData.Properties["severity"] = notification.Severity; + + await _notificationDispatcher.DispatchAsync("TestApplicationNotofication", notificationData, + notificationSeverity: notification.Severity); - await _notificationDispatcher.DispatcheAsync(notificationInfo); + // await _notificationDispatcher.DispatcheAsync(notificationInfo); } } diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/Notifications/MessageServiceDefinitionProvider.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/Notifications/MessageServiceDefinitionProvider.cs new file mode 100644 index 000000000..2dcca0a0c --- /dev/null +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN/Abp/MessageService/Notifications/MessageServiceDefinitionProvider.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.MessageService.Localization; +using LINGYUN.Abp.Notifications; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.MessageService.LINGYUN.Abp.MessageService.Notifications +{ + public class MessageServiceDefinitionProvider : NotificationDefinitionProvider + { + public override void Define(INotificationDefinitionContext context) + { + context.Add(new NotificationDefinition( + "TestApplicationNotofication", + L("TestApplicationNotofication"), + L("TestApplicationNotofication"), + NotificationType.Application, + true)); + } + + protected LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200609151853_Create-User-Subscription-Column-UserName.Designer.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200609151853_Create-User-Subscription-Column-UserName.Designer.cs new file mode 100644 index 000000000..1c75e4d1d --- /dev/null +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200609151853_Create-User-Subscription-Column-UserName.Designer.cs @@ -0,0 +1,503 @@ +// +using System; +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MessageService.Migrations +{ + [DbContext(typeof(MessageServiceHostMigrationsDbContext))] + [Migration("20200609151853_Create-User-Subscription-Column-UserName")] + partial class CreateUserSubscriptionColumnUserName + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "3.1.4") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Address") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("AllowAnonymous") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendMessage") + .HasColumnType("tinyint(1)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime(6)"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("char(36)"); + + b.Property("MaxUserCount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(20) CHARACTER SET utf8mb4") + .HasMaxLength(20); + + b.Property("Notice") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("Tag") + .HasColumnType("varchar(512) CHARACTER SET utf8mb4") + .HasMaxLength(512); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AllowAddPeople") + .HasColumnType("tinyint(1)"); + + b.Property("AllowDissolveGroup") + .HasColumnType("tinyint(1)"); + + b.Property("AllowKickPeople") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendNotice") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSilence") + .HasColumnType("tinyint(1)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("IsSuperAdmin") + .HasColumnType("tinyint(1)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)"); + + b.Property("LastModifierId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppChatGroupAdmins"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("ShieldUserId") + .HasColumnType("char(36)"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("SendState") + .HasColumnType("tinyint"); + + b.Property("SendUserName") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupMessages"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("ShieldUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatBlacks"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AllowAddFriend") + .HasColumnType("tinyint(1)"); + + b.Property("AllowAnonymous") + .HasColumnType("tinyint(1)"); + + b.Property("AllowReceiveMessage") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendMessage") + .HasColumnType("tinyint(1)"); + + b.Property("RequireAddFriendValition") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatSettings"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("ReceiveUserId") + .HasColumnType("char(36)"); + + b.Property("SendState") + .HasColumnType("tinyint"); + + b.Property("SendUserName") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ReceiveUserId"); + + b.ToTable("AppUserMessages"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserSpecialFocus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("FocusUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserSpecialFocuss"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("ExpirationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationData") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("NotificationTypeName") + .IsRequired() + .HasColumnType("varchar(512) CHARACTER SET utf8mb4") + .HasMaxLength(512); + + b.Property("Severity") + .HasColumnType("tinyint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NotificationName"); + + b.ToTable("AppNotifications"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("ReadStatus") + .HasColumnType("int"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationId") + .HasName("IX_Tenant_User_Notification_Id"); + + b.ToTable("AppUserNotifications"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("UserName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128) + .HasDefaultValue("/"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationName") + .IsUnique() + .HasName("IX_Tenant_User_Notification_Name"); + + b.ToTable("AppUserSubscribes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200609151853_Create-User-Subscription-Column-UserName.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200609151853_Create-User-Subscription-Column-UserName.cs new file mode 100644 index 000000000..5c109d763 --- /dev/null +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200609151853_Create-User-Subscription-Column-UserName.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace LINGYUN.Abp.MessageService.Migrations +{ + public partial class CreateUserSubscriptionColumnUserName : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UserName", + table: "AppUserSubscribes", + maxLength: 128, + nullable: false, + defaultValue: "/"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UserName", + table: "AppUserSubscribes"); + } + } +} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs index 8704b41fc..cccaa5a84 100644 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs @@ -4,6 +4,7 @@ using LINGYUN.Abp.MessageService.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; namespace LINGYUN.Abp.MessageService.Migrations { @@ -14,7 +15,8 @@ namespace LINGYUN.Abp.MessageService.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.3") + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "3.1.4") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b => @@ -478,6 +480,13 @@ namespace LINGYUN.Abp.MessageService.Migrations b.Property("UserId") .HasColumnType("char(36)"); + b.Property("UserName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128) + .HasDefaultValue("/"); + b.HasKey("Id"); b.HasIndex("TenantId", "UserId", "NotificationName") diff --git a/vueJs/src/views/admin/users/components/UserCreateForm.vue b/vueJs/src/views/admin/users/components/UserCreateForm.vue index af0f148d0..3312553e8 100644 --- a/vueJs/src/views/admin/users/components/UserCreateForm.vue +++ b/vueJs/src/views/admin/users/components/UserCreateForm.vue @@ -141,11 +141,11 @@ export default class extends Vue { private createUserRules = { userName: [ { required: true, message: this.l('userProfile.pleaseInputUserName'), trigger: 'blur' }, - { min: 3, max: 20, message: this.l('global.charLengthRange', { min: 3, max: 20 }), trigger: 'blur' } + { min: 3, max: 128, message: this.l('global.charLengthRange', { min: 3, max: 128 }), trigger: 'blur' } ], name: [ { required: true, message: this.l('userProfile.pleaseInputName'), trigger: 'blur' }, - { min: 3, max: 50, message: this.l('global.charLengthRange', { min: 3, max: 50 }), trigger: 'blur' } + { min: 2, max: 256, message: this.l('global.charLengthRange', { min: 2, max: 256 }), trigger: 'blur' } ], email: [ { required: true, message: this.l('userProfile.pleaseInputEmail'), trigger: 'blur' },