Browse Source

Merge branch 'dev' into maliming/patch-docs

pull/2542/head
maliming 7 years ago
parent
commit
d3ac57ab47
  1. 4
      docs/en/Modules/Docs.md
  2. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs
  3. 5
      framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs
  4. 6
      framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IBackgroundJobExecuter.cs
  5. 3
      framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs
  6. 3
      framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs
  7. 93
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
  8. 55
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs
  9. 14
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/BackgroundWorkerContext.cs
  10. 22
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs
  11. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs
  12. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
  13. 3
      framework/test/SimpleConsoleDemo/Program.cs
  14. 4
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs
  15. 20
      framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_Tests.cs
  16. 7
      framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/UnitOfWork_Events_Tests.cs
  17. 7
      modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs
  18. 30
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs
  19. 1
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj
  20. 36
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs
  21. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs
  22. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Devices/DeviceFlowCodes.cs
  23. 143
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Devices/DeviceFlowStore.cs
  24. 27
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Devices/IDeviceFlowCodesRepository.cs
  25. 6
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/IPersistentGrantRepository.cs
  26. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs
  27. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerBuilderExtensions.cs
  28. 34
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs
  29. 34
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupOptions.cs
  30. 88
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupService.cs
  31. 51
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesRepository.cs
  32. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/AbpIdentityServerEntityFrameworkCoreModule.cs
  33. 3
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IIdentityServerDbContext.cs
  34. 4
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs
  35. 19
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs
  36. 30
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs
  37. 3
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContext.cs
  38. 6
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContextExtensions.cs
  39. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbModule.cs
  40. 3
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IAbpIdentityServerMongoDbContext.cs
  41. 51
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs
  42. 14
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs
  43. 95
      modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Devices/DeviceFlowStore_Tests.cs
  44. 37
      modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Tokens/TokenCleanupService_Tests.cs
  45. 52
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs
  46. 15
      npm/ng-packs/packages/account/src/lib/models/account.ts
  47. 1
      npm/ng-packs/scripts/package.json
  48. 3
      npm/ng-packs/scripts/tsconfig.json
  49. 5
      npm/ng-packs/scripts/yarn.lock

4
docs/en/Modules/Docs.md

