committed by
GitHub
207 changed files with 7374 additions and 1119 deletions
@ -0,0 +1,31 @@ |
|||
<template> |
|||
<SettingForm :save-api="settingFormRef.saveApi" :setting-groups="group" tab-position="left" /> |
|||
</template> |
|||
<script lang="ts" setup> |
|||
import { ref, onMounted } from 'vue'; |
|||
import { useAbpStoreWithOut } from '/@/store/modules/abp'; |
|||
|
|||
import { SettingForm } from '/@/components/SettingManagement'; |
|||
import { SettingGroup } from '/@/api/settings/model/settingModel'; |
|||
import { getCurrentUserSettings, setCurrentUserSettings } from '/@/api/settings/settings'; |
|||
|
|||
interface ISettingForm { |
|||
providerName: string; |
|||
providerKey?: string; |
|||
saveApi: (...args: any) => Promise<any>; |
|||
} |
|||
|
|||
const abpStore = useAbpStoreWithOut(); |
|||
const group = ref<SettingGroup[]>([]); |
|||
const settingFormRef = ref<ISettingForm>({ |
|||
providerName: 'U', |
|||
providerKey: abpStore.getApplication.currentUser.id, |
|||
saveApi: setCurrentUserSettings, |
|||
}); |
|||
|
|||
onMounted(() => { |
|||
getCurrentUserSettings().then((res) => { |
|||
group.value = res.items; |
|||
}) |
|||
}); |
|||
</script> |
|||
@ -1,13 +1,8 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.Aliyun.SettingManagement |
|||
{ |
|||
public interface IAliyunSettingAppService |
|||
public interface IAliyunSettingAppService : IReadonlySettingAppService |
|||
{ |
|||
Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync(); |
|||
|
|||
Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync(); |
|||
} |
|||
} |
|||
|
|||
@ -1,74 +0,0 @@ |
|||
using DotNetCore.CAP.Persistence; |
|||
using LINGYUN.Abp.EventBus.CAP; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.BackgroundWorkers; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace DotNetCore.CAP.Processor |
|||
{ |
|||
/// <summary>
|
|||
/// 过期消息清理任务
|
|||
/// </summary>
|
|||
public class AbpCapExpiresMessageCleanupBackgroundWorker : AsyncPeriodicBackgroundWorkerBase |
|||
{ |
|||
/// <summary>
|
|||
/// 过期消息清理配置
|
|||
/// </summary>
|
|||
protected AbpCAPEventBusOptions Options { get; } |
|||
/// <summary>
|
|||
/// Initializer
|
|||
/// </summary>
|
|||
protected IStorageInitializer Initializer { get; } |
|||
/// <summary>
|
|||
/// Storage
|
|||
/// </summary>
|
|||
protected IDataStorage Storage{ get; } |
|||
/// <summary>
|
|||
/// 创建过期消息清理任务
|
|||
/// </summary>
|
|||
/// <param name="timer"></param>
|
|||
/// <param name="storage"></param>
|
|||
/// <param name="initializer"></param>
|
|||
/// <param name="options"></param>
|
|||
/// <param name="serviceScopeFactory"></param>
|
|||
public AbpCapExpiresMessageCleanupBackgroundWorker( |
|||
AbpAsyncTimer timer, |
|||
IDataStorage storage, |
|||
IStorageInitializer initializer, |
|||
IOptions<AbpCAPEventBusOptions> options, |
|||
IServiceScopeFactory serviceScopeFactory) |
|||
: base(timer, serviceScopeFactory) |
|||
{ |
|||
Storage = storage; |
|||
Options = options.Value; |
|||
Initializer = initializer; |
|||
|
|||
timer.Period = Options.CleanUpExpiresMessageInterval; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 异步执行任务
|
|||
/// </summary>
|
|||
/// <param name="workerContext"></param>
|
|||
/// <returns></returns>
|
|||
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) |
|||
{ |
|||
var tables = new[] |
|||
{ |
|||
Initializer.GetPublishedTableName(), |
|||
Initializer.GetReceivedTableName() |
|||
}; |
|||
|
|||
foreach (var table in tables) |
|||
{ |
|||
Logger.LogDebug($"Collecting expired data from table: {table}"); |
|||
var time = DateTime.Now; |
|||
await Storage.DeleteExpiresAsync(table, time, Options.CleanUpExpiresMessageBatch); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,119 +0,0 @@ |
|||
using DotNetCore.CAP.Internal; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace DotNetCore.CAP.Processor |
|||
{ |
|||
/// <summary>
|
|||
/// CapProcessingServer
|
|||
/// </summary>
|
|||
public class AbpCapProcessingServer : IProcessingServer |
|||
{ |
|||
private readonly CancellationTokenSource _cts; |
|||
private readonly ILogger _logger; |
|||
private readonly ILoggerFactory _loggerFactory; |
|||
private readonly IServiceProvider _provider; |
|||
|
|||
private Task _compositeTask; |
|||
private ProcessingContext _context; |
|||
private bool _disposed; |
|||
/// <summary>
|
|||
/// CapProcessingServer
|
|||
/// </summary>
|
|||
/// <param name="logger"></param>
|
|||
/// <param name="loggerFactory"></param>
|
|||
/// <param name="provider"></param>
|
|||
public AbpCapProcessingServer( |
|||
ILogger<AbpCapProcessingServer> logger, |
|||
ILoggerFactory loggerFactory, |
|||
IServiceProvider provider) |
|||
{ |
|||
_logger = logger; |
|||
_loggerFactory = loggerFactory; |
|||
_provider = provider; |
|||
_cts = new CancellationTokenSource(); |
|||
} |
|||
/// <summary>
|
|||
/// Start
|
|||
/// </summary>
|
|||
public void Start(CancellationToken stoppingToken) |
|||
{ |
|||
_logger.LogInformation("Starting the processing server."); |
|||
stoppingToken.Register(() => |
|||
{ |
|||
_cts.Cancel(); |
|||
}); |
|||
|
|||
_context = new ProcessingContext(_provider, _cts.Token); |
|||
|
|||
var processorTasks = GetProcessors() |
|||
.Select(InfiniteRetry) |
|||
.Select(p => p.ProcessAsync(_context)); |
|||
_compositeTask = Task.WhenAll(processorTasks); |
|||
} |
|||
/// <summary>
|
|||
/// Pulse
|
|||
/// </summary>
|
|||
public void Pulse() |
|||
{ |
|||
_logger.LogTrace("Pulsing the processor."); |
|||
} |
|||
/// <summary>
|
|||
/// Dispose
|
|||
/// </summary>
|
|||
public void Dispose() |
|||
{ |
|||
if (_disposed) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
_disposed = true; |
|||
|
|||
_logger.LogInformation("Shutting down the processing server..."); |
|||
_cts.Cancel(); |
|||
|
|||
_compositeTask?.Wait((int)TimeSpan.FromSeconds(10).TotalMilliseconds); |
|||
} |
|||
catch (AggregateException ex) |
|||
{ |
|||
var innerEx = ex.InnerExceptions[0]; |
|||
if (!(innerEx is OperationCanceledException)) |
|||
{ |
|||
_logger.LogWarning(innerEx, $"Expected an OperationCanceledException, but found '{innerEx.Message}'."); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogWarning(ex, "An exception was occured when disposing."); |
|||
} |
|||
finally |
|||
{ |
|||
_logger.LogInformation("### CAP shutdown!"); |
|||
} |
|||
} |
|||
|
|||
private IProcessor InfiniteRetry(IProcessor inner) |
|||
{ |
|||
return new InfiniteRetryProcessor(inner, _loggerFactory); |
|||
} |
|||
|
|||
private IProcessor[] GetProcessors() |
|||
{ |
|||
var returnedProcessors = new List<IProcessor> |
|||
{ |
|||
_provider.GetRequiredService<TransportCheckProcessor>(), |
|||
_provider.GetRequiredService<MessageNeedToRetryProcessor>(), |
|||
}; |
|||
|
|||
return returnedProcessors.ToArray(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,21 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<Description>Cap分布式事件总线</Description> |
|||
<GenerateDocumentationFile>true</GenerateDocumentationFile> |
|||
<DocumentationFile>$(SolutionDir)modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.xml</DocumentationFile> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<Description>Cap分布式事件总线</Description> |
|||
<GenerateDocumentationFile>true</GenerateDocumentationFile> |
|||
<DocumentationFile>$(SolutionDir)modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.xml</DocumentationFile> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="DotNetCore.CAP" Version="$(DotNetCoreCAPPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.BackgroundWorkers" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.EventBus" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Json" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="DotNetCore.CAP" Version="$(DotNetCoreCAPPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.EventBus" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Json" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
|
|||
@ -1,19 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.SignalR" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,12 +0,0 @@ |
|||
using Volo.Abp.AspNetCore.SignalR; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.RealTime.SignalR |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpRealTimeModule), |
|||
typeof(AbpAspNetCoreSignalRModule))] |
|||
public class AbpRealTimeSignalRModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -1,98 +0,0 @@ |
|||
using LINGYUN.Abp.RealTime.Client; |
|||
using Microsoft.Extensions.Logging; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.AspNetCore.SignalR; |
|||
using Volo.Abp.AspNetCore.WebClientInfo; |
|||
|
|||
namespace LINGYUN.Abp.RealTime.SignalR |
|||
{ |
|||
public abstract class OnlineClientHubBase : AbpHub, IClient |
|||
{ |
|||
protected IWebClientInfoProvider WebClientInfoProvider => LazyServiceProvider.LazyGetRequiredService<IWebClientInfoProvider>(); |
|||
protected IOnlineClientManager OnlineClientManager => LazyServiceProvider.LazyGetRequiredService<IOnlineClientManager>(); |
|||
|
|||
public override async Task OnConnectedAsync() |
|||
{ |
|||
await base.OnConnectedAsync(); |
|||
|
|||
IOnlineClient onlineClient = CreateClientForCurrentConnection(); |
|||
OnlineClientManager.Add(onlineClient); |
|||
|
|||
await OnConnectedAsync(onlineClient); |
|||
} |
|||
|
|||
public async Task OnConnectedAsync(IOnlineClient client) |
|||
{ |
|||
Logger.LogDebug("A client is connected: " + client.ToString()); |
|||
|
|||
// 角色添加进组
|
|||
foreach (var role in client.Roles) |
|||
{ |
|||
await Groups.AddToGroupAsync(client.ConnectionId, role); |
|||
} |
|||
|
|||
await OnClientConnectedAsync(client); |
|||
} |
|||
|
|||
public override async Task OnDisconnectedAsync(Exception exception) |
|||
{ |
|||
// 从通讯组移除
|
|||
var onlineClient = OnlineClientManager.GetByConnectionIdOrNull(Context.ConnectionId); |
|||
await OnDisconnectedAsync(onlineClient); |
|||
|
|||
await base.OnDisconnectedAsync(exception); |
|||
} |
|||
|
|||
public async Task OnDisconnectedAsync(IOnlineClient client) |
|||
{ |
|||
if (client != null) |
|||
{ |
|||
try |
|||
{ |
|||
// 角色添加进组
|
|||
foreach (var role in client.Roles) |
|||
{ |
|||
await Groups.RemoveFromGroupAsync(client.ConnectionId, role); |
|||
} |
|||
|
|||
Logger.LogDebug("A client is disconnected: " + client); |
|||
// 移除在线客户端
|
|||
OnlineClientManager.Remove(Context.ConnectionId); |
|||
|
|||
await OnClientDisconnectedAsync(client); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogWarning(ex.ToString(), ex); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected virtual IOnlineClient CreateClientForCurrentConnection() |
|||
{ |
|||
return new OnlineClient( |
|||
Context.ConnectionId, |
|||
WebClientInfoProvider.ClientIpAddress, |
|||
CurrentTenant.Id, |
|||
CurrentUser.Id) |
|||
{ |
|||
ConnectTime = Clock.Now, |
|||
UserName = CurrentUser.UserName, |
|||
UserAccount = CurrentUser.UserName, |
|||
Roles = CurrentUser.Roles ?? new string[0], |
|||
Properties = Context.Items |
|||
}; |
|||
} |
|||
|
|||
protected virtual Task OnClientConnectedAsync(IOnlineClient client) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual Task OnClientDisconnectedAsync(IOnlineClient client) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.BlobStoring" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.OssManagement.HttpApi.Client\LINGYUN.Abp.OssManagement.HttpApi.Client.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,12 @@ |
|||
using LINGYUN.Abp.OssManagement; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.OssManagement |
|||
{ |
|||
[DependsOn(typeof(AbpBlobStoringModule))] |
|||
[DependsOn(typeof(AbpOssManagementHttpApiClientModule))] |
|||
public class AbpBlobStoringOssManagementModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.OssManagement; |
|||
|
|||
public static class OssManagementBlobContainerConfigurationExtensions |
|||
{ |
|||
public static OssManagementBlobProviderConfiguration GetOssManagementConfiguration( |
|||
this BlobContainerConfiguration containerConfiguration) |
|||
{ |
|||
return new OssManagementBlobProviderConfiguration(containerConfiguration); |
|||
} |
|||
|
|||
public static BlobContainerConfiguration UseOssManagement( |
|||
this BlobContainerConfiguration containerConfiguration, |
|||
Action<OssManagementBlobProviderConfiguration> fileSystemConfigureAction) |
|||
{ |
|||
containerConfiguration.ProviderType = typeof(OssManagementBlobProvider); |
|||
containerConfiguration.NamingNormalizers.TryAdd<OssManagementBlobNamingNormalizer>(); |
|||
|
|||
fileSystemConfigureAction(new OssManagementBlobProviderConfiguration(containerConfiguration)); |
|||
|
|||
return containerConfiguration; |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using System; |
|||
using System.Text; |
|||
using System.Web; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.OssManagement |
|||
{ |
|||
public class OssManagementBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency |
|||
{ |
|||
public string NormalizeBlobName(string blobName) |
|||
{ |
|||
// 路径需要URL编码
|
|||
return HttpUtility.UrlEncode(blobName, Encoding.UTF8); |
|||
} |
|||
|
|||
public string NormalizeContainerName(string containerName) |
|||
{ |
|||
// 取消反斜杠开头
|
|||
return containerName.EnsureStartsWith('/'); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
using LINGYUN.Abp.OssManagement; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using System; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.Content; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.OssManagement |
|||
{ |
|||
public class OssManagementBlobProvider : BlobProviderBase, ITransientDependency |
|||
{ |
|||
public ILogger<OssManagementBlobProvider> Logger { protected get; set; } |
|||
|
|||
private readonly IOssObjectAppService _ossObjectAppService; |
|||
public OssManagementBlobProvider( |
|||
IOssObjectAppService ossObjectAppService) |
|||
{ |
|||
_ossObjectAppService = ossObjectAppService; |
|||
|
|||
Logger = NullLogger<OssManagementBlobProvider>.Instance; |
|||
} |
|||
|
|||
public override async Task<bool> DeleteAsync(BlobProviderDeleteArgs args) |
|||
{ |
|||
var configuration = args.Configuration.GetOssManagementConfiguration(); |
|||
await _ossObjectAppService.DeleteAsync(new GetOssObjectInput |
|||
{ |
|||
Bucket = configuration.Bucket, |
|||
Object = args.BlobName |
|||
}); |
|||
return true; |
|||
} |
|||
|
|||
public override async Task<bool> ExistsAsync(BlobProviderExistsArgs args) |
|||
{ |
|||
try |
|||
{ |
|||
var configuration = args.Configuration.GetOssManagementConfiguration(); |
|||
var oss = await _ossObjectAppService.GetAsync(new GetOssObjectInput |
|||
{ |
|||
Bucket = configuration.Bucket, |
|||
Object = args.BlobName |
|||
}); |
|||
return oss != null; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogWarning("An error occurred while getting the OSS object, always returning that the object does not exist"); |
|||
Logger.LogWarning(ex.Message); |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public override async Task<Stream> GetOrNullAsync(BlobProviderGetArgs args) |
|||
{ |
|||
try |
|||
{ |
|||
var configuration = args.Configuration.GetOssManagementConfiguration(); |
|||
var content = await _ossObjectAppService.GetContentAsync(new GetOssObjectInput |
|||
{ |
|||
Bucket = configuration.Bucket, |
|||
Object = args.BlobName |
|||
}); |
|||
|
|||
return content?.GetStream(); |
|||
} |
|||
catch(Exception ex) |
|||
{ |
|||
Logger.LogWarning("An error occurred while getting the OSS object and an empty data stream will be returned"); |
|||
Logger.LogWarning(ex.Message); |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public override async Task SaveAsync(BlobProviderSaveArgs args) |
|||
{ |
|||
var configuration = args.Configuration.GetOssManagementConfiguration(); |
|||
await _ossObjectAppService.CreateAsync(new CreateOssObjectInput |
|||
{ |
|||
Bucket = configuration.Bucket, |
|||
Overwrite = true, |
|||
FileName = args.BlobName, |
|||
File = new RemoteStreamContent(args.BlobStream) |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using Volo.Abp; |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.OssManagement |
|||
{ |
|||
public class OssManagementBlobProviderConfiguration |
|||
{ |
|||
public string Bucket |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(OssManagementBlobProviderConfigurationNames.Bucket); |
|||
set => _containerConfiguration.SetConfiguration(OssManagementBlobProviderConfigurationNames.Bucket, Check.NotNullOrWhiteSpace(value, nameof(value))); |
|||
} |
|||
|
|||
private readonly BlobContainerConfiguration _containerConfiguration; |
|||
|
|||
public OssManagementBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) |
|||
{ |
|||
_containerConfiguration = containerConfiguration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Abp.BlobStoring.OssManagement |
|||
{ |
|||
public class OssManagementBlobProviderConfigurationNames |
|||
{ |
|||
public const string Bucket = "OssManagement:Bucket"; |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
# LINGYUN.Abp.BlobStoring.OssManagement |
|||
|
|||
abp框架对象存储提供者**IBlobProvider**的Oss管理模块实现 |
|||
|
|||
## 配置使用 |
|||
|
|||
模块按需引用, 依赖于OssManagement模块, 所以需要配置远端Oss管理模块的客户端代理 |
|||
|
|||
事先定义**appsettings.json**文件 |
|||
|
|||
```json |
|||
{ |
|||
"OssManagement": { |
|||
"Bucket": "你定义的BucketName" |
|||
}, |
|||
"RemoteServices": { |
|||
"AbpOssManagement": { |
|||
"BaseUrl": "http://127.0.0.1:30025", |
|||
"IdentityClient": "InternalServiceClient", |
|||
"UseCurrentAccessToken": false |
|||
} |
|||
}, |
|||
"IdentityClients": { |
|||
"InternalServiceClient": { |
|||
"Authority": "http://127.0.0.1:44385", |
|||
"RequireHttps": false, |
|||
"GrantType": "client_credentials", |
|||
"Scope": "lingyun-abp-application", |
|||
"ClientId": "InternalServiceClient", |
|||
"ClientSecret": "1q2w3E*" |
|||
} |
|||
} |
|||
} |
|||
|
|||
``` |
|||
|
|||
```csharp |
|||
[DependsOn(typeof(AbpBlobStoringOssManagementModule))] |
|||
public class YouProjectModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
Configure<AbpBlobStoringOptions>(options => |
|||
{ |
|||
services.ExecutePreConfiguredActions(options); |
|||
// YouContainer use oss management |
|||
options.Containers.Configure<YouContainer>((containerConfiguration) => |
|||
{ |
|||
containerConfiguration.UseOssManagement(config => |
|||
{ |
|||
config.Bucket = configuration[OssManagementBlobProviderConfigurationNames.Bucket]; |
|||
}); |
|||
}); |
|||
|
|||
// all container use oss management |
|||
options.Containers.ConfigureAll((containerName, containerConfiguration) => |
|||
{ |
|||
// use oss management |
|||
containerConfiguration.UseOssManagement(config => |
|||
{ |
|||
config.Bucket = configuration[OssManagementBlobProviderConfigurationNames.Bucket]; |
|||
}); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
``` |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -1,162 +0,0 @@ |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using System.Net.Http; |
|||
using System.Net.Http.Headers; |
|||
using System.Reflection; |
|||
using System.Text; |
|||
using System.Text.Json; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.DynamicProxying; |
|||
using Volo.Abp.Http.Modeling; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Tracing; |
|||
|
|||
namespace LINGYUN.Abp.OssManagement |
|||
{ |
|||
public class LINGYUNApiDescriptionFinder : IApiDescriptionFinder, ITransientDependency |
|||
{ |
|||
public ICancellationTokenProvider CancellationTokenProvider { get; set; } |
|||
protected IApiDescriptionCache Cache { get; } |
|||
protected AbpCorrelationIdOptions AbpCorrelationIdOptions { get; } |
|||
protected ICorrelationIdProvider CorrelationIdProvider { get; } |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
|
|||
public LINGYUNApiDescriptionFinder( |
|||
IApiDescriptionCache cache, |
|||
IOptions<AbpCorrelationIdOptions> abpCorrelationIdOptions, |
|||
ICorrelationIdProvider correlationIdProvider, |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
Cache = cache; |
|||
AbpCorrelationIdOptions = abpCorrelationIdOptions.Value; |
|||
CorrelationIdProvider = correlationIdProvider; |
|||
CurrentTenant = currentTenant; |
|||
CancellationTokenProvider = NullCancellationTokenProvider.Instance; |
|||
} |
|||
|
|||
public async Task<ActionApiDescriptionModel> FindActionAsync(HttpClient client, string baseUrl, Type serviceType, MethodInfo method) |
|||
{ |
|||
var apiDescription = await GetApiDescriptionAsync(client, baseUrl); |
|||
|
|||
//TODO: Cache finding?
|
|||
|
|||
var methodParameters = method.GetParameters().ToArray(); |
|||
|
|||
foreach (var module in apiDescription.Modules.Values) |
|||
{ |
|||
foreach (var controller in module.Controllers.Values) |
|||
{ |
|||
if (!controller.Implements(serviceType)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var action in controller.Actions.Values) |
|||
{ |
|||
if (action.Name == method.Name && action.ParametersOnMethod.Count == methodParameters.Length) |
|||
{ |
|||
var found = true; |
|||
|
|||
for (int i = 0; i < methodParameters.Length; i++) |
|||
{ |
|||
if (!TypeMatches(action.ParametersOnMethod[i], methodParameters[i])) |
|||
{ |
|||
found = false; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (found) |
|||
{ |
|||
return action; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
throw new AbpException($"Could not found remote action for method: {method} on the URL: {baseUrl}"); |
|||
} |
|||
|
|||
public virtual async Task<ApplicationApiDescriptionModel> GetApiDescriptionAsync(HttpClient client, string baseUrl) |
|||
{ |
|||
return await Cache.GetAsync(baseUrl, () => GetApiDescriptionFromServerAsync(client, baseUrl)); |
|||
} |
|||
|
|||
protected virtual async Task<ApplicationApiDescriptionModel> GetApiDescriptionFromServerAsync( |
|||
HttpClient client, |
|||
string baseUrl) |
|||
{ |
|||
var requestMessage = new HttpRequestMessage( |
|||
HttpMethod.Get, |
|||
baseUrl.EnsureEndsWith('/') + "api/abp/api-definition" |
|||
); |
|||
|
|||
AddHeaders(requestMessage); |
|||
|
|||
var response = await client.SendAsync( |
|||
requestMessage, |
|||
CancellationTokenProvider.Token |
|||
); |
|||
|
|||
if (!response.IsSuccessStatusCode) |
|||
{ |
|||
throw new AbpException("Remote service returns error! StatusCode = " + response.StatusCode); |
|||
} |
|||
|
|||
var content = await response.Content.ReadAsStringAsync(); |
|||
|
|||
var result = JsonSerializer.Deserialize<ApplicationApiDescriptionModel>(content, new JsonSerializerOptions |
|||
{ |
|||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase |
|||
}); |
|||
|
|||
return (ApplicationApiDescriptionModel)result; |
|||
} |
|||
|
|||
protected virtual void AddHeaders(HttpRequestMessage requestMessage) |
|||
{ |
|||
//CorrelationId
|
|||
requestMessage.Headers.Add(AbpCorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get()); |
|||
|
|||
//TenantId
|
|||
if (CurrentTenant.Id.HasValue) |
|||
{ |
|||
//TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key
|
|||
requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); |
|||
} |
|||
|
|||
//Culture
|
|||
//TODO: Is that the way we want? Couldn't send the culture (not ui culture)
|
|||
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; |
|||
if (!currentCulture.IsNullOrEmpty()) |
|||
{ |
|||
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture)); |
|||
} |
|||
|
|||
//X-Requested-With
|
|||
requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest"); |
|||
} |
|||
|
|||
protected virtual bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter) |
|||
{ |
|||
return NormalizeTypeName(actionParameter.TypeAsString) == |
|||
NormalizeTypeName(methodParameter.ParameterType.GetFullNameWithAssemblyName()); |
|||
} |
|||
|
|||
protected virtual string NormalizeTypeName(string typeName) |
|||
{ |
|||
const string placeholder = "%COREFX%"; |
|||
const string netCoreLib = "System.Private.CoreLib"; |
|||
const string netFxLib = "mscorlib"; |
|||
|
|||
return typeName.Replace(netCoreLib, placeholder).Replace(netFxLib, placeholder); |
|||
} |
|||
} |
|||
} |
|||
@ -1,13 +1,8 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.OssManagement.SettingManagement |
|||
{ |
|||
public interface IOssManagementSettingAppService |
|||
public interface IOssManagementSettingAppService : IReadonlySettingAppService |
|||
{ |
|||
Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync(); |
|||
|
|||
Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync(); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,23 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace LINGYUN.Abp.SettingManagement |
|||
{ |
|||
public class SettingGroupResult |
|||
{ |
|||
public IList<SettingGroupDto> Items { get; } |
|||
|
|||
public SettingGroupResult() |
|||
{ |
|||
Items = new List<SettingGroupDto>(); |
|||
} |
|||
|
|||
public void AddGroup(SettingGroupDto group) |
|||
{ |
|||
if (group.Settings.Any(g => g.Details.Any())) |
|||
{ |
|||
Items.Add(group); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.SettingManagement |
|||
{ |
|||
public interface IReadonlySettingAppService : IApplicationService |
|||
{ |
|||
Task<SettingGroupResult> GetAllForGlobalAsync(); |
|||
|
|||
Task<SettingGroupResult> GetAllForCurrentTenantAsync(); |
|||
} |
|||
} |
|||
@ -1,17 +1,11 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.SettingManagement |
|||
{ |
|||
public interface ISettingAppService : IApplicationService |
|||
public interface ISettingAppService : IReadonlySettingAppService |
|||
{ |
|||
Task SetGlobalAsync(UpdateSettingsDto input); |
|||
|
|||
Task SetCurrentTenantAsync(UpdateSettingsDto input); |
|||
|
|||
Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync(); |
|||
|
|||
Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync(); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,12 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.SettingManagement |
|||
{ |
|||
public interface IUserSettingAppService : IApplicationService |
|||
{ |
|||
Task SetCurrentUserAsync(UpdateSettingsDto input); |
|||
|
|||
Task<SettingGroupResult> GetAllForCurrentUserAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,247 @@ |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.Extensions.Options; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Identity.Settings; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.SettingManagement.Localization; |
|||
using Volo.Abp.Settings; |
|||
using Volo.Abp.Timing; |
|||
using Volo.Abp.Users; |
|||
|
|||
namespace LINGYUN.Abp.SettingManagement |
|||
{ |
|||
[Authorize] |
|||
public class UserSettingAppService : ApplicationService, IUserSettingAppService |
|||
{ |
|||
protected AbpLocalizationOptions LocalizationOptions { get; } |
|||
|
|||
protected IDistributedEventBus EventBus { get; } |
|||
protected ISettingManager SettingManager { get; } |
|||
protected ISettingDefinitionManager SettingDefinitionManager { get; } |
|||
|
|||
protected IDistributedCache<SettingCacheItem> Cache { get; } |
|||
public UserSettingAppService( |
|||
IDistributedEventBus eventBus, |
|||
ISettingManager settingManager, |
|||
IDistributedCache<SettingCacheItem> cache, |
|||
IOptions<AbpLocalizationOptions> localizationOptions, |
|||
ISettingDefinitionManager settingDefinitionManager) |
|||
{ |
|||
Cache = cache; |
|||
EventBus = eventBus; |
|||
SettingManager = settingManager; |
|||
SettingDefinitionManager = settingDefinitionManager; |
|||
LocalizationOptions = localizationOptions.Value; |
|||
LocalizationResource = typeof(AbpSettingManagementResource); |
|||
} |
|||
|
|||
public virtual async Task SetCurrentUserAsync(UpdateSettingsDto input) |
|||
{ |
|||
// 增加特性检查
|
|||
await CheckFeatureAsync(); |
|||
|
|||
foreach (var setting in input.Settings) |
|||
{ |
|||
await SettingManager.SetForCurrentUserAsync(setting.Name, setting.Value); |
|||
} |
|||
|
|||
CurrentUnitOfWork.OnCompleted(async () => |
|||
{ |
|||
// 发送刷新用户缓存事件
|
|||
await EventBus.PublishAsync(new CurrentApplicationConfigurationCacheResetEventData()); |
|||
}); |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
} |
|||
|
|||
public virtual async Task<SettingGroupResult> GetAllForCurrentUserAsync() |
|||
{ |
|||
return await GetAllForProviderAsync(UserSettingValueProvider.ProviderName, CurrentUser.GetId().ToString()); |
|||
} |
|||
|
|||
protected virtual async Task<SettingGroupResult> GetAllForProviderAsync(string providerName, string providerKey) |
|||
{ |
|||
var settingGroups = new SettingGroupResult(); |
|||
|
|||
#region 系统设置
|
|||
|
|||
var sysSettingGroup = new SettingGroupDto(L["DisplayName:System"], L["Description:System"]); |
|||
// 语言
|
|||
var languageSetting = sysSettingGroup.AddSetting(L["DisplayName:System.Language"], L["Description:System.Language"]); |
|||
languageSetting.AddDetail( |
|||
SettingDefinitionManager.Get(LocalizationSettingNames.DefaultLanguage), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage, providerName, providerKey), |
|||
ValueType.Option, |
|||
providerName) |
|||
?.AddOptions(LocalizationOptions.Languages.Select(l => new OptionDto(l.DisplayName, l.CultureName))); |
|||
// 时区
|
|||
var timingSetting = sysSettingGroup.AddSetting(L["DisplayName:System.Timing"], L["Description:System.Timing"]); |
|||
timingSetting.AddDetail( |
|||
SettingDefinitionManager.Get(TimingSettingNames.TimeZone), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(TimingSettingNames.TimeZone, providerName, providerKey), |
|||
ValueType.String, |
|||
providerName); |
|||
settingGroups.AddGroup(sysSettingGroup); |
|||
|
|||
#endregion
|
|||
|
|||
#region 身份标识设置
|
|||
|
|||
// 身份标识设置
|
|||
var identitySetting = new SettingGroupDto(L["DisplayName:Identity"], L["Description:Identity"]); |
|||
|
|||
|
|||
#region 登录
|
|||
|
|||
var signinSetting = identitySetting.AddSetting(L["DisplayName:Identity.SignIn"], L["Description:Identity.SignIn"]); |
|||
signinSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.SignIn.EnablePhoneNumberConfirmation), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.SignIn.EnablePhoneNumberConfirmation, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
signinSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.SignIn.RequireConfirmedEmail), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
signinSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
|
|||
#endregion
|
|||
|
|||
#region 密码
|
|||
|
|||
var passwordSetting = identitySetting.AddSetting(L["DisplayName:Identity.Password"], L["Description:Identity.Password"]); |
|||
passwordSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.Password.RequireDigit), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.Password.RequireDigit, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
passwordSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.Password.RequiredLength), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.Password.RequiredLength, providerName, providerKey), |
|||
ValueType.Number, |
|||
providerName); |
|||
passwordSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.Password.RequiredUniqueChars), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.Password.RequiredUniqueChars, providerName, providerKey), |
|||
ValueType.Number, |
|||
providerName); |
|||
passwordSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.Password.RequireLowercase), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.Password.RequireLowercase, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
passwordSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.Password.RequireUppercase), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.Password.RequireUppercase, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
passwordSetting.AddDetail( |
|||
SettingDefinitionManager.Get(IdentitySettingNames.Password.RequireNonAlphanumeric), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(IdentitySettingNames.Password.RequireNonAlphanumeric, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
|
|||
#endregion
|
|||
|
|||
settingGroups.AddGroup(identitySetting); |
|||
|
|||
#endregion
|
|||
|
|||
#region 邮件设置
|
|||
|
|||
var emailSettingGroup = new SettingGroupDto(L["DisplayName:Emailing"], L["Description:Emailing"]); |
|||
var defaultMailSetting = emailSettingGroup.AddSetting(L["DisplayName:Emailing.Default"], L["Description:Emailing.Default"]); |
|||
defaultMailSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.DefaultFromAddress), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.DefaultFromAddress, providerName, providerKey), |
|||
ValueType.String, |
|||
providerName); |
|||
defaultMailSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.DefaultFromDisplayName), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.DefaultFromDisplayName, providerName, providerKey), |
|||
ValueType.String, |
|||
providerName); |
|||
|
|||
var smtpSetting = emailSettingGroup.AddSetting(L["DisplayName:Emailing.Smtp"], L["Description:Emailing.Smtp"]); |
|||
smtpSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.Smtp.EnableSsl), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.Smtp.EnableSsl, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
smtpSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.Smtp.UseDefaultCredentials), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.Smtp.UseDefaultCredentials, providerName, providerKey), |
|||
ValueType.Boolean, |
|||
providerName); |
|||
smtpSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.Smtp.Domain), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.Smtp.Domain, providerName, providerKey), |
|||
ValueType.String, |
|||
providerName); |
|||
smtpSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.Smtp.Host), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.Smtp.Host, providerName, providerKey), |
|||
ValueType.String, |
|||
providerName); |
|||
smtpSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.Smtp.Port), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.Smtp.Port, providerName, providerKey), |
|||
ValueType.Number, |
|||
providerName); |
|||
smtpSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.Smtp.UserName), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.Smtp.UserName, providerName, providerKey), |
|||
ValueType.String, |
|||
providerName); |
|||
smtpSetting.AddDetail( |
|||
SettingDefinitionManager.Get(EmailSettingNames.Smtp.Password), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(EmailSettingNames.Smtp.Password, providerName, providerKey), |
|||
ValueType.String, |
|||
providerName); |
|||
|
|||
settingGroups.AddGroup(emailSettingGroup); |
|||
|
|||
#endregion
|
|||
|
|||
return settingGroups; |
|||
} |
|||
|
|||
protected virtual async Task CheckFeatureAsync() |
|||
{ |
|||
await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.Enable); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace LINGYUN.Abp.SettingManagement |
|||
{ |
|||
[RemoteService(Name = AbpSettingManagementRemoteServiceConsts.RemoteServiceName)] |
|||
[Area("settingManagement")] |
|||
[Route("api/setting-management/settings")] |
|||
public class UserSettingController : AbpController, IUserSettingAppService |
|||
{ |
|||
private readonly IUserSettingAppService _service; |
|||
|
|||
public UserSettingController( |
|||
IUserSettingAppService service) |
|||
{ |
|||
_service = service; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-current-user")] |
|||
public virtual async Task<SettingGroupResult> GetAllForCurrentUserAsync() |
|||
{ |
|||
return await _service.GetAllForCurrentUserAsync(); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("change-current-user")] |
|||
public virtual async Task SetCurrentUserAsync(UpdateSettingsDto input) |
|||
{ |
|||
await _service.SetCurrentUserAsync(input); |
|||
} |
|||
} |
|||
} |
|||
@ -1,13 +1,8 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.SettingManagement |
|||
{ |
|||
public interface IWeChatSettingAppService |
|||
public interface IWeChatSettingAppService : IReadonlySettingAppService |
|||
{ |
|||
Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync(); |
|||
|
|||
Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync(); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,10 @@ |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.Components |
|||
{ |
|||
[BlobContainerName(Name)] |
|||
public class WorkflowContainer |
|||
{ |
|||
public const string Name = "workflow"; |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using System.Linq; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore |
|||
{ |
|||
public static class EfCoreRepositoryExtensions |
|||
{ |
|||
public static IQueryable<PersistedWorkflow> IncludeIf( |
|||
this IQueryable<PersistedWorkflow> quertable, |
|||
bool includeDetails = true) |
|||
{ |
|||
return !includeDetails ? quertable : |
|||
quertable |
|||
.Include(x => x.ExecutionPointers) |
|||
.ThenInclude(p => p.ExtensionAttributes); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using WorkflowCore.Interface; |
|||
using WorkflowCore.Models; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.Persistence |
|||
{ |
|||
public class AbpWorkflowPurger : IWorkflowPurger |
|||
{ |
|||
private readonly IWorkflowRepository _workflowRepository; |
|||
|
|||
public AbpWorkflowPurger( |
|||
IWorkflowRepository workflowRepository) |
|||
{ |
|||
_workflowRepository = workflowRepository; |
|||
} |
|||
|
|||
public virtual async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan) |
|||
{ |
|||
var olderThanUtc = olderThan.ToUniversalTime(); |
|||
|
|||
var workflows = await _workflowRepository |
|||
.GetOlderListAsync(status, olderThanUtc, includeDetails: true); |
|||
|
|||
await _workflowRepository.DeleteManyAsync(workflows); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Uow; |
|||
using WorkflowCore.Interface; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore |
|||
{ |
|||
/// <summary>
|
|||
/// 当触发新的工作流时,如果持久层在事务中会导致默认队列获取工作流实例失败
|
|||
/// 建立一个事务适配队列在工作单元结束时再将消息入队
|
|||
/// </summary>
|
|||
public class AbpUnitOfWorkQueueProvider : IQueueProvider |
|||
{ |
|||
private readonly IUnitOfWorkManager _unitOfWorkManager; |
|||
private readonly IQueueAdapterProvider _queueProvider; |
|||
|
|||
public AbpUnitOfWorkQueueProvider( |
|||
IQueueAdapterProvider queueProvider, |
|||
IUnitOfWorkManager unitOfWorkManager) |
|||
{ |
|||
_queueProvider = queueProvider; |
|||
_unitOfWorkManager = unitOfWorkManager; |
|||
} |
|||
|
|||
public bool IsDequeueBlocking => _queueProvider.IsDequeueBlocking; |
|||
|
|||
public virtual async Task<string> DequeueWork(QueueType queue, CancellationToken cancellationToken) |
|||
{ |
|||
if (_unitOfWorkManager.Current != null && !_unitOfWorkManager.Current.IsCompleted) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return await _queueProvider.DequeueWork(queue, cancellationToken); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_queueProvider.Dispose(); |
|||
} |
|||
|
|||
public async Task QueueWork(string id, QueueType queue) |
|||
{ |
|||
if (_unitOfWorkManager.Current != null) |
|||
{ |
|||
_unitOfWorkManager.Current.OnCompleted(async () => |
|||
{ |
|||
await _queueProvider.QueueWork(id, queue); |
|||
}); |
|||
} |
|||
else |
|||
{ |
|||
await _queueProvider.QueueWork(id, queue); |
|||
} |
|||
} |
|||
|
|||
public async Task Start() |
|||
{ |
|||
await _queueProvider.Start(); |
|||
} |
|||
|
|||
public async Task Stop() |
|||
{ |
|||
await _queueProvider.Stop(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using Microsoft.Extensions.Logging; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.ExceptionHandling; |
|||
using WorkflowCore.Interface; |
|||
using WorkflowCore.Models; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.ExceptionHandling |
|||
{ |
|||
/// <summary>
|
|||
/// 不会自动注册到容器
|
|||
/// 需要时手动注册
|
|||
/// </summary>
|
|||
public class ExceptionNotifierHandler : IWorkflowErrorHandler |
|||
{ |
|||
public WorkflowErrorHandling Type => WorkflowErrorHandling.Terminate; |
|||
|
|||
private readonly IExceptionNotifier _exceptionNotifier; |
|||
|
|||
public ExceptionNotifierHandler(IExceptionNotifier exceptionNotifier) |
|||
{ |
|||
_exceptionNotifier = exceptionNotifier; |
|||
} |
|||
|
|||
public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception, Queue<ExecutionPointer> bubbleUpQueue) |
|||
{ |
|||
_ = _exceptionNotifier.NotifyAsync( |
|||
new ExceptionNotificationContext( |
|||
exception, |
|||
LogLevel.Warning)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using WorkflowCore.Interface; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore |
|||
{ |
|||
public interface IQueueAdapterProvider : IDisposable |
|||
{ |
|||
bool IsDequeueBlocking { get; } |
|||
|
|||
Task QueueWork(string id, QueueType queue); |
|||
|
|||
Task<string> DequeueWork(QueueType queue, CancellationToken cancellationToken); |
|||
|
|||
Task Start(); |
|||
|
|||
Task Stop(); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
namespace LINGYUN.Abp.WorkflowCore |
|||
{ |
|||
/// <summary>
|
|||
/// 实现接口用于启动多租户
|
|||
/// </summary>
|
|||
public interface IStepMultiTenant |
|||
{ |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue