Browse Source

Merge pull request #1 from abpframework/master

sync fork
pull/509/head
Yuhang Ji 7 years ago
committed by GitHub
parent
commit
57c7acd76b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      docs/Best-Practices/Index.md
  2. 4
      docs/Getting-Started-Console-Application.md
  3. 1
      docs/Tutorials/AspNetCore-Mvc/Part-I.md
  4. 38
      docs/Virtual-File-System.md
  5. 1
      modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
  6. 1
      modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json
  7. 14
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
  8. 7
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs
  9. 23
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/detail.js
  10. BIN
      modules/docs/screenshot.png
  11. 14
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json
  12. 2
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs
  13. 2
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs
  14. 6
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs
  15. 6
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs
  16. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleClaim.cs
  17. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserClaim.cs
  18. 1
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs
  19. 33
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs
  20. 35
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs
  21. 24
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs
  22. 25
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs
  23. 21
      modules/identityserver/Volo.Abp.IdentityServer.sln
  24. 24
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj
  25. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo.Abp.IdentityServer.MongoDB.csproj
  26. 37
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs
  27. 34
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContext.cs
  28. 42
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContextExtensions.cs
  29. 30
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbModule.cs
  30. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IAbpIdentityServerMongoDbContext.cs
  31. 12
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IdentityServerMongoModelBuilderConfigurationOptions.cs
  32. 36
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs
  33. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs
  34. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs
  35. 49
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs
  36. 7
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs
  37. 24
      modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj
  38. 33
      modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs
  39. 7
      modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs
  40. 11
      modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs
  41. 10
      modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs
  42. 29
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo.Abp.IdentityServer.TestBase.csproj
  43. 16
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBase.cs
  44. 38
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBaseModule.cs
  45. 68
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs
  46. 32
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs
  47. 29
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ClientRepository_Tests.cs
  48. 28
      modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs

10
docs/Best-Practices/Index.md

@ -2,13 +2,13 @@
### Introduction
This document describes the **best practices** and **conventions** for who want to develop **modules** that satisfies the following specifications:
This document describes the **best practices** and **conventions** for those who want to develop **modules** that satisfy the following specifications:
* Develop the module that applies the **Domain Driven Design** patterns & best practices.
* Develop the module as **DBMS and ORM independent**.
* Develop the module that can be used as a **remote service / microservice** as well as can be integrated to a **monolithic** application.
* Develop modules that conform to the **Domain Driven Design** patterns & best practices.
* Develop modules with **DBMS and ORM independence**.
* Develop modules that can be used as a **remote service / microservice** as well as being compatible with a **monolithic** application.
Also, this guide is mostly usable for the **application development**.
Also, this guide is mostly usable for general **application development**.
### Guides

4
docs/Getting-Started-Console-Application.md

@ -1,6 +1,6 @@
## Getting Started ABP With Console Application
This tutorial explains how to start ABP from scratch with minimal dependencies. You generally want to start with a ***[startup template](https://abp.io/Templates)***.
This tutorial explains how to start ABP from scratch with minimal dependencies. You generally want to start with a **[startup template](https://abp.io/Templates)**.
### Create A New Project
@ -121,4 +121,4 @@ While it's enough for this simple code example, it's always suggested to create
### Source Code
Get source code of the sample project created in this tutorial from [here](../samples/BasicConsoleApplication).
Get source code of the sample project created in this tutorial from [here](../samples/BasicConsoleApplication).

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

@ -173,7 +173,6 @@ 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 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

38
docs/Virtual-File-System.md

@ -1,16 +1,16 @@
## Virtual File System
The Virtual File System makes it possible to manage files that do not physically exist on the file system (disk). It's mainly used to embed (js, css, image, cshtml...) files into assemblies and use them like physical files on runtime.
The Virtual File System makes it possible to manage files that do not physically exist on the file system (disk). It's mainly used to embed (js, css, image, cshtml...) files into assemblies and use them like physical files at runtime.
### Volo.Abp.VirtualFileSystem Package
Volo.Abp.VirtualFileSystem is the core package of the virtual file system. Install it to your project using the package manager console (PMC):
Volo.Abp.VirtualFileSystem is the core package of the virtual file system. Install it in your project using the package manager console (PMC):
```
Install-Package Volo.Abp.VirtualFileSystem
```
> This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually.
> This package is already installed by default with the startup template. So, most of the time, you will not need to install it manually.
Then you can add **AbpVirtualFileSystemModule** dependency to your module:
@ -30,7 +30,7 @@ namespace MyCompany.MyProject
#### Registering Embedded Files
A file should be first marked as embedded resource to embed the file into the assembly. The easiest way to do it is to select the file from the **Solution Explorer** and set **Build Action** to **Embedded Resource** from the **Properties** window. Example:
A file should be first marked as an embedded resource to embed the file into the assembly. The easiest way to do it is to select the file from the **Solution Explorer** and set **Build Action** to **Embedded Resource** from the **Properties** window. Example:
![build-action-embedded-resource-sample](images/build-action-embedded-resource-sample.png)
@ -44,7 +44,7 @@ If you want to add multiple files, this can be tedious. Alternatively, you can d
This configuration recursively adds all files under the **MyResources** folder of the project (including the files you will add in the future).
Then the module should be configured using `VirtualFileSystemOptions` to register the embedded files to the virtual file system. Example:
Then the module needs to be configured using `VirtualFileSystemOptions` to register the embedded files to the virtual file system. Example:
````C#
using Microsoft.Extensions.DependencyInjection;
@ -70,7 +70,7 @@ namespace MyCompany.MyProject
}
````
The `AddEmbedded` extension method takes a class, finds all embedded files from the assembly of the given class and registers them to the virtual file system. More concisely it could be written as shown below:
The `AddEmbedded` extension method takes a class, finds all embedded files from the assembly of the given class and registers them to the virtual file system. More concisely it could be written as follows:
````C#
options.FileSets.Add(new EmbeddedFileSet(typeof(MyModule).Assembly));
@ -78,7 +78,7 @@ options.FileSets.Add(new EmbeddedFileSet(typeof(MyModule).Assembly));
#### Getting Virtual Files: IVirtualFileProvider
After embedding a file into an assembly and registering to the virtual file system, `IVirtualFileProvider` can be used to get files or directory contents:
After embedding a file into an assembly and registering it to the virtual file system, the `IVirtualFileProvider` interface can be used to get files or directory contents:
````C#
public class MyService
@ -104,13 +104,13 @@ public class MyService
#### Dealing With Embedded Files During Development
Embedding a file into a module assembly and using it from another project by just referencing the assembly (or adding a nuget package) is very valuable for creating a re-usable module. However, it makes it a bit hard to develop the module itself.
Embedding a file into a module assembly and being able to use it from another project just by referencing the assembly (or adding a nuget package) is invaluable for creating a re-usable module. However, it does make it a little bit harder to develop the module itself.
Assume that you are developing a module that contains an embedded JavaScript file. Whenever you change the file you must re-compile the project, re-start the application and refresh the browser page to take the change. Obviously, it is very time consuming and tedious.
Let's assume that you're developing a module that contains an embedded JavaScript file. Whenever you change this file you must re-compile the project, re-start the application and refresh the browser page to take the change. Obviously, this is very time consuming and tedious.
What is needed is the ability for the application to directly use the physical file at development time and a browser refresh shows any change in the JavaScript file. `ReplaceEmbeddedByPyhsical` method makes that possible.
What is needed is the ability for the application to directly use the physical file at development time and a have a browser refresh reflect any change made in the JavaScript file. The `ReplaceEmbeddedByPyhsical` method makes all this possible.
The example below shows an application depends on a module (`MyModule`) that contains embedded files and the application can reach the source code of the module on the development time.
The example below shows an application that depends on a module (`MyModule`) that itself contains embedded files. The application can reach the source code of the module at development time.
````C#
[DependsOn(typeof(MyModule))]
@ -140,26 +140,26 @@ The code above assumes that `MyWebAppModule` and `MyModule` are two different pr
### ASP.NET Core Integration
Virtual File System is well integrated to ASP.NET Core:
The Virtual File System is well integrated to ASP.NET Core:
* Virtual files can be used just like physical (static) files on a web application.
* Razor Views, Razor Pages, js, css, image files and all other web contents can be embedded into assemblies and used just like the physical files.
* Virtual files can be used just like physical (static) files in a web application.
* Razor Views, Razor Pages, js, css, image files and all other web content types can be embedded into assemblies and used just like the physical files.
* An application (or another module) can override a virtual file of a module just like placing a file with the same name and extension into the same folder of the virtual file.
#### Virtual Files Middleware
Virtual Files Middleware is used to serve embedded (js, css, image...) files to clients/browsers just like physical files in the **wwwroot** folder. Add it just after the static file middleware as shown below:
The Virtual Files Middleware is used to serve embedded (js, css, image...) files to clients/browsers just like physical files in the **wwwroot** folder. Add it just after the static file middleware as shown below:
````C#
app.UseVirtualFiles();
````
Adding virtual files middleware after the static files middleware makes it possible to override a virtual file by a physical file by placing in the same location.
Adding virtual files middleware after the static files middleware makes it possible to override a virtual file with a real physical file simply by placing it in the same location as the virtual file.
> Virtual Files Middleware only serves the virtual wwwroot folder contents just like the static files.
>The Virtual File Middleware only serves the virtual wwwroot folder contents - just like the other static files.
#### Views & Pages
Embedded razor views/pages are available in the application without any configuration. Just place them into standard Views/Pages virtual folders in the module development.
Embedded razor views/pages are available in the application without any configuration. Simply place them into the standard Views/Pages virtual folders of the module being developed.
An embedded view/page can be overrided if a module/application locates a new file into the same location.
An embedded view/page can be overrided if a module/application locates a new file into the same location as mentioned above.

1
modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json

@ -6,6 +6,7 @@
"Title": "Title",
"Delete": "Delete",
"Reply": "Reply",
"ReplyTo": "Reply To {0}",
"ContinueReading": "Continue Reading",
"DaysAgo": "{0} days ago",
"YearsAgo": "{0} years ago",

1
modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json

@ -5,6 +5,7 @@
"Title": "Başlık",
"Delete": "Sil",
"Reply": "Yanıtla",
"ReplyTo": "{0}'a cevap ver",
"Menu:BlogManagement": "Blog Yönetimi",
"ContinueReading": "Devamı...",
"DaysAgo": "{0} Gün Önce",

14
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml

@ -23,6 +23,9 @@
<abp-style src="/Pages/Blog/Shared/Styles/blog.css" />
</abp-style-bundle>
}
<abp-input asp-for="FocusCommentId"/>
<div class="vs-blog">
<div class="row">
<div class="col-md-12 mx-auto">
@ -173,8 +176,8 @@
<div class="comment-form mt-4 replyForm">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">
@L["ReplyTo"]
@(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName)
@L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName]
</h3>
<div>
<form method="post">
@ -185,6 +188,7 @@
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Comment"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
</div>
@ -201,6 +205,7 @@
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@commentWithRepliesDto.Comment.Text</textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
</div>
@ -249,8 +254,7 @@
<div class="comment-form mt-4 replyForm">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">
@L["ReplyTo"]
@(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName)
@L["ReplyTo",commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName]
</h3>
<div>
<form method="post">
@ -260,6 +264,7 @@
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
</div>
@ -276,6 +281,7 @@
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@reply.Text</textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value" />
</form>
</div>
</div>