@ -501,6 +501,10 @@ You can also use variables in a text, adding **_Value** postfix to its key:
This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider.
````
Also, **Document_Language_Code** and **Document_Version** keys are pre-defined if you want to get the language code or the version of the current document (This may be useful for creating links that redirects to another documentation system in another domain).
------
**IMPORTANT NOTICE**: Scriban uses "{{" and "}}" for syntax. Therefore, you must use escape blocks if you are going to use those in your document (an Angular document, for example). See [Scriban docs](<https://github.com/lunet-io/scriban/blob/master/doc/language.md#13-escape-block> ) for more information.
### 8- Creating the Navigation Document

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs

@ -7,7 +7,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
{
public class AbpTabLinkTagHelperService : AbpTagHelperService<AbpTabLinkTagHelper>
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
SetPlaceholderForNameIfNotProvided();
@ -18,6 +18,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
tabHeaderItems.Add(new TabItem(tabHeader, "", false, TagHelper.Name, TagHelper.ParentDropdownName, false));
output.SuppressOutput();
return Task.CompletedTask;
}
protected virtual string GetTabHeaderItem(TagHelperContext context, TagHelperOutput output)

5
framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs

@ -4,7 +4,6 @@ using Microsoft.Extensions.Options;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundJobs
{
@ -21,7 +20,7 @@ namespace Volo.Abp.BackgroundJobs
Logger = NullLogger<BackgroundJobExecuter>.Instance;
}
public virtual void Execute(JobExecutionContext context)
public virtual async Task ExecuteAsync(JobExecutionContext context)
{
var job = context.ServiceProvider.GetService(context.JobType);
if (job == null)
@ -41,7 +40,7 @@ namespace Volo.Abp.BackgroundJobs
{
if (jobExecuteMethod.Name == nameof(IAsyncBackgroundJob<object>.ExecuteAsync))
{
AsyncHelper.RunSync(() => (Task) jobExecuteMethod.Invoke(job, new[] {context.JobArgs}));
await ((Task) jobExecuteMethod.Invoke(job, new[] {context.JobArgs})).ConfigureAwait(false);
}
else
{

6
framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IBackgroundJobExecuter.cs

@ -1,7 +1,9 @@
namespace Volo.Abp.BackgroundJobs
using System.Threading.Tasks;
namespace Volo.Abp.BackgroundJobs
{
public interface IBackgroundJobExecuter
{
void Execute(JobExecutionContext context);
Task ExecuteAsync(JobExecutionContext context);
}
}

3
framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs

@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundJobs.Hangfire
{
@ -25,7 +26,7 @@ namespace Volo.Abp.BackgroundJobs.Hangfire
{
var jobType = Options.GetJob(typeof(TArgs)).JobType;
var context = new JobExecutionContext(scope.ServiceProvider, jobType, args);
JobExecuter.Execute(context);
AsyncHelper.RunSync(() => JobExecuter.ExecuteAsync(context));
}
}
}

3
framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs

@ -10,6 +10,7 @@ using Nito.AsyncEx;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using Volo.Abp.RabbitMQ;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundJobs.RabbitMQ
{
@ -181,7 +182,7 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
try
{
JobExecuter.Execute(context);
AsyncHelper.RunSync(() => JobExecuter.ExecuteAsync(context));
ChannelAccessor.Channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
}
catch (BackgroundJobExecutionException)

93
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs

@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -9,92 +10,88 @@ using Volo.Abp.Timing;
namespace Volo.Abp.BackgroundJobs
{
public class BackgroundJobWorker : PeriodicBackgroundWorkerBase, IBackgroundJobWorker
public class BackgroundJobWorker : AsyncPeriodicBackgroundWorkerBase, IBackgroundJobWorker
{
protected AbpBackgroundJobOptions JobOptions { get; }
protected AbpBackgroundJobWorkerOptions WorkerOptions { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; }
public BackgroundJobWorker(
AbpTimer timer,
IOptions<AbpBackgroundJobOptions> jobOptions,
IOptions<AbpBackgroundJobWorkerOptions> workerOptions,
IServiceScopeFactory serviceScopeFactory)
: base(timer)
: base(
timer,
serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
WorkerOptions = workerOptions.Value;
JobOptions = jobOptions.Value;
Timer.Period = WorkerOptions.JobPollPeriod;
}
protected override void DoWork()
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var store = scope.ServiceProvider.GetRequiredService<IBackgroundJobStore>();
var store = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobStore>();
var waitingJobs = AsyncHelper.RunSync(() => store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount));
var waitingJobs = await store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount).ConfigureAwait(false);
if (!waitingJobs.Any())
{
return;
}
if (!waitingJobs.Any())
{
return;
}
var jobExecuter = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobExecuter>();
var clock = workerContext.ServiceProvider.GetRequiredService<IClock>();
var serializer = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobSerializer>();
var jobExecuter = scope.ServiceProvider.GetRequiredService<IBackgroundJobExecuter>();
var clock = scope.ServiceProvider.GetRequiredService<IClock>();
var serializer = scope.ServiceProvider.GetRequiredService<IBackgroundJobSerializer>();
foreach (var jobInfo in waitingJobs)
{
jobInfo.TryCount++;
jobInfo.LastTryTime = clock.Now;
foreach (var jobInfo in waitingJobs)
try
{
jobInfo.TryCount++;
jobInfo.LastTryTime = clock.Now;
var jobConfiguration = JobOptions.GetJob(jobInfo.JobName);
var jobArgs = serializer.Deserialize(jobInfo.JobArgs, jobConfiguration.ArgsType);
var context = new JobExecutionContext(workerContext.ServiceProvider, jobConfiguration.JobType, jobArgs);
try
{
var jobConfiguration = JobOptions.GetJob(jobInfo.JobName);
var jobArgs = serializer.Deserialize(jobInfo.JobArgs, jobConfiguration.ArgsType);
var context = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType, jobArgs);
await jobExecuter.ExecuteAsync(context).ConfigureAwait(false);
try
{
jobExecuter.Execute(context);
await store.DeleteAsync(jobInfo.Id).ConfigureAwait(false);
}
catch (BackgroundJobExecutionException)
{
var nextTryTime = CalculateNextTryTime(jobInfo, clock);
AsyncHelper.RunSync(() => store.DeleteAsync(jobInfo.Id));
if (nextTryTime.HasValue)
{
jobInfo.NextTryTime = nextTryTime.Value;
}
catch (BackgroundJobExecutionException)
else
{
var nextTryTime = CalculateNextTryTime(jobInfo, clock);
if (nextTryTime.HasValue)
{
jobInfo.NextTryTime = nextTryTime.Value;
}
else
{
jobInfo.IsAbandoned = true;
}
TryUpdate(store, jobInfo);
jobInfo.IsAbandoned = true;
}
await TryUpdateAsync(store, jobInfo).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.LogException(ex);
jobInfo.IsAbandoned = true;
TryUpdate(store, jobInfo);
}
}
catch (Exception ex)
{
Logger.LogException(ex);
jobInfo.IsAbandoned = true;
await TryUpdateAsync(store, jobInfo).ConfigureAwait(false);
}
}
}
protected virtual void TryUpdate(IBackgroundJobStore store, BackgroundJobInfo jobInfo)
protected virtual async Task TryUpdateAsync(IBackgroundJobStore store, BackgroundJobInfo jobInfo)
{
try
{
AsyncHelper.RunSync(() => store.UpdateAsync(jobInfo));
await store.UpdateAsync(jobInfo).ConfigureAwait(false);
}
catch (Exception updateEx)
{

55
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs

@ -0,0 +1,55 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundWorkers
{
public abstract class AsyncPeriodicBackgroundWorkerBase : BackgroundWorkerBase
{
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected AbpTimer Timer { get; }
protected AsyncPeriodicBackgroundWorkerBase(
AbpTimer timer,
IServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
Timer = timer;
Timer.Elapsed += Timer_Elapsed;
}
public override async Task StartAsync(CancellationToken cancellationToken = default)
{
await base.StartAsync(cancellationToken).ConfigureAwait(false);
Timer.Start(cancellationToken);
}
public override async Task StopAsync(CancellationToken cancellationToken = default)
{
Timer.Stop(cancellationToken);
await base.StopAsync(cancellationToken).ConfigureAwait(false);
}
private void Timer_Elapsed(object sender, System.EventArgs e)
{
try
{
using (var scope = ServiceScopeFactory.CreateScope())
{
AsyncHelper.RunSync(
() => DoWorkAsync(new PeriodicBackgroundWorkerContext(scope.ServiceProvider))
);
}
}
catch (Exception ex)
{
Logger.LogException(ex);
}
}
protected abstract Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext);
}
}

14
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/BackgroundWorkerContext.cs

@ -0,0 +1,14 @@
using System;
namespace Volo.Abp.BackgroundWorkers
{
public class PeriodicBackgroundWorkerContext
{
public IServiceProvider ServiceProvider { get; }
public PeriodicBackgroundWorkerContext(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
}
}

22
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs

@ -1,6 +1,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.Threading;
@ -11,14 +12,14 @@ namespace Volo.Abp.BackgroundWorkers
/// </summary>
public abstract class PeriodicBackgroundWorkerBase : BackgroundWorkerBase
{
protected readonly AbpTimer Timer;
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected AbpTimer Timer { get; }
/// <summary>
/// Initializes a new instance of the <see cref="PeriodicBackgroundWorkerBase"/> class.
/// </summary>
/// <param name="timer">A timer.</param>
protected PeriodicBackgroundWorkerBase(AbpTimer timer)
protected PeriodicBackgroundWorkerBase(
AbpTimer timer,
IServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
Timer = timer;
Timer.Elapsed += Timer_Elapsed;
}
@ -34,12 +35,15 @@ namespace Volo.Abp.BackgroundWorkers
Timer.Stop(cancellationToken);
await base.StopAsync(cancellationToken).ConfigureAwait(false);
}
private void Timer_Elapsed(object sender, System.EventArgs e)
{
try
{
DoWork();
using (var scope = ServiceScopeFactory.CreateScope())
{
DoWork(new PeriodicBackgroundWorkerContext(scope.ServiceProvider));
}
}
catch (Exception ex)
{
@ -50,6 +54,6 @@ namespace Volo.Abp.BackgroundWorkers
/// <summary>
/// Periodic works should be done by implementing this method.
/// </summary>
protected abstract void DoWork();
protected abstract void DoWork(PeriodicBackgroundWorkerContext workerContext);
}
}

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs

@ -24,12 +24,12 @@ namespace Volo.Abp.Cli.Commands
AbpCliOptions = cliOptions.Value;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
public Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
if (string.IsNullOrWhiteSpace(commandLineArgs.Target))
{
Logger.LogInformation(GetUsageInfo());
return;
return Task.CompletedTask;
}
var commandType = AbpCliOptions.Commands[commandLineArgs.Target];
@ -39,6 +39,8 @@ namespace Volo.Abp.Cli.Commands
var command = (IConsoleCommand) scope.ServiceProvider.GetRequiredService(commandType);
Logger.LogInformation(command.GetUsageInfo());
}
return Task.CompletedTask;
}
public string GetUsageInfo()

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs

@ -48,7 +48,7 @@ namespace Volo.Abp.Cli.ProjectModification
.ConfigureAwait(false)).ConfigureAwait(false);
}
public async Task AddAsync(string projectFile, NugetPackageInfo package)
public Task AddAsync(string projectFile, NugetPackageInfo package)
{
using (DirectoryHelper.ChangeCurrentDirectory(Path.GetDirectoryName(projectFile)))
{
@ -71,6 +71,8 @@ namespace Volo.Abp.Cli.ProjectModification
Logger.LogInformation("Successfully installed.");
}
return Task.CompletedTask;
}
protected virtual async Task<NugetPackageInfo> FindNugetPackageInfoAsync(string moduleName)

3
framework/test/SimpleConsoleDemo/Program.cs

@ -10,7 +10,7 @@ namespace SimpleConsoleDemo
{
class Program
{
static async Task Main(string[] args)
static void Main(string[] args)
{
using (var application = AbpApplicationFactory.Create<MyConsoleModule>(options =>
{
@ -42,7 +42,6 @@ namespace SimpleConsoleDemo
writer.Write();
}
Console.WriteLine();
Console.WriteLine("Press ENTER to exit!");
Console.ReadLine();

4
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs

@ -23,7 +23,7 @@ namespace Volo.Abp.BackgroundJobs
//Act
_backgroundJobExecuter.Execute(
await _backgroundJobExecuter.ExecuteAsync(
new JobExecutionContext(
ServiceProvider,
typeof(MyJob),
@ -46,7 +46,7 @@ namespace Volo.Abp.BackgroundJobs
//Act
_backgroundJobExecuter.Execute(
await _backgroundJobExecuter.ExecuteAsync(
new JobExecutionContext(
ServiceProvider,
typeof(MyAsyncJob),

20
framework/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_Tests.cs

@ -38,7 +38,7 @@ namespace Volo.Abp.Caching
}
[Fact]
public async Task GetOrAddAsync()
public void GetOrAdd()
{
var personCache = GetRequiredService<IDistributedCache<PersonCacheItem>>();
@ -49,12 +49,12 @@ namespace Volo.Abp.Caching
bool factoryExecuted = false;
var cacheItem = await personCache.GetOrAddAsync(cacheKey,
async () =>
var cacheItem = personCache.GetOrAdd(cacheKey,
() =>
{
factoryExecuted = true;
return new PersonCacheItem(personName);
}).ConfigureAwait(false);
});
factoryExecuted.ShouldBeTrue();
cacheItem.Name.ShouldBe(personName);
@ -63,12 +63,12 @@ namespace Volo.Abp.Caching
factoryExecuted = false;
cacheItem = await personCache.GetOrAddAsync(cacheKey,
async () =>
cacheItem = personCache.GetOrAdd(cacheKey,
() =>
{
factoryExecuted = true;
return new PersonCacheItem(personName);
}).ConfigureAwait(false);
});
factoryExecuted.ShouldBeFalse();
cacheItem.Name.ShouldBe(personName);
@ -165,12 +165,12 @@ namespace Volo.Abp.Caching
bool factoryExecuted = false;
var cacheItem = await personCache.GetOrAddAsync(cacheKey,
async () =>
var cacheItem = personCache.GetOrAdd(cacheKey,
() =>
{
factoryExecuted = true;
return new PersonCacheItem(personName);
}).ConfigureAwait(false);
});
factoryExecuted.ShouldBeTrue();
cacheItem.Name.ShouldBe(personName);

7
framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/UnitOfWork_Events_Tests.cs

@ -24,7 +24,12 @@ namespace Volo.Abp.Uow
using (var uow = _unitOfWorkManager.Begin())
{
uow.OnCompleted(async () => completed = true);
uow.OnCompleted(() =>
{
completed = true;
return Task.CompletedTask;
});
uow.Disposed += (sender, args) => disposed = true;
await uow.CompleteAsync().ConfigureAwait(false);

7
modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs

@ -23,7 +23,7 @@ namespace Volo.Docs.Documents
IDocumentStoreFactory documentStoreFactory,
IDistributedCache<DocumentWithDetailsDto> documentCache,
IDistributedCache<LanguageConfig> languageCache,
IDistributedCache<DocumentResourceDto> resourceCache,
IDistributedCache<DocumentResourceDto> resourceCache,
IHostEnvironment hostEnvironment)
{
_projectRepository = projectRepository;
@ -107,6 +107,11 @@ namespace Volo.Docs.Documents
try
{
if (string.IsNullOrWhiteSpace(project.ParametersDocumentName))
{
return await Task.FromResult<DocumentParametersDto>(null);
}
var document = await GetDocumentWithDetailsDtoAsync(
project,
project.ParametersDocumentName,

30
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs

@ -91,7 +91,7 @@ namespace Volo.Docs.Pages.Documents.Project
try
{
await SetProjectAsync();
await SetProjectAsync();
}
catch (EntityNotFoundException e)
{
@ -391,9 +391,12 @@ namespace Volo.Docs.Pages.Documents.Project
private async Task ConvertDocumentContentToHtmlAsync()
{
await SetDocumentPreferences();
await SetDocumentPreferencesAsync();
SetUserPreferences();
UserPreferences.Add("Document_Language_Code", LanguageCode);
UserPreferences.Add("Document_Version", Version);
Document.Content = await _documentSectionRenderer.RenderAsync(Document.Content, UserPreferences);
var converter = _documentToHtmlConverterFactory.Create(Document.Format ?? Project.Format);
@ -431,27 +434,30 @@ namespace Volo.Docs.Pages.Documents.Project
{
continue;
}
var key = keyValue.Split("=")[0];
var value = keyValue.Split("=")[1];
UserPreferences.Add(key, value);
UserPreferences.Add(key + "_Value", DocumentPreferences.Parameters?.FirstOrDefault(p=>p.Name == key)
?.Values.FirstOrDefault(v=>v.Key == value).Value);
UserPreferences.Add(key + "_Value", DocumentPreferences.Parameters?.FirstOrDefault(p => p.Name == key)
?.Values.FirstOrDefault(v => v.Key == value).Value);
}
}
var query = Request.Query;
foreach (var keyValue in query)
foreach (var (key, value) in query)
{
if (UserPreferences.ContainsKey(keyValue.Key))
if (UserPreferences.ContainsKey(key))
{
UserPreferences.Remove(keyValue.Key);
UserPreferences.Remove(keyValue.Key + "_Value");
UserPreferences.Remove(key);
UserPreferences.Remove(key + "_Value");
}
UserPreferences.Add(keyValue.Key, keyValue.Value);
UserPreferences.Add(keyValue.Key + "_Value", DocumentPreferences.Parameters?.FirstOrDefault(p => p.Name == keyValue.Key)
?.Values.FirstOrDefault(v => v.Key == keyValue.Value).Value);
UserPreferences.Add(key, value);
UserPreferences.Add(key + "_Value",
DocumentPreferences.Parameters?.FirstOrDefault(p => p.Name == key)?.Values
.FirstOrDefault(v => v.Key == value).Value);
}
if (DocumentPreferences?.Parameters == null)
@ -469,7 +475,7 @@ namespace Volo.Docs.Pages.Documents.Project
}
}
public async Task SetDocumentPreferences()
public async Task SetDocumentPreferencesAsync()
{
var projectParameters = await _documentAppService.GetParametersAsync(
new GetParametersDocumentInput

1
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj

@ -20,6 +20,7 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.BackgroundWorkers\Volo.Abp.BackgroundWorkers.csproj" />
</ItemGroup>
<ItemGroup>

36
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs

@ -1,11 +1,13 @@
using System.Security.Cryptography.X509Certificates;
using IdentityServer4.Services;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Volo.Abp.AutoMapper;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Caching;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Tokens;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
using Volo.Abp.Validation;
@ -18,7 +20,8 @@ namespace Volo.Abp.IdentityServer
typeof(AbpIdentityDomainModule),
typeof(AbpSecurityModule),
typeof(AbpCachingModule),
typeof(AbpValidationModule)
typeof(AbpValidationModule),
typeof(AbpBackgroundWorkersModule)
)]
public class AbpIdentityServerDomainModule : AbpModule
{
@ -28,12 +31,12 @@ namespace Volo.Abp.IdentityServer
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<ClientAutoMapperProfile>(validate: true);
options.AddProfile<IdentityServerAutoMapperProfile>(validate: true);
});
AddIdentityServer(context.Services);
}
private static void AddIdentityServer(IServiceCollection services)
{
var configuration = services.GetConfiguration();
@ -58,7 +61,12 @@ namespace Volo.Abp.IdentityServer
if (!services.IsAdded<IPersistedGrantService>())
{
identityServerBuilder.AddInMemoryPersistedGrants();
services.TryAddSingleton<IPersistedGrantStore, InMemoryPersistedGrantStore>();
}
if (!services.IsAdded<IDeviceFlowStore>())
{
services.TryAddSingleton<IDeviceFlowStore, InMemoryDeviceFlowStore>();
}
if (!services.IsAdded<IClientStore>())
@ -72,5 +80,19 @@ namespace Volo.Abp.IdentityServer
identityServerBuilder.AddInMemoryIdentityResources(configuration.GetSection("IdentityServer:IdentityResources"));
}
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var options = context.ServiceProvider.GetRequiredService<IOptions<TokenCleanupOptions>>().Value;
if (options.IsCleanupEnabled)
{
context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.Add(
context.ServiceProvider
.GetRequiredService<TokenCleanupBackgroundWorker>()
);
}
}
}
}

2
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs

@ -108,10 +108,10 @@ namespace Volo.Abp.IdentityServer.Clients
}
public Client(Guid id, [NotNull] string clientId)
: base(id)
{
Check.NotNull(clientId, nameof(clientId));
Id = id;
ClientId = clientId;
//TODO: Replace magics with constants?

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Devices/DeviceFlowCodes.cs

@ -0,0 +1,31 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace Volo.Abp.IdentityServer.Devices
{
public class DeviceFlowCodes : CreationAuditedAggregateRoot<Guid>
{
public virtual string DeviceCode { get; set; }
public virtual string UserCode { get; set; }
public virtual string SubjectId { get; set; }
public virtual string ClientId { get; set; }
public virtual DateTime? Expiration { get; set; }
public virtual string Data { get; set; }
private DeviceFlowCodes()
{
}
public DeviceFlowCodes(Guid id)
: base(id)
{
}
}
}

143
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Devices/DeviceFlowStore.cs

@ -0,0 +1,143 @@
using System;
using System.Threading.Tasks;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using IdentityServer4.Stores.Serialization;
using JetBrains.Annotations;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
namespace Volo.Abp.IdentityServer.Devices
{
public class DeviceFlowStore : IDeviceFlowStore, ITransientDependency
{
protected IDeviceFlowCodesRepository DeviceFlowCodesRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
protected IPersistentGrantSerializer PersistentGrantSerializer { get; }
public DeviceFlowStore(
IDeviceFlowCodesRepository deviceFlowCodesRepository,
IGuidGenerator guidGenerator,
IPersistentGrantSerializer persistentGrantSerializer)
{
DeviceFlowCodesRepository = deviceFlowCodesRepository;
GuidGenerator = guidGenerator;
PersistentGrantSerializer = persistentGrantSerializer;
}
public async Task StoreDeviceAuthorizationAsync(string deviceCode, string userCode, DeviceCode data)
{
Check.NotNull(deviceCode, nameof(deviceCode));
Check.NotNull(userCode, nameof(userCode));
Check.NotNull(data, nameof(data));
await DeviceFlowCodesRepository
.InsertAsync(
new DeviceFlowCodes(GuidGenerator.Create())
{
DeviceCode = deviceCode,
UserCode = userCode,
ClientId = data.ClientId,
SubjectId = data.Subject?.FindFirst(JwtClaimTypes.Subject).Value,
CreationTime = data.CreationTime,
Expiration = data.CreationTime.AddSeconds(data.Lifetime),
Data = Serialize(data)
}
).ConfigureAwait(false);
}
public async Task<DeviceCode> FindByUserCodeAsync(string userCode)
{
Check.NotNull(userCode, nameof(userCode));
var deviceCodes = await DeviceFlowCodesRepository
.FindByUserCodeAsync(userCode)
.ConfigureAwait(false);
if (deviceCodes == null)
{
return null;
}
return DeserializeToDeviceCode(deviceCodes.Data);
}
public async Task<DeviceCode> FindByDeviceCodeAsync(string deviceCode)
{
Check.NotNull(deviceCode, nameof(deviceCode));
var deviceCodes = await DeviceFlowCodesRepository
.FindByDeviceCodeAsync(deviceCode)
.ConfigureAwait(false);
if (deviceCodes == null)
{
return null;
}
return DeserializeToDeviceCode(deviceCodes.Data);
}
public async Task UpdateByUserCodeAsync(string userCode, DeviceCode data)
{
Check.NotNull(userCode, nameof(userCode));
Check.NotNull(data, nameof(data));
var deviceCodes = await DeviceFlowCodesRepository
.FindByUserCodeAsync(userCode)
.ConfigureAwait(false);
if (deviceCodes == null)
{
throw new InvalidOperationException($"Could not update device code by the given userCode: {userCode}");
}
deviceCodes.SubjectId = data.Subject?.FindFirst(JwtClaimTypes.Subject).Value;
deviceCodes.Data = Serialize(data);
await DeviceFlowCodesRepository
.UpdateAsync(deviceCodes, autoSave: true)
.ConfigureAwait(false);
}
public async Task RemoveByDeviceCodeAsync(string deviceCode)
{
Check.NotNull(deviceCode, nameof(deviceCode));
var deviceCodes = await DeviceFlowCodesRepository
.FindByDeviceCodeAsync(deviceCode)
.ConfigureAwait(false);
if (deviceCodes == null)
{
return;
}
await DeviceFlowCodesRepository
.DeleteAsync(deviceCodes, autoSave: true)
.ConfigureAwait(false);
}
private string Serialize([CanBeNull] DeviceCode deviceCode)
{
if (deviceCode == null)
{
return null;
}
return PersistentGrantSerializer.Serialize(deviceCode);
}
protected virtual DeviceCode DeserializeToDeviceCode([CanBeNull] string data)
{
if (data == null)
{
return null;
}
return PersistentGrantSerializer.Deserialize<DeviceCode>(data);
}
}
}

27
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Devices/IDeviceFlowCodesRepository.cs

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.Devices
{
public interface IDeviceFlowCodesRepository : IBasicRepository<DeviceFlowCodes, Guid>
{
Task<DeviceFlowCodes> FindByUserCodeAsync(
string userCode,
CancellationToken cancellationToken = default
);
Task<DeviceFlowCodes> FindByDeviceCodeAsync(
string deviceCode,
CancellationToken cancellationToken = default
);
Task<List<DeviceFlowCodes>> GetListByExpirationAsync(
DateTime maxExpirationDate,
int maxResultCount,
CancellationToken cancellationToken = default
);
}
}

6
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/IPersistentGrantRepository.cs

@ -18,6 +18,12 @@ namespace Volo.Abp.IdentityServer.Grants
CancellationToken cancellationToken = default
);
Task<List<PersistedGrant>> GetListByExpirationAsync(
DateTime maxExpirationDate,
int maxResultCount,
CancellationToken cancellationToken = default
);
Task DeleteAsync(
string subjectId,
string clientId,

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientAutoMapperProfile.cs → modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs

@ -2,14 +2,15 @@
using System.Security.Claims;
using AutoMapper;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.Clients
namespace Volo.Abp.IdentityServer
{
public class ClientAutoMapperProfile : Profile
public class IdentityServerAutoMapperProfile : Profile
{
public ClientAutoMapperProfile()
public IdentityServerAutoMapperProfile()
{
//TODO: Reverse maps will not used probably. Remove those will not used

2
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerBuilderExtensions.cs

@ -1,6 +1,7 @@
using IdentityServer4.Stores;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
namespace Volo.Abp.IdentityServer
@ -10,6 +11,7 @@ namespace Volo.Abp.IdentityServer
public static IIdentityServerBuilder AddAbpStores(this IIdentityServerBuilder builder)
{
builder.Services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
builder.Services.AddTransient<IDeviceFlowStore, DeviceFlowStore>();
return builder
.AddClientStore<ClientStore>()

34
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs

@ -0,0 +1,34 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Threading;
namespace Volo.Abp.IdentityServer.Tokens
{
public class TokenCleanupBackgroundWorker : AsyncPeriodicBackgroundWorkerBase
{
protected TokenCleanupOptions Options { get; }
public TokenCleanupBackgroundWorker(
AbpTimer timer,
IServiceScopeFactory serviceScopeFactory,
IOptions<TokenCleanupOptions> options)
: base(
timer,
serviceScopeFactory)
{
Options = options.Value;
timer.Period = Options.CleanupPeriod;
}
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
await workerContext
.ServiceProvider
.GetRequiredService<TokenCleanupService>()
.CleanAsync()
.ConfigureAwait(false);
}
}
}

34
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupOptions.cs

@ -0,0 +1,34 @@
using Volo.Abp.BackgroundWorkers;
namespace Volo.Abp.IdentityServer.Tokens
{
public class TokenCleanupOptions
{
/// <summary>
/// Default: 3,600,000 ms.
/// </summary>
public int CleanupPeriod { get; set; } = 3_600_000;
/// <summary>
/// Default value: 100.
/// </summary>
public int CleanupBatchSize { get; set; } = 100;
/// <summary>
/// The number of loop if there are
/// more than <see cref="CleanupBatchSize"/> tokens in the database.
/// So, if <see cref="CleanupLoopCount"/> is 10 and <see cref="CleanupBatchSize"/> is 100,
/// then the cleanup worker will clean 1,000 items in one <see cref="CleanupPeriod"/> at max.
///
/// Default value: 10.
/// </summary>
public int CleanupLoopCount { get; set; } = 10;
/// <summary>
/// Default value: true.
/// If <see cref="AbpBackgroundWorkerOptions.IsEnabled"/> is false,
/// this property is ignored and the cleanup worker doesn't work for this application instance.
/// </summary>
public bool IsCleanupEnabled { get; set; } = true;
}
}

88
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupService.cs

@ -0,0 +1,88 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.Timing;
using Volo.Abp.Uow;
namespace Volo.Abp.IdentityServer.Tokens
{
public class TokenCleanupService : ITransientDependency
{
protected IPersistentGrantRepository PersistentGrantRepository { get; }
protected IDeviceFlowCodesRepository DeviceFlowCodesRepository { get; }
protected IClock Clock { get; }
protected TokenCleanupOptions Options { get; }
public TokenCleanupService(
IPersistentGrantRepository persistentGrantRepository,
IDeviceFlowCodesRepository deviceFlowCodesRepository,
IClock clock,
IOptions<TokenCleanupOptions> options)
{
PersistentGrantRepository = persistentGrantRepository;
DeviceFlowCodesRepository = deviceFlowCodesRepository;
Clock = clock;
Options = options.Value;
}
public virtual async Task CleanAsync()
{
await RemoveGrantsAsync()
.ConfigureAwait(false);
await RemoveDeviceCodesAsync()
.ConfigureAwait(false);
}
[UnitOfWork]
protected virtual async Task RemoveGrantsAsync()
{
for (int i = 0; i < Options.CleanupLoopCount; i++)
{
var persistentGrants = await PersistentGrantRepository
.GetListByExpirationAsync(Clock.Now, Options.CleanupBatchSize)
.ConfigureAwait(false);
//TODO: Can be optimized if the repository implements the batch deletion
foreach (var persistentGrant in persistentGrants)
{
await PersistentGrantRepository
.DeleteAsync(persistentGrant)
.ConfigureAwait(false);
}
//No need to continue to query if it gets more than max items.
if (persistentGrants.Count < Options.CleanupBatchSize)
{
break;
}
}
}
protected virtual async Task RemoveDeviceCodesAsync()
{
for (int i = 0; i < Options.CleanupLoopCount; i++)
{
var deviceFlowCodeses = await DeviceFlowCodesRepository
.GetListByExpirationAsync(Clock.Now, Options.CleanupBatchSize)
.ConfigureAwait(false);
//TODO: Can be optimized if the repository implements the batch deletion
foreach (var deviceFlowCodes in deviceFlowCodeses)
{
await DeviceFlowCodesRepository
.DeleteAsync(deviceFlowCodes)
.ConfigureAwait(false);
}
//No need to continue to query if it gets more than max items.
if (deviceFlowCodeses.Count < Options.CleanupBatchSize)
{
break;
}
}
}
}
}

51
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Devices/DeviceFlowCodesRepository.cs

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
namespace Volo.Abp.IdentityServer.Devices
{
public class DeviceFlowCodesRepository : EfCoreRepository<IIdentityServerDbContext, DeviceFlowCodes, Guid>,
IDeviceFlowCodesRepository
{
public DeviceFlowCodesRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<DeviceFlowCodes> FindByUserCodeAsync(
string userCode,
CancellationToken cancellationToken = default)
{
return await DbSet
.FirstOrDefaultAsync(d => d.UserCode == userCode, GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task<DeviceFlowCodes> FindByDeviceCodeAsync(
string deviceCode,
CancellationToken cancellationToken = default)
{
return await DbSet
.FirstOrDefaultAsync(d => d.DeviceCode == deviceCode, GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task<List<DeviceFlowCodes>> GetListByExpirationAsync(DateTime maxExpirationDate, int maxResultCount,
CancellationToken cancellationToken = default)
{
return await DbSet
.Where(x => x.Expiration != null && x.Expiration < maxExpirationDate)
.OrderBy(x => x.ClientId)
.Take(maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
}
}

2
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/AbpIdentityServerEntityFrameworkCoreModule.cs

@ -2,6 +2,7 @@
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.Modularity;
@ -34,6 +35,7 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
options.AddRepository<ApiResource, ApiResourceRepository>();
options.AddRepository<IdentityResource, IdentityResourceRepository>();
options.AddRepository<PersistedGrant, PersistentGrantRepository>();
options.AddRepository<DeviceFlowCodes, DeviceFlowCodesRepository>();
});
}
}

3
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IIdentityServerDbContext.cs

@ -3,6 +3,7 @@ using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
@ -46,5 +47,7 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
DbSet<ClientProperty> ClientProperties { get; set; }
DbSet<PersistedGrant> PersistedGrants { get; set; }
DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
}
}

4
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs

@ -3,6 +3,7 @@ using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
@ -47,6 +48,8 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
public DbSet<PersistedGrant> PersistedGrants { get; set; }
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
public IdentityServerDbContext(DbContextOptions<IdentityServerDbContext> options)
: base(options)
{
@ -56,6 +59,7 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureIdentityServer();
}
}

19
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs

@ -6,6 +6,7 @@ using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
@ -289,6 +290,24 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
apiScopeClaim.Property(x => x.Type).HasMaxLength(UserClaimConsts.TypeMaxLength).IsRequired();
apiScopeClaim.Property(x => x.Name).HasMaxLength(ApiScopeConsts.NameMaxLength).IsRequired();
});
builder.Entity<DeviceFlowCodes>(b =>
{
b.ToTable(options.TablePrefix + "DeviceFlowCodes", options.Schema);
b.ConfigureByConvention();
b.Property(x => x.DeviceCode).HasMaxLength(200).IsRequired();
b.Property(x => x.UserCode).HasMaxLength(200).IsRequired();
b.Property(x => x.SubjectId).HasMaxLength(200);
b.Property(x => x.ClientId).HasMaxLength(200).IsRequired();
b.Property(x => x.Expiration).IsRequired();
b.Property(x => x.Data).HasMaxLength(50000).IsRequired();
b.HasIndex(x => new { x.UserCode }).IsUnique();
b.HasIndex(x => x.DeviceCode).IsUnique();
b.HasIndex(x => x.Expiration);
});
}
}
}

30
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs

@ -12,26 +12,42 @@ namespace Volo.Abp.IdentityServer.Grants
{
public class PersistentGrantRepository : EfCoreRepository<IIdentityServerDbContext, PersistedGrant, Guid>, IPersistentGrantRepository
{
public PersistentGrantRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider) : base(dbContextProvider)
public PersistentGrantRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public Task<PersistedGrant> FindByKeyAsync(
public async Task<PersistedGrant> FindByKeyAsync(
string key,
CancellationToken cancellationToken = default)
{
return DbSet
.FirstOrDefaultAsync(x => x.Key == key, GetCancellationToken(cancellationToken));
return await DbSet
.FirstOrDefaultAsync(x => x.Key == key, GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public Task<List<PersistedGrant>> GetListBySubjectIdAsync(
public async Task<List<PersistedGrant>> GetListBySubjectIdAsync(
string subjectId,
CancellationToken cancellationToken = default)
{
return DbSet
return await DbSet
.Where(x => x.SubjectId == subjectId)
.ToListAsync(GetCancellationToken(cancellationToken));
.ToListAsync(GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task<List<PersistedGrant>> GetListByExpirationAsync(
DateTime maxExpirationDate,
int maxResultCount,
CancellationToken cancellationToken = default)
{
return await DbSet
.Where(x => x.Expiration != null && x.Expiration < maxExpirationDate)
.OrderBy(x => x.ClientId)
.Take(maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task DeleteAsync(

3
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContext.cs

@ -2,6 +2,7 @@
using Volo.Abp.Data;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.MongoDB;
using IdentityResource = Volo.Abp.IdentityServer.IdentityResources.IdentityResource;
@ -19,6 +20,8 @@ namespace Volo.Abp.IdentityServer.MongoDB
public IMongoCollection<PersistedGrant> PersistedGrants => Collection<PersistedGrant>();
public IMongoCollection<DeviceFlowCodes> DeviceFlowCodes => Collection<DeviceFlowCodes>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);

6
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContextExtensions.cs

@ -1,6 +1,7 @@
using System;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.MongoDB;
@ -39,6 +40,11 @@ namespace Volo.Abp.IdentityServer.MongoDB
{
b.CollectionName = options.CollectionPrefix + "PersistedGrants";
});
builder.Entity<DeviceFlowCodes>(b =>
{
b.CollectionName = options.CollectionPrefix + "DeviceFlowCodes";
});
}
}
}

2
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbModule.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.Modularity;
using Volo.Abp.MongoDB;
@ -32,6 +33,7 @@ namespace Volo.Abp.IdentityServer.MongoDB
options.AddRepository<IdentityResource, MongoIdentityResourceRepository>();
options.AddRepository<Client, MongoClientRepository>();
options.AddRepository<PersistedGrant, MongoPersistentGrantRepository>();
options.AddRepository<DeviceFlowCodes, MongoDeviceFlowCodesRepository>();
});
}
}

3
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IAbpIdentityServerMongoDbContext.cs

@ -1,6 +1,7 @@
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.MongoDB;
@ -18,5 +19,7 @@ namespace Volo.Abp.IdentityServer.MongoDB
IMongoCollection<IdentityResource> IdentityResources { get; }
IMongoCollection<PersistedGrant> PersistedGrants { get; }
IMongoCollection<DeviceFlowCodes> DeviceFlowCodes { get; }
}
}

51
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class MongoDeviceFlowCodesRepository :
MongoDbRepository<IAbpIdentityServerMongoDbContext, DeviceFlowCodes, Guid>, IDeviceFlowCodesRepository
{
public MongoDeviceFlowCodesRepository(
IMongoDbContextProvider<IAbpIdentityServerMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<DeviceFlowCodes> FindByUserCodeAsync(
string userCode,
CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.FirstOrDefaultAsync(d => d.UserCode == userCode, GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task<DeviceFlowCodes> FindByDeviceCodeAsync(string deviceCode, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.FirstOrDefaultAsync(d => d.DeviceCode == deviceCode, GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task<List<DeviceFlowCodes>> GetListByExpirationAsync(
DateTime maxExpirationDate,
int maxResultCount,
CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.Where(x => x.Expiration != null && x.Expiration < maxExpirationDate)
.OrderBy(x => x.ClientId)
.Take(maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
}
}

14
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs

@ -27,7 +27,19 @@ namespace Volo.Abp.IdentityServer.MongoDB
{
return await GetMongoQueryable()
.Where(x => x.SubjectId == subjectId)
.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false);
.ToListAsync(GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task<List<PersistedGrant>> GetListByExpirationAsync(DateTime maxExpirationDate, int maxResultCount,
CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.Where(x => x.Expiration != null && x.Expiration < maxExpirationDate)
.OrderBy(x => x.ClientId)
.Take(maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken))
.ConfigureAwait(false);
}
public async Task DeleteAsync(string subjectId, string clientId, CancellationToken cancellationToken = default)

95
modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Devices/DeviceFlowStore_Tests.cs

@ -0,0 +1,95 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Shouldly;
using Xunit;
namespace Volo.Abp.IdentityServer.Devices
{
public class DeviceFlowStore_Tests : AbpIdentityServerTestBase
{
private readonly IDeviceFlowStore _deviceFlowStore;
public DeviceFlowStore_Tests()
{
_deviceFlowStore = GetRequiredService<IDeviceFlowStore>();
}
[Fact]
public async Task StoreDeviceAuthorizationAsync()
{
await _deviceFlowStore.StoreDeviceAuthorizationAsync(
"DeviceCode-Test1",
"UserCode-Test1",
new DeviceCode
{
ClientId = "ClientId1",
AuthorizedScopes = new string[] { "s1", "s2" },
IsAuthorized = true,
Lifetime = 42,
RequestedScopes = new string[] { "rs1" },
Subject = new ClaimsPrincipal(
new[]
{
new ClaimsIdentity(new[]
{
new Claim(JwtClaimTypes.Subject, "sid1")
})
}
)
}
);
void Check(DeviceCode deviceCode)
{
deviceCode.ClientId.ShouldBe("ClientId1");
deviceCode.AuthorizedScopes.ShouldNotBeNull();
deviceCode.AuthorizedScopes.Count().ShouldBe(2);
deviceCode.AuthorizedScopes.ShouldContain("s1");
deviceCode.AuthorizedScopes.ShouldContain("s2");
deviceCode.IsAuthorized.ShouldBeTrue();
deviceCode.Lifetime.ShouldBe(42);
deviceCode.RequestedScopes.ShouldNotBeNull();
deviceCode.RequestedScopes.Count().ShouldBe(1);
deviceCode.RequestedScopes.ShouldContain("rs1");
deviceCode.Subject.ShouldNotBeNull();
deviceCode.Subject.Claims.ShouldContain(x => x.Type == JwtClaimTypes.Subject && x.Value == "sid1");
}
Check(await _deviceFlowStore.FindByUserCodeAsync("UserCode-Test1"));
Check(await _deviceFlowStore.FindByDeviceCodeAsync("DeviceCode-Test1"));
}
[Fact]
public async Task RemoveByDeviceCodeAsync()
{
(await _deviceFlowStore.FindByDeviceCodeAsync("DeviceCode1")).ShouldNotBeNull();
await _deviceFlowStore.RemoveByDeviceCodeAsync("DeviceCode1");
(await _deviceFlowStore.FindByDeviceCodeAsync("DeviceCode1")).ShouldBeNull();
}
[Fact]
public async Task UpdateByDeviceCodeAsync()
{
var deviceCode = await _deviceFlowStore.FindByDeviceCodeAsync("DeviceCode1");
deviceCode.ShouldNotBeNull();
deviceCode.Lifetime.ShouldBe(42);
await _deviceFlowStore.UpdateByUserCodeAsync(
"DeviceFlowCodesUserCode1",
new DeviceCode
{
Lifetime = 43
}
);
deviceCode = await _deviceFlowStore.FindByDeviceCodeAsync("DeviceCode1");
deviceCode.Lifetime.ShouldBe(43);
}
}
}

37
modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Tokens/TokenCleanupService_Tests.cs

@ -0,0 +1,37 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Xunit;
namespace Volo.Abp.IdentityServer.Tokens
{
public class TokenCleanupService_Tests : AbpIdentityServerTestBase
{
private readonly IPersistentGrantRepository _persistentGrantRepository;
private readonly IDeviceFlowCodesRepository _deviceFlowCodesRepository;
private readonly TokenCleanupService _tokenCleanupService;
public TokenCleanupService_Tests()
{
_persistentGrantRepository = GetRequiredService<IPersistentGrantRepository>();
_deviceFlowCodesRepository = GetRequiredService<IDeviceFlowCodesRepository>();
_tokenCleanupService = GetRequiredService<TokenCleanupService>();
}
[Fact]
public async Task Should_Clear_Expired_Tokens()
{
var persistentGrantCount = await _persistentGrantRepository.GetCountAsync();
var deviceFlowCodesCount = await _deviceFlowCodesRepository.GetCountAsync();
await _tokenCleanupService.CleanAsync();
(await _persistentGrantRepository.GetCountAsync())
.ShouldBe(persistentGrantCount - 1);
(await _deviceFlowCodesRepository.GetCountAsync())
.ShouldBe(deviceFlowCodesCount - 1);
}
}
}

52
modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs

@ -6,8 +6,10 @@ using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Devices;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.Timing;
namespace Volo.Abp.IdentityServer
{
@ -19,7 +21,9 @@ namespace Volo.Abp.IdentityServer
private readonly IIdentityResourceRepository _identityResourceRepository;
private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository;
private readonly IPersistentGrantRepository _persistentGrantRepository;
private readonly IDeviceFlowCodesRepository _deviceFlowCodesRepository;
private readonly AbpIdentityServerTestData _testData;
private readonly IClock _clock;
public AbpIdentityServerTestDataBuilder(
IGuidGenerator guidGenerator,
@ -28,7 +32,9 @@ namespace Volo.Abp.IdentityServer
IIdentityResourceRepository identityResourceRepository,
IIdentityClaimTypeRepository identityClaimTypeRepository,
AbpIdentityServerTestData testData,
IPersistentGrantRepository persistentGrantRepository)
IPersistentGrantRepository persistentGrantRepository,
IDeviceFlowCodesRepository deviceFlowCodesRepository,
IClock clock)
{
_testData = testData;
_guidGenerator = guidGenerator;
@ -37,10 +43,13 @@ namespace Volo.Abp.IdentityServer
_identityResourceRepository = identityResourceRepository;
_identityClaimTypeRepository = identityClaimTypeRepository;
_persistentGrantRepository = persistentGrantRepository;
_clock = clock;
_deviceFlowCodesRepository = deviceFlowCodesRepository;
}
public async Task BuildAsync()
{
await AddDeviceFlowCodes().ConfigureAwait(false);
await AddPersistedGrants().ConfigureAwait(false);
await AddIdentityResources().ConfigureAwait(false);
await AddApiResources().ConfigureAwait(false);
@ -48,6 +57,34 @@ namespace Volo.Abp.IdentityServer
await AddClaimTypes().ConfigureAwait(false);
}
private async Task AddDeviceFlowCodes()
{
await _deviceFlowCodesRepository.InsertAsync(
new DeviceFlowCodes(_guidGenerator.Create())
{
ClientId = "c1",
DeviceCode = "DeviceCode1",
Expiration = _clock.Now.AddDays(1),
Data = "{\"Lifetime\":\"42\"}",
UserCode = "DeviceFlowCodesUserCode1",
SubjectId = "DeviceFlowCodesSubjectId1"
}
);
await _deviceFlowCodesRepository.InsertAsync(
new DeviceFlowCodes(_guidGenerator.Create())
{
ClientId = "c1",
DeviceCode = "DeviceCode2",
Expiration = _clock.Now.AddDays(-1),
Data = "",
UserCode = "DeviceFlowCodesUserCode2",
SubjectId = "DeviceFlowCodesSubjectId2"
}
);
}
private async Task AddPersistedGrants()
{
await _persistentGrantRepository.InsertAsync(new PersistedGrant(_guidGenerator.Create())
@ -74,7 +111,18 @@ namespace Volo.Abp.IdentityServer
SubjectId = "PersistedGrantSubjectId3",
ClientId = "c1",
Type = "c1type",
Data = ""
Data = "",
Expiration = _clock.Now.AddDays(1),
}).ConfigureAwait(false);
await _persistentGrantRepository.InsertAsync(new PersistedGrant(_guidGenerator.Create())
{
Key = "PersistedGrantKey_Expired1",
SubjectId = "PersistedGrantSubjectId_Expired1",
ClientId = "c1",
Type = "c1type",
Data = "",
Expiration = _clock.Now.AddDays(-1)
}).ConfigureAwait(false);
}

15
npm/ng-packs/packages/account/src/lib/models/account.ts

@ -6,24 +6,13 @@ export namespace Account {
readonly cancelContentRef?: TemplateRef<any>;
}
// tslint:disable-next-line: no-empty-interface
//tslint:disable
export interface AuthWrapperComponentOutputs {}
// tslint:disable-next-line: no-empty-interface
export interface TenantBoxComponentInputs {}
// tslint:disable-next-line: no-empty-interface
export interface TenantBoxComponentOutputs {}
// tslint:disable-next-line: no-empty-interface
export interface PersonalSettingsComponentInputs {}
// tslint:disable-next-line: no-empty-interface
export interface PersonalSettingsComponentOutputs {}
// tslint:disable-next-line: no-empty-interface
export interface ChangePasswordComponentInputs {}
// tslint:disable-next-line: no-empty-interface
export interface ChangePasswordComponentOutputs {}
// tslint:enable
}

1
npm/ng-packs/scripts/package.json

@ -20,6 +20,7 @@
"typescript": "^3.7.4"
},
"devDependencies": {
"@types/node": "^13.1.2",
"esm": "^3.2.25",
"ts-node": "^8.5.4",
"tsconfig-paths": "^3.9.0"

3
npm/ng-packs/scripts/tsconfig.json

@ -10,7 +10,8 @@
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"esModuleInterop": true
"esModuleInterop": true,
"types": ["node"]
},
"exclude": ["node_modules", "dist"]
}

5
npm/ng-packs/scripts/yarn.lock

@ -7,6 +7,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/node@^13.1.2":
version "13.1.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.2.tgz#fe94285bf5e0782e1a9e5a8c482b1c34465fa385"
integrity sha512-B8emQA1qeKerqd1dmIsQYnXi+mmAzTB7flExjmy5X1aVAKFNNNDubkavwR13kR6JnpeLp3aLoJhwn9trWPAyFQ==
ansi-bgblack@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ansi-bgblack/-/ansi-bgblack-0.1.1.tgz#a68ba5007887701b6aafbe3fa0dadfdfa8ee3ca2"

Loading…
Cancel
Save