Browse Source

Merge branch 'master' of https://github.com/volosoft/abp

pull/454/head
Alper Ebicoglu 8 years ago
parent
commit
e5bb814b62
  1. 1
      build-all.ps1
  2. 2
      build-test-all.ps1
  3. 32
      docs/Dependency-Injection.md
  4. 22
      docs/Entities.md
  5. 40
      docs/Tutorials/AspNetCore-Mvc/Part-I.md
  6. 5
      modules/blogging/README.md
  7. 17
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs
  8. 14
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimValueType.cs
  9. 13
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIDentityClaimTypeRepository.cs
  10. 51
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdenityClaimTypeManager.cs
  11. 44
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs
  12. 24
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs
  13. 2
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs
  14. 2
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs
  15. 11
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs
  16. 5
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs
  17. 2
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs
  18. 5
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs
  19. 1
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs
  20. 2
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs
  21. 23
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs
  22. 3
      modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj
  23. 2
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestBase.cs
  24. 9
      modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/IdentityClaimTypeRepository_Tests.cs
  25. 7
      modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs
  26. 12
      modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs
  27. 40
      modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityClaimTypeRepository_Tests.cs
  28. 2
      modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs
  29. 53
      modules/identityserver/Volo.Abp.IdentityServer.sln
  30. 16
      modules/identityserver/common.props
  31. 20
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo.Abp.IdentityServer.Domain.Shared.csproj
  32. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/AbpIdentityServerDomainSharedModule.cs
  33. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiResourceConsts.cs
  34. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiScopeConsts.cs
  35. 8
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientClaimConsts.cs
  36. 25
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientConsts.cs
  37. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientCorsOriginConsts.cs
  38. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientGrantTypeConsts.cs
  39. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientIdPRestrictionConsts.cs
  40. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUriConsts.cs
  41. 8
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPropertyConsts.cs
  42. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientRedirectUriConsts.cs
  43. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientScopeConsts.cs
  44. 10
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Grants/PersistedGrantConsts.cs
  45. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceConsts.cs
  46. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/SecretConsts.cs
  47. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/UserClaimConsts.cs
  48. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj
  49. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj.DotSettings
  50. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs
  51. 48
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs
  52. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerConsts.cs
  53. 47
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs
  54. 17
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerOptions.cs
  55. 76
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs
  56. 26
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResourceClaim.cs
  57. 64
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScope.cs
  58. 32
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScopeClaim.cs
  59. 36
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs
  60. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/IApiResourceRepository.cs
  61. 42
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs
  62. 33
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs
  63. 196
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs
  64. 86
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientAutoMapperProfile.cs
  65. 30
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientClaim.cs
  66. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientCorsOrigin.cs
  67. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs
  68. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientIdPRestriction.cs
  69. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUri.cs
  70. 33
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientProperty.cs
  71. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientRedirectUri.cs
  72. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs
  73. 36
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs
  74. 24
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientStore.cs
  75. 17
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/IClientRepository.cs
  76. 34
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/IPersistentGrantRepository.cs
  77. 32
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrant.cs
  78. 72
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrantStore.cs
  79. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IIdentityResourceRepository.cs
  80. 26
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityClaim.cs
  81. 60
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResource.cs
  82. 27
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Jwt/JwtTokenMiddleware.cs
  83. 59
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs
  84. 37
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs
  85. 37
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs
  86. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/UserClaim.cs
  87. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj
  88. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj.DotSettings
  89. 55
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/AbpIdentityServerEfCoreQueryableExtensions.cs
  90. 59
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs
  91. 34
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs
  92. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/AbpIdentityServerEntityFrameworkCoreModule.cs
  93. 50
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IIdentityServerDbContext.cs
  94. 66
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs
  95. 228
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs
  96. 60
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs
  97. 47
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs
  98. 33
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests.csproj
  99. 10
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityApplicationTestBase.cs
  100. 129
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs

1
build-all.ps1