7
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs

@ -31,6 +31,9 @@ namespace Volo.Blogging.Pages.Blog.Posts
public int CommentCount { get; set; }
[HiddenInput]
public Guid FocusCommentId { get; set; }
public PostWithDetailsDto Post { get; set; }
public IReadOnlyList<CommentWithRepliesDto> CommentsWithReplies { get; set; }
@ -51,13 +54,15 @@ namespace Volo.Blogging.Pages.Blog.Posts
public async Task OnPostAsync()
{
await _commentAppService.CreateAsync(new CreateCommentDto()
var comment = await _commentAppService.CreateAsync(new CreateCommentDto()
{
RepliedCommentId = NewComment.RepliedCommentId,
PostId = NewComment.PostId,
Text = NewComment.Text
});
FocusCommentId = comment.Id;
await GetData();
}

23
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/detail.js

@ -3,6 +3,7 @@
var l = abp.localization.getResource('Blogging');
$('div .replyForm').hide();
$('div .editForm').hide();
$('form[class="editFormClass"]').submit(function (event) {
@ -25,6 +26,16 @@
});
});
$('.editCancelButton').click(function (event) {
event.preventDefault();
$('div .editForm').hide();
});
$('.replyCancelButton').click(function (event) {
event.preventDefault();
$('div .replyForm').hide();
});
$('.replyLink').click(function (event) {
event.preventDefault();
$('div .editForm').hide();
@ -44,7 +55,7 @@
}
});
$('.deleteLink').click(function(event) {
$('.deleteLink').click(function (event) {
event.preventDefault();
var linkElement = $(this);
var deleteCommentId = linkElement.attr('data-deleteid');
@ -53,7 +64,7 @@
abp.message.confirm(
l('CommentDeletionWarningMessage'), // TODO: localize
l('Are you sure?'),
function(isConfirmed) {
function (isConfirmed) {
if (isConfirmed) {
$.ajax({
type: "POST",
@ -79,7 +90,7 @@
abp.message.confirm(
l('PostDeletionWarningMessage'), // TODO: localize
l('AreYouSure'),
function(isConfirmed) {
function (isConfirmed) {
if (isConfirmed) {
$.ajax({
type: "POST",
@ -119,4 +130,10 @@
}
});
if ($('#FocusCommentId').val() != '00000000-0000-0000-0000-000000000000') {
$('html, body').animate({
scrollTop: ($('#' + $('#FocusCommentId').val()).offset().top - 150)
}, 500);
}
})(jQuery);

BIN
modules/docs/screenshot.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 118 KiB

14
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json

@ -0,0 +1,14 @@
{
"culture": "es",
"texts": {
"Documents": "Documentos",
"BackToWebsite": "Regresar al sitio",
"Version": "Versión",
"Edit": "Editar",
"InThisDocument": "En este documento",
"GoToTop": "Subir",
"Projects": "Proyecto(s)",
"NoProjectWarning": "¡Aun no hay proyectos!",
"DocumentNotFound": "¡Oops, no se encontró el documento solicitado!"
}
}

2
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs

@ -36,7 +36,7 @@ namespace Volo.Abp.Identity
[Authorize(IdentityPermissions.Users.Default)]
public async Task<PagedResultDto<IdentityUserDto>> GetListAsync(GetIdentityUsersInput input)
{
var count = await _userRepository.GetCountAsync(); //TODO:
var count = await _userRepository.GetCountAsync(input.Filter); //TODO:
var list = await _userRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter);
return new PagedResultDto<IdentityUserDto>(

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

@ -6,7 +6,7 @@ namespace Volo.Abp.Identity
{
public class IdentityClaimTypeConsts
{
public const int MaxNameLength = 128;
public const int MaxNameLength = 256;
public const int MaxRegexLength = 512;

6
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs

@ -22,6 +22,12 @@ namespace Volo.Abp.Identity
CancellationToken cancellationToken = default
);
Task UpdateClaimsAsync(Guid id, List<IdentityRoleClaim> claims);
Task<List<IdentityRoleClaim>> GetClaimsAsync(
Guid id,
CancellationToken cancellationToken = default);
Task<long> GetCountAsync(
CancellationToken cancellationToken = default
);

6
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs

@ -40,6 +40,8 @@ namespace Volo.Abp.Identity
CancellationToken cancellationToken = default
);
Task UpdateClaimsAsync(Guid id, List<IdentityUserClaim> claims);
Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync(
string normalizedRoleName,
bool includeDetails = false,
@ -61,6 +63,10 @@ namespace Volo.Abp.Identity
CancellationToken cancellationToken = default
);
Task<List<IdentityUserClaim>> GetClaimsAsync(
Guid id,
CancellationToken cancellationToken = default);
Task<long> GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default

2
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleClaim.cs

@ -32,7 +32,7 @@ namespace Volo.Abp.Identity
RoleId = roleId;
}
protected internal IdentityRoleClaim(
public IdentityRoleClaim(
Guid id,
Guid roleId,
[NotNull] string claimType,

2
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserClaim.cs

@ -25,7 +25,7 @@ namespace Volo.Abp.Identity
UserId = userId;
}
protected internal IdentityUserClaim(Guid id, Guid userId, [NotNull] string claimType, string claimValue, Guid? tenantId)
public IdentityUserClaim(Guid id, Guid userId, [NotNull] string claimType, string claimValue, Guid? tenantId)
: base(id, claimType, claimValue, tenantId)
{
UserId = userId;

1
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs

@ -15,6 +15,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
{
options.AddRepository<IdentityUser, EfCoreIdentityUserRepository>();
options.AddRepository<IdentityRole, EfCoreIdentityRoleRepository>();
options.AddRepository<IdentityClaimType, EfCoreIdentityClaimTypeRepository>();
});
}
}

33
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs

@ -7,15 +7,18 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Guids;
namespace Volo.Abp.Identity.EntityFrameworkCore
{
public class EfCoreIdentityRoleRepository : EfCoreRepository<IIdentityDbContext, IdentityRole, Guid>, IIdentityRoleRepository
{
public EfCoreIdentityRoleRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider)
private readonly IGuidGenerator _guidGenerator;
public EfCoreIdentityRoleRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
_guidGenerator = guidGenerator;
}
public virtual async Task<IdentityRole> FindByNormalizedNameAsync(
@ -42,6 +45,32 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task UpdateClaimsAsync(Guid id, List<IdentityRoleClaim> claims)
{
var dbSet = DbContext.Set<IdentityRoleClaim>();
var oldClaims = dbSet.Where(c => c.RoleId == id).ToList();
foreach (var oldClaim in oldClaims)
{
dbSet.Remove(oldClaim);
}
foreach (var claim in claims)
{
dbSet.Add(new IdentityRoleClaim(_guidGenerator.Create(), id, claim.ClaimType, claim.ClaimValue, CurrentTenant.Id));
}
}
public async Task<List<IdentityRoleClaim>> GetClaimsAsync(Guid id, CancellationToken cancellationToken = default)
{
var query = from roleClaim in DbContext.Set<IdentityRoleClaim>()
where roleClaim.RoleId == id
select roleClaim;
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<long> GetCountAsync(CancellationToken cancellationToken = default)
{
return await this.LongCountAsync(GetCancellationToken(cancellationToken));

35
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs

@ -8,15 +8,18 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Guids;
namespace Volo.Abp.Identity.EntityFrameworkCore
{
public class EfCoreIdentityUserRepository : EfCoreRepository<IIdentityDbContext, IdentityUser, Guid>, IIdentityUserRepository
{
public EfCoreIdentityUserRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider)
private readonly IGuidGenerator _guidGenerator;
public EfCoreIdentityUserRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
_guidGenerator = guidGenerator;
}
public virtual async Task<IdentityUser> FindByNormalizedUserNameAsync(
@ -131,6 +134,34 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<IdentityUserClaim>> GetClaimsAsync(
Guid id,
CancellationToken cancellationToken = default)
{
var query = from userClaim in DbContext.Set<IdentityUserClaim>()
where userClaim.UserId == id
select userClaim;
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task UpdateClaimsAsync(Guid id, List<IdentityUserClaim> claims)
{
var dbSet = DbContext.Set<IdentityUserClaim>();
var oldClaims = dbSet.Where(c => c.UserId == id).ToList();
foreach (var oldClaim in oldClaims)
{
dbSet.Remove(oldClaim);
}
foreach (var claim in claims)
{
dbSet.Add(new IdentityUserClaim(_guidGenerator.Create(), id, claim.ClaimType, claim.ClaimValue, CurrentTenant.Id));
}
}
public virtual async Task<long> GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default)

24
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs

@ -7,15 +7,19 @@ using System.Linq.Dynamic.Core;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.Guids;
using Volo.Abp.MongoDB;
namespace Volo.Abp.Identity.MongoDB
{
public class MongoIdentityRoleRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentityRole, Guid>, IIdentityRoleRepository
{
public MongoIdentityRoleRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider)
private readonly IGuidGenerator _guidGenerator;
public MongoIdentityRoleRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
_guidGenerator = guidGenerator;
}
public async Task<IdentityRole> FindByNormalizedNameAsync(
@ -40,6 +44,24 @@ namespace Volo.Abp.Identity.MongoDB
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task UpdateClaimsAsync(Guid id, List<IdentityRoleClaim> claims)
{
var role = await GetAsync(id);
role.Claims.Clear();
foreach (var claim in claims)
{
role.Claims.Add(new IdentityRoleClaim(_guidGenerator.Create(), id, claim.ClaimType, claim.ClaimValue, CurrentTenant.Id));
}
}
public async Task<List<IdentityRoleClaim>> GetClaimsAsync(Guid id, CancellationToken cancellationToken = default)
{
var role = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken));
return role.Claims.ToList();
}
public async Task<long> GetCountAsync(CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()

25
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs

@ -8,16 +8,19 @@ using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.Guids;
using Volo.Abp.MongoDB;
namespace Volo.Abp.Identity.MongoDB
{
public class MongoIdentityUserRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentityUser, Guid>, IIdentityUserRepository
{
public MongoIdentityUserRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider)
private readonly IGuidGenerator _guidGenerator;
public MongoIdentityUserRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
_guidGenerator = guidGenerator;
}
public async Task<IdentityUser> FindByNormalizedUserNameAsync(
@ -118,6 +121,24 @@ namespace Volo.Abp.Identity.MongoDB
return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<IdentityUserClaim>> GetClaimsAsync(Guid id, CancellationToken cancellationToken = default)
{
var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken));
return user.Claims.ToList();
}
public async Task UpdateClaimsAsync(Guid id, List<IdentityUserClaim> claims)
{
var user = await GetAsync(id);
user.Claims.Clear();
foreach (var claim in claims)
{
user.Claims.Add(new IdentityUserClaim(_guidGenerator.Create(), id, claim.ClaimType, claim.ClaimValue, CurrentTenant.Id));
}
}
public async Task<long> GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default)

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

@ -15,6 +15,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2C792EC1-B
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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.IdentityServer.MongoDB", "src\Volo.Abp.IdentityServer.MongoDB\Volo.Abp.IdentityServer.MongoDB.csproj", "{FC6CC65A-27B9-43D4-8F20-D941B4987B2C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.IdentityServer.TestBase", "test\Volo.Abp.IdentityServer.TestBase\Volo.Abp.IdentityServer.TestBase.csproj", "{9CD1BFDB-DD76-4194-ACAD-A64541AC2069}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.IdentityServer.MongoDB.Tests", "test\Volo.Abp.IdentityServer.MongoDB.Tests\Volo.Abp.IdentityServer.MongoDB.Tests.csproj", "{2E18B471-7FCA-497B-90FF-6AA9172CC62F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -37,6 +43,18 @@ Global
{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
{FC6CC65A-27B9-43D4-8F20-D941B4987B2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC6CC65A-27B9-43D4-8F20-D941B4987B2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC6CC65A-27B9-43D4-8F20-D941B4987B2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC6CC65A-27B9-43D4-8F20-D941B4987B2C}.Release|Any CPU.Build.0 = Release|Any CPU
{9CD1BFDB-DD76-4194-ACAD-A64541AC2069}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9CD1BFDB-DD76-4194-ACAD-A64541AC2069}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9CD1BFDB-DD76-4194-ACAD-A64541AC2069}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9CD1BFDB-DD76-4194-ACAD-A64541AC2069}.Release|Any CPU.Build.0 = Release|Any CPU
{2E18B471-7FCA-497B-90FF-6AA9172CC62F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2E18B471-7FCA-497B-90FF-6AA9172CC62F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E18B471-7FCA-497B-90FF-6AA9172CC62F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E18B471-7FCA-497B-90FF-6AA9172CC62F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -46,6 +64,9 @@ Global
{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}
{FC6CC65A-27B9-43D4-8F20-D941B4987B2C} = {59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}
{9CD1BFDB-DD76-4194-ACAD-A64541AC2069} = {2C792EC1-BA27-44ED-B7CC-D0939553F1B2}
{2E18B471-7FCA-497B-90FF-6AA9172CC62F} = {2C792EC1-BA27-44ED-B7CC-D0939553F1B2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {45562023-C330-4060-A583-2BA10F472D3D}

24
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.MongoDB.Tests</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.MongoDB.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.IdentityServer.MongoDB\Volo.Abp.IdentityServer.MongoDB.csproj" />
<ProjectReference Include="..\Volo.Abp.IdentityServer.TestBase\Volo.Abp.IdentityServer.TestBase.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="Mongo2Go" Version="2.2.1" />
</ItemGroup>
</Project>

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

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.MongoDB</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.MongoDB</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.MongoDB\Volo.Abp.MongoDB.csproj" />
</ItemGroup>
</Project>

37
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs

@ -0,0 +1,37 @@
using MongoDB.Bson.Serialization;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.Threading;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class AbpIdentityServerBsonClassMap
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
BsonClassMap.RegisterClassMap<ApiResource>(map =>
{
map.AutoMap();
});
BsonClassMap.RegisterClassMap<Client>(map =>
{
map.AutoMap();
});
BsonClassMap.RegisterClassMap<IdentityResource>(map =>
{
map.AutoMap();
});
BsonClassMap.RegisterClassMap<PersistedGrant>(map =>
{
map.AutoMap();
});
});
}
}
}

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

@ -0,0 +1,34 @@
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.MongoDB;
using IdentityResource = Volo.Abp.IdentityServer.IdentityResources.IdentityResource;
namespace Volo.Abp.IdentityServer.MongoDB
{
[ConnectionStringName("AbpIdentityServer")]
public class AbpIdentityServerMongoDbContext : AbpMongoDbContext, IAbpIdentityServerMongoDbContext
{
public static string CollectionPrefix { get; set; } = AbpIdentityServerConsts.DefaultDbTablePrefix;
public IMongoCollection<ApiResource> ApiResources => Collection<ApiResource>();
public IMongoCollection<Client> Clients => Collection<Client>();
public IMongoCollection<IdentityResource> IdentityResources => Collection<IdentityResource>();
public IMongoCollection<PersistedGrant> PersistedGrants => Collection<PersistedGrant>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.ConfigureIdentityServer(options =>
{
options.CollectionPrefix = CollectionPrefix;
});
}
}
}

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

@ -0,0 +1,42 @@
using System;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public static class AbpIdentityServerMongoDbContextExtensions
{
public static void ConfigureIdentityServer(
this IMongoModelBuilder builder,
Action<IdentityServerMongoModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new IdentityServerMongoModelBuilderConfigurationOptions();
optionsAction?.Invoke(options);
builder.Entity<ApiResource>(b =>
{
b.CollectionName = options.CollectionPrefix + "ApiResources";
});
builder.Entity<Client>(b =>
{
b.CollectionName = options.CollectionPrefix + "Clients";
});
builder.Entity<IdentityResource>(b =>
{
b.CollectionName = options.CollectionPrefix + "IdentityResources";
});
builder.Entity<PersistedGrant>(b =>
{
b.CollectionName = options.CollectionPrefix + "PersistedGrants";
});
}
}
}

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

@ -0,0 +1,30 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.Modularity;
using Volo.Abp.MongoDB;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
using Client = Volo.Abp.IdentityServer.Clients.Client;
using IdentityResource = Volo.Abp.IdentityServer.IdentityResources.IdentityResource;
namespace Volo.Abp.IdentityServer.MongoDB
{
[DependsOn(
typeof(AbpIdentityServerDomainModule),
typeof(AbpMongoDbModule)
)]
public class AbpIdentityServerMongoDbModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
AbpIdentityServerBsonClassMap.Configure();
context.Services.AddMongoDbContext<AbpIdentityServerMongoDbContext>(options =>
{
options.AddRepository<ApiResource, MongoApiResourceRepository>();
options.AddRepository<IdentityResource, MongoIdentityResourceRepository>();
options.AddRepository<Client, MongoClientRepository>();
options.AddRepository<PersistedGrant, MongoPersistedGrantRepository>();
});
}
}
}

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

@ -0,0 +1,22 @@
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.MongoDB;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
namespace Volo.Abp.IdentityServer.MongoDB
{
[ConnectionStringName("AbpIdentityServer")]
public interface IAbpIdentityServerMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<ApiResource> ApiResources { get; }
IMongoCollection<Client> Clients { get; }
IMongoCollection<IdentityResource> IdentityResources { get; }
IMongoCollection<PersistedGrant> PersistedGrants { get; }
}
}

12
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IdentityServerMongoModelBuilderConfigurationOptions.cs

@ -0,0 +1,12 @@
using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class IdentityServerMongoModelBuilderConfigurationOptions : MongoModelBuilderConfigurationOptions
{
public IdentityServerMongoModelBuilderConfigurationOptions()
: base(AbpIdentityServerConsts.DefaultDbTablePrefix)
{
}
}
}

36
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class MongoApiResourceRepository : MongoDbRepository<IAbpIdentityServerMongoDbContext, ApiResource, Guid>, IApiResourceRepository
{
public MongoApiResourceRepository(IMongoDbContextProvider<IAbpIdentityServerMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<ApiResource> FindByNameAsync(string name, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.Where(ar=>ar.Name == name)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<ApiResource>> GetListByScopesAsync(string[] scopeNames, bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.Where(ar=>ar.Scopes.Any(x=> scopeNames.Contains(x.Name)))
.ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

22
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs

@ -0,0 +1,22 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class MongoClientRepository : MongoDbRepository<IAbpIdentityServerMongoDbContext, Client, Guid>, IClientRepository
{
public MongoClientRepository(IMongoDbContextProvider<IAbpIdentityServerMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<Client> FindByCliendIdAsync(string clientId, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable().FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken));
}
}
}

28
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class MongoIdentityResourceRepository : MongoDbRepository<IAbpIdentityServerMongoDbContext, IdentityResource, Guid>, IIdentityResourceRepository
{
public MongoIdentityResourceRepository(IMongoDbContextProvider<IAbpIdentityServerMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<List<IdentityResource>> GetListByScopesAsync(string[] scopeNames, bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.Where(ar => scopeNames.Contains(ar.Name))
.ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

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

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class MongoPersistedGrantRepository : MongoDbRepository<IAbpIdentityServerMongoDbContext, PersistedGrant, Guid>, IPersistentGrantRepository
{
public MongoPersistedGrantRepository(IMongoDbContextProvider<IAbpIdentityServerMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<PersistedGrant> FindByKeyAsync(string key, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.FirstOrDefaultAsync(x => x.Key == key, GetCancellationToken(cancellationToken));
}
public async Task<List<PersistedGrant>> GetListBySubjectIdAsync(string subjectId, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.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)
);
}
}
}

7
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs

@ -0,0 +1,7 @@

namespace Volo.Abp.IdentityServer
{
public class ApiResourceRepository_Tests //: ApiResourceRepository_Tests<AbpIdentityServerTestEntityFrameworkCoreModule>
{
}
}

24
modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.MongoDB.Tests</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.MongoDB.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.IdentityServer.MongoDB\Volo.Abp.IdentityServer.MongoDB.csproj" />
<ProjectReference Include="..\Volo.Abp.IdentityServer.TestBase\Volo.Abp.IdentityServer.TestBase.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="Mongo2Go" Version="2.2.1" />
</ItemGroup>
</Project>

33
modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs

@ -0,0 +1,33 @@
using Microsoft.Extensions.DependencyInjection;
using Mongo2Go;
using Volo.Abp.Data;
using Volo.Abp.IdentityServer.MongoDB;
using Volo.Abp.Modularity;
namespace Volo.Abp.IdentityServer
{
[DependsOn(
typeof(AbpIdentityServerTestBaseModule),
typeof(AbpIdentityServerMongoDbModule)
)]
public class AbpIdentityServerMongoDbTestModule : AbpModule
{
private MongoDbRunner _mongoDbRunner;
public override void ConfigureServices(ServiceConfigurationContext context)
{
_mongoDbRunner = MongoDbRunner.Start();
context.Services.Configure<DbConnectionOptions>(options =>
{
options.ConnectionStrings.Default = _mongoDbRunner.ConnectionString;
});
}
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
_mongoDbRunner.Dispose();
}
}
}

7
modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs

@ -0,0 +1,7 @@

namespace Volo.Abp.IdentityServer
{
public class ApiResourceRepository_Tests : ApiResourceRepository_Tests<AbpIdentityServerMongoDbTestModule>
{
}
}

11
modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.IdentityServer
{
public class ClientRepository_Tests : ClientRepository_Tests<AbpIdentityServerMongoDbTestModule>
{
}
}

10
modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.IdentityServer
{
public class IdentityResourceRepository_Tests : IdentityResourceRepository_Tests<AbpIdentityServerMongoDbTestModule>
{
}
}

29
modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo.Abp.IdentityServer.TestBase.csproj

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.TestBase</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.TestBase</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.TestBase\Volo.Abp.TestBase.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.IdentityServer.Domain\Volo.Abp.IdentityServer.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<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>

16
modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBase.cs

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Modularity;
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule>
where TStartupModule : IAbpModule
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

38
modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBaseModule.cs

@ -0,0 +1,38 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
namespace Volo.Abp.IdentityServer
{
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpTestBaseModule),
typeof(AbpIdentityServerDomainModule)
)]
public class AbpIdentityServerTestBaseModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAlwaysAllowPermissionChecker();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
SeedTestData(context);
}
private static void SeedTestData(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())
{
//var dataSeeder = scope.ServiceProvider.GetRequiredService<IIdentityServerDataSeeder>();
//AsyncHelper.RunSync(() => dataSeeder.SeedAsync("1q2w3E*"));
scope.ServiceProvider
.GetRequiredService<AbpIdentityServerTestDataBuilder>()
.Build();
}
}
}
}

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

