diff --git a/docs/Best-Practices/Index.md b/docs/Best-Practices/Index.md
index bf2592c1cf..93d6409909 100644
--- a/docs/Best-Practices/Index.md
+++ b/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
diff --git a/docs/Getting-Started-Console-Application.md b/docs/Getting-Started-Console-Application.md
index 0f10c7f505..ab7530522b 100644
--- a/docs/Getting-Started-Console-Application.md
+++ b/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).
\ No newline at end of file
+Get source code of the sample project created in this tutorial from [here](../samples/BasicConsoleApplication).
diff --git a/docs/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/Tutorials/AspNetCore-Mvc/Part-I.md
index 649ac03de6..5ed244a53c 100644
--- a/docs/Tutorials/AspNetCore-Mvc/Part-I.md
+++ b/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
diff --git a/docs/Virtual-File-System.md b/docs/Virtual-File-System.md
index 97892d89b0..9ee0e106d4 100644
--- a/docs/Virtual-File-System.md
+++ b/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:

@@ -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.
diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
index 17612e8fa2..b9e7b543b9 100644
--- a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
+++ b/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",
diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json
index e5e8adc60d..a5a705d506 100644
--- a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json
+++ b/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",
diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
index f3e2728de0..4d560ee5af 100644
--- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
+++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
@@ -23,6 +23,9 @@
}
+
+
+
@@ -173,8 +176,8 @@
@@ -201,6 +205,7 @@
+
@@ -249,8 +254,7 @@
@@ -276,6 +281,7 @@
+
diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs
index 7e02cd8d3a..953c3aa8a1 100644
--- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml.cs
+++ b/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 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();
}
diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/detail.js b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/detail.js
index 7b042fd79a..1ab4ba1167 100644
--- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/detail.js
+++ b/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);
diff --git a/modules/docs/screenshot.png b/modules/docs/screenshot.png
index 60368b08b2..55ff411f0c 100644
Binary files a/modules/docs/screenshot.png and b/modules/docs/screenshot.png differ
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json
new file mode 100644
index 0000000000..5a2813c0e7
--- /dev/null
+++ b/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!"
+ }
+}
\ No newline at end of file
diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs
index 919bc536a9..c20c4109f3 100644
--- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs
+++ b/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> 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(
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs
index 5581c53638..1b691f404c 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs
+++ b/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;
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs
index d27de75865..78fc5d54a6 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs
+++ b/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 claims);
+
+ Task> GetClaimsAsync(
+ Guid id,
+ CancellationToken cancellationToken = default);
+
Task GetCountAsync(
CancellationToken cancellationToken = default
);
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs
index 98269da005..20eb1a749d 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs
+++ b/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 claims);
+
Task> GetListByNormalizedRoleNameAsync(
string normalizedRoleName,
bool includeDetails = false,
@@ -61,6 +63,10 @@ namespace Volo.Abp.Identity
CancellationToken cancellationToken = default
);
+ Task> GetClaimsAsync(
+ Guid id,
+ CancellationToken cancellationToken = default);
+
Task GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleClaim.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleClaim.cs
index 70cf33b3d5..83f5416f9d 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleClaim.cs
+++ b/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,
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserClaim.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserClaim.cs
index d302beb7c2..d91db39b33 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserClaim.cs
+++ b/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;
diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs
index f7211df12f..b3ff5c368b 100644
--- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs
+++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs
@@ -15,6 +15,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
{
options.AddRepository();
options.AddRepository();
+ options.AddRepository();
});
}
}
diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs
index ddce85ac1c..7a317ee530 100644
--- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs
+++ b/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, IIdentityRoleRepository
{
- public EfCoreIdentityRoleRepository(IDbContextProvider dbContextProvider)
+ private readonly IGuidGenerator _guidGenerator;
+
+ public EfCoreIdentityRoleRepository(IDbContextProvider dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
-
+ _guidGenerator = guidGenerator;
}
public virtual async Task FindByNormalizedNameAsync(
@@ -42,6 +45,32 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
.ToListAsync(GetCancellationToken(cancellationToken));
}
+ public async Task UpdateClaimsAsync(Guid id, List claims)
+ {
+ var dbSet = DbContext.Set();
+
+ 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> GetClaimsAsync(Guid id, CancellationToken cancellationToken = default)
+ {
+ var query = from roleClaim in DbContext.Set()
+ where roleClaim.RoleId == id
+ select roleClaim;
+
+ return await query.ToListAsync(GetCancellationToken(cancellationToken));
+ }
+
public virtual async Task GetCountAsync(CancellationToken cancellationToken = default)
{
return await this.LongCountAsync(GetCancellationToken(cancellationToken));
diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs
index fed25edeb7..7cef5b5735 100644
--- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs
+++ b/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, IIdentityUserRepository
{
- public EfCoreIdentityUserRepository(IDbContextProvider dbContextProvider)
+ private readonly IGuidGenerator _guidGenerator;
+
+ public EfCoreIdentityUserRepository(IDbContextProvider dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
-
+ _guidGenerator = guidGenerator;
}
public virtual async Task FindByNormalizedUserNameAsync(
@@ -131,6 +134,34 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
+ public virtual async Task> GetClaimsAsync(
+ Guid id,
+ CancellationToken cancellationToken = default)
+ {
+ var query = from userClaim in DbContext.Set()
+ where userClaim.UserId == id
+ select userClaim;
+
+ return await query.ToListAsync(GetCancellationToken(cancellationToken));
+ }
+
+ public async Task UpdateClaimsAsync(Guid id, List claims)
+ {
+ var dbSet = DbContext.Set();
+
+ 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 GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default)
diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs
index 1686579c0f..b8975ac441 100644
--- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs
+++ b/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, IIdentityRoleRepository
{
- public MongoIdentityRoleRepository(IMongoDbContextProvider dbContextProvider)
+ private readonly IGuidGenerator _guidGenerator;
+
+ public MongoIdentityRoleRepository(IMongoDbContextProvider dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
+ _guidGenerator = guidGenerator;
}
public async Task FindByNormalizedNameAsync(
@@ -40,6 +44,24 @@ namespace Volo.Abp.Identity.MongoDB
.ToListAsync(GetCancellationToken(cancellationToken));
}
+ public async Task UpdateClaimsAsync(Guid id, List 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> GetClaimsAsync(Guid id, CancellationToken cancellationToken = default)
+ {
+ var role = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken));
+ return role.Claims.ToList();
+ }
+
public async Task GetCountAsync(CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs
index c9187953da..9bbea54e72 100644
--- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs
+++ b/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, IIdentityUserRepository
{
- public MongoIdentityUserRepository(IMongoDbContextProvider dbContextProvider)
+ private readonly IGuidGenerator _guidGenerator;
+
+ public MongoIdentityUserRepository(IMongoDbContextProvider dbContextProvider, IGuidGenerator guidGenerator)
: base(dbContextProvider)
{
-
+ _guidGenerator = guidGenerator;
}
public async Task 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> 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 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 GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default)
diff --git a/modules/identityserver/Volo.Abp.IdentityServer.sln b/modules/identityserver/Volo.Abp.IdentityServer.sln
index fcdc057cf3..03e2b5a9af 100644
--- a/modules/identityserver/Volo.Abp.IdentityServer.sln
+++ b/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}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj
new file mode 100644
index 0000000000..5a7d60a821
--- /dev/null
+++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ netcoreapp2.1
+ Volo.Abp.IdentityServer.MongoDB.Tests
+ Volo.Abp.IdentityServer.MongoDB.Tests
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo.Abp.IdentityServer.MongoDB.csproj b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo.Abp.IdentityServer.MongoDB.csproj
new file mode 100644
index 0000000000..72179c1d3c
--- /dev/null
+++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo.Abp.IdentityServer.MongoDB.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ netstandard2.0
+ Volo.Abp.IdentityServer.MongoDB
+ Volo.Abp.IdentityServer.MongoDB
+ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs
new file mode 100644
index 0000000000..f55ad596c8
--- /dev/null
+++ b/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(map =>
+ {
+ map.AutoMap();
+ });
+ BsonClassMap.RegisterClassMap(map =>
+ {
+ map.AutoMap();
+ });
+ BsonClassMap.RegisterClassMap(map =>
+ {
+ map.AutoMap();
+ });
+ BsonClassMap.RegisterClassMap(map =>
+ {
+ map.AutoMap();
+ });
+ });
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContext.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContext.cs
new file mode 100644
index 0000000000..2803b91f8c
--- /dev/null
+++ b/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 ApiResources => Collection();
+
+ public IMongoCollection Clients => Collection();
+
+ public IMongoCollection IdentityResources => Collection();
+
+ public IMongoCollection PersistedGrants => Collection();
+
+ protected override void CreateModel(IMongoModelBuilder modelBuilder)
+ {
+ base.CreateModel(modelBuilder);
+
+ modelBuilder.ConfigureIdentityServer(options =>
+ {
+ options.CollectionPrefix = CollectionPrefix;
+ });
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContextExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbContextExtensions.cs
new file mode 100644
index 0000000000..6f81a67493
--- /dev/null
+++ b/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 optionsAction = null)
+ {
+ Check.NotNull(builder, nameof(builder));
+
+ var options = new IdentityServerMongoModelBuilderConfigurationOptions();
+
+ optionsAction?.Invoke(options);
+
+ builder.Entity(b =>
+ {
+ b.CollectionName = options.CollectionPrefix + "ApiResources";
+ });
+
+ builder.Entity(b =>
+ {
+ b.CollectionName = options.CollectionPrefix + "Clients";
+ });
+ builder.Entity(b =>
+ {
+ b.CollectionName = options.CollectionPrefix + "IdentityResources";
+ });
+
+ builder.Entity(b =>
+ {
+ b.CollectionName = options.CollectionPrefix + "PersistedGrants";
+ });
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbModule.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbModule.cs
new file mode 100644
index 0000000000..599f60f579
--- /dev/null
+++ b/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(options =>
+ {
+ options.AddRepository();
+ options.AddRepository();
+ options.AddRepository();
+ options.AddRepository();
+ });
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IAbpIdentityServerMongoDbContext.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IAbpIdentityServerMongoDbContext.cs
new file mode 100644
index 0000000000..cbe1cf867f
--- /dev/null
+++ b/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 ApiResources { get; }
+
+ IMongoCollection Clients { get; }
+
+ IMongoCollection IdentityResources { get; }
+
+ IMongoCollection PersistedGrants { get; }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IdentityServerMongoModelBuilderConfigurationOptions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/IdentityServerMongoModelBuilderConfigurationOptions.cs
new file mode 100644
index 0000000000..bb88711e9e
--- /dev/null
+++ b/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)
+ {
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs
new file mode 100644
index 0000000000..26ab375882
--- /dev/null
+++ b/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, IApiResourceRepository
+ {
+ public MongoApiResourceRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+
+ public virtual async Task FindByNameAsync(string name, bool includeDetails = true, CancellationToken cancellationToken = default)
+ {
+ return await GetMongoQueryable()
+ .Where(ar=>ar.Name == name)
+ .FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
+ }
+
+ public virtual async Task> 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));
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs
new file mode 100644
index 0000000000..f3ebe4bb62
--- /dev/null
+++ b/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, IClientRepository
+ {
+ public MongoClientRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+
+ public async Task FindByCliendIdAsync(string clientId, bool includeDetails = true, CancellationToken cancellationToken = default)
+ {
+ return await GetMongoQueryable().FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken));
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs
new file mode 100644
index 0000000000..ed84284369
--- /dev/null
+++ b/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, IIdentityResourceRepository
+ {
+ public MongoIdentityResourceRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+
+ public async Task> GetListByScopesAsync(string[] scopeNames, bool includeDetails = false,
+ CancellationToken cancellationToken = default)
+ {
+ return await GetMongoQueryable()
+ .Where(ar => scopeNames.Contains(ar.Name))
+ .ToListAsync(GetCancellationToken(cancellationToken));
+ }
+ }
+}
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs
new file mode 100644
index 0000000000..b85d3d3e06
--- /dev/null
+++ b/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, IPersistentGrantRepository
+ {
+ public MongoPersistedGrantRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+
+ public async Task FindByKeyAsync(string key, CancellationToken cancellationToken = default)
+ {
+
+ return await GetMongoQueryable()
+ .FirstOrDefaultAsync(x => x.Key == key, GetCancellationToken(cancellationToken));
+ }
+
+ public async Task> 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)
+ );
+ }
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs
new file mode 100644
index 0000000000..965d2c8893
--- /dev/null
+++ b/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
+ {
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj
new file mode 100644
index 0000000000..5a7d60a821
--- /dev/null
+++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ netcoreapp2.1
+ Volo.Abp.IdentityServer.MongoDB.Tests
+ Volo.Abp.IdentityServer.MongoDB.Tests
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs
new file mode 100644
index 0000000000..f1e81bf21f
--- /dev/null
+++ b/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(options =>
+ {
+ options.ConnectionStrings.Default = _mongoDbRunner.ConnectionString;
+ });
+ }
+
+ public override void OnApplicationShutdown(ApplicationShutdownContext context)
+ {
+ _mongoDbRunner.Dispose();
+ }
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs
new file mode 100644
index 0000000000..032505266d
--- /dev/null
+++ b/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
+ {
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs
new file mode 100644
index 0000000000..29b006cd99
--- /dev/null
+++ b/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
+ {
+
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs
new file mode 100644
index 0000000000..2b44b2c6a0
--- /dev/null
+++ b/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
+ {
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo.Abp.IdentityServer.TestBase.csproj b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo.Abp.IdentityServer.TestBase.csproj
new file mode 100644
index 0000000000..3cf0bab9d4
--- /dev/null
+++ b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo.Abp.IdentityServer.TestBase.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp2.1
+ Volo.Abp.IdentityServer.TestBase
+ Volo.Abp.IdentityServer.TestBase
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBase.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBase.cs
new file mode 100644
index 0000000000..a78caec8d0
--- /dev/null
+++ b/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 : AbpIntegratedTest
+ where TStartupModule : IAbpModule
+ {
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBaseModule.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestBaseModule.cs
new file mode 100644
index 0000000000..b5617e489f
--- /dev/null
+++ b/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();
+ //AsyncHelper.RunSync(() => dataSeeder.SeedAsync("1q2w3E*"));
+
+ scope.ServiceProvider
+ .GetRequiredService()
+ .Build();
+ }
+ }
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs
new file mode 100644
index 0000000000..472c23b7e2
--- /dev/null
+++ b/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"));
+ }
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs
new file mode 100644
index 0000000000..db8eacae5c
--- /dev/null
+++ b/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 : AbpIdentityServerTestBase
+ where TStartupModule : IAbpModule
+ {
+ protected IApiResourceRepository apiResourceRepository { get; }
+
+ public ApiResourceRepository_Tests()
+ {
+ apiResourceRepository = ServiceProvider.GetRequiredService();
+ }
+
+ [Fact]
+ public async Task FindByNormalizedNameAsync()
+ {
+ (await apiResourceRepository.FindByNameAsync("NewApiResource2")).ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task GetListByScopesAsync()
+ {
+ (await apiResourceRepository.GetListByScopesAsync(new []{ "NewApiResource2", "NewApiResource3"})).Count.ShouldBe(2);
+ }
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ClientRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/ClientRepository_Tests.cs
new file mode 100644
index 0000000000..8770e7969c
--- /dev/null
+++ b/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 : AbpIdentityServerTestBase
+ where TStartupModule : IAbpModule
+ {
+ protected IClientRepository clientRepository { get; }
+
+ public ClientRepository_Tests()
+ {
+ clientRepository = ServiceProvider.GetRequiredService();
+ }
+
+ [Fact]
+ public async Task FindByCliendIdAsync()
+ {
+ (await clientRepository.FindByCliendIdAsync("ClientId2")).ShouldNotBeNull();
+ }
+ }
+}
diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs
new file mode 100644
index 0000000000..a9487657b3
--- /dev/null
+++ b/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 : AbpIdentityServerTestBase
+ where TStartupModule : IAbpModule
+ {
+ private IIdentityResourceRepository identityResourceRepository;
+ public IdentityResourceRepository_Tests()
+ {
+ identityResourceRepository = ServiceProvider.GetRequiredService();
+ }
+
+ [Fact]
+ public async Task GetListByScopesAsync()
+ {
+ (await identityResourceRepository.GetListByScopesAsync(new []{"", "NewIdentityResource2" })).Count.ShouldBe(1);
+ }
+ }
+}
- @L["ReplyTo"] - @(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName) + @L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName] +