@ -10,6 +10,7 @@ $solutionPaths = (
"modules/permission-management",
"modules/setting-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",
"modules/account",
"modules/docs",

2
build-test-all.ps1

@ -10,6 +10,7 @@ $solutionsPaths = (
"modules/permission-management",
"modules/setting-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",
"modules/account",
"modules/docs",
@ -54,6 +55,7 @@ $testProjectPaths = (
"modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests",
"modules/identity/test/Volo.Abp.Identity.Domain.Tests",
"modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests",
"modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests",
"modules/identity/test/Volo.Abp.Identity.MongoDB.Tests",
"modules/identity/test/Volo.Abp.Identity.Application.Tests",
"modules/permission-management/test/Volo.Abp.PermissionManagement.Tests",

32
docs/Dependency-Injection.md

@ -4,7 +4,7 @@ ABP's Dependency Injection system is developed based on Microsoft's <a href="htt
### Modularity
Since ABP is a modular framework, every module defines it's services and registers to dependency injection in a seperated place, in it's own <a href="Module-Development-Basics.md" target="_blank">module class</a>. Example:
Since ABP is a modular framework, every module defines it's own services and registers via dependency injection in it's own seperate <a href="Module-Development-Basics.md" target="_blank">module class</a>. Example:
````C#
public class BlogModule : AbpModule
@ -18,7 +18,7 @@ public class BlogModule : AbpModule
### Conventional Registration
ABP introduces conventional service registration. You should do nothing to register services by convention. It's automatically done. If you want to disable it, you can set `SkipAutoServiceRegistration` to `true` by overriding the `PreConfigureServices` method.
ABP introduces conventional service registration. You need not do anything to register a service by convention. It's automatically done. If you want to disable it, you can set `SkipAutoServiceRegistration` to `true` by overriding the `PreConfigureServices` method.
````C#
public class BlogModule : AbpModule
@ -87,11 +87,11 @@ public class TaxCalculator : ITransientDependency
}
````
``TaxCalculator`` is automatically registered with transient lifetime since it implements ``ITransientDependency``.
``TaxCalculator`` is automatically registered with a transient lifetime since it implements ``ITransientDependency``.
#### Dependency Attribute
Another way of configuring a service for dependency injection is to use ``DependencyAttribute``. It has given properties:
Another way of configuring a service for dependency injection is to use ``DependencyAttribute``. It has the following properties:
* ``Lifetime``: Lifetime of the registration: ``Singleton``, ``Transient`` or ``Scoped``.
* ``TryRegister``: Set ``true`` to register the service only it's not registered before. Uses TryAdd... extension methods of IServiceCollection.
@ -108,7 +108,7 @@ public class TaxCalculator
````
``Dependency`` attribute has higher priority then dependency interfaces if it defines the ``Lifetime`` property.
``Dependency`` attribute has a higher priority than other dependency interfaces if it defines the ``Lifetime`` property.
#### ExposeServices Attribute
@ -126,7 +126,7 @@ public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransie
#### Exposed Services by Convention
If you do not specify which services to expose, ABP expose services by convention. If you think the ``TaxCalculator`` defined above:
If you do not specify which services to expose, ABP expose services by convention. So taking the ``TaxCalculator`` defined above:
* The class itself is exposed by default. That means you can inject it by ``TaxCalculator`` class.
* Default interfaces are exposed by default. Default interfaces are determined by naming convention. In this example, ``ICalculator`` and ``ITaxCalculator`` are default interfaces of ``TaxCalculator``, but ``ICanCalculate`` is not.
@ -164,11 +164,11 @@ public class BlogModule : AbpModule
### Injecting Dependencies
There are three common ways of using a service that is registered before.
There are three common ways of using a service that has already been registered.
#### Contructor Injection
This is the most common way of injecting a service into a class. Example:
This is the most common way of injecting a service into a class. For example:
````C#
public class TaxAppService : ApplicationService
@ -187,13 +187,13 @@ public class TaxAppService : ApplicationService
}
````
``TaxAppService`` gets ``ITaxCalculator`` in it's constructor. Dependency injection system automatically provides the requested service on the runtime.
``TaxAppService`` gets ``ITaxCalculator`` in it's constructor. The dependency injection system automatically provides the requested service at runtime.
Constructor injection is preffered way of injecting dependencies to a class. In that way, the class can not be constructed unless all constructor-injected dependencies are provided. Thus, the class explicitly declares it's required services.
#### Property Injection
Property injection is not supported by Microsoft Dependency Injection library. However, ABP integates to 3rd-party DI providers (<a href="https://autofac.org/" target="_blank">Autofac</a>, for example) to make property injection possible. Example:
Property injection is not supported by Microsoft Dependency Injection library. However, ABP can integrate with 3rd-party DI providers (<a href="https://autofac.org/" target="_blank">Autofac</a>, for example) to make property injection possible. Example:
````C#
public class MyService : ITransientDependency
@ -212,15 +212,15 @@ public class MyService : ITransientDependency
}
````
For a property-injection dependency, you declare a public property with public setter. Thus, DI framework can set it after creating your class.
For a property-injection dependency, you declare a public property with public setter. This allows the DI framework to set it after creating your class.
Property injected dependencies are generally considered as **optional** dependencies. That means the service can properly work without them. ``Logger`` is such a dependency, ``MyService`` can continue to work without logging.
To make the dependency properly optional, we generally set a default/fallback value to the dependency. In this sample, NullLogger is used as fallback. Thus, ``MyService`` can work but does not write logs if DI framework or you don't set Logger property after creating ``MyService``.
One restriction of property injection is that you can not use the dependency in your constructor, since it's set after the object consturction.
One restriction of property injection is that you cannot use the dependency in your constructor, since it's set after the object construction.
Property injection is also useful when you want to design a base class that has some common services injected by default. If you would use constructor injection, all derived classes should also inject depended services into their constructors which makes development harder. However, be carefully using property injection for non-optional services since it makes hard to see requirements of a class.
Property injection is also useful when you want to design a base class that has some common services injected by default. If you're going to use constructor injection, all derived classes should also inject depended services into their own constructors which makes development harder. However, be very careful using property injection for non-optional services as it makes it harder to clearly see the requirements of a class.
#### Resolve Service from IServiceProvider
@ -246,7 +246,7 @@ public class MyService : ITransientDependency
#### Releasing/Disposing Services
If you used constructor or property injection, you never need to release services. However, if you resolved service from ``IServiceProvider``, you may need to care about releasing services in some cases.
If you used constructor or property injection, you don't need to be concerned about releasing a service's resources. However, if you have resolved a service from ``IServiceProvider``, you might, in some cases, need to take care about releasing the services.
ASP.NET Core releases all services in the end of current HTTP request, even if you directly resolved from ``IServiceProvider`` (assuming you injected IServiceProvider). But, there are several cases where you may want to release/dispose manually resolved services:
@ -254,7 +254,7 @@ ASP.NET Core releases all services in the end of current HTTP request, even if y
* You only have a reference to the root service provider.
* You may want to immediately release & dispose services (for example, you may creating too many services with big memory usage and don't want to overuse memory).
In any way, you can use such a code block to safely and immediately release services:
In any case, you can use such a 'using' code block to safely and immediately release services:
````C#
using (var scope = _serviceProvider.CreateScope())
@ -268,4 +268,4 @@ Both services are released when the created scope is disposed (at the end of the
### See Also
* [ASP.NET Core Dependency Injection Best Practices, Tips & Tricks](https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96)
* [ASP.NET Core Dependency Injection Best Practices, Tips & Tricks](https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96)

22
docs/Entities.md

@ -69,12 +69,12 @@ Notice that you also need to define keys of the entity in your **object-to-relat
> Notice that ABP creates default repositories only for aggregate roots by default. However, it's possible to include all entities. See repository documentation (TODO: link) for more.
ABP does not force you to use aggregate roots, you can only use the `Entity` class as defined before. However, if you want to implement DDD and want to create aggregate root classes, there are some best practices you may want to consider:
ABP does not force you to use aggregate roots, you can in fact use the `Entity` class as defined before. However, if you want to implement DDD and want to create aggregate root classes, there are some best practices you may want to consider:
* An aggregate root is responsible to preserve it's own integrity. This is also true for all entities, but aggregate root has responsibility for it's sub entities too. So, the aggregate root always be in a valid state.
* An aggregate root can be referenced by it's Id. Do not reference it by navigation property.
* An aggregate root is responsible to preserve it's own integrity. This is also true for all entities, but aggregate root has responsibility for it's sub entities too. So, the aggregate root must always be in a valid state.
* An aggregate root can be referenced by it's Id. Do not reference it by it's navigation property.
* An aggregate root is treated as a single unit. It's retrieved and updated as a single unit. It's generally considered as a transaction boundary.
* Work with sub-entities over the aggregate root, do not modify them independently.
* Work with sub-entities over the aggregate root- do not modify them independently.
#### Aggregate Example
@ -158,19 +158,19 @@ public class OrderLine : Entity
}
````
> If you do not want derive your aggregate root from the base `AggregateRoot<TKey>` class, you can directly implement `IAggregateRoot<TKey>` interface.
> If you do not want to derive your aggregate root from the base `AggregateRoot<TKey>` class, you can directly implement the `IAggregateRoot<TKey>` interface.
`Order` is an **aggregate root** with `Guid` type `Id` property. It has a collection of `OrderLine` entities. `OrderLine` is another entity with a composite primary key (`OrderLine` and ` ProductId`).
While this example may not implement all best practices of an aggregate root, it follows some good practices:
While this example may not implement all the best practices of an aggregate root, it still follows good practices:
* `Order` has a public constructor that takes **minimal requirements** to construct an `Order` instance. So, it's not possible to create an order without an id and reference number. The **protected/private** constructor is only necessary to **deserialize** object while reading from a data source.
* `OrderLine` constructor is internal, so it only allows to be created by the domain layer. It's used inside of `Order.AddProduct` method.
* `Order` has a public constructor that takes **minimal requirements** to construct an `Order` instance. So, it's not possible to create an order without an id and reference number. The **protected/private** constructor is only necessary to **deserialize** the object while reading from a data source.
* `OrderLine` constructor is internal, so it is only allowed to be created by the domain layer. It's used inside of the `Order.AddProduct` method.
* `Order.AddProduct` implements the business rule to add a product to an order.
* All properties have `protected` setters. This is to prevent entity from arbitrary changes from outside of the entity. For instance, it would be dangerous to set `TotalItemCount` without adding a new product to the order. It's value is maintained by the `AddProduct` method.
* All properties have `protected` setters. This is to prevent the entity from arbitrary changes from outside of the entity. For exmple, it would be dangerous to set `TotalItemCount` without adding a new product to the order. It's value is maintained by the `AddProduct` method.
ABP does not force you to apply any DDD rule or pattern. However, it tries to make it possible and easier when you want to apply. The documentation also follows this principle.
ABP does not force you to apply any DDD rule or patterns. However, it tries to make it possible and easier when you do want to apply them. The documentation also follows the same principle.
#### Aggregate Roots with Composite Keys
While it's not common (and not suggested) for aggregate roots, it's possible to define composite keys just as defined for entities above. Use non-generic `AggregateRoot` base class in that case.
While it's not common (and not suggested) for aggregate roots, it isin fact possible to define composite keys in the same way as defined for the mentioned entities above. Use non-generic `AggregateRoot` base class in that case.

40
docs/Tutorials/AspNetCore-Mvc/Part-I.md

@ -14,11 +14,11 @@ You can download the **source code** of the application [from here](https://gith
### Creating the Project
Go to the [startup template page](https://abp.io/Templates) and download a new project named `Acme.BookStore`, create database and run the application by following the [template document](../../Getting-Started-AspNetCore-MVC-Template.md).
Go to the [startup template page](https://abp.io/Templates) and download a new project named `Acme.BookStore`, create the database and run the application by following the [template document](../../Getting-Started-AspNetCore-MVC-Template.md).
### Solution Structure
This is the layered solution structure created from the startup template:
This is the how the layered solution structure looks after it's created from the startup template:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png)
@ -50,10 +50,10 @@ namespace Acme.BookStore
}
````
* ABP has two fundamental base classes for entities: `AggregateRoot` and `Entity`. **Aggregate Root** is one of the **Domain Driven Design (DDD)** concepts. See [entity document](../../Entities.md) for details and best practices.
* ABP has two fundamental base classes for entities: `AggregateRoot` and `Entity`. **Aggregate Root** is one of the **Domain Driven Design (DDD)** concepts. See [entity document](../../Entities.md) for more details and best practices.
* `Book` entity inherits `AuditedAggregateRoot` which adds some auditing properties (`CreationTime`, `CreatorId`, `LastModificationTime`... etc.) on top of the `AggregateRoot` class.
* `Guid` is the **primary key type** of the `Book` entity.
* Used **data annotation attributes** in this code for EF Core mappings. You could use EF Core's [fluent mapping API](https://docs.microsoft.com/en-us/ef/core/modeling) instead.
* Used **data annotation attributes** in this code for EF Core mappings. Alternatively you could use EF Core's [fluent mapping API](https://docs.microsoft.com/en-us/ef/core/modeling) instead.
#### BookType Enum
@ -79,7 +79,7 @@ namespace Acme.BookStore
#### Add Book Entity to Your DbContext
EF Core requires to relate entities with your DbContext. The easiest way is to add a `DbSet` property to the `BookStoreDbContext` class in the `Acme.BookStore.EntityFrameworkCore` project, as shown below:
EF Core requires you to relate entities with your DbContext. The easiest way to do this is to add a `DbSet` property to the `BookStoreDbContext` class in the `Acme.BookStore.EntityFrameworkCore` project, as shown below:
````C#
public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
@ -91,7 +91,7 @@ public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
#### Add New Migration & Update the Database
Startup template uses [EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to create and maintain the database schema. Open the **Package Manager Console (PMC)** (under the *Tools/Nuget Package Manager* menu), select the `Acme.BookStore.EntityFrameworkCore` as the **default project** and execute the following command:
The Startup template uses [EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to create and maintain the database schema. Open the **Package Manager Console (PMC)** (under the *Tools/Nuget Package Manager* menu), select the `Acme.BookStore.EntityFrameworkCore` as the **default project** and execute the following command:
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration.png)
@ -136,10 +136,10 @@ namespace Acme.BookStore
}
````
* **DTO** classes are used to **transfer data** between the *presentation layer* and the *application layer*. See the [Data Transfer Objects document](../../Data-Transfer-Objects.md) for details.
* `BookDto` is used to transfer a book data to the presentation layer to show a book information on the UI.
* `BookDto` is derived from the `AuditedEntityDto<Guid>` which has audit properties just like the `Book` defined above.
* `[AutoMapFrom(typeof(Book))]` is used to create AutoMapper mapping from the `Book` class to the `BookDto` class. Thus, you can automatically convert `Book` objects to `BookDto` objects (instead of manually copy all properties).
* **DTO** classes are used to **transfer data** between the *presentation layer* and the *application layer*. See the [Data Transfer Objects document](../../Data-Transfer-Objects.md) for more details.
* `BookDto` is used to transfer book data to the presentation layer in order to show the book information on the UI.
* `BookDto` is derived from the `AuditedEntityDto<Guid>` which has audit properties just like the `Book` class defined above.
* `[AutoMapFrom(typeof(Book))]` is used to create AutoMapper mapping from the `Book` class to the `BookDto` class. In this way, you get automatic convertion of `Book` objects to `BookDto` objects (instead of manually copy all properties).
#### CreateUpdateBookDto
@ -173,7 +173,7 @@ namespace Acme.BookStore
* This DTO class is used to get book information from the user interface while creating or updating a book.
* It defines data annotation attributes (like `[Required]`) to define validations for the properties. DTOs are automatically validated by ABP.
* Each property has a `[Display]` property which set the label text on UI forms for the related input (it's also integrated to the localization system). The same DTO will be used as View Model. That's why it defines that attribute. You may find incorrect to use DTOs as View Models. You could use a separated view model class, but we thought it's practical and makes the sample project less complex.
* Each property has a `[Display]` property which set the label text on UI forms for the related input (it's also integrated to the localization system). The same DTO will be used as a View Model. That's why it defines that attribute. You may be inclined to think it's incorrect to use DTOs as View Models. There is nothing stopping you from using a separated view model class, but we thought it's practical and makes the sample project less complex.
#### IBookAppService
@ -199,7 +199,7 @@ namespace Acme.BookStore
}
````
* Defining interfaces for application services is <u>not required</u> by the framework. However, it's suggested as a good practice.
* Defining interfaces for application services is <u>not required</u> by the framework. However, it's suggested as best practice.
* `IAsyncCrudAppService` defines common **CRUD** methods: `GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync` and `DeleteAsync`. It's not required to extend it. Instead, you could inherit from the empty `IApplicationService` interface and define your own methods.
* There are some variations of the `IAsyncCrudAppService` where you can use a single DTO or separated DTOs for each method.
@ -229,13 +229,13 @@ namespace Acme.BookStore
}
````
* `BookAppService` is derived from `AsyncCrudAppService<...>` which implements all CRUD methods defined above.
* `BookAppService` is derived from `AsyncCrudAppService<...>` which implements all the CRUD methods defined above.
* `BookAppService` injects `IRepository<Book, Guid>` which is the default repository created for the `Book` entity. ABP automatically creates repositories for each aggregate root (or entity). See the [repository document](../../Repositories.md).
* `BookAppService` uses `IObjectMapper` to convert `Book` objects to `BookDto` objects and `CreateUpdateBookDto` objects to `Book` objects. Startup template uses the [AutoMapper](http://automapper.org/) library as object mapping provider. You defined mappings using the `AutoMapFrom` and the `AutoMapTo` attributes above. See the [AutoMapper integration document](../../AutoMapper-Integration.md) for details.
* `BookAppService` uses `IObjectMapper` to convert `Book` objects to `BookDto` objects and `CreateUpdateBookDto` objects to `Book` objects. The Startup template uses the [AutoMapper](http://automapper.org/) library as object mapping provider. You defined mappings using the `AutoMapFrom` and the `AutoMapTo` attributes above. See the [AutoMapper integration document](../../AutoMapper-Integration.md) for details.
### Auto API Controllers
You normally create **Controllers** to expose application services as **HTTP API** endpoints. Thus, browser or 3rd-party clients can call via AJAX.
You normally create **Controllers** to expose application services as **HTTP API** endpoints. Thus allowing browser or 3rd-party clients to call them via AJAX.
ABP can **automagically** configures your application services as MVC API Controllers by convention.
@ -255,7 +255,7 @@ ABP **dynamically** creates JavaScript **proxies** for all API endpoints. So, yo
#### Testing in the Browser Developer Console
You can just test the JavaScript proxy using your favorite browser's **Developer Console** now. Run the application again, open your browser's **developer tools** (shortcut: F12), switch to the **Console** tab, type the following code and press enter:
You can easily test the JavaScript proxy using your favorite browser's **Developer Console** now. Run the application again, open your browser's **developer tools** (shortcut: F12), switch to the **Console** tab, type the following code and press enter:
````js
acme.bookStore.book.getList({}).done(function (result) { console.log(result); });
@ -267,7 +267,7 @@ acme.bookStore.book.getList({}).done(function (result) { console.log(result); })
* `{}` argument is used to send an empty object to the `GetListAsync` method which normally expects an object of type `PagedAndSortedResultRequestDto` which is used to send paging and sorting options to the server.
* `getList` function returns a `promise`. So, you can pass a callback to the `done` (or `then`) function to get the result from the server.
Running this code produces such an output:
Running this code produces the following output:
![bookstore-test-js-proxy-getlist](images/bookstore-test-js-proxy-getlist.png)
@ -387,7 +387,7 @@ Change the `Pages/Books/Index.cshtml` as following:
````
* `abp-script` [tag helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro) is used to add external **scripts** to the page. It has many additional features compared to standard `script` tag. It handles **minification** and **versioning** for example. See the [bundling & minification document](../../AspNetCore/Bundling-Minification.md) for details.
* `abp-card` and `abp-table` are **tag helpers** for Twitter Bootstrap's [card component](http://getbootstrap.com/docs/4.1/components/card/). There are many tag helpers in ABP to easily use most of the [bootstrap](https://getbootstrap.com/) components. You can use regular HTML tags instead of these tag helpers, but using tag helpers reduces HTML code and prevents errors by help of the intellisense and compile time type checking. See the [tag helpers document](../../AspNetCore/Tag-Helpers.md).
* `abp-card` and `abp-table` are **tag helpers** for Twitter Bootstrap's [card component](http://getbootstrap.com/docs/4.1/components/card/). There are many tag helpers in ABP to easily use most of the [bootstrap](https://getbootstrap.com/) components. You can also use regular HTML tags instead of these tag helpers, but using tag helpers reduces HTML code and prevents errors by help of the intellisense and compile time type checking. See the [tag helpers document](../../AspNetCore/Tag-Helpers.md).
* You can **localize** the column names in the localization file as you did for the menu items above.
##### Add a Script File
@ -414,7 +414,7 @@ $(function () {
````
* `abp.libs.datatables.createAjax` is a helper function to adapt ABP's dynamic JavaScript API proxies to Datatable's format.
* `abp.libs.datatables.normalizeConfiguration` is another helper function. It's not required to use it, but it simplifies the datatables configuration by providing conventional values for missing options.
* `abp.libs.datatables.normalizeConfiguration` is another helper function. There's no requirment to use it, but it simplifies the datatables configuration by providing conventional values for missing options.
* `acme.bookStore.book.getList` is the function to get list of books (you have seen it before).
* See [Datatable's documentation](https://datatables.net/manual/) for more configuration options.
@ -424,4 +424,4 @@ The final UI is shown below:
### Next Part
See the [next part](Part-II.md) of this tutorial.
See the [next part](Part-II.md) of this tutorial.

5
modules/blogging/README.md

@ -1,2 +1,3 @@
# abp-blog
ABP Blogging Module
# Blogging Module
This module is used for ABP blog: https://abp.io/blog/abp/

17
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.Identity
{
public class IdentityClaimTypeConsts
{
public const int MaxNameLength = 128;
public const int MaxRegexLength = 512;
public const int MaxRegexDescriptionLength = 128;
public const int MaxDescriptionLength = 256;
}
}

14
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimValueType.cs

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.Identity
{
public enum IdentityClaimValueType
{
String,
Int,
Boolean,
DateTime
}
}

13
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIDentityClaimTypeRepository.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Identity
{
public interface IIdentityClaimTypeRepository : IBasicRepository<IdentityClaimType, Guid>
{
Task<bool> DoesNameExist(string name, Guid? claimTypeId = null);
}
}

51
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdenityClaimTypeManager.cs

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.Abp.Guids;
namespace Volo.Abp.Identity
{
public class IdenityClaimTypeManager : IDomainService
{
private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository;
private readonly IGuidGenerator _guidGenerator;
public IdenityClaimTypeManager(IIdentityClaimTypeRepository identityClaimTypeRepository, IGuidGenerator guidGenerator)
{
_identityClaimTypeRepository = identityClaimTypeRepository;
_guidGenerator = guidGenerator;
}
public async Task<IdentityClaimType> GetAsync(Guid id)
{
return await _identityClaimTypeRepository.GetAsync(id);
}
public async Task<IdentityClaimType> CreateAsync(IdentityClaimType claimType)
{
if (await _identityClaimTypeRepository.DoesNameExist(claimType.Name))
{
throw new AbpException($"Name Exist: {claimType.Name}");
}
return await _identityClaimTypeRepository.InsertAsync(claimType);
}
public async Task<IdentityClaimType> UpdateAsync(IdentityClaimType claimType)
{
if (await _identityClaimTypeRepository.DoesNameExist(claimType.Name, claimType.Id))
{
throw new AbpException($"Name Exist: {claimType.Name}");
}
return await _identityClaimTypeRepository.UpdateAsync(claimType);
}
public async Task DeleteAsync(Guid id)
{
await _identityClaimTypeRepository.DeleteAsync(id);
}
}
}

44
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Identity
{
public class IdentityClaimType : Entity<Guid>
{
public virtual string Name { get; protected set; }
public virtual bool Required { get; protected set; }
public virtual bool IsStatic { get; protected set; }
public virtual string Regex { get; protected set; }
public virtual string RegexDescription { get; protected set; }
public virtual string Description { get; protected set; }
public virtual IdentityClaimValueType ValueType { get; protected set; }
protected IdentityClaimType()
{
}
public IdentityClaimType(Guid id, [NotNull] string name, bool required, bool isStatic, [CanBeNull]string regex, [CanBeNull]string regexDescription, [CanBeNull] string description, IdentityClaimValueType valueType = IdentityClaimValueType.String)
{
Check.NotNull(name, nameof(name));
Name = name;
Required = required;
IsStatic = isStatic;
Regex = regex;
RegexDescription = regexDescription;
Description = description;
ValueType = valueType;
}
}
}

24
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.Identity.EntityFrameworkCore
{
public class EfCoreIdentityClaimTypeRepository : EfCoreRepository<IIdentityDbContext, IdentityClaimType, Guid>, IIdentityClaimTypeRepository
{
public EfCoreIdentityClaimTypeRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<bool> DoesNameExist(string name, Guid? claimTypeId = null)
{
return await DbSet.WhereIf(claimTypeId != null, ct => ct.Id == claimTypeId).CountAsync(ct => ct.Name == name) > 0;
}
}
}

2
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs

@ -10,5 +10,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
DbSet<IdentityUser> Users { get; set; }
DbSet<IdentityRole> Roles { get; set; }
DbSet<IdentityClaimType> ClaimTypes { get; set; }
}
}

2
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs

@ -18,6 +18,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
public DbSet<IdentityRole> Roles { get; set; }
public DbSet<IdentityClaimType> ClaimTypes { get; set; }
public IdentityDbContext(DbContextOptions<IdentityDbContext> options)
: base(options)
{

11
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs

@ -112,6 +112,17 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
b.HasIndex(uc => uc.RoleId);
});
builder.Entity<IdentityClaimType>(b =>
{
b.ToTable(options.TablePrefix + "ClaimTypes", options.Schema);
b.Property(uc => uc.Name).HasMaxLength(IdentityClaimTypeConsts.MaxNameLength).IsRequired(); // make unique
b.Property(uc => uc.Regex).HasMaxLength(IdentityClaimTypeConsts.MaxRegexLength);
b.Property(uc => uc.RegexDescription).HasMaxLength(IdentityClaimTypeConsts.MaxRegexDescriptionLength);
b.Property(uc => uc.Description).HasMaxLength(IdentityClaimTypeConsts.MaxDescriptionLength);
});
}
}
}

5
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs

@ -22,6 +22,11 @@ namespace Volo.Abp.Identity.MongoDB
{
map.AutoMap();
});
BsonClassMap.RegisterClassMap<IdentityClaimType>(map =>
{
map.AutoMap();
});
});
}
}

2
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs

@ -13,6 +13,8 @@ namespace Volo.Abp.Identity.MongoDB
public IMongoCollection<IdentityRole> Roles => Collection<IdentityRole>();
public IMongoCollection<IdentityClaimType> ClaimTypes => Collection<IdentityClaimType>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);

5
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs

@ -24,6 +24,11 @@ namespace Volo.Abp.Identity.MongoDB
{
b.CollectionName = options.CollectionPrefix + "Roles";
});
builder.Entity<IdentityClaimType>(b =>
{
b.CollectionName = options.CollectionPrefix + "ClaimTypes";
});
}
}
}

1
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs

@ -18,6 +18,7 @@ namespace Volo.Abp.Identity.MongoDB
{
options.AddRepository<IdentityUser, MongoIdentityUserRepository>();
options.AddRepository<IdentityRole, MongoIdentityRoleRepository>();
options.AddRepository<IdentityClaimType, MongoIdentityRoleRepository>();
});
}
}

2
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs

@ -10,5 +10,7 @@ namespace Volo.Abp.Identity.MongoDB
IMongoCollection<IdentityUser> Users { get; }
IMongoCollection<IdentityRole> Roles { get; }
IMongoCollection<IdentityClaimType> ClaimTypes { get; }
}
}

23
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
namespace Volo.Abp.Identity.MongoDB
{
public class MongoIdentityClaimTypeRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentityClaimType, Guid>, IIdentityClaimTypeRepository
{
public MongoIdentityClaimTypeRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<bool> DoesNameExist(string name, Guid? claimTypeId = null)
{
return GetMongoQueryable().WhereIf(claimTypeId != null, ct => ct.Id == claimTypeId).Count(ct => ct.Name == name) > 0;
}
}
}

3
modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj

@ -20,8 +20,7 @@
</ItemGroup>
<ItemGroup>
<Content Remove="Pages\**\*.*" />
<Content Include="Pages\**\*.cs" />
<Content Remove="Pages\**\*.cshtml" />
<Content Remove="Localization\Resources\**\*.json" />
<Content Remove="compilerconfig.json" />
<Content Remove="compilerconfig.json.defaults" />

2
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestBase.cs

@ -4,4 +4,4 @@
{
}
}
}

9
modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/IdentityClaimTypeRepository_Tests.cs

@ -0,0 +1,9 @@
using Volo.Abp.Identity.EntityFrameworkCore;
namespace Volo.Abp.Identity.MongoDB
{
public class IdentityClaimTypeRepository_Tests : IdentityClaimTypeRepository_Tests<AbpIdentityEntityFrameworkCoreTestModule>
{
}
}

7
modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.Identity.MongoDB
{
public class IdentityClaimTypeRepository_Tests : IdentityClaimTypeRepository_Tests<AbpIdentityMongoDbTestModule>
{
}
}

12
modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs

@ -9,6 +9,7 @@ namespace Volo.Abp.Identity
{
private readonly IGuidGenerator _guidGenerator;
private readonly IIdentityUserRepository _userRepository;
private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository;
private readonly IIdentityRoleRepository _roleRepository;
private readonly ILookupNormalizer _lookupNormalizer;
private readonly IdentityTestData _testData;
@ -20,12 +21,14 @@ namespace Volo.Abp.Identity
public AbpIdentityTestDataBuilder(
IGuidGenerator guidGenerator,
IIdentityUserRepository userRepository,
IIdentityClaimTypeRepository identityClaimTypeRepository,
IIdentityRoleRepository roleRepository,
ILookupNormalizer lookupNormalizer,
IdentityTestData testData)
{
_guidGenerator = guidGenerator;
_userRepository = userRepository;
_identityClaimTypeRepository = identityClaimTypeRepository;
_roleRepository = roleRepository;
_lookupNormalizer = lookupNormalizer;
_testData = testData;
@ -35,6 +38,7 @@ namespace Volo.Abp.Identity
{
AddRoles();
AddUsers();
AddClaimTypes();
}
private void AddRoles()
@ -73,5 +77,13 @@ namespace Volo.Abp.Identity
neo.AddClaim(_guidGenerator, new Claim("TestClaimType", "43"));
_userRepository.Insert(neo);
}
private void AddClaimTypes()
{
var ageClaim = new IdentityClaimType(_testData.AgeClaimId, "Age", false, false, null, null, null,IdentityClaimValueType.Int);
_identityClaimTypeRepository.Insert(ageClaim);
var educationClaim = new IdentityClaimType(_testData.EducationClaimId, "Education", true, false, null, null, null);
_identityClaimTypeRepository.Insert(educationClaim);
}
}
}

40
modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityClaimTypeRepository_Tests.cs

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Guids;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.Identity
{
public abstract class IdentityClaimTypeRepository_Tests<TStartupModule> : AbpIdentityTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
protected IIdentityClaimTypeRepository ClaimTypeRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
public IdentityClaimTypeRepository_Tests()
{
ClaimTypeRepository = ServiceProvider.GetRequiredService<IIdentityClaimTypeRepository>();
GuidGenerator = ServiceProvider.GetRequiredService<IGuidGenerator>();
}
[Fact]
public async Task Should_Check_Name_If_It_Is_Uniquee()
{
var claim = (await ClaimTypeRepository.GetListAsync()).FirstOrDefault();
var result1 = await ClaimTypeRepository.DoesNameExist(claim.Name);
result1.ShouldBe(true);
var result2 = await ClaimTypeRepository.DoesNameExist(Guid.NewGuid().ToString());
result2.ShouldBe(false);
}
}
}

2
modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs

@ -10,5 +10,7 @@ namespace Volo.Abp.Identity
public Guid UserJohnId { get; } = Guid.NewGuid();
public Guid UserDavidId { get; } = Guid.NewGuid();
public Guid UserNeoId { get; } = Guid.NewGuid();
public Guid AgeClaimId { get; } = Guid.NewGuid();
public Guid EducationClaimId { get; } = Guid.NewGuid();
}
}

53
modules/identityserver/Volo.Abp.IdentityServer.sln

@ -0,0 +1,53 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2047
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.Domain", "src\Volo.Abp.IdentityServer.Domain\Volo.Abp.IdentityServer.Domain.csproj", "{A3B81AEE-EE96-4F75-856B-55B25D8822E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.Domain.Shared", "src\Volo.Abp.IdentityServer.Domain.Shared\Volo.Abp.IdentityServer.Domain.Shared.csproj", "{FC035412-78AD-424C-BECE-B19D04C7B5A6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.EntityFrameworkCore", "src\Volo.Abp.IdentityServer.EntityFrameworkCore\Volo.Abp.IdentityServer.EntityFrameworkCore.csproj", "{F352D620-1CBF-4658-953F-70BA73B458F1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2C792EC1-BA27-44ED-B7CC-D0939553F1B2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.EntityFrameworkCore.Tests", "test\Volo.Abp.IdentityServer.EntityFrameworkCore.Tests\Volo.Abp.IdentityServer.EntityFrameworkCore.Tests.csproj", "{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Release|Any CPU.Build.0 = Release|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Release|Any CPU.Build.0 = Release|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Release|Any CPU.Build.0 = Release|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A3B81AEE-EE96-4F75-856B-55B25D8822E2} = {59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}
{FC035412-78AD-424C-BECE-B19D04C7B5A6} = {59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}
{F352D620-1CBF-4658-953F-70BA73B458F1} = {59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82} = {2C792EC1-BA27-44ED-B7CC-D0939553F1B2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {45562023-C330-4060-A583-2BA10F472D3D}
EndGlobalSection
EndGlobal

16
modules/identityserver/common.props

@ -0,0 +1,16 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.3.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>http://www.aspnetboilerplate.com/images/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>http://abp.io</PackageProjectUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/volosoft/abp/</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.1" PrivateAssets="All" />
</ItemGroup>
</Project>

20
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo.Abp.IdentityServer.Domain.Shared.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.Domain.Shared</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.Domain.Shared</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/AbpIdentityServerDomainSharedModule.cs

@ -0,0 +1,9 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerDomainSharedModule : AbpModule
{
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiResourceConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiResourceConsts
{
public const int NameMaxLength = 200;
public const int DisplayNameMaxLength = 200;
public const int DescriptionMaxLength = 1000;
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiScopeConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiScopeConsts
{
public const int NameMaxLength = 196;
public const int DisplayNameMaxLength = 128;
public const int DescriptionMaxLength = 256;
}
}

8
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientClaimConsts.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientClaimConsts
{
public const int TypeMaxLength = 250;
public const int ValueMaxLength = 250;
}
}

25
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientConsts.cs

@ -0,0 +1,25 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientConsts
{
public const int ClientIdMaxLength = 200;
public const int ProtocolTypeMaxLength = 200;
public const int ClientNameMaxLength = 200;
public const int ClientUriMaxLength = 2000;
public const int LogoUriMaxLength = 2000;
public const int DescriptionMaxLength = 1000;
public const int FrontChannelLogoutUriMaxLength = 2000;
public const int BackChannelLogoutUriMaxLength = 2000;
public const int ClientClaimsPrefixMaxLength = 200;
public const int PairWiseSubjectSaltMaxLength = 200;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientCorsOriginConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientCorsOriginConsts
{
public const int OriginMaxLength = 150;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientGrantTypeConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientGrantTypeConsts
{
public const int GrantTypeMaxLength = 196;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientIdPRestrictionConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientIdPRestrictionConsts
{
public const int ProviderMaxLength = 64;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUriConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientPostLogoutRedirectUriConsts
{
public const int PostLogoutRedirectUriMaxLength = 2000;
}
}

8
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPropertyConsts.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientPropertyConsts
{
public const int KeyMaxLength = 250;
public const int ValueMaxLength = 2000;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientRedirectUriConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientRedirectUriConsts
{
public const int RedirectUriMaxLength = 2000;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientScopeConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientScopeConsts
{
public const int ScopeMaxLength = 196;
}
}

10
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Grants/PersistedGrantConsts.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.IdentityServer.Grants
{
public class PersistedGrantConsts
{
public const int KeyMaxLength = 200;
public const int TypeMaxLength = 50;
public const int SubjectIdMaxLength = 200;
public const int ClientIdMaxLength = 200;
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer.IdentityResources
{
public class IdentityResourceConsts
{
public const int NameMaxLength = 200;
public const int DisplayNameMaxLength = 200;
public const int DescriptionMaxLength = 1000;
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/SecretConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer
{
public class SecretConsts
{
public const int TypeMaxLength = 32;
public const int ValueMaxLength = 196;
public const int DescriptionMaxLength = 256;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/UserClaimConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer
{
public class UserClaimConsts
{
public const int TypeMaxLength = 196;
}
}

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

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.Domain</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.Domain</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.IdentityServer.Domain.Shared\Volo.Abp.IdentityServer.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\modules\identity\src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IdentityServer4" Version="2.2.0" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" />
</ItemGroup>
</Project>

2
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj.DotSettings

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

28
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs

@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using IdentityServer4.Services;
using Microsoft.Extensions.Logging;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.IdentityServer
{
public class AbpClaimsService : DefaultClaimsService
{
public AbpClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger)
: base(profile, logger)
{
}
protected override IEnumerable<Claim> GetOptionalClaims(ClaimsPrincipal subject)
{
var tenantClaim = subject.FindFirst(AbpClaimTypes.TenantId);
if (tenantClaim == null)
{
return base.GetOptionalClaims(subject);
}
return base.GetOptionalClaims(subject).Union(new[] { tenantClaim });
}
}
}

48
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs

@ -0,0 +1,48 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using IdentityModel;
using IdentityServer4.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.AspNetIdentity;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.IdentityServer
{
public static class AbpIdentityServerBuilderExtensions
{
public static IIdentityServerBuilder AddAbpIdentityServer(
this IIdentityServerBuilder builder,
Action<AbpIdentityServerOptions> optionsAction = null)
{
var options = new AbpIdentityServerOptions();
optionsAction?.Invoke(options);
//TODO: AspNet Identity integration lines. Can be extracted to a extension method
builder.AddAspNetIdentity<IdentityUser>();
builder.AddProfileService<AbpProfileService>();
builder.AddResourceOwnerValidator<AbpResourceOwnerPasswordValidator>();
builder.Services.Replace(ServiceDescriptor.Transient<IClaimsService, AbpClaimsService>());
if (options.UpdateAbpClaimTypes)
{
AbpClaimTypes.UserId = JwtClaimTypes.Subject;
AbpClaimTypes.UserName = JwtClaimTypes.Name;
AbpClaimTypes.Role = JwtClaimTypes.Role;
AbpClaimTypes.Email = JwtClaimTypes.Email;
}
if (options.UpdateJwtSecurityTokenHandlerDefaultInboundClaimTypeMap)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.UserId] = AbpClaimTypes.UserId;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.UserName] = AbpClaimTypes.UserName;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.Role] = AbpClaimTypes.Role;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.Email] = AbpClaimTypes.Email;
}
return builder;
}
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer
{
public static class AbpIdentityServerConsts
{
public const string DefaultDbTablePrefix = "IdentityServer";
public const string DefaultDbSchema = null;
}
}

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

@ -0,0 +1,47 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Domain;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
namespace Volo.Abp.IdentityServer
{
[DependsOn(typeof(AbpIdentityServerDomainSharedModule))]
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
[DependsOn(typeof(AbpIdentityDomainModule))]
[DependsOn(typeof(AbpSecurityModule))]
public class AbpIdentityServerDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<ClientAutoMapperProfile>(validate: true);
});
AddIdentityServer(context.Services);
}
private static void AddIdentityServer(IServiceCollection services)
{
var identityServerBuilder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
});
identityServerBuilder
.AddDeveloperSigningCredential() //TODO: Should be able to change this!
.AddClientStore<ClientStore>()
.AddResourceStore<ResourceStore>()
.AddAbpIdentityServer();
services.ExecutePreConfiguredActions(identityServerBuilder);
}
}
}

17
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerOptions.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerOptions
{
/// <summary>
/// Updates <see cref="JwtSecurityTokenHandler.DefaultInboundClaimTypeMap"/> to be compatible with identity server claims.
/// Default: true.
/// </summary>
public bool UpdateJwtSecurityTokenHandlerDefaultInboundClaimTypeMap { get; set; } = true;
/// <summary>
/// Updates <see cref="AbpClaimTypes"/> to be compatible with identity server claims.
/// Default: true.
/// </summary>
public bool UpdateAbpClaimTypes { get; set; } = true;
}
}

76
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using IdentityServer4;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiResource : AggregateRoot<Guid>
{
[NotNull]
public virtual string Name { get; protected set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual bool Enabled { get; set; }
public virtual List<ApiSecret> Secrets { get; protected set; }
public virtual List<ApiScope> Scopes { get; protected set; }
public virtual List<ApiResourceClaim> UserClaims { get; protected set; }
protected ApiResource()
{
}
public ApiResource(Guid id, [NotNull] string name, string displayName = null, string description = null)
{
Check.NotNull(name, nameof(name));
Id = id;
Name = name;
DisplayName = displayName;
Description = description;
Enabled = true;
Secrets = new List<ApiSecret>();
Scopes = new List<ApiScope>();
UserClaims = new List<ApiResourceClaim>();
Scopes.Add(new ApiScope(id, name, displayName, description));
}
public virtual void AddSecret(
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null)
{
Secrets.Add(new ApiSecret(Id, value, expiration, type, description));
}
public virtual void AddScope(
[NotNull] string name,
string displayName = null,
string description = null,
bool required = false,
bool emphasize = false,
bool showInDiscoveryDocument = true)
{
Scopes.Add(new ApiScope(Id, name, displayName, description, required, emphasize, showInDiscoveryDocument));
}
public virtual void AddUserClaim([NotNull] string type)
{
UserClaims.Add(new ApiResourceClaim(Id, type));
}
}
}

26
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResourceClaim.cs

@ -0,0 +1,26 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiResourceClaim : UserClaim
{
public virtual Guid ApiResourceId { get; set; }
protected ApiResourceClaim()
{
}
protected internal ApiResourceClaim(Guid apiResourceId, [NotNull] string type)
: base(type)
{
ApiResourceId = apiResourceId;
}
public override object[] GetKeys()
{
return new object[] {ApiResourceId, Type};
}
}
}

64
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScope.cs

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiScope : Entity
{
public virtual Guid ApiResourceId { get; protected set; }
[NotNull]
public virtual string Name { get; protected set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual bool Required { get; set; }
public virtual bool Emphasize { get; set; }
public virtual bool ShowInDiscoveryDocument { get; set; }
public virtual List<ApiScopeClaim> UserClaims { get; protected set; }
protected ApiScope()
{
}
protected internal ApiScope(
Guid apiResourceId,
[NotNull] string name,
string displayName = null,
string description = null,
bool required = false,
bool emphasize = false,
bool showInDiscoveryDocument = true)
{
Check.NotNull(name, nameof(name));
ApiResourceId = apiResourceId;
Name = name;
DisplayName = displayName ?? name;
Description = description;
Required = required;
Emphasize = emphasize;
ShowInDiscoveryDocument = showInDiscoveryDocument;
UserClaims = new List<ApiScopeClaim>();
}
public virtual void AddUserClaim([NotNull] string type)
{
UserClaims.Add(new ApiScopeClaim(ApiResourceId, Name, type));
}
public override object[] GetKeys()
{
return new object[] { ApiResourceId, Name };
}
}
}

32
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScopeClaim.cs

@ -0,0 +1,32 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiScopeClaim : UserClaim
{
public Guid ApiResourceId { get; protected set; }
[NotNull]
public string Name { get; protected set; }
protected ApiScopeClaim()
{
}
protected internal ApiScopeClaim(Guid apiResourceId, [NotNull] string name, [NotNull] string type)
: base(type)
{
Check.NotNull(name, nameof(name));
ApiResourceId = apiResourceId;
Name = name;
}
public override object[] GetKeys()
{
return new object[] { ApiResourceId, Name, Type };
}
}
}

36
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs

@ -0,0 +1,36 @@
using System;
using IdentityServer4;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiSecret : Secret
{
public virtual Guid ApiResourceId { get; protected set; }
protected ApiSecret()
{
}
protected internal ApiSecret(
Guid apiResourceId,
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null
) : base(
value,
expiration,
type,
description)
{
ApiResourceId = apiResourceId;
}
public override object[] GetKeys()
{
return new object[] { ApiResourceId, Type, Value };
}
}
}

28
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/IApiResourceRepository.cs

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.ApiResources
{
public interface IApiResourceRepository : IBasicRepository<ApiResource, Guid>
{
Task<ApiResource> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
Task<List<ApiResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<ApiResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default
);
}
}

42
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs

@ -0,0 +1,42 @@
using System.Threading.Tasks;
using System.Security.Principal;
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace Volo.Abp.IdentityServer.AspNetIdentity
{
public class AbpProfileService : ProfileService<IdentityUser>
{
private readonly ICurrentTenant _currentTenant;
public AbpProfileService(
IdentityUserManager userManager,
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
ICurrentTenant currentTenant)
: base(userManager, claimsFactory)
{
_currentTenant = currentTenant;
}
[UnitOfWork]
public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
using (_currentTenant.Change(context.Subject.FindTenantId()))
{
await base.GetProfileDataAsync(context);
}
}
[UnitOfWork]
public override async Task IsActiveAsync(IsActiveContext context)
{
using (_currentTenant.Change(context.Subject.FindTenantId()))
{
await base.IsActiveAsync(context);
}
}
}
}

33
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

@ -0,0 +1,33 @@
using System.Threading.Tasks;
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Volo.Abp.Identity;
using Volo.Abp.Uow;
namespace Volo.Abp.IdentityServer.AspNetIdentity
{
public class AbpResourceOwnerPasswordValidator : ResourceOwnerPasswordValidator<IdentityUser>
{
public AbpResourceOwnerPasswordValidator(
IdentityUserManager userManager,
SignInManager<IdentityUser> signInManager,
IEventService events,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger
) : base(
userManager,
signInManager,
events,
logger)
{
}
[UnitOfWork]
public override async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
await base.ValidateAsync(context);
}
}
}

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

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using IdentityServer4;
using IdentityServer4.Models;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
namespace Volo.Abp.IdentityServer.Clients
{
public class Client : AggregateRoot<Guid>
{
public virtual string ClientId { get; set; }
public virtual string ClientName { get; set; }
public virtual string Description { get; set; }
public virtual string ClientUri { get; set; }
public virtual string LogoUri { get; set; }
public virtual bool Enabled { get; set; } = true;
public virtual string ProtocolType { get; set; }
public virtual bool RequireClientSecret { get; set; }
public virtual bool RequireConsent { get; set; }
public virtual bool AllowRememberConsent { get; set; }
public virtual bool AlwaysIncludeUserClaimsInIdToken { get; set; }
public virtual bool RequirePkce { get; set; }
public virtual bool AllowPlainTextPkce { get; set; }
public virtual bool AllowAccessTokensViaBrowser { get; set; }
public virtual string FrontChannelLogoutUri { get; set; }
public virtual bool FrontChannelLogoutSessionRequired { get; set; }
public virtual string BackChannelLogoutUri { get; set; }
public virtual bool BackChannelLogoutSessionRequired { get; set; }
public virtual bool AllowOfflineAccess { get; set; }
public virtual int IdentityTokenLifetime { get; set; }
public virtual int AccessTokenLifetime { get; set; }
public virtual int AuthorizationCodeLifetime { get; set; }
public virtual int? ConsentLifetime { get; set; }
public virtual int AbsoluteRefreshTokenLifetime { get; set; }
public virtual int SlidingRefreshTokenLifetime { get; set; }
public virtual int RefreshTokenUsage { get; set; }
public virtual bool UpdateAccessTokenClaimsOnRefresh { get; set; }
public virtual int RefreshTokenExpiration { get; set; }
public virtual int AccessTokenType { get; set; }
public virtual bool EnableLocalLogin { get; set; }
public virtual bool IncludeJwtId { get; set; }
public virtual bool AlwaysSendClientClaims { get; set; }
public virtual string ClientClaimsPrefix { get; set; }
public virtual string PairWiseSubjectSalt { get; set; }
public virtual List<ClientScope> AllowedScopes { get; set; }
public virtual List<ClientSecret> ClientSecrets { get; set; }
public virtual List<ClientGrantType> AllowedGrantTypes { get; set; }
public virtual List<ClientCorsOrigin> AllowedCorsOrigins { get; set; }
public virtual List<ClientRedirectUri> RedirectUris { get; set; }
public virtual List<ClientPostLogoutRedirectUri> PostLogoutRedirectUris { get; set; }
public virtual List<ClientIdPRestriction> IdentityProviderRestrictions { get; set; }
public virtual List<ClientClaim> Claims { get; set; }
public virtual List<ClientProperty> Properties { get; set; }
protected Client()
{
}
public Client(Guid id, [NotNull] string clientId)
{
Check.NotNull(clientId, nameof(clientId));
Id = id;
ClientId = clientId;
//TODO: Replace magics with constants?
ProtocolType = IdentityServerConstants.ProtocolTypes.OpenIdConnect;
RequireClientSecret = true;
RequireConsent = true;
AllowRememberConsent = true;
FrontChannelLogoutSessionRequired = true;
BackChannelLogoutSessionRequired = true;
IdentityTokenLifetime = 300;
AccessTokenLifetime = 3600;
AuthorizationCodeLifetime = 300;
AbsoluteRefreshTokenLifetime = 2592000;
SlidingRefreshTokenLifetime = 1296000;
RefreshTokenUsage = (int)TokenUsage.OneTimeOnly;
RefreshTokenExpiration = (int)TokenExpiration.Absolute;
AccessTokenType = (int)IdentityServer4.Models.AccessTokenType.Jwt;
EnableLocalLogin = true;
ClientClaimsPrefix = "client_";
AllowedScopes = new List<ClientScope>();
ClientSecrets = new List<ClientSecret>();
AllowedGrantTypes = new List<ClientGrantType>();
AllowedCorsOrigins = new List<ClientCorsOrigin>();
RedirectUris = new List<ClientRedirectUri>();
PostLogoutRedirectUris = new List<ClientPostLogoutRedirectUri>();
IdentityProviderRestrictions = new List<ClientIdPRestriction>();
Claims = new List<ClientClaim>();
Properties = new List<ClientProperty>();
}
public virtual void AddGrantType([NotNull] string grantType)
{
AllowedGrantTypes.Add(new ClientGrantType(Id, grantType));
}
public virtual void AddGrantTypes(IEnumerable<string> grantTypes)
{
AllowedGrantTypes.AddRange(
grantTypes.Select(
grantType => new ClientGrantType(Id, grantType)
)
);
}
public virtual void AddSecret([NotNull] string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null)
{
ClientSecrets.Add(new ClientSecret(Id, value, expiration, type, description));
}
public virtual void AddScope([NotNull] string scope)
{
AllowedScopes.Add(new ClientScope(Id, scope));
}
public virtual void AddCorsOrigin([NotNull] string origin)
{
AllowedCorsOrigins.Add(new ClientCorsOrigin(Id, origin));
}
public virtual void AddRedirectUri([NotNull] string redirectUri)
{
RedirectUris.Add(new ClientRedirectUri(Id, redirectUri));
}
public virtual void AddPostLogoutRedirectUri([NotNull] string postLogoutRedirectUri)
{
PostLogoutRedirectUris.Add(new ClientPostLogoutRedirectUri(Id, postLogoutRedirectUri));
}
public virtual void AddIdentityProviderRestriction([NotNull] string provider)
{
IdentityProviderRestrictions.Add(new ClientIdPRestriction(Id, provider));
}
public virtual void AddProperty([NotNull] string key)
{
Properties.Add(new ClientProperty(Id, key));
}
public virtual void AddClaim(IGuidGenerator guidGenerator, [NotNull] string type, string value)
{
Claims.Add(new ClientClaim(guidGenerator.Create(), Id, type, value));
}
}
}

86
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientAutoMapperProfile.cs

@ -0,0 +1,86 @@
using System.Collections.Generic;
using System.Security.Claims;
using AutoMapper;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientAutoMapperProfile : Profile
{
public ClientAutoMapperProfile()
{
//TODO: Reverse maps will not used probably. Remove those will not used
CreateMap<Client, IdentityServer4.Models.Client>();
CreateMap<ClientCorsOrigin, string>()
.ConstructUsing(src => src.Origin)
.ReverseMap()
.ForMember(dest => dest.Origin, opt => opt.MapFrom(src => src));
CreateMap<ApiResource, IdentityServer4.Models.ApiResource>()
.ForMember(dest => dest.ApiSecrets, opt => opt.MapFrom(src => src.Secrets));
//TODO: Why PersistedGrant mapping is in this profile?
CreateMap<PersistedGrant, IdentityServer4.Models.PersistedGrant>().ReverseMap();
CreateMap<IdentityResource, IdentityServer4.Models.IdentityResource>();
CreateMap<UserClaim, string>()
.ConstructUsing(src => src.Type)
.ReverseMap()
.ForMember(dest => dest.Type, opt => opt.MapFrom(src => src));
CreateMap<ApiSecret, IdentityServer4.Models.Secret>();
CreateMap<ApiScope, IdentityServer4.Models.Scope>();
CreateMap<ClientProperty, KeyValuePair<string, string>>()
.ReverseMap();
CreateMap<Client, IdentityServer4.Models.Client>()
.ForMember(dest => dest.ProtocolType, opt => opt.Condition(srs => srs != null))
.ReverseMap();
CreateMap<ClientCorsOrigin, string>()
.ConstructUsing(src => src.Origin)
.ReverseMap()
.ForMember(dest => dest.Origin, opt => opt.MapFrom(src => src));
CreateMap<ClientIdPRestriction, string>()
.ConstructUsing(src => src.Provider)
.ReverseMap()
.ForMember(dest => dest.Provider, opt => opt.MapFrom(src => src));
CreateMap<ClientClaim, Claim>(MemberList.None)
.ConstructUsing(src => new Claim(src.Type, src.Value))
.ReverseMap();
CreateMap<ClientScope, string>()
.ConstructUsing(src => src.Scope)
.ReverseMap()
.ForMember(dest => dest.Scope, opt => opt.MapFrom(src => src));
CreateMap<ClientPostLogoutRedirectUri, string>()
.ConstructUsing(src => src.PostLogoutRedirectUri)
.ReverseMap()
.ForMember(dest => dest.PostLogoutRedirectUri, opt => opt.MapFrom(src => src));
CreateMap<ClientRedirectUri, string>()
.ConstructUsing(src => src.RedirectUri)
.ReverseMap()
.ForMember(dest => dest.RedirectUri, opt => opt.MapFrom(src => src));
CreateMap<ClientGrantType, string>()
.ConstructUsing(src => src.GrantType)
.ReverseMap()
.ForMember(dest => dest.GrantType, opt => opt.MapFrom(src => src));
CreateMap<ClientSecret, IdentityServer4.Models.Secret>(MemberList.Destination)
.ForMember(dest => dest.Type, opt => opt.Condition(srs => srs != null))
.ReverseMap();
}
}
}

30
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientClaim.cs

@ -0,0 +1,30 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientClaim : Entity<Guid>
{
public virtual Guid ClientId { get; set; }
public virtual string Type { get; set; }
public virtual string Value { get; set; }
protected ClientClaim()
{
}
protected internal ClientClaim(Guid id, Guid clientId, [NotNull] string type, string value)
{
Check.NotNull(type, nameof(type));
Id = id;
ClientId = clientId;
Type = type;
Value = value;
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientCorsOrigin.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientCorsOrigin : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string Origin { get; protected set; }
protected ClientCorsOrigin()
{
}
protected internal ClientCorsOrigin(Guid clientId, [NotNull] string origin)
{
Check.NotNull(origin, nameof(origin));
ClientId = clientId;
Origin = origin;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Origin };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientGrantType : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string GrantType { get; protected set; }
protected ClientGrantType()
{
}
protected internal ClientGrantType(Guid clientId, [NotNull] string grantType)
{
Check.NotNull(grantType, nameof(grantType));
ClientId = clientId;
GrantType = grantType;
}
public override object[] GetKeys()
{
return new object[] { ClientId, GrantType };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientIdPRestriction.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientIdPRestriction : Entity
{
public virtual Guid ClientId { get; set; }
public virtual string Provider { get; set; }
protected ClientIdPRestriction()
{
}
protected internal ClientIdPRestriction(Guid clientId, [NotNull] string provider)
{
Check.NotNull(provider, nameof(provider));
ClientId = clientId;
Provider = provider;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Provider };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUri.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientPostLogoutRedirectUri : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string PostLogoutRedirectUri { get; protected set; }
protected ClientPostLogoutRedirectUri()
{
}
protected internal ClientPostLogoutRedirectUri(Guid clientId, [NotNull] string postLogoutRedirectUri)
{
Check.NotNull(postLogoutRedirectUri, nameof(postLogoutRedirectUri));
ClientId = clientId;
PostLogoutRedirectUri = postLogoutRedirectUri;
}
public override object[] GetKeys()
{
return new object[] { ClientId, PostLogoutRedirectUri };
}
}
}

33
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientProperty.cs

@ -0,0 +1,33 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientProperty : Entity
{
public virtual Guid ClientId { get; set; }
public virtual string Key { get; set; }
public virtual string Value { get; set; }
protected ClientProperty()
{
}
protected internal ClientProperty(Guid clientId, [NotNull] string key)
{
Check.NotNull(key, nameof(key));
ClientId = clientId;
Key = key;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Key };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientRedirectUri.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientRedirectUri : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string RedirectUri { get; protected set; }
protected ClientRedirectUri()
{
}
protected internal ClientRedirectUri(Guid clientId, [NotNull] string redirectUri)
{
Check.NotNull(redirectUri, nameof(redirectUri));
ClientId = clientId;
RedirectUri = redirectUri;
}
public override object[] GetKeys()
{
return new object[] { ClientId, RedirectUri };
}
}
}

28
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs

@ -0,0 +1,28 @@
using System;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientScope : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string Scope { get; protected set; }
protected ClientScope()
{
}
protected internal ClientScope(Guid clientId, string scope)
{
ClientId = clientId;
Scope = scope;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Scope };
}
}
}

36
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs

@ -0,0 +1,36 @@
using System;
using IdentityServer4;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientSecret : Secret
{
public virtual Guid ClientId { get; protected set; }
protected ClientSecret()
{
}
protected internal ClientSecret(
Guid clientId,
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null
) : base(
value,
expiration,
type,
description)
{
ClientId = clientId;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Type, Value };
}
}
}

24
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientStore.cs

@ -0,0 +1,24 @@
using System.Threading.Tasks;
using IdentityServer4.Stores;
using Volo.Abp.ObjectMapping;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientStore : IClientStore
{
private readonly IClientRepository _clientRepository;
private readonly IObjectMapper _objectMapper;
public ClientStore(IClientRepository clientRepository, IObjectMapper objectMapper)
{
_clientRepository = clientRepository;
_objectMapper = objectMapper;
}
public virtual async Task<IdentityServer4.Models.Client> FindClientByIdAsync(string clientId)
{
var client = await _clientRepository.FindByCliendIdAsync(clientId);
return _objectMapper.Map<Client, IdentityServer4.Models.Client>(client);
}
}
}

17
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/IClientRepository.cs

@ -0,0 +1,17 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.Clients
{
public interface IClientRepository : IBasicRepository<Client, Guid>
{
Task<Client> FindByCliendIdAsync(
[NotNull] string clientId,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
}
}

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

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.Grants
{
public interface IPersistentGrantRepository : IBasicRepository<PersistedGrant, Guid>
{
Task<PersistedGrant> FindByKeyAsync(
string key,
CancellationToken cancellationToken = default
);
Task<List<PersistedGrant>> GetListBySubjectIdAsync(
string key,
CancellationToken cancellationToken = default
);
Task DeleteAsync(
string subjectId,
string clientId,
CancellationToken cancellationToken = default
);
Task DeleteAsync(
string subjectId,
string clientId,
string type,
CancellationToken cancellationToken = default
);
}
}

32
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrant.cs

@ -0,0 +1,32 @@
using System;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Grants
{
public class PersistedGrant : AggregateRoot<Guid>
{
public virtual string Key { get; set; }
public virtual string Type { get; set; }
public virtual string SubjectId { get; set; }
public virtual string ClientId { get; set; }
public virtual DateTime CreationTime { get; set; }
public virtual DateTime? Expiration { get; set; }
public virtual string Data { get; set; }
protected PersistedGrant()
{
}
public PersistedGrant(Guid id)
{
Id = id;
}
}
}

72
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrantStore.cs

@ -0,0 +1,72 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Stores;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.ObjectMapping;
namespace Volo.Abp.IdentityServer.Grants
{
public class PersistedGrantStore : IPersistedGrantStore, ITransientDependency
{
private readonly IPersistentGrantRepository _persistentGrantRepository;
private readonly IObjectMapper _objectMapper;
private readonly IGuidGenerator _guidGenerator;
public PersistedGrantStore(IPersistentGrantRepository persistentGrantRepository, IObjectMapper objectMapper, IGuidGenerator guidGenerator)
{
_persistentGrantRepository = persistentGrantRepository;
_objectMapper = objectMapper;
_guidGenerator = guidGenerator;
}
public virtual async Task StoreAsync(IdentityServer4.Models.PersistedGrant grant)
{
var entity = _objectMapper.Map<IdentityServer4.Models.PersistedGrant, PersistedGrant>(grant);
var existing = await _persistentGrantRepository.FindByKeyAsync(grant.Key);
if (existing == null)
{
entity.Id = _guidGenerator.Create();
await _persistentGrantRepository.InsertAsync(entity);
}
else
{
await _persistentGrantRepository.UpdateAsync(entity);
}
}
public virtual async Task<IdentityServer4.Models.PersistedGrant> GetAsync(string key)
{
var persistedGrant = await _persistentGrantRepository.FindByKeyAsync(key);
return _objectMapper.Map<PersistedGrant, IdentityServer4.Models.PersistedGrant>(persistedGrant);
}
public virtual async Task<IEnumerable<IdentityServer4.Models.PersistedGrant>> GetAllAsync(string subjectId)
{
var persistedGrants = await _persistentGrantRepository.GetListBySubjectIdAsync(subjectId);
return persistedGrants.Select(x => _objectMapper.Map<PersistedGrant, IdentityServer4.Models.PersistedGrant>(x));
}
public virtual async Task RemoveAsync(string key)
{
var persistedGrant = await _persistentGrantRepository.FindByKeyAsync(key);
if (persistedGrant == null)
{
return;
}
await _persistentGrantRepository.DeleteAsync(persistedGrant);
}
public virtual async Task RemoveAllAsync(string subjectId, string clientId)
{
await _persistentGrantRepository.DeleteAsync(subjectId, clientId);
}
public virtual async Task RemoveAllAsync(string subjectId, string clientId, string type)
{
await _persistentGrantRepository.DeleteAsync(subjectId, clientId, type);
}
}
}

22
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IIdentityResourceRepository.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.IdentityResources
{
public interface IIdentityResourceRepository : IBasicRepository<IdentityResource, Guid>
{
Task<List<IdentityResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<IdentityResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default
);
}
}

26
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityClaim.cs

@ -0,0 +1,26 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.IdentityResources
{
public class IdentityClaim : UserClaim
{
public virtual Guid IdentityResourceId { get; set; }
protected IdentityClaim()
{
}
protected internal IdentityClaim(Guid identityResourceId, [NotNull] string type)
: base(type)
{
IdentityResourceId = identityResourceId;
}
public override object[] GetKeys()
{
return new object[] { IdentityResourceId, Type };
}
}
}

60
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResource.cs

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.IdentityResources
{
public class IdentityResource : AggregateRoot<Guid>
{
public virtual string Name { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual bool Enabled { get; set; }
public virtual bool Required { get; set; }
public virtual bool Emphasize { get; set; }
public virtual bool ShowInDiscoveryDocument { get; set; }
public virtual List<IdentityClaim> UserClaims { get; set; }
protected IdentityResource()
{
}
public IdentityResource(
Guid id,
[NotNull] string name,
string displayName = null,
string description = null,
bool enabled = true,
bool required = false,
bool emphasize = false,
bool showInDiscoveryDocument = true)
{
Check.NotNull(name, nameof(name));
Id = id;
Name = name;
DisplayName = displayName;
Description = description;
Enabled = enabled;
Required = required;
Emphasize = emphasize;
ShowInDiscoveryDocument = showInDiscoveryDocument;
UserClaims = new List<IdentityClaim>();
}
public virtual void AddUserClaim([NotNull] string type)
{
UserClaims.Add(new IdentityClaim(Id, type));
}
}
}

27
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Jwt/JwtTokenMiddleware.cs

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
namespace Volo.Abp.IdentityServer.Jwt
{
//TODO: Should we move this to another package..?
public static class JwtTokenMiddleware
{
public static IApplicationBuilder UseJwtTokenMiddleware(this IApplicationBuilder app, string schema)
{
return app.Use(async (ctx, next) =>
{
if (ctx.User.Identity?.IsAuthenticated != true)
{
var result = await ctx.AuthenticateAsync(schema);
if (result.Succeeded && result.Principal != null)
{
ctx.User = result.Principal;
}
}
await next();
});
}
}
}

59
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs

@ -0,0 +1,59 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.ObjectMapping;
using ApiResource = IdentityServer4.Models.ApiResource;
using IdentityResource = Volo.Abp.IdentityServer.IdentityResources.IdentityResource;
namespace Volo.Abp.IdentityServer
{
public class ResourceStore : IResourceStore
{
private readonly IIdentityResourceRepository _identityResourceRepository;
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IObjectMapper _objectMapper;
public ResourceStore(
IIdentityResourceRepository identityResourceRepository,
IObjectMapper objectMapper,
IApiResourceRepository apiResourceRepository)
{
_identityResourceRepository = identityResourceRepository;
_objectMapper = objectMapper;
_apiResourceRepository = apiResourceRepository;
}
public virtual async Task<IEnumerable<IdentityServer4.Models.IdentityResource>> FindIdentityResourcesByScopeAsync(IEnumerable<string> scopeNames)
{
var resource = await _identityResourceRepository.GetListByScopesAsync(scopeNames.ToArray(), includeDetails: true);
return _objectMapper.Map<List<IdentityResource>, List<IdentityServer4.Models.IdentityResource>>(resource);
}
public virtual async Task<IEnumerable<ApiResource>> FindApiResourcesByScopeAsync(IEnumerable<string> scopeNames)
{
var resources = await _apiResourceRepository.GetListByScopesAsync(scopeNames.ToArray(), includeDetails: true);
return resources.Select(x => _objectMapper.Map<ApiResources.ApiResource, ApiResource>(x));
}
public virtual async Task<ApiResource> FindApiResourceAsync(string name)
{
var resource = await _apiResourceRepository.FindByNameAsync(name);
return _objectMapper.Map<ApiResources.ApiResource, ApiResource>(resource);
}
public virtual async Task<Resources> GetAllResourcesAsync()
{
var identityResources = await _identityResourceRepository.GetListAsync(includeDetails: true);
var apiResources = await _apiResourceRepository.GetListAsync(includeDetails: true);
return new Resources(
_objectMapper.Map<List<IdentityResource>, IdentityServer4.Models.IdentityResource[]>(identityResources),
_objectMapper.Map<List<ApiResources.ApiResource>, ApiResource[]>(apiResources)
);
}
}
}

37
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs

@ -0,0 +1,37 @@
using System;
using IdentityServer4;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer
{
public abstract class Secret : Entity
{
public virtual string Type { get; protected set; }
public virtual string Value { get; set; }
public virtual string Description { get; set; }
public virtual DateTime? Expiration { get; set; }
protected Secret()
{
}
protected Secret(
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null)
{
Check.NotNull(value, nameof(value));
Value = value;
Expiration = expiration;
Type = type;
Description = description;
}
}
}

37
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs

@ -0,0 +1,37 @@
namespace Volo.Abp.IdentityServer.Temp
{
//TODO: Remove!
//internal static class IdentityServerConfig
//{
// public static IEnumerable<ApiResource> GetApiResources()
// {
// return new List<ApiResource>
// {
// new ApiResource("api1", "My API")
// };
// }
// public static IEnumerable<IdentityServer4.Models.Client> GetClients()
// {
// return new List<Client>
// {
// new Client
// {
// ClientId = "client",
// // no interactive user, use the clientid/secret for authentication
// AllowedGrantTypes = GrantTypes.ClientCredentials,
// // secret for authentication
// ClientSecrets =
// {
// new IdentityServer4.Models.Secret("secret".Sha256())
// },
// // scopes that client has access to
// AllowedScopes = { "api1" }
// }
// };
// }
//}
}

22
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/UserClaim.cs

@ -0,0 +1,22 @@
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer
{
public abstract class UserClaim : Entity
{
public virtual string Type { get; protected set; }
protected UserClaim()
{
}
protected UserClaim([NotNull] string type)
{
Check.NotNull(type, nameof(type));
Type = type;
}
}
}

22
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.EntityFrameworkCore</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.EntityFrameworkCore</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.IdentityServer.Domain\Volo.Abp.IdentityServer.Domain.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.EntityFrameworkCore\Volo.Abp.EntityFrameworkCore.csproj" />
</ItemGroup>
</Project>

2
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj.DotSettings

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

55
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/AbpIdentityServerEfCoreQueryableExtensions.cs

@ -0,0 +1,55 @@
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer
{
public static class AbpIdentityServerEfCoreQueryableExtensions
{
public static IQueryable<ApiResource> IncludeDetails(this IQueryable<ApiResource> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
.Include(x => x.Secrets)
.Include(x => x.UserClaims)
.Include(x => x.Scopes)
.ThenInclude(s => s.UserClaims);
}
public static IQueryable<IdentityResource> IncludeDetails(this IQueryable<IdentityResource> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
.Include(x => x.UserClaims);
}
public static IQueryable<Client> IncludeDetails(this IQueryable<Client> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
.Include(x => x.AllowedGrantTypes)
.Include(x => x.RedirectUris)
.Include(x => x.PostLogoutRedirectUris)
.Include(x => x.AllowedScopes)
.Include(x => x.ClientSecrets)
.Include(x => x.Claims)
.Include(x => x.IdentityProviderRestrictions)
.Include(x => x.AllowedCorsOrigins)
.Include(x => x.Properties);
}
}
}

59
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs

@ -0,0 +1,59 @@
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.ApiResources
{
public class ApiResourceRepository : EfCoreRepository<IIdentityServerDbContext, ApiResource, Guid>, IApiResourceRepository
{
public ApiResourceRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<ApiResource> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
var query = from apiResource in DbSet.IncludeDetails(includeDetails)
where apiResource.Name == name
select apiResource;
return await query
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<ApiResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var query = from api in DbSet.IncludeDetails(includeDetails)
where api.Scopes.Any(x => scopeNames.Contains(x.Name))
select api;
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<ApiResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await DbSet
.IncludeDetails(includeDetails)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public override IQueryable<ApiResource> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

34
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs

@ -0,0 +1,34 @@
using System;
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.Clients
{
public class ClientRepository : EfCoreRepository<IIdentityServerDbContext, Client, Guid>, IClientRepository
{
public ClientRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<Client> FindByCliendIdAsync(
string clientId,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await DbSet
.IncludeDetails(includeDetails)
.FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken));
}
public override IQueryable<Client> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

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

@ -0,0 +1,28 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.Modularity;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
[DependsOn(typeof(AbpIdentityServerDomainModule))]
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class AbpIdentityServerEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<IdentityServerDbContext>(options =>
{
options.AddDefaultRepositories<IIdentityServerDbContext>();
options.AddRepository<Client, ClientRepository>();
options.AddRepository<ApiResource, ApiResourceRepository>();
options.AddRepository<IdentityResource, IdentityResourceRepository>();
options.AddRepository<PersistedGrant, PersistentGrantRepository>();
});
}
}
}

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

@ -0,0 +1,50 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
[ConnectionStringName("AbpIdentityServer")]
public interface IIdentityServerDbContext : IEfCoreDbContext
{
DbSet<ApiResource> ApiResources { get; set; }
DbSet<ApiSecret> ApiSecrets { get; set; }
DbSet<ApiResourceClaim> ApiResourceClaims { get; set; }
DbSet<ApiScope> ApiScopes { get; set; }
DbSet<ApiScopeClaim> ApiScopeClaims { get; set; }
DbSet<IdentityResource> IdentityResources { get; set; }
DbSet<IdentityClaim> IdentityClaims { get; set; }
DbSet<Client> Clients { get; set; }
DbSet<ClientGrantType> ClientGrantTypes { get; set; }
DbSet<ClientRedirectUri> ClientRedirectUris { get; set; }
DbSet<ClientPostLogoutRedirectUri> ClientPostLogoutRedirectUris { get; set; }
DbSet<ClientScope> ClientScopes { get; set; }
DbSet<ClientSecret> ClientSecrets { get; set; }
DbSet<ClientClaim> ClientClaims { get; set; }
DbSet<ClientIdPRestriction> ClientIdPRestrictions { get; set; }
DbSet<ClientCorsOrigin> ClientCorsOrigins { get; set; }
DbSet<ClientProperty> ClientProperties { get; set; }
DbSet<PersistedGrant> PersistedGrants { get; set; }
}
}

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

@ -0,0 +1,66 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
[ConnectionStringName("AbpIdentityServer")]
public class IdentityServerDbContext : AbpDbContext<IdentityServerDbContext>, IIdentityServerDbContext
{
public static string TablePrefix { get; set; } = AbpIdentityServerConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = AbpIdentityServerConsts.DefaultDbSchema;
public DbSet<ApiResource> ApiResources { get; set; }
public DbSet<ApiSecret> ApiSecrets { get; set; }
public DbSet<ApiResourceClaim> ApiResourceClaims { get; set; }
public DbSet<ApiScope> ApiScopes { get; set; }
public DbSet<ApiScopeClaim> ApiScopeClaims { get; set; }
public DbSet<IdentityResource> IdentityResources { get; set; }
public DbSet<IdentityClaim> IdentityClaims { get; set; }
public DbSet<Client> Clients { get; set; }
public DbSet<ClientGrantType> ClientGrantTypes { get; set; }
public DbSet<ClientRedirectUri> ClientRedirectUris { get; set; }
public DbSet<ClientPostLogoutRedirectUri> ClientPostLogoutRedirectUris { get; set; }
public DbSet<ClientScope> ClientScopes { get; set; }
public DbSet<ClientSecret> ClientSecrets { get; set; }
public DbSet<ClientClaim> ClientClaims { get; set; }
public DbSet<ClientIdPRestriction> ClientIdPRestrictions { get; set; }
public DbSet<ClientCorsOrigin> ClientCorsOrigins { get; set; }
public DbSet<ClientProperty> ClientProperties { get; set; }
public DbSet<PersistedGrant> PersistedGrants { get; set; }
public IdentityServerDbContext(DbContextOptions<IdentityServerDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureIdentityServer(TablePrefix, Schema);
}
}
}

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

@ -0,0 +1,228 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
public static class IdentityServerDbContextModelCreatingExtensions
{
public static void ConfigureIdentityServer(
this ModelBuilder builder,
[CanBeNull] string tablePrefix = AbpIdentityServerConsts.DefaultDbTablePrefix,
[CanBeNull] string schema = AbpIdentityServerConsts.DefaultDbSchema)
{
Check.NotNull(builder, nameof(builder));
if (tablePrefix == null)
{
tablePrefix = "";
}
builder.Entity<Client>(client =>
{
client.ToTable(tablePrefix + "Clients", schema);
client.Property(x => x.ClientId).HasMaxLength(ClientConsts.ClientIdMaxLength).IsRequired();
client.Property(x => x.ProtocolType).HasMaxLength(ClientConsts.ProtocolTypeMaxLength).IsRequired();
client.Property(x => x.ClientName).HasMaxLength(ClientConsts.ClientNameMaxLength);
client.Property(x => x.ClientUri).HasMaxLength(ClientConsts.ClientUriMaxLength);
client.Property(x => x.LogoUri).HasMaxLength(ClientConsts.LogoUriMaxLength);
client.Property(x => x.Description).HasMaxLength(ClientConsts.DescriptionMaxLength);
client.Property(x => x.FrontChannelLogoutUri).HasMaxLength(ClientConsts.FrontChannelLogoutUriMaxLength);
client.Property(x => x.BackChannelLogoutUri).HasMaxLength(ClientConsts.BackChannelLogoutUriMaxLength);
client.Property(x => x.ClientClaimsPrefix).HasMaxLength(ClientConsts.ClientClaimsPrefixMaxLength);
client.Property(x => x.PairWiseSubjectSalt).HasMaxLength(ClientConsts.PairWiseSubjectSaltMaxLength);
client.HasMany(x => x.AllowedScopes).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.ClientSecrets).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.AllowedGrantTypes).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.AllowedCorsOrigins).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.RedirectUris).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.PostLogoutRedirectUris).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.IdentityProviderRestrictions).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.Claims).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.Properties).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasIndex(x => x.ClientId).IsUnique();
});
builder.Entity<ClientGrantType>(grantType =>
{
grantType.ToTable(tablePrefix + "ClientGrantTypes", schema);
grantType.HasKey(x => new { x.ClientId, x.GrantType });
grantType.Property(x => x.GrantType).HasMaxLength(ClientGrantTypeConsts.GrantTypeMaxLength).IsRequired();
});
builder.Entity<ClientRedirectUri>(redirectUri =>
{
redirectUri.ToTable(tablePrefix + "ClientRedirectUris", schema);
redirectUri.HasKey(x => new { x.ClientId, x.RedirectUri });
redirectUri.Property(x => x.RedirectUri).HasMaxLength(ClientRedirectUriConsts.RedirectUriMaxLength).IsRequired();
});
builder.Entity<ClientPostLogoutRedirectUri>(postLogoutRedirectUri =>
{
postLogoutRedirectUri.ToTable(tablePrefix + "ClientPostLogoutRedirectUris", schema);
postLogoutRedirectUri.HasKey(x => new { x.ClientId, x.PostLogoutRedirectUri });
postLogoutRedirectUri.Property(x => x.PostLogoutRedirectUri).HasMaxLength(ClientPostLogoutRedirectUriConsts.PostLogoutRedirectUriMaxLength).IsRequired();
});
builder.Entity<ClientScope>(scope =>
{
scope.ToTable(tablePrefix + "ClientScopes", schema);
scope.HasKey(x => new { x.ClientId, x.Scope });
scope.Property(x => x.Scope).HasMaxLength(ClientScopeConsts.ScopeMaxLength).IsRequired();
});
builder.Entity<ClientSecret>(secret =>
{
secret.ToTable(tablePrefix + "ClientSecrets", schema);
secret.HasKey(x => new { x.ClientId, x.Type, x.Value });
secret.Property(x => x.Type).HasMaxLength(SecretConsts.TypeMaxLength).IsRequired();
secret.Property(x => x.Value).HasMaxLength(SecretConsts.ValueMaxLength).IsRequired();
secret.Property(x => x.Description).HasMaxLength(SecretConsts.DescriptionMaxLength);
});
builder.Entity<ClientClaim>(claim =>
{
claim.ToTable(tablePrefix + "ClientClaims", schema);
claim.Property(x => x.Type).HasMaxLength(ClientClaimConsts.TypeMaxLength).IsRequired();
claim.Property(x => x.Value).HasMaxLength(ClientClaimConsts.ValueMaxLength).IsRequired();
});
builder.Entity<ClientIdPRestriction>(idPRestriction =>
{
idPRestriction.ToTable(tablePrefix + "ClientIdPRestrictions", schema);
idPRestriction.HasKey(x => new { x.ClientId, x.Provider });
idPRestriction.Property(x => x.Provider).HasMaxLength(ClientIdPRestrictionConsts.ProviderMaxLength).IsRequired();
});
builder.Entity<ClientCorsOrigin>(corsOrigin =>
{
corsOrigin.ToTable(tablePrefix + "ClientCorsOrigins", schema);
corsOrigin.HasKey(x => new { x.ClientId, x.Origin });
corsOrigin.Property(x => x.Origin).HasMaxLength(ClientCorsOriginConsts.OriginMaxLength).IsRequired();
});
builder.Entity<ClientProperty>(property =>
{
property.ToTable(tablePrefix + "ClientProperties", schema);
property.HasKey(x => new { x.ClientId, x.Key });
property.Property(x => x.Key).HasMaxLength(ClientPropertyConsts.KeyMaxLength).IsRequired();
property.Property(x => x.Value).HasMaxLength(ClientPropertyConsts.ValueMaxLength).IsRequired();
});
builder.Entity<PersistedGrant>(grant =>
{
grant.ToTable(tablePrefix + "PersistedGrants", schema);
grant.Property(x => x.Key).HasMaxLength(PersistedGrantConsts.KeyMaxLength).ValueGeneratedNever();
grant.Property(x => x.Type).HasMaxLength(PersistedGrantConsts.TypeMaxLength).IsRequired();
grant.Property(x => x.SubjectId).HasMaxLength(PersistedGrantConsts.SubjectIdMaxLength);
grant.Property(x => x.ClientId).HasMaxLength(PersistedGrantConsts.ClientIdMaxLength).IsRequired();
grant.Property(x => x.CreationTime).IsRequired();
grant.Property(x => x.Data).IsRequired();
grant.HasKey(x => x.Key); //TODO: What about Id!!!
grant.HasIndex(x => new { x.SubjectId, x.ClientId, x.Type });
});
builder.Entity<IdentityResource>(identityResource =>
{
identityResource.ToTable(tablePrefix + "IdentityResources", schema);
identityResource.Property(x => x.Name).HasMaxLength(IdentityResourceConsts.NameMaxLength).IsRequired();
identityResource.Property(x => x.DisplayName).HasMaxLength(IdentityResourceConsts.DisplayNameMaxLength);
identityResource.Property(x => x.Description).HasMaxLength(IdentityResourceConsts.DescriptionMaxLength);
identityResource.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.IdentityResourceId).IsRequired();
});
builder.Entity<IdentityClaim>(claim =>
{
claim.ToTable(tablePrefix + "IdentityClaims", schema);
claim.HasKey(x => new { x.IdentityResourceId, x.Type });
claim.Property(x => x.Type).HasMaxLength(UserClaimConsts.TypeMaxLength).IsRequired();
});
builder.Entity<ApiResource>(apiResource =>
{
apiResource.ToTable(tablePrefix + "ApiResources", schema);
apiResource.Property(x => x.Name).HasMaxLength(ApiResourceConsts.NameMaxLength).IsRequired();
apiResource.Property(x => x.DisplayName).HasMaxLength(ApiResourceConsts.DisplayNameMaxLength);
apiResource.Property(x => x.Description).HasMaxLength(ApiResourceConsts.DescriptionMaxLength);
apiResource.HasMany(x => x.Secrets).WithOne().HasForeignKey(x => x.ApiResourceId).IsRequired();
apiResource.HasMany(x => x.Scopes).WithOne().HasForeignKey(x => x.ApiResourceId).IsRequired();
apiResource.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.ApiResourceId).IsRequired();
});
builder.Entity<ApiSecret>(apiSecret =>
{
apiSecret.ToTable(tablePrefix + "ApiSecrets", schema);
apiSecret.HasKey(x => new { x.ApiResourceId, x.Type, x.Value });
apiSecret.Property(x => x.Type).HasMaxLength(SecretConsts.TypeMaxLength).IsRequired();
apiSecret.Property(x => x.Value).HasMaxLength(SecretConsts.ValueMaxLength).IsRequired();
apiSecret.Property(x => x.Description).HasMaxLength(SecretConsts.DescriptionMaxLength);
});
builder.Entity<ApiResourceClaim>(apiClaim =>
{
apiClaim.ToTable(tablePrefix + "ApiClaims", schema);
apiClaim.HasKey(x => new { x.ApiResourceId, x.Type });
apiClaim.Property(x => x.Type).HasMaxLength(UserClaimConsts.TypeMaxLength).IsRequired();
});
builder.Entity<ApiScope>(apiScope =>
{
apiScope.ToTable(tablePrefix + "ApiScopes", schema);
apiScope.HasKey(x => new { x.ApiResourceId, x.Name });
apiScope.Property(x => x.Name).HasMaxLength(ApiScopeConsts.NameMaxLength).IsRequired();
apiScope.Property(x => x.DisplayName).HasMaxLength(ApiScopeConsts.DisplayNameMaxLength);
apiScope.Property(x => x.Description).HasMaxLength(ApiScopeConsts.DescriptionMaxLength);
apiScope.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => new { x.ApiResourceId, x.Name }).IsRequired();
});
builder.Entity<ApiScopeClaim>(apiScopeClaim =>
{
apiScopeClaim.ToTable(tablePrefix + "ApiScopeClaims", schema);
apiScopeClaim.HasKey(x => new { x.ApiResourceId, x.Name, x.Type });
apiScopeClaim.Property(x => x.Type).HasMaxLength(UserClaimConsts.TypeMaxLength).IsRequired();
apiScopeClaim.Property(x => x.Name).HasMaxLength(ApiScopeConsts.NameMaxLength).IsRequired();
});
}
}
}

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

@ -0,0 +1,60 @@
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.Grants
{
public class PersistentGrantRepository : EfCoreRepository<IIdentityServerDbContext, PersistedGrant, Guid>, IPersistentGrantRepository
{
public PersistentGrantRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public Task<PersistedGrant> FindByKeyAsync(
string key,
CancellationToken cancellationToken = default)
{
return DbSet
.FirstOrDefaultAsync(x => x.Key == key, GetCancellationToken(cancellationToken));
}
public Task<List<PersistedGrant>> GetListBySubjectIdAsync(
string subjectId,
CancellationToken cancellationToken = default)
{
return DbSet
.Where(x => x.SubjectId == subjectId)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task DeleteAsync(
string subjectId,
string clientId,
CancellationToken cancellationToken = default)
{
await DeleteAsync(
x => x.SubjectId == subjectId && x.ClientId == clientId,
cancellationToken: GetCancellationToken(cancellationToken)
);
}
public async Task DeleteAsync(
string subjectId,
string clientId,
string type,
CancellationToken cancellationToken = default)
{
await DeleteAsync(
x => x.SubjectId == subjectId && x.ClientId == clientId && x.Type == type,
cancellationToken: GetCancellationToken(cancellationToken)
);
}
}
}

47
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs

@ -0,0 +1,47 @@
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.IdentityResources
{
public class IdentityResourceRepository : EfCoreRepository<IIdentityServerDbContext, IdentityResource, Guid>, IIdentityResourceRepository
{
public IdentityResourceRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<List<IdentityResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var query = from identityResource in DbSet.IncludeDetails(includeDetails)
where scopeNames.Contains(identityResource.Name)
select identityResource;
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<IdentityResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await DbSet
.IncludeDetails(includeDetails)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public override IQueryable<IdentityResource> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

33
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests.csproj

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.EntityFrameworkCore.Tests</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.EntityFrameworkCore.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.IdentityServer.EntityFrameworkCore\Volo.Abp.IdentityServer.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\modules\identity\src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.TestBase\Volo.Abp.TestBase.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.1.0" />
<PackageReference Include="NSubstitute" Version="3.1.0" />
<PackageReference Include="Shouldly" Version="3.0.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.extensibility.execution" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>
</Project>

10
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityApplicationTestBase.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerTestBase : AbpIntegratedTest<AbpIdentityServerTestEntityFrameworkCoreModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

129
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs

@ -0,0 +1,129 @@
using IdentityServer4.Models;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
using Client = Volo.Abp.IdentityServer.Clients.Client;
using IdentityResource = Volo.Abp.IdentityServer.IdentityResources.IdentityResource;
using PersistedGrant = Volo.Abp.IdentityServer.Grants.PersistedGrant;
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerTestDataBuilder : ITransientDependency
{
private readonly IGuidGenerator _guidGenerator;
private readonly IClientRepository _clientRepository;
private readonly IPersistentGrantRepository _persistentGrantRepository;
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IIdentityResourceRepository _identityResourceRepository;
public AbpIdentityServerTestDataBuilder(
IClientRepository clientRepository,
IGuidGenerator guidGenerator,
IPersistentGrantRepository persistentGrantRepository,
IApiResourceRepository apiResourceRepository,
IIdentityResourceRepository identityResourceRepository)
{
_clientRepository = clientRepository;
_guidGenerator = guidGenerator;
_persistentGrantRepository = persistentGrantRepository;
_apiResourceRepository = apiResourceRepository;
_identityResourceRepository = identityResourceRepository;
}
public void Build()
{
AddClients();
AddPersistentGrants();
AddApiResources();
AddIdentityResources();
}
private void AddClients()
{
var client42 = new Client(_guidGenerator.Create(), "42")
{
ProtocolType = "TestProtocol-42"
};
client42.AddCorsOrigin("Origin1");
client42.AddScope("api1");
_clientRepository.Insert(client42);
}
private void AddPersistentGrants()
{
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "38",
ClientId = "TestClientId-38",
Type = "TestType-38",
SubjectId = "TestSubject",
Data = "TestData-38"
});
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "37",
ClientId = "TestClientId-37",
Type = "TestType-37",
SubjectId = "TestSubject",
Data = "TestData-37"
});
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "36",
ClientId = "TestClientId-X",
Type = "TestType-36",
SubjectId = "TestSubject-X",
Data = "TestData-36"
});
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "35",
ClientId = "TestClientId-X",
Type = "TestType-35",
SubjectId = "TestSubject-X",
Data = "TestData-35"
});
}
private void AddApiResources()
{
var apiResource = new ApiResource(_guidGenerator.Create(), "Test-ApiResource-Name-1")
{
Enabled = true,
Description = "Test-ApiResource-Description-1",
DisplayName = "Test-ApiResource-DisplayName-1"
};
apiResource.AddSecret("secret".Sha256());
apiResource.AddScope("Test-ApiResource-ApiScope-Name-1", "Test-ApiResource-ApiScope-DisplayName-1");
apiResource.AddUserClaim("Test-ApiResource-Claim-Type-1");
_apiResourceRepository.Insert(apiResource);
}
private void AddIdentityResources()
{
var identityResource = new IdentityResource(_guidGenerator.Create(), "Test-Identity-Resource-Name-1")
{
Description = "Test-Identity-Resource-Description-1",
DisplayName = "Test-Identity-Resource-DisplayName-1",
Required = true,
Emphasize = true
};
identityResource.AddUserClaim("Test-Identity-Resource-1-IdentityClaim-Type-1");
_identityResourceRepository.Insert(identityResource);
}
}
}

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

Loading…
Cancel
Save