@ -0,0 +1,68 @@
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;
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerTestDataBuilder : ITransientDependency
{
private readonly IGuidGenerator _guidGenerator;
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IClientRepository _clientRepository;
private readonly IIdentityResourceRepository _identityResourceRepository;
//private readonly IPersistentGrantRepository _persistentGrantRepository;
public AbpIdentityServerTestDataBuilder(
IGuidGenerator guidGenerator,
IApiResourceRepository apiResourceRepository,
IClientRepository clientRepository,
IIdentityResourceRepository identityResourceRepository
/*IPersistentGrantRepository persistentGrantRepository*/)
{
_guidGenerator = guidGenerator;
_apiResourceRepository = apiResourceRepository;
_clientRepository = clientRepository;
_identityResourceRepository = identityResourceRepository;
//_persistentGrantRepository = persistentGrantRepository;
}
public void Build()
{
AddPersistedGrants();
AddIdentityResources();
AddApiResources();
AddClients();
}
private void AddPersistedGrants()
{
//_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()));
//_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()));
//_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()));
}
private void AddIdentityResources()
{
_identityResourceRepository.Insert(new IdentityResource(_guidGenerator.Create(), "NewIdentityResource1"));
_identityResourceRepository.Insert(new IdentityResource(_guidGenerator.Create(), "NewIdentityResource2"));
_identityResourceRepository.Insert(new IdentityResource(_guidGenerator.Create(), "NewIdentityResource3"));
}
private void AddApiResources()
{
_apiResourceRepository.Insert(new ApiResource(_guidGenerator.Create(), "NewApiResource1"));
_apiResourceRepository.Insert(new ApiResource(_guidGenerator.Create(), "NewApiResource2"));
_apiResourceRepository.Insert(new ApiResource(_guidGenerator.Create(), "NewApiResource3"));
}
private void AddClients()
{
_clientRepository.Insert(new Client(_guidGenerator.Create(), "ClientId1"));
_clientRepository.Insert(new Client(_guidGenerator.Create(), "ClientId2"));
_clientRepository.Insert(new Client(_guidGenerator.Create(), "ClientId3"));
}
}
}

32
modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs

@ -0,0 +1,32 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.IdentityServer
{
public abstract class ApiResourceRepository_Tests<TStartupModule> : AbpIdentityServerTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
protected IApiResourceRepository apiResourceRepository { get; }
public ApiResourceRepository_Tests()
{
apiResourceRepository = ServiceProvider.GetRequiredService<IApiResourceRepository>();
}
[Fact]
public async Task FindByNormalizedNameAsync()
{
(await apiResourceRepository.FindByNameAsync("NewApiResource2")).ShouldNotBeNull();
}
[Fact]
public async Task GetListByScopesAsync()
{
(await apiResourceRepository.GetListByScopesAsync(new []{ "NewApiResource2", "NewApiResource3"})).Count.ShouldBe(2);
}
}
}

29
modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ClientRepository_Tests.cs

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.IdentityServer
{
public abstract class ClientRepository_Tests<TStartupModule> : AbpIdentityServerTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
protected IClientRepository clientRepository { get; }
public ClientRepository_Tests()
{
clientRepository = ServiceProvider.GetRequiredService<IClientRepository>();
}
[Fact]
public async Task FindByCliendIdAsync()
{
(await clientRepository.FindByCliendIdAsync("ClientId2")).ShouldNotBeNull();
}
}
}

28
modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.IdentityServer
{
public class IdentityResourceRepository_Tests<TStartupModule> : AbpIdentityServerTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private IIdentityResourceRepository identityResourceRepository;
public IdentityResourceRepository_Tests()
{
identityResourceRepository = ServiceProvider.GetRequiredService<IIdentityResourceRepository>();
}
[Fact]
public async Task GetListByScopesAsync()
{
(await identityResourceRepository.GetListByScopesAsync(new []{"", "NewIdentityResource2" })).Count.ShouldBe(1);
}
}
}
Loading…
Cancel
Save