diff --git a/docs/en/Distributed-Event-Bus.md b/docs/en/Distributed-Event-Bus.md index 5fe85a468d..21b1b07256 100644 --- a/docs/en/Distributed-Event-Bus.md +++ b/docs/en/Distributed-Event-Bus.md @@ -228,7 +228,7 @@ namespace AbpDemo ```` * `MyHandler` implements the `IDistributedEventHandler>`. -* It is required to register your handler class to the [dependency injection](Dependency-Injection.md) system. Implementing `ITransient` like in this example is an easy way. +* It is required to register your handler class to the [dependency injection](Dependency-Injection.md) system. Implementing `ITransientDependency` like in this example is an easy way. ### Configuration diff --git a/docs/en/Object-To-Object-Mapping.md b/docs/en/Object-To-Object-Mapping.md index f5ca805611..c12b260921 100644 --- a/docs/en/Object-To-Object-Mapping.md +++ b/docs/en/Object-To-Object-Mapping.md @@ -12,7 +12,7 @@ public class UserAppService : ApplicationService _userRepository = userRepository; } - public void CreateUser(CreateUserInput input) + public async Task CreateUser(CreateUserInput input) { //Manually creating a User object from the CreateUserInput object var user = new User @@ -23,7 +23,7 @@ public class UserAppService : ApplicationService Password = input.Password }; - _userRepository.Insert(user); + await _userRepository.InsertAsync(user); } } ``` @@ -46,12 +46,12 @@ public class UserAppService : ApplicationService _userRepository = userRepository; } - public void CreateUser(CreateUserInput input) + public async Task CreateUser(CreateUserInput input) { //Automatically creating a new User object using the CreateUserInput object var user = ObjectMapper.Map(input); - _userRepository.Insert(user); + await _userRepository.InsertAsync(user); } } ```` diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 5ecee2074b..e373871183 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -25,15 +25,17 @@ You can find the source code of the completed application [here](https://github. {{end}} -## Creating a New Solution +## Install ABP CLI Tool -We will use the [ABP CLI](../../CLI.md) to create new solutions with the ABP Framework. You can run the following command in a command-line terminal to install it: +We will use the [ABP CLI](../../CLI.md) to create new ABP solutions. You can run the following command on a terminal window to install this dotnet tool: ````bash dotnet tool install -g Volo.Abp.Cli ```` -Then create an empty folder, open a command-line terminal and execute the following command in the terminal: +## Create Your ABP Solution + +Create an empty folder, open a command-line terminal and execute the following command in the terminal: ````bash abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} diff --git a/docs/zh-Hans/Object-To-Object-Mapping.md b/docs/zh-Hans/Object-To-Object-Mapping.md index 402acdc4f6..62c1d17add 100644 --- a/docs/zh-Hans/Object-To-Object-Mapping.md +++ b/docs/zh-Hans/Object-To-Object-Mapping.md @@ -12,7 +12,7 @@ public class UserAppService : ApplicationService _userRepository = userRepository; } - public void CreateUser(CreateUserInput input) + public async Task CreateUser(CreateUserInput input) { //Manually creating a User object from the CreateUserInput object var user = new User @@ -23,7 +23,7 @@ public class UserAppService : ApplicationService Password = input.Password }; - _userRepository.Insert(user); + await _userRepository.InsertAsync(user); } } ``` @@ -46,12 +46,12 @@ public class UserAppService : ApplicationService _userRepository = userRepository; } - public void CreateUser(CreateUserInput input) + public async Task CreateUser(CreateUserInput input) { //Automatically creating a new User object using the CreateUserInput object var user = ObjectMapper.Map(input); - _userRepository.Insert(user); + await _userRepository.InsertAsync(user); } } ```` diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs index 0b229235fa..f92c9d7bb9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs @@ -7,7 +7,6 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; [Serializable] public class ApplicationLocalizationConfigurationDto { - //TODO: Rename to Texts? public Dictionary> Values { get; set; } public List Languages { get; set; } diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs index b477c6c11e..75d463f30f 100644 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs +++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs @@ -30,7 +30,7 @@ public class PermissionDefinition : IHasSimpleStateCheckers - public List Providers { get; } //TODO: Rename to AllowedProviders? + public List Providers { get; } public List> StateCheckers { get; } @@ -122,14 +122,14 @@ public class PermissionDefinition : IHasSimpleStateCheckers - /// Set the property. + /// Adds one or more providers to the list. /// This is a shortcut for nested calls on this object. /// public virtual PermissionDefinition WithProviders(params string[] providers) { if (!providers.IsNullOrEmpty()) { - Providers.AddRange(providers); + Providers.AddIfNotContains(providers); } return this; diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpBlazoriseUiModalExtensions.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpBlazoriseUiModalExtensions.cs new file mode 100644 index 0000000000..3b71613fc5 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpBlazoriseUiModalExtensions.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Blazorise; + +namespace Volo.Abp.BlazoriseUI; + +public static class AbpBlazoriseUiModalExtensions +{ + public static Task CancelClosingModalWhenFocusLost(this Modal modal, ModalClosingEventArgs eventArgs) + { + // cancel close if clicked outside of modal area + eventArgs.Cancel = eventArgs.CloseReason == CloseReason.FocusLostClosing; + + return Task.CompletedTask; + } +} diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/IHasExtraProperties.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/IHasExtraProperties.cs index 03598e1164..ed2d11c250 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/IHasExtraProperties.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/IHasExtraProperties.cs @@ -1,7 +1,5 @@ namespace Volo.Abp.Data; -//TODO: Move to Volo.Abp.Data.ObjectExtending namespace at 4.0? - public interface IHasExtraProperties { ExtraPropertyDictionary ExtraProperties { get; } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs index ee96d1c160..536a407271 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs @@ -39,7 +39,7 @@ public class SettingDefinition /// A list of allowed providers to get/set value of this setting. /// An empty list indicates that all providers are allowed. /// - public List Providers { get; } //TODO: Rename to AllowedProviders + public List Providers { get; } /// /// Is this setting inherited from parent scopes. @@ -91,14 +91,14 @@ public class SettingDefinition } /// - /// Sets a property in the dictionary. + /// Adds one or more providers to the list. /// This is a shortcut for nested calls on this object. /// public virtual SettingDefinition WithProviders(params string[] providers) { if (!providers.IsNullOrEmpty()) { - Providers.AddRange(providers); + Providers.AddIfNotContains(providers); } return this; diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json index 8ce00a7c5b..29035fb57f 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json @@ -24,6 +24,8 @@ "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "This field must be a string or array type with a minimum length of '{0}'.", "ThisFieldIsNotAValidPhoneNumber.": "This field is not a valid phone number.", "ThisFieldMustBeBetween{0}And{1}": "This field must be between {0} and {1}.", + "ThisFieldMustBeGreaterThanOrEqual{0}":"This field must be greater than or equal to {0}.", + "ThisFieldMustBeLessOrEqual{0}":"This field must be less than or equal to {0}.", "ThisFieldMustMatchTheRegularExpression{0}": "This field must match the regular expression '{0}'.", "ThisFieldIsRequired.": "This field is required.", "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "This field must be a string with a maximum length of {0}.", diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs index 9a6be48e5f..5e953e82d6 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs @@ -46,6 +46,7 @@ using Volo.CmsKit.Comments; using Volo.CmsKit.MediaDescriptors; using Volo.CmsKit.Reactions; using Volo.CmsKit.Ratings; +using Volo.CmsKit.Contents; namespace Volo.CmsKit; @@ -152,6 +153,11 @@ public class CmsKitWebUnifiedModule : AbpModule { options.IsEnabled = MultiTenancyConsts.IsEnabled; }); + + Configure(options => + { + options.AddWidget("ExComment", "CommentDate", "DecisionCommentDate"); + }); } private void ConfigureCmsKit(ServiceConfigurationContext context) diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/CommentDate.cshtml b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/CommentDate.cshtml new file mode 100644 index 0000000000..7921c0ecbd --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/CommentDate.cshtml @@ -0,0 +1,11 @@ +@model Volo.CmsKit.ViewComponents.CommentDateViewComponent + +

Welcome Comment Date Component

+@if (Model.IsShow) +{ +

@DateTime.Today.ToLongDateString()

+} +else +{ +

Without date

+} \ No newline at end of file diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/CommentDateViewComponent.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/CommentDateViewComponent.cs new file mode 100644 index 0000000000..4122bb1481 --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/CommentDateViewComponent.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Widgets; + +namespace Volo.CmsKit.ViewComponents; + +[Widget( + AutoInitialize = true +)] + +[ViewComponent(Name = "CommentDate")] +public class CommentDateViewComponent : AbpViewComponent +{ + public bool IsShow { get; set; } + + public CommentDateViewComponent() + { + } + + public virtual async Task InvokeAsync(string isShow) + { + return View("~/ViewComponents/CommentDate.cshtml", new CommentDateViewComponent() { IsShow = bool.Parse(isShow) }); + } +} diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/DecisionCommentDate.cshtml b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/DecisionCommentDate.cshtml new file mode 100644 index 0000000000..0622000bb7 --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/DecisionCommentDate.cshtml @@ -0,0 +1,6 @@ +@using Volo.CmsKit.ViewComponents +@model DecisionCommentDateViewModel + +
+ +
diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/DecisionCommentDateViewComponent.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/DecisionCommentDateViewComponent.cs new file mode 100644 index 0000000000..c4f52d508a --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/ViewComponents/DecisionCommentDateViewComponent.cs @@ -0,0 +1,32 @@ +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Widgets; +using Volo.Abp.Localization; + +namespace Volo.CmsKit.ViewComponents; + +[Widget( + AutoInitialize = true +)] + +[ViewComponent(Name = "DecisionCommentDate")] +public class DecisionCommentDateViewComponent : AbpViewComponent +{ + public DecisionCommentDateViewComponent() + { + } + + public virtual async Task InvokeAsync() + { + return View("~/ViewComponents/DecisionCommentDate.cshtml", new DecisionCommentDateViewModel()); + } +} + +public class DecisionCommentDateViewModel +{ + [DisplayName("Show date in the component")] + public bool IsShow { get; set; } = true; +} diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/_ViewImports.cshtml b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/_ViewImports.cshtml similarity index 100% rename from modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/_ViewImports.cshtml rename to modules/cms-kit/host/Volo.CmsKit.Web.Unified/_ViewImports.cshtml diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml index 159bd66b5f..27a5be8083 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml @@ -98,3 +98,4 @@ } + \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml index 04a41ffe5a..fc7987cc5b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml @@ -95,3 +95,4 @@ + \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js index 9fd95b0e14..375b7ad41b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js @@ -7,7 +7,7 @@ $(function () { Published: 1, SendToReview: 2 }; - + var $selectBlog = $('#BlogSelectionSelect'); var $formCreate = $('#form-blog-post-create'); var $title = $('#ViewModel_Title'); @@ -250,21 +250,17 @@ $(function () { var fileUploadUri = "/api/cms-kit-admin/media/blogpost"; var fileUriPrefix = "/api/cms-kit/media/"; - initAllEditors(); + initEditor(); - function initAllEditors() { - $('.content-editor').each(function (i, item) { - initEditor(item); - }); - } + var editor; - function initEditor(element) { - var $editorContainer = $(element); + function initEditor() { + var $editorContainer = $("#ContentEditor"); var inputName = $editorContainer.data('input-id'); var $editorInput = $('#' + inputName); var initialValue = $editorInput.val(); - var editor = new toastui.Editor({ + editor = new toastui.Editor({ el: $editorContainer[0], usageStatistics: false, useCommandShortcut: true, @@ -333,6 +329,11 @@ $(function () { }); } + $('#GeneratedWidgetText').on('change', function () { + var txt = $('#GeneratedWidgetText').val(); + editor.insertText(txt); + }); + function createAddWidgetButton() { const button = document.createElement('button'); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js index 98505c479e..51e3eda96c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js @@ -161,21 +161,16 @@ $(function () { var fileUploadUri = "/api/cms-kit-admin/media/blogpost"; var fileUriPrefix = "/api/cms-kit/media/"; - initAllEditors(); + initEditor(); - function initAllEditors() { - $('.content-editor').each(function (i, item) { - initEditor(item); - }); - } - - function initEditor(element) { - var $editorContainer = $(element); + var editor; + function initEditor() { + var $editorContainer = $("#ContentEditor"); var inputName = $editorContainer.data('input-id'); var $editorInput = $('#' + inputName); var initialValue = $editorInput.val(); - var editor = new toastui.Editor({ + editor = new toastui.Editor({ el: $editorContainer[0], usageStatistics: false, useCommandShortcut: true, @@ -255,6 +250,11 @@ $(function () { ); }); + $('#GeneratedWidgetText').on('change', function () { + var txt = $('#GeneratedWidgetText').val(); + editor.insertText(txt); + }); + function createAddWidgetButton() { const button = document.createElement('button'); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml index 3219538d46..87831e4e1d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml @@ -1,5 +1,6 @@ @page @using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @using Volo.CmsKit.Admin.Web.Pages @using Volo.CmsKit.Localization @using Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents; @@ -20,15 +21,17 @@
@if (Model.Widgets.Count() > 1) { + foreach (var item in Model.ViewModel.Details) { - + } -
-
- } else { @@ -36,4 +39,7 @@ }
+ + + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/addWidgetModal.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/addWidgetModal.js index 02539d377a..2f625fe2fa 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/addWidgetModal.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/addWidgetModal.js @@ -3,6 +3,8 @@ $(function () { abp.modals.addWidgetModal = function () { var initModal = function () { + var activeEditor; + var activeForm; let widgetName, widgetType; $("#ViewModel_Widget").change(function () { @@ -11,54 +13,28 @@ $(function () { $('.widget-detail').attr('hidden', 'true'); - $('#editor-' + widgetName).removeAttr('hidden'); - }); - - $("#save-changes").click(function () { - var widgetKey = $("#WidgetCode").val(); - if (widgetKey != undefined) { - let html = " " - $("#PropertySideId").append(html); - } + activeEditor = $('#editor-' + widgetName); + activeEditor.removeAttr('hidden'); - var keys = []; - var values = []; - $(".properties").each(function () { - if (($.trim($(this).val()).length > 0)) { - keys.push(this.id); - values.push($(this).val()); - } - }); + activeForm = $('#editor-' + widgetName + ' form'); + }); - var contentEditorText = $("#ContentEditor")[0].innerText - .replace('WritePreview', '') - .replace('MarkdownWYSIWYG', '') - .replace('W', ''); + $(".save-changes").click(function () { - let updatedText = ''; - if (widgetType != undefined) { + let properties = activeForm.serializeFormToObject(); - updatedText = "[Widget Type=\"" + widgetType + "\" "; + let widgetText = "[Widget Type=\"" + widgetType + "\" "; - for (var i = 0; i < keys.length; i++) { - updatedText += keys[i] + "=\"" + values[i]; - updatedText += i == (keys.length - 1) ? "\"" : "\" "; + for (var propertyName in properties) { + if (!propertyName.includes(']') && !propertyName.includes('[')) { + widgetText += propertyName + "=\"" + properties[propertyName] + "\" "; } - - updatedText += "]"; } - if (contentEditorText == '\n\n\n') { - //TODO fails event - var fixedData = "
" + updatedText + "
"; - var innerHtml = $("#ContentEditor")[0].innerHTML; - var replacedInnerHtml = innerHtml.replace('

', fixedData); - $("#ContentEditor")[0].innerHTML = replacedInnerHtml; - } - else { - $('.ProseMirror div').contents()[0].data = contentEditorText + updatedText; - } + widgetText = widgetText.trim() + "]"; + $('#GeneratedWidgetText').val(widgetText); + $("#GeneratedWidgetText").trigger("change"); $('#addWidgetModal').modal('hide'); }); }; diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml index 9348b07507..da3226420f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml @@ -76,3 +76,4 @@ + \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml index ea6f8c9a1b..d24ad8bc06 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml @@ -83,3 +83,4 @@ + \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js index 8dc2ab9eb4..49a482bf33 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/create.js @@ -89,21 +89,16 @@ $(function () { var fileUploadUri = "/api/cms-kit-admin/media/page"; var fileUriPrefix = "/api/cms-kit/media/"; - initAllEditors(); - - function initAllEditors() { - $('.content-editor').each(function (i, item) { - initEditor(item); - }); - } - - function initEditor(element) { - var $editorContainer = $(element); + initEditor(); + + var editor; + function initEditor() { + var $editorContainer = $("#ContentEditor"); var inputName = $editorContainer.data('input-id'); var $editorInput = $('#' + inputName); var initialValue = $editorInput.val(); - var editor = new toastui.Editor({ + editor = new toastui.Editor({ el: $editorContainer[0], usageStatistics: false, useCommandShortcut: true, @@ -138,7 +133,7 @@ $(function () { } }); } - + function uploadFile(blob, callback, source) { var UPPY_OPTIONS = { endpoint: fileUploadUri, @@ -171,8 +166,12 @@ $(function () { }); } + $('#GeneratedWidgetText').on('change',function () { + var txt = $('#GeneratedWidgetText').val(); + editor.insertText(txt); + }); + function createAddWidgetButton() { - //TODO add auth const button = document.createElement('button'); button.className = 'toastui-editor-toolbar-icons last dropdown'; diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js index f8b837cc1f..565f758552 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/update.js @@ -59,21 +59,16 @@ $(function () { var fileUploadUri = "/api/cms-kit-admin/media/page"; var fileUriPrefix = "/api/cms-kit/media/"; - initAllEditors(); + initEditor(); - function initAllEditors() { - $('.content-editor').each(function (i, item) { - initEditor(item); - }); - } - - function initEditor(element) { - var $editorContainer = $(element); + var editor; + function initEditor() { + var $editorContainer = $("#ContentEditor"); var inputName = $editorContainer.data('input-id'); var $editorInput = $('#' + inputName); var initialValue = $editorInput.val(); - var editor = new toastui.Editor({ + editor = new toastui.Editor({ el: $editorContainer[0], usageStatistics: false, useCommandShortcut: true, @@ -141,6 +136,11 @@ $(function () { }); } + $('#GeneratedWidgetText').on('change', function () { + var txt = $('#GeneratedWidgetText').val(); + editor.insertText(txt); + }); + function createAddWidgetButton() { const button = document.createElement('button'); diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/CmsKitContentWidgetOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/CmsKitContentWidgetOptions.cs index 1ff76acf79..b87f286b5c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/CmsKitContentWidgetOptions.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/CmsKitContentWidgetOptions.cs @@ -11,7 +11,7 @@ public class CmsKitContentWidgetOptions WidgetConfigs = new(); } - public void AddWidget(string widgetKey, string widgetName, string editorWidgetName = null) + public void AddWidget(string widgetKey, string widgetName, string editorWidgetName) { var config = new ContentWidgetConfig(widgetName, editorWidgetName); WidgetConfigs.Add(widgetKey, config); diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml index 5a92ae2b04..2aa3c0ce8b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml @@ -40,6 +40,7 @@ { @await Component.InvokeAsync(contentFragment.GetProperty("Type"), contentFragment.ExtraProperties.ConvertToDynamicObject()) } + } diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs new file mode 100644 index 0000000000..f338d3d7d1 --- /dev/null +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs @@ -0,0 +1,27 @@ +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.CmsKit.Admin.Contents; +using Xunit; + +namespace Volo.CmsKit.Contents; + +public class ContentAdminAppService_Tests : CmsKitApplicationTestBase +{ + private readonly IContentAdminAppService _contentAdminAppService; + + public ContentAdminAppService_Tests() + { + _contentAdminAppService = GetRequiredService(); + } + + [Fact] + public async Task ShouldGet_PagedListAsync() + { + var widgets = await _contentAdminAppService.GetWidgetsAsync(); + + widgets.Items.Count.ShouldBe(0); + widgets.Items.Any().ShouldBeFalse(); + } + +} diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentParser_Test.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentParser_Test.cs index 108d883a70..b08a127111 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentParser_Test.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentParser_Test.cs @@ -20,8 +20,8 @@ public class ContentParser_Test : CmsKitDomainTestBase [Fact] public async Task ParseAsync_ShouldWorkWithDifferentWidgetTypes() { - _options.Value.AddWidget(testData.PollName, testData.WidgetName); - _options.Value.AddWidget("ImageGallery", "ImageGallery"); + _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); + _options.Value.AddWidget("ImageGallery", "ImageGallery", string.Empty); contentParser = new ContentParser(_options); var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. @@ -54,7 +54,7 @@ public class ContentParser_Test : CmsKitDomainTestBase [Fact] public async Task ParseAsync_ShouldWorkWithWrongConfigOptions() { - _options.Value.AddWidget(testData.WidgetName, testData.PollName); + _options.Value.AddWidget(testData.WidgetName, testData.PollName, string.Empty); contentParser = new ContentParser(_options); var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. @@ -70,7 +70,7 @@ public class ContentParser_Test : CmsKitDomainTestBase [Fact] public async Task ParseAsync_ShouldWorkWithWrongWidgetType() { - _options.Value.AddWidget(testData.PollName, testData.WidgetName); + _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); contentParser = new ContentParser(_options); var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. @@ -86,7 +86,7 @@ public class ContentParser_Test : CmsKitDomainTestBase [Fact] public async Task ParseAsync_ShouldWorkWithWrongPollName() { - _options.Value.AddWidget(testData.PollName, testData.WidgetName); + _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); contentParser = new ContentParser(_options); var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. @@ -103,7 +103,7 @@ public class ContentParser_Test : CmsKitDomainTestBase [MemberData(nameof(ExampleData))] public async Task ParseAsync_ShouldWorkProperlyWithCorrectInputs(string content, int expectedLine) { - _options.Value.AddWidget(testData.PollName, testData.WidgetName); + _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); contentParser = new ContentParser(_options); var widgets = await contentParser.ParseAsync(content); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs index bad2b0f595..7f5481decb 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs @@ -23,9 +23,10 @@ public class EfCoreOpenIddictScopeRepository : EfCoreRepository x.Name.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.DisplayName.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Description.Contains(filter)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => + x.Name.Contains(filter) || + x.DisplayName.Contains(filter) || + x.Description.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictScope.Name) : sorting) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -34,9 +35,10 @@ public class EfCoreOpenIddictScopeRepository : EfCoreRepository GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.DisplayName.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Description.Contains(filter)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => + x.Name.Contains(filter) || + x.DisplayName.Contains(filter) || + x.Description.Contains(filter)) .LongCountAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs index 21317b3683..fe0042e54c 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Dynamic.Core; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; @@ -67,12 +68,15 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { var tokenQueryable = await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)); - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + + var authorizations = await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.CreationDate < date) .Where(x => x.Status != OpenIddictConstants.Statuses.Valid || - (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && tokenQueryable.Any(t => t.AuthorizationId == x.Id))) + (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc)) .OrderBy(x => x.Id) .Take(count) .ToListAsync(GetCancellationToken(cancellationToken)); + + return authorizations.Where(x => tokenQueryable.Any(t => t.AuthorizationId == x.Id)).ToList(); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs index 2d35445abc..3411f520e9 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs @@ -22,9 +22,10 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository x.Name.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.DisplayName.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Description.Contains(filter)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => + x.Name.Contains(filter) || + x.DisplayName.Contains(filter) || + x.Description.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictScope.Name) : sorting) .PageBy(skipCount, maxResultCount) .As>() @@ -34,9 +35,10 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.DisplayName.Contains(filter)) - .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Description.Contains(filter)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => + x.Name.Contains(filter) || + x.DisplayName.Contains(filter) || + x.Description.Contains(filter)) .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs index b58b11e75a..18d43a155e 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs @@ -33,7 +33,7 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.ApplicationId == authorizationId) + .Where(x => x.AuthorizationId == authorizationId) .ToListAsync(GetCancellationToken(cancellationToken)); await DeleteManyAsync(tokens, autoSave, GetCancellationToken(cancellationToken)); @@ -102,16 +102,18 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { - return await (from token in await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)) - join authorization in (await GetMongoQueryableAsync(cancellationToken)) - on token.AuthorizationId equals authorization.Id into ta - from a in ta - where token.CreationDate < date - where (token.Status != OpenIddictConstants.Statuses.Inactive && - token.Status != OpenIddictConstants.Statuses.Valid) || - (a != null && a.Status != OpenIddictConstants.Statuses.Valid) || - token.ExpirationDate < DateTime.UtcNow - orderby token.Id - select token).Take(count).ToListAsync(GetCancellationToken(cancellationToken)); + var authorizationIds = await (await GetMongoQueryableAsync(cancellationToken)) + .Where(x => x.Status != OpenIddictConstants.Statuses.Valid) + .Select(x => x.Id) + .ToListAsync(GetCancellationToken(cancellationToken)); + + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + .Where(x => x.CreationDate < date) + .Where(x => (x.Status != OpenIddictConstants.Statuses.Inactive && + x.Status != OpenIddictConstants.Statuses.Valid) || + authorizationIds.Contains(x.Id) || + x.ExpirationDate < DateTime.UtcNow) + .OrderBy(x => x.Id) + .Take(count).ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore_Tests.cs index 9cd7361efb..81dafe33c3 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore_Tests.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore_Tests.cs @@ -15,10 +15,12 @@ namespace Volo.Abp.OpenIddict.Applications; public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase { private readonly IOpenIddictApplicationStore _applicationStore; + private readonly AbpOpenIddictTestData _testData; public AbpOpenIddictApplicationStore_Tests() { _applicationStore = ServiceProvider.GetRequiredService>(); + _testData = ServiceProvider.GetRequiredService(); } [Fact] @@ -32,10 +34,10 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task FindByIdAsync_Should_Return_Application_If_Found() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); application.ShouldNotBeNull(); - application.ClientId.ShouldBe(AbpOpenIddictTestData.App1ClientId); + application.ClientId.ShouldBe(_testData.App1ClientId); application.ConsentType.ShouldBe(OpenIddictConstants.ConsentTypes.Explicit); application.DisplayName.ShouldBe("Test Application"); } @@ -51,10 +53,10 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task FindByClientIdAsync_Should_Return_Application_If_Found() { - var application = await _applicationStore.FindByClientIdAsync(AbpOpenIddictTestData.App1ClientId, CancellationToken.None); + var application = await _applicationStore.FindByClientIdAsync(_testData.App1ClientId, CancellationToken.None); application.ShouldNotBeNull(); - application.ClientId.ShouldBe(AbpOpenIddictTestData.App1ClientId); + application.ClientId.ShouldBe(_testData.App1ClientId); application.ConsentType.ShouldBe(OpenIddictConstants.ConsentTypes.Explicit); application.DisplayName.ShouldBe("Test Application"); } @@ -91,12 +93,12 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task DeleteAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); application.ShouldNotBeNull(); await _applicationStore.DeleteAsync(application, CancellationToken.None); - application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); application.ShouldBeNull(); } @@ -131,16 +133,16 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetClientIdAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var clientId = await _applicationStore.GetClientIdAsync(application, CancellationToken.None); - clientId.ShouldBe(AbpOpenIddictTestData.App1ClientId); + clientId.ShouldBe(_testData.App1ClientId); } [Fact] public async Task GetClientSecretAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var secret = await _applicationStore.GetClientIdAsync(application, CancellationToken.None); secret.ShouldBe("Client1"); @@ -149,7 +151,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetClientTypeAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var clientType = await _applicationStore.GetClientTypeAsync(application, CancellationToken.None); clientType.ShouldBe(OpenIddictConstants.ClientTypes.Public); @@ -158,7 +160,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetConsentTypeAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var consentType = await _applicationStore.GetConsentTypeAsync(application, CancellationToken.None); consentType.ShouldBe(OpenIddictConstants.ConsentTypes.Explicit); @@ -167,7 +169,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetDisplayNameAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var displayName = await _applicationStore.GetDisplayNameAsync(application, CancellationToken.None); displayName.ShouldBe("Test Application"); @@ -176,16 +178,16 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetIdAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var id = await _applicationStore.GetIdAsync(application, CancellationToken.None); - id.ShouldBe(AbpOpenIddictTestData.App1Id.ToString()); + id.ShouldBe(_testData.App1Id.ToString()); } [Fact] public async Task GetPermissionsAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var permissions = await _applicationStore.GetPermissionsAsync(application, CancellationToken.None); permissions.Length.ShouldBeGreaterThan(0); @@ -194,7 +196,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetPostLogoutRedirectUrisAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var postLogoutRedirectUris = await _applicationStore.GetPostLogoutRedirectUrisAsync(application, CancellationToken.None); postLogoutRedirectUris.Length.ShouldBe(1); @@ -204,7 +206,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetRedirectUrisAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var redirectUris = await _applicationStore.GetRedirectUrisAsync(application, CancellationToken.None); redirectUris.Length.ShouldBe(1); @@ -214,7 +216,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetPropertiesAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var properties = await _applicationStore.GetPropertiesAsync(application, CancellationToken.None); properties.Count.ShouldBe(0); @@ -223,7 +225,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task GetRequirementsAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); var requirements = await _applicationStore.GetRequirementsAsync(application, CancellationToken.None); requirements.Length.ShouldBe(0); @@ -254,7 +256,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase public async Task SetClientIdAsync() { var clientId = Guid.NewGuid().ToString(); - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetClientIdAsync(application, clientId, CancellationToken.None); application.ClientId.ShouldBe(clientId); @@ -264,7 +266,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase public async Task SetClientSecretAsync() { var clientSecret = Guid.NewGuid().ToString(); - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetClientSecretAsync(application, clientSecret, CancellationToken.None); application.ClientSecret.ShouldBe(clientSecret); @@ -273,7 +275,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task SetClientTypeAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetClientTypeAsync(application, OpenIddictConstants.ClientTypes.Confidential, CancellationToken.None); application.Type.ShouldBe(OpenIddictConstants.ClientTypes.Confidential); @@ -282,7 +284,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task SetConsentTypeAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetConsentTypeAsync(application, OpenIddictConstants.ConsentTypes.Systematic, CancellationToken.None); application.ConsentType.ShouldBe(OpenIddictConstants.ConsentTypes.Systematic); @@ -292,7 +294,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase public async Task SetDisplayNameAsync() { var displayName = Guid.NewGuid().ToString(); - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetDisplayNameAsync(application, displayName, CancellationToken.None); application.DisplayName.ShouldBe(displayName); @@ -305,7 +307,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase displayNames = displayNames.Add(CultureInfo.GetCultureInfo("en"), "Test Application"); displayNames = displayNames.Add(CultureInfo.GetCultureInfo("zh-Hans"), "测试应用程序"); - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetDisplayNamesAsync(application, displayNames, CancellationToken.None); application.DisplayNames.ShouldContain("Test Application"); @@ -315,7 +317,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task SetPermissionsAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetPermissionsAsync(application, ImmutableArray.Create(OpenIddictConstants.Permissions.Endpoints.Authorization), CancellationToken.None); application.Permissions.ShouldBe("[\""+OpenIddictConstants.Permissions.Endpoints.Authorization+"\"]"); @@ -324,7 +326,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task SetPostLogoutRedirectUrisAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetPostLogoutRedirectUrisAsync(application, ImmutableArray.Create("https://abp.io"), CancellationToken.None); application.PostLogoutRedirectUris.ShouldBe("[\"https://abp.io\"]"); @@ -333,7 +335,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task SetPropertiesAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetPropertiesAsync(application, ImmutableDictionary.Create(), CancellationToken.None); application.Properties.ShouldBeNull(); @@ -342,7 +344,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task SetRedirectUrisAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetRedirectUrisAsync(application, ImmutableArray.Create("https://abp.io"), CancellationToken.None); application.RedirectUris.ShouldBe("[\"https://abp.io\"]"); @@ -351,7 +353,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task SetRequirementsAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); await _applicationStore.SetRequirementsAsync(application, ImmutableArray.Create(OpenIddictConstants.Requirements.Features.ProofKeyForCodeExchange), CancellationToken.None); application.Requirements.ShouldBe("[\""+OpenIddictConstants.Requirements.Features.ProofKeyForCodeExchange+"\"]"); @@ -360,7 +362,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase [Fact] public async Task UpdateAsync() { - var application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + var application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); application.ClientId = "new_client_id"; application.Type = OpenIddictConstants.ClientTypes.Public; application.RedirectUris = "https://new_logout_uri"; @@ -368,7 +370,7 @@ public class AbpOpenIddictApplicationStore_Tests : OpenIddictDomainTestBase application.DisplayName = "new_display_name"; await _applicationStore.UpdateAsync(application, CancellationToken.None); - application = await _applicationStore.FindByIdAsync(AbpOpenIddictTestData.App1Id.ToString(), CancellationToken.None); + application = await _applicationStore.FindByIdAsync(_testData.App1Id.ToString(), CancellationToken.None); application.ShouldNotBeNull(); application.ClientId.ShouldBe("new_client_id"); diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore_Tests.cs new file mode 100644 index 0000000000..a392d1f89c --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore_Tests.cs @@ -0,0 +1,128 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using OpenIddict.Abstractions; +using Shouldly; +using Xunit; + +namespace Volo.Abp.OpenIddict.Authorizations; + +public class AbpOpenIddictAuthorizationStore_Tests : OpenIddictDomainTestBase +{ + private readonly IOpenIddictAuthorizationStore _authorizationStore; + private readonly AbpOpenIddictTestData _testData; + + public AbpOpenIddictAuthorizationStore_Tests() + { + _authorizationStore = ServiceProvider.GetRequiredService>(); + _testData = ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task CountAsync() + { + var count = await _authorizationStore.CountAsync(CancellationToken.None); + count.ShouldBe(2); + } + + [Fact] + public async Task CreateAsync() + { + var id = Guid.NewGuid(); + await _authorizationStore.CreateAsync(new OpenIddictAuthorizationModel { + Id = id, + ApplicationId = _testData.App1Id, + Status = "TestStatus3", + Subject = "TestSubject3", + Type = OpenIddictConstants.AuthorizationTypes.Permanent + }, CancellationToken.None); + + var authorization = await _authorizationStore.FindByIdAsync(id.ToString(), CancellationToken.None); + + authorization.ShouldNotBeNull(); + authorization.Status.ShouldBe("TestStatus3"); + authorization.Subject.ShouldBe("TestSubject3"); + authorization.Type.ShouldBe(OpenIddictConstants.AuthorizationTypes.Permanent); + } + + [Fact] + public async Task DeleteAsync() + { + var authorization = await _authorizationStore.FindByIdAsync(_testData.Authorization1Id.ToString(), CancellationToken.None); + await _authorizationStore.DeleteAsync(authorization, CancellationToken.None); + + authorization = await _authorizationStore.FindByIdAsync(_testData.Authorization1Id.ToString(), CancellationToken.None); + authorization.ShouldBeNull(); + } + + [Fact] + public async Task FindByIdAsync_Should_Return_Null_If_Not_Found() + { + var authorization = await _authorizationStore.FindByIdAsync(new Guid().ToString(), CancellationToken.None); + authorization.ShouldBeNull(); + } + + [Fact] + public async Task FindByIdAsync_Should_Return_Authorization_If_Not_Found() + { + var authorization = await _authorizationStore.FindByIdAsync(_testData.Authorization1Id.ToString(), CancellationToken.None); + authorization.ShouldNotBeNull(); + authorization.Status.ShouldBe("TestStatus1"); + authorization.Subject.ShouldBe("TestSubject1"); + authorization.Type.ShouldBe(OpenIddictConstants.AuthorizationTypes.Permanent); + } + + [Fact] + public async Task FindByApplicationIdAsync_Should_Return_Empty_If_Not_Found() + { + var authorizations = await _authorizationStore.FindByApplicationIdAsync(new Guid().ToString(), CancellationToken.None).ToListAsync(); + + authorizations.Count.ShouldBe(0); + } + + [Fact] + public async Task FindByApplicationIdAsync_Should_Return_Authorizations_If_Found() + { + var authorizations = await _authorizationStore.FindByApplicationIdAsync(_testData.App1Id.ToString(), CancellationToken.None).ToListAsync(); + + authorizations.Count.ShouldBe(1); + } + + [Fact] + public async Task FindBySubjectAsync_Should_Return_Empty_If_Not_Found() + { + var authorizations = await _authorizationStore.FindBySubjectAsync(new Guid().ToString(), CancellationToken.None).ToListAsync(); + + authorizations.Count.ShouldBe(0); + } + + [Fact] + public async Task FindBySubjectAsync_Should_Return_Authorizations_If_Found() + { + var authorizations = await _authorizationStore.FindBySubjectAsync("TestSubject1", CancellationToken.None).ToListAsync(); + + authorizations.Count.ShouldBe(1); + } + + [Fact] + public async Task UpdateAsync() + { + var authorization = await _authorizationStore.FindByIdAsync(_testData.Authorization1Id.ToString(), CancellationToken.None); + + authorization.Status = "New status"; + authorization.Subject = "New subject"; + authorization.Type = OpenIddictConstants.AuthorizationTypes.AdHoc; + authorization.ApplicationId = _testData.App2Id; + + await _authorizationStore.UpdateAsync(authorization, CancellationToken.None); + + authorization = await _authorizationStore.FindByIdAsync(_testData.Authorization1Id.ToString(), CancellationToken.None); + + authorization.Status.ShouldBe("New status"); + authorization.Subject.ShouldBe("New subject"); + authorization.Type.ShouldBe(OpenIddictConstants.AuthorizationTypes.AdHoc); + authorization.ApplicationId.ShouldBe(_testData.App2Id); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/OpenIddictDomainTestModule.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/OpenIddictDomainTestModule.cs index ae3a7fd880..b061e36c69 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/OpenIddictDomainTestModule.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/OpenIddictDomainTestModule.cs @@ -12,5 +12,5 @@ namespace Volo.Abp.OpenIddict; )] public class OpenIddictDomainTestModule : AbpModule { - + } diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore_Tests.cs new file mode 100644 index 0000000000..1c6701c848 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore_Tests.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections.Immutable; +using System.Globalization; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using OpenIddict.Abstractions; +using Shouldly; +using Xunit; + +namespace Volo.Abp.OpenIddict.Scopes; + +public class AbpOpenIddictScopeStore_Tests : OpenIddictDomainTestBase +{ + private readonly IOpenIddictScopeStore _scopeStore; + private readonly AbpOpenIddictTestData _testData; + + public AbpOpenIddictScopeStore_Tests() + { + _scopeStore = ServiceProvider.GetRequiredService>(); + _testData = ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task CountAsync() + { + var count = await _scopeStore.CountAsync(CancellationToken.None); + count.ShouldBe(2); + } + + [Fact] + public async Task CreateAsync() + { + await _scopeStore.CreateAsync( + new OpenIddictScopeModel { + Name = "scope3", Description = "scope3 description", DisplayName = "scope3 display name" + }, CancellationToken.None); + + var scope = await _scopeStore.FindByNameAsync("scope3", CancellationToken.None); + + scope.ShouldNotBeNull(); + scope.Name.ShouldBe("scope3"); + scope.Description.ShouldBe("scope3 description"); + scope.DisplayName.ShouldBe("scope3 display name"); + scope.Descriptions.ShouldBeNull(); + scope.DisplayNames.ShouldBeNull(); + scope.Resources.ShouldBeNull(); + } + + [Fact] + public async Task DeleteAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.DeleteAsync(scope, CancellationToken.None); + + scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + scope.ShouldBeNull(); + } + + [Fact] + public async Task FindByIdAsync_Should_Return_Null_If_Not_Found() + { + var nonExistingId = Guid.NewGuid().ToString(); + var scope = await _scopeStore.FindByIdAsync(nonExistingId, CancellationToken.None); + scope.ShouldBeNull(); + } + + [Fact] + public async Task FindByIdAsync_Should_Return_Scope_If_Found() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + + scope.ShouldNotBeNull(); + scope.Name.ShouldBe(_testData.Scope1Name); + scope.DisplayName.ShouldBe("Test Scope 1"); + scope.Description.ShouldBe("Test Scope 1"); + scope.DisplayNames.ShouldContain("测试范围1"); + scope.DisplayNames.ShouldContain("Test Kapsamı 1"); + scope.Resources.ShouldBe("[\"TestScope1Resource\"]"); + } + + [Fact] + public async Task FindByNameAsync_Should_Return_Null_If_Not_Found() + { + var nonExistingName = Guid.NewGuid().ToString(); + var scope = await _scopeStore.FindByNameAsync(nonExistingName, CancellationToken.None); + scope.ShouldBeNull(); + } + + [Fact] + public async Task FindByNameAsync_Should_Return_Application_If_Found() + { + var scope = await _scopeStore.FindByNameAsync(_testData.Scope1Name, CancellationToken.None); + + scope.ShouldNotBeNull(); + scope.Name.ShouldBe(_testData.Scope1Name); + scope.DisplayName.ShouldBe("Test Scope 1"); + scope.Description.ShouldBe("Test Scope 1"); + scope.DisplayNames.ShouldContain("测试范围1"); + scope.DisplayNames.ShouldContain("Test Kapsamı 1"); + scope.Resources.ShouldBe("[\"TestScope1Resource\"]"); + } + + [Fact] + public async Task FindByNamesAsync_Should_Return_Empty_If_Not_Found() + { + var scopes = await _scopeStore + .FindByNamesAsync(ImmutableArray.Create("non-existing-name"), CancellationToken.None).ToListAsync(); + scopes.Count.ShouldBe(0); + } + + [Fact] + public async Task FindByNamesAsync_Should_Return_Scopes_If_Found() + { + var scopes = await _scopeStore + .FindByNamesAsync(ImmutableArray.Create("Scope1", "Scope2", "Scope3"), CancellationToken.None) + .ToListAsync(); + scopes.Count.ShouldBe(2); + } + + [Fact] + public async Task FindByResourceAsync_Should_Return_Empty_If_Not_Found() + { + var scopes = await _scopeStore.FindByResourceAsync("non-existing-resource", CancellationToken.None) + .ToListAsync(); + scopes.Count.ShouldBe(0); + } + + [Fact] + public async Task FindByResourceAsync_Should_Return_Scopes_If_Found() + { + var scopes = await _scopeStore.FindByResourceAsync("TestScope1Resource", CancellationToken.None).ToListAsync(); + scopes.Count.ShouldBe(1); + } + + [Fact] + public async Task GetDescriptionAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var description = await _scopeStore.GetDescriptionAsync(scope, CancellationToken.None); + description.ShouldBe("Test Scope 1"); + } + + [Fact] + public async Task GetDescriptionsAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var descriptions = await _scopeStore.GetDescriptionsAsync(scope, CancellationToken.None); + descriptions.Count.ShouldBe(0); + } + + [Fact] + public async Task GetDisplayNameAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var displayName = await _scopeStore.GetDisplayNameAsync(scope, CancellationToken.None); + displayName.ShouldBe("Test Scope 1"); + } + + [Fact] + public async Task GetDisplayNamesAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var displayNames = await _scopeStore.GetDisplayNamesAsync(scope, CancellationToken.None); + displayNames.Count.ShouldBe(2); + } + + [Fact] + public async Task GetIdAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var id = await _scopeStore.GetIdAsync(scope, CancellationToken.None); + id.ShouldBe(_testData.Scope1Id.ToString()); + } + + [Fact] + public async Task GetNameAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var name = await _scopeStore.GetNameAsync(scope, CancellationToken.None); + name.ShouldBe("Scope1"); + } + + [Fact] + public async Task GetPropertiesAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var properties = await _scopeStore.GetPropertiesAsync(scope, CancellationToken.None); + properties.Count.ShouldBe(0); + } + + [Fact] + public async Task GetResourcesAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + var resources = await _scopeStore.GetResourcesAsync(scope, CancellationToken.None); + resources.Length.ShouldBe(1); + resources.First().ShouldBe("TestScope1Resource"); + } + + [Fact] + public async Task InstantiateAsync() + { + var scope = await _scopeStore.InstantiateAsync(CancellationToken.None); + scope.ShouldNotBeNull(); + } + + [Fact] + public async Task ListAsync_Should_Return_Empty_If_Not_Found() + { + var scopes = await _scopeStore.ListAsync(2, 2, CancellationToken.None).ToListAsync(); + scopes.Count.ShouldBe(0); + } + + [Fact] + public async Task ListAsync_Should_Return_Applications_If_Found() + { + var scopes = await _scopeStore.ListAsync(2, 0, CancellationToken.None).ToListAsync(); + + scopes.Count.ShouldBe(2); + } + + [Fact] + public async Task SetDescriptionAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.SetDescriptionAsync(scope, "New Test Scope 1 Description", CancellationToken.None); + + scope.Description.ShouldBe("New Test Scope 1 Description"); + } + + [Fact] + public async Task SetDescriptionsAsync() + { + var descriptions = ImmutableDictionary.Create(); + descriptions = descriptions.Add(CultureInfo.GetCultureInfo("en"), "Test Scope"); + descriptions = descriptions.Add(CultureInfo.GetCultureInfo("zh-Hans"), "测试范围"); + + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.SetDescriptionsAsync(scope, descriptions, CancellationToken.None); + + scope.Descriptions.ShouldContain("Test Scope"); + scope.Descriptions.ShouldContain("测试范围"); + } + + [Fact] + public async Task SetDisplayNameAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.SetDisplayNameAsync(scope, "New Test Scope 1 Display Name", CancellationToken.None); + + scope.DisplayName.ShouldBe("New Test Scope 1 Display Name"); + } + + [Fact] + public async Task SetDisplayNamesAsync() + { + var displayNames = ImmutableDictionary.Create(); + displayNames = displayNames.Add(CultureInfo.GetCultureInfo("en"), "Test Scope"); + displayNames = displayNames.Add(CultureInfo.GetCultureInfo("zh-Hans"), "测试范围"); + + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.SetDisplayNamesAsync(scope, displayNames, CancellationToken.None); + + scope.DisplayNames.ShouldContain("Test Scope"); + scope.DisplayNames.ShouldContain("测试范围"); + } + + [Fact] + public async Task SetNameAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.SetNameAsync(scope, "New Test Scope 1 Name", CancellationToken.None); + + scope.Name.ShouldBe("New Test Scope 1 Name"); + } + + [Fact] + public async Task SetPropertiesAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.SetPropertiesAsync(scope, ImmutableDictionary.Create(), + CancellationToken.None); + + scope.Properties.ShouldBeNull(); + } + + [Fact] + public async Task SetResourcesAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + await _scopeStore.SetResourcesAsync(scope, ImmutableArray.Create("TestScope1Resource", "TestScope1Resource2"), + CancellationToken.None); + + scope.Resources.ShouldContain("TestScope1Resource"); + scope.Resources.ShouldContain("TestScope1Resource2"); + } + + [Fact] + public async Task UpdateAsync() + { + var scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + scope.Name = "New Test Scope 1 Name"; + scope.DisplayName = "New Test Scope 1 Display Name"; + scope.Resources = "New Test Scope 1 Resource"; + scope.Properties = "New Test Scope 1 Properties"; + scope.Description = "New Test Scope 1 Description"; + scope.Descriptions = "New Test Scope 1 Descriptions"; + scope.DisplayNames = "New Test Scope 1 Display Names"; + + await _scopeStore.UpdateAsync(scope, CancellationToken.None); + + scope = await _scopeStore.FindByIdAsync(_testData.Scope1Id.ToString(), CancellationToken.None); + scope.Name.ShouldBe("New Test Scope 1 Name"); + scope.DisplayName.ShouldBe("New Test Scope 1 Display Name"); + scope.Resources.ShouldBe("New Test Scope 1 Resource"); + scope.Properties.ShouldBe("New Test Scope 1 Properties"); + scope.Description.ShouldBe("New Test Scope 1 Description"); + scope.Descriptions.ShouldBe("New Test Scope 1 Descriptions"); + scope.DisplayNames.ShouldBe("New Test Scope 1 Display Names"); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore_Tests.cs new file mode 100644 index 0000000000..94e5d5710d --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore_Tests.cs @@ -0,0 +1,156 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using OpenIddict.Abstractions; +using Shouldly; +using Xunit; + +namespace Volo.Abp.OpenIddict.Tokens; + +public class AbpOpenIddictTokenStore_Tests : OpenIddictDomainTestBase +{ + private readonly IOpenIddictTokenStore _tokenStore; + private readonly AbpOpenIddictTestData _testData; + + public AbpOpenIddictTokenStore_Tests() + { + _tokenStore = ServiceProvider.GetRequiredService>(); + _testData = ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task CountAsync() + { + var count = await _tokenStore.CountAsync(CancellationToken.None); + count.ShouldBe(2); + } + + [Fact] + public async Task CreateAsync() + { + await _tokenStore.CreateAsync(new OpenIddictTokenModel + { + ApplicationId = _testData.App1Id, + Payload = "TestPayload3", + Subject = "TestSubject3", + Type = "TestType3", + Status = OpenIddictConstants.Statuses.Inactive, + + }, CancellationToken.None); + + var tokens = await _tokenStore.FindBySubjectAsync("TestSubject3", CancellationToken.None).ToListAsync(); + + tokens.Count.ShouldBe(1); + var token = tokens.First(); + token.ApplicationId.ShouldBe(_testData.App1Id); + token.Payload.ShouldBe("TestPayload3"); + token.Subject.ShouldBe("TestSubject3"); + token.Type.ShouldBe("TestType3"); + token.Status.ShouldBe(OpenIddictConstants.Statuses.Inactive); + } + + [Fact] + public async Task DeleteAsync() + { + var token = await _tokenStore.FindByIdAsync(_testData.Token1Id.ToString(), CancellationToken.None); + await _tokenStore.DeleteAsync(token, CancellationToken.None); + + token = await _tokenStore.FindByIdAsync(_testData.Token1Id.ToString(), CancellationToken.None); + token.ShouldBeNull(); + } + + [Fact] + public async Task FindAsync_Should_Return_Empty_If_Not_Found() + { + var tokens = await _tokenStore.FindAsync("non_existing_subject", _testData.App1Id.ToString(), "non_existing_status", "non_existing_type", CancellationToken.None).ToListAsync(); + + tokens.Count.ShouldBe(0); + } + + [Fact] + public async Task FindAsync_Should_Return_Tokens_If_Found() + { + var tokens = await _tokenStore.FindAsync("TestSubject1", _testData.App1Id.ToString(),OpenIddictConstants.Statuses.Redeemed, "TestType1", CancellationToken.None).ToListAsync(); + + tokens.Count.ShouldBe(1); + } + + [Fact] + public async Task FindByApplicationIdAsync_Should_Return_Empty_If_Not_Found() + { + var tokens = await _tokenStore.FindByApplicationIdAsync(Guid.NewGuid().ToString(), CancellationToken.None).ToListAsync(); + + tokens.Count.ShouldBe(0); + } + + [Fact] + public async Task FindByApplicationIdAsync_Should_Return_Tokens_If_Found() + { + var tokens = await _tokenStore.FindByApplicationIdAsync(_testData.App1Id.ToString(), CancellationToken.None).ToListAsync(); + + tokens.Count.ShouldBe(1); + } + + [Fact] + public async Task FindByIdAsync_Should_Return_Null_If_Not_Found() + { + var nonExistingId = Guid.NewGuid().ToString(); + var token = await _tokenStore.FindByIdAsync(nonExistingId, CancellationToken.None); + token.ShouldBeNull(); + } + + [Fact] + public async Task FindByIdAsync_Should_Return_Token_If_Found() + { + var token = await _tokenStore.FindByIdAsync(_testData.Token1Id.ToString(), CancellationToken.None); + + token.ShouldNotBeNull(); + token.ApplicationId.ShouldBe(_testData.App1Id); + token.Payload.ShouldBe("TestPayload1"); + token.Subject.ShouldBe("TestSubject1"); + token.Type.ShouldBe("TestType1"); + token.Status.ShouldBe(OpenIddictConstants.Statuses.Redeemed); + token.ExpirationDate.ShouldNotBeNull(); + } + + [Fact] + public async Task FindByReferenceIdAsync_Should_Return_Null_If_Not_Found() + { + var token = await _tokenStore.FindByReferenceIdAsync(Guid.NewGuid().ToString(), CancellationToken.None); + token.ShouldBeNull(); + } + + [Fact] + public async Task FindByReferenceIdAsync_Should_Return_Token_If_Found() + { + var token = await _tokenStore.FindByIdAsync(_testData.Token1Id.ToString(), CancellationToken.None); + token = await _tokenStore.FindByReferenceIdAsync(token.ReferenceId, CancellationToken.None); + token.ShouldNotBeNull(); + } + + [Fact] + public async Task UpdateAsync() + { + var token = await _tokenStore.FindByIdAsync(_testData.Token1Id.ToString(), CancellationToken.None); + + var now = DateTime.Now; + token.ApplicationId = _testData.App2Id; + token.Payload = "New payload"; + token.Status = OpenIddictConstants.Statuses.Revoked; + token.Subject = "New subject"; + token.Type = "New type"; + token.ExpirationDate = now; + + await _tokenStore.UpdateAsync(token, CancellationToken.None); + token = await _tokenStore.FindByIdAsync(_testData.Token1Id.ToString(), CancellationToken.None); + + token.ApplicationId.ShouldBe(_testData.App2Id); + token.Payload.ShouldBe("New payload"); + token.Subject.ShouldBe("New subject"); + token.Type.ShouldBe("New type"); + token.Status.ShouldBe(OpenIddictConstants.Statuses.Revoked); + token.ExpirationDate.ShouldBe(now); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Tokens/TokenCleanupService_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Tokens/TokenCleanupService_Tests.cs new file mode 100644 index 0000000000..64a1e3f013 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.Domain.Tests/Volo/Abp/OpenIddict/Tokens/TokenCleanupService_Tests.cs @@ -0,0 +1,35 @@ +using System.Threading.Tasks; +using OpenIddict.Abstractions; +using Shouldly; +using Xunit; + +namespace Volo.Abp.OpenIddict.Tokens; + +public class TokenCleanupService_Tests : OpenIddictDomainTestBase +{ + private readonly IOpenIddictTokenManager _tokenManager; + private readonly IOpenIddictAuthorizationManager _authorizationManager; + private readonly TokenCleanupService _tokenCleanupService; + + public TokenCleanupService_Tests() + { + _tokenManager = GetRequiredService(); + _authorizationManager = GetRequiredService(); + _tokenCleanupService = GetRequiredService(); + } + + [Fact] + public async Task Should_Clear_Expired_Tokens() + { + var tokensCount = await _tokenManager.CountAsync(); + var authorizationsCount = await _authorizationManager.CountAsync(); + + await _tokenCleanupService.CleanAsync(); + + (await _tokenManager.CountAsync()) + .ShouldBe(tokensCount - 1); + + (await _authorizationManager.CountAsync()) + .ShouldBe(authorizationsCount - 1); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests.csproj b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests.csproj index f3b8602433..acfe196697 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests.csproj +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictApplicationRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictApplicationRepository_Tests.cs new file mode 100644 index 0000000000..0501e03c4c --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictApplicationRepository_Tests.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.OpenIddict.EntityFrameworkCore; + +public class OpenIddictApplicationRepository_Tests : OpenIddictApplicationRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictAuthorizationRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictAuthorizationRepository_Tests.cs new file mode 100644 index 0000000000..402189b27f --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictAuthorizationRepository_Tests.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.OpenIddict.EntityFrameworkCore; + +public class OpenIddictAuthorizationRepository_Tests : OpenIddictAuthorizationRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestBase.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestBase.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestBase.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestBase.cs diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestModule.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestModule.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestModule.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictEntityFrameworkCoreTestModule.cs diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictScopeRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictScopeRepository_Tests.cs new file mode 100644 index 0000000000..233949aca5 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictScopeRepository_Tests.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.OpenIddict.EntityFrameworkCore; + +public class OpenIddictScopeRepository_Tests : OpenIddictScopeRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictTokenRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictTokenRepository_Tests.cs new file mode 100644 index 0000000000..4cc70280a2 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.EntityFrameworkCore.Tests/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictTokenRepository_Tests.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.OpenIddict.EntityFrameworkCore; + +public class OpenIddictTokenRepository_Tests : OpenIddictTokenRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/OpenIddictMongoDbTestModule.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/OpenIddictMongoDbTestModule.cs deleted file mode 100644 index bdd4bdfa57..0000000000 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/OpenIddictMongoDbTestModule.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using Volo.Abp.Data; -using Volo.Abp.Modularity; -using Volo.Abp.Identity.MongoDB; - -namespace Volo.Abp.OpenIddict.MongoDB; - -[DependsOn( - typeof(OpenIddictTestBaseModule), - typeof(AbpIdentityMongoDbModule), - typeof(AbpOpenIddictMongoDbModule) - )] -public class OpenIddictMongoDbTestModule : AbpModule -{ - public override void ConfigureServices(ServiceConfigurationContext context) - { - var stringArray = MongoDbFixture.ConnectionString.Split('?'); - var connectionString = stringArray[0].EnsureEndsWith('/') + - "Db_" + - Guid.NewGuid().ToString("N") + "/?" + stringArray[1]; - - Configure(options => - { - options.ConnectionStrings.Default = connectionString; - }); - } -} diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj index 8eeb4386de..97e8e7121d 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/MongoDbFixture.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/MongoTestCollection.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoTestCollection.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/MongoTestCollection.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoTestCollection.cs diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictApplicationRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictApplicationRepository_Tests.cs new file mode 100644 index 0000000000..09a9c709b7 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictApplicationRepository_Tests.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Volo.Abp.OpenIddict.MongoDB; + +[Collection(MongoTestCollection.Name)] +public class OpenIddictApplicationRepository_Tests : OpenIddictApplicationRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictAuthorizationRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictAuthorizationRepository_Tests.cs new file mode 100644 index 0000000000..1e71f74b6b --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictAuthorizationRepository_Tests.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Volo.Abp.OpenIddict.MongoDB; + +[Collection(MongoTestCollection.Name)] +public class OpenIddictAuthorizationRepository_Tests : OpenIddictAuthorizationRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/OpenIddictMongoDbTestBase.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictMongoDbTestBase.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/MongoDB/OpenIddictMongoDbTestBase.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictMongoDbTestBase.cs diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictMongoDbTestModule.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictMongoDbTestModule.cs new file mode 100644 index 0000000000..60017fc99b --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictMongoDbTestModule.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using MongoDB.Driver; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Identity.MongoDB; +using Volo.Abp.MongoDB; +using Volo.Abp.Uow; + +namespace Volo.Abp.OpenIddict.MongoDB; + +[DependsOn( + typeof(OpenIddictTestBaseModule), + typeof(AbpIdentityMongoDbModule), + typeof(AbpOpenIddictMongoDbModule) + )] +public class OpenIddictMongoDbTestModule : AbpModule +{ + private static string _connectionString; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var stringArray = MongoDbFixture.ConnectionString.Split('?'); + _connectionString = stringArray[0].EnsureEndsWith('/') + + "Db_" + + Guid.NewGuid().ToString("N") + "/?" + stringArray[1]; + + Configure(options => + { + options.ConnectionStrings.Default = _connectionString; + }); + } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + Migrate(context); + } + + private static void Migrate(ApplicationInitializationContext context) + { + var dbContexts = context.ServiceProvider.GetServices(); + + foreach (var dbContext in dbContexts) + { + var mongoUrl = new MongoUrl(_connectionString); + var databaseName = mongoUrl.DatabaseName; + var client = new MongoClient(mongoUrl); + + if (databaseName.IsNullOrWhiteSpace()) + { + databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()); + } + + (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName)); + } + } +} diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictScopeRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictScopeRepository_Tests.cs new file mode 100644 index 0000000000..58e2332df3 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictScopeRepository_Tests.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Volo.Abp.OpenIddict.MongoDB; + +[Collection(MongoTestCollection.Name)] +public class OpenIddictScopeRepository_Tests : OpenIddictScopeRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictTokenRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictTokenRepository_Tests.cs new file mode 100644 index 0000000000..bbd88ba8f8 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/OpenIddictTokenRepository_Tests.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Volo.Abp.OpenIddict.MongoDB; + +[Collection(MongoTestCollection.Name)] +public class OpenIddictTokenRepository_Tests : OpenIddictTokenRepository_Tests +{ + +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/AbpOpenIddictTestData.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/AbpOpenIddictTestData.cs deleted file mode 100644 index fdaf2d03a3..0000000000 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/AbpOpenIddictTestData.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace Volo.Abp.OpenIddict; - -public static class AbpOpenIddictTestData -{ - public static Guid App1Id { get; set; } = Guid.NewGuid(); - public static string App1ClientId { get; set; } = "Client1"; - public static Guid App2Id { get; set; } = Guid.NewGuid(); - public static string App2ClientId { get; set; } = "Client2"; - - public static Guid Scope1Id { get; set; } = Guid.NewGuid(); - public static string Scope1Name { get; set; } = "Scope1"; - public static Guid Scope2Id { get; set; } = Guid.NewGuid(); - public static string Scope2Name { get; set; } = "Scope2"; -} diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/AbpOpenIddictTestData.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/AbpOpenIddictTestData.cs new file mode 100644 index 0000000000..f31208ed2f --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/AbpOpenIddictTestData.cs @@ -0,0 +1,25 @@ +using System; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.OpenIddict; + +public class AbpOpenIddictTestData : ISingletonDependency +{ + public Guid App1Id { get; set; } = Guid.NewGuid(); + public string App1ClientId { get; set; } = "Client1"; + public Guid App2Id { get; set; } = Guid.NewGuid(); + public string App2ClientId { get; set; } = "Client2"; + + public Guid Scope1Id { get; set; } = Guid.NewGuid(); + public string Scope1Name { get; set; } = "Scope1"; + public Guid Scope2Id { get; set; } = Guid.NewGuid(); + public string Scope2Name { get; set; } = "Scope2"; + + public Guid Token1Id { get; set; } = Guid.NewGuid(); + + public Guid Token2Id { get; set; } = Guid.NewGuid(); + + public Guid Authorization1Id { get; set; } = Guid.NewGuid(); + + public Guid Authorization2Id { get; set; } = Guid.NewGuid(); +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictApplicationRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictApplicationRepository_Tests.cs new file mode 100644 index 0000000000..b29c90f248 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictApplicationRepository_Tests.cs @@ -0,0 +1,65 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.Applications; +using Xunit; + +namespace Volo.Abp.OpenIddict; + +public abstract class OpenIddictApplicationRepository_Tests : OpenIddictTestBase + where TStartupModule : IAbpModule +{ + private readonly IOpenIddictApplicationRepository _applicationRepository; + private readonly AbpOpenIddictTestData _testData; + + protected OpenIddictApplicationRepository_Tests() + { + _applicationRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetListAsync() + { + (await _applicationRepository.GetListAsync()).Count.ShouldBe(2); + (await _applicationRepository.GetListAsync("id", 1, int.MaxValue)).Count.ShouldBe(1); + (await _applicationRepository.GetListAsync("id", 0, int.MaxValue, filter: _testData.App1ClientId)).Count.ShouldBe(1); + } + + [Fact] + public async Task GetCountAsync() + { + (await _applicationRepository.GetCountAsync()).ShouldBe(2); + (await _applicationRepository.GetCountAsync(filter: _testData.App1ClientId)).ShouldBe(1); + } + + [Fact] + public async Task FindByClientIdAsync() + { + var application = await _applicationRepository.FindByClientIdAsync(_testData.App1ClientId); + + application.ShouldNotBeNull(); + application.ClientId.ShouldBe(_testData.App1ClientId); + } + + [Fact] + public async Task FindByPostLogoutRedirectUriAsync() + { + var applications = await _applicationRepository.FindByPostLogoutRedirectUriAsync("https://abp.io"); + applications.Count.ShouldBe(2); + } + + [Fact] + public async Task FindByRedirectUriAsync() + { + var applications = await _applicationRepository.FindByRedirectUriAsync("https://abp.io"); + applications.Count.ShouldBe(2); + } + + [Fact] + public async Task ListAsync() + { + (await _applicationRepository.ListAsync(int.MaxValue , 0)).Count.ShouldBe(2); + (await _applicationRepository.ListAsync(int.MaxValue , 2)).Count.ShouldBe(0); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictAuthorizationRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictAuthorizationRepository_Tests.cs new file mode 100644 index 0000000000..72e82d6ebe --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictAuthorizationRepository_Tests.cs @@ -0,0 +1,72 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using OpenIddict.Abstractions; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.Authorizations; +using Xunit; + +namespace Volo.Abp.OpenIddict; + +public abstract class OpenIddictAuthorizationRepository_Tests : OpenIddictTestBase + where TStartupModule : IAbpModule +{ + private readonly IOpenIddictAuthorizationRepository _authorizationRepository; + private readonly AbpOpenIddictTestData _testData; + + public OpenIddictAuthorizationRepository_Tests() + { + _authorizationRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task FindAsync() + { + (await _authorizationRepository.FindAsync(subject:"TestSubject1", client: new Guid())).Count.ShouldBe(0); + (await _authorizationRepository.FindAsync(subject:"TestSubject1", client: _testData.App1Id)).Count.ShouldBe(1); + (await _authorizationRepository.FindAsync(subject:"TestSubject1", client: _testData.App1Id, status: "NonExistsStatus")).Count.ShouldBe(0); + (await _authorizationRepository.FindAsync(subject:"TestSubject1", client: _testData.App1Id, status: "TestStatus1")).Count.ShouldBe(1); + (await _authorizationRepository.FindAsync(subject:"TestSubject1", client: _testData.App1Id, status: "TestStatus1" ,type: "NonExistsType")).Count.ShouldBe(0); + (await _authorizationRepository.FindAsync(subject:"TestSubject1", client: _testData.App1Id, status: "TestStatus1" ,type: OpenIddictConstants.AuthorizationTypes.Permanent)).Count.ShouldBe(1); + } + + [Fact] + public async Task FindByApplicationIdAsync() + { + var authorizations = await _authorizationRepository.FindByApplicationIdAsync(_testData.App1Id); + + authorizations.Count.ShouldBe(1); + authorizations.First().ApplicationId.ShouldBe(_testData.App1Id); + } + + [Fact] + public async Task FindByIdAsync() + { + var authorization = await _authorizationRepository.FindByIdAsync(_testData.Authorization1Id); + + authorization.ShouldNotBeNull(); + authorization.Id.ShouldBe(_testData.Authorization1Id); + } + + [Fact] + public async Task FindBySubjectAsync() + { + (await _authorizationRepository.FindBySubjectAsync(subject:"TestSubject1")).Count.ShouldBe(1); + } + + [Fact] + public async Task ListAsync() + { + (await _authorizationRepository.ListAsync(int.MaxValue, 0)).Count.ShouldBe(2); + (await _authorizationRepository.ListAsync(int.MaxValue, 2)).Count.ShouldBe(0); + } + + [Fact] + public async Task GetPruneListAsync() + { + var threshold = DateTime.UtcNow - TimeSpan.FromDays(14); + (await _authorizationRepository.GetPruneListAsync(threshold, int.MaxValue)).Count.ShouldBe(1); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictDataSeedContributor.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictDataSeedContributor.cs similarity index 54% rename from modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictDataSeedContributor.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictDataSeedContributor.cs index cc045b3004..1b9dbed4ca 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictDataSeedContributor.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictDataSeedContributor.cs @@ -2,43 +2,59 @@ using System.Globalization; using System.Threading.Tasks; using OpenIddict.Abstractions; +using OpenIddict.Core; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Authorizations; using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.OpenIddict.Tokens; +using Volo.Abp.Timing; namespace Volo.Abp.OpenIddict; public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency { - private readonly IGuidGenerator _guidGenerator; - private readonly ICurrentTenant _currentTenant; private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictScopeManager _scopeManager; + private readonly IOpenIddictTokenManager _tokenManager; + private readonly IOpenIddictAuthorizationManager _authorizationManager; + private readonly AbpOpenIddictTestData _testData; + private readonly IClock _clock; public OpenIddictDataSeedContributor( - IGuidGenerator guidGenerator, ICurrentTenant currentTenant, IOpenIddictApplicationManager applicationManager, IOpenIddictScopeManager scopeManager) + IOpenIddictApplicationManager applicationManager, + IOpenIddictScopeManager scopeManager, + IOpenIddictTokenManager tokenManager, + IOpenIddictAuthorizationManager authorizationManager, + IClock clock, + AbpOpenIddictTestData testData) { - _guidGenerator = guidGenerator; - _currentTenant = currentTenant; _applicationManager = applicationManager; _scopeManager = scopeManager; + _tokenManager = tokenManager; + _authorizationManager = authorizationManager; + _clock = clock; + _testData = testData; } public async Task SeedAsync(DataSeedContext context) { await CreateScopesAsync(); await CreateApplicationsAsync(); + await CreateAuthorizationsAsync(); + await CreateTokensAsync(); } private async Task CreateScopesAsync() { - var scope1 = (OpenIddictScopeModel)await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor() + await _scopeManager.CreateAsync(await GetOpenIddictScopeModelAsync(_testData.Scope1Id, new OpenIddictScopeDescriptor { - Name = AbpOpenIddictTestData.Scope1Name, + Name = _testData.Scope1Name, DisplayName = "Test Scope 1", + Description = "Test Scope 1", DisplayNames = { [CultureInfo.GetCultureInfo("zh-Hans")] = "测试范围1", @@ -48,13 +64,13 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep { "TestScope1Resource" } - }); - AbpOpenIddictTestData.Scope1Id = scope1.Id; - - var scope2 = (OpenIddictScopeModel)await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor() + })); + + await _scopeManager.CreateAsync(await GetOpenIddictScopeModelAsync(_testData.Scope2Id, new OpenIddictScopeDescriptor() { - Name = AbpOpenIddictTestData.Scope2Name, + Name = _testData.Scope2Name, DisplayName = "Test Scope 2", + Description = "Test Scope 2", DisplayNames = { [CultureInfo.GetCultureInfo("zh-Hans")] = "测试范围2", @@ -64,16 +80,21 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep { "TestScopeResource2" } - }); - AbpOpenIddictTestData.Scope2Id = scope2.Id; + })); } - + private async Task GetOpenIddictScopeModelAsync(Guid id, OpenIddictScopeDescriptor scopeDescriptor) + { + var scope = new OpenIddictScopeModel{Id = id}; + await _scopeManager.PopulateAsync(scope, scopeDescriptor); + return scope; + } + private async Task CreateApplicationsAsync() { - var app1 = (OpenIddictApplicationModel)await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor + await _applicationManager.CreateAsync(await GetOpenIddictApplicationModelAsync(_testData.App1Id, new OpenIddictApplicationDescriptor { - ClientId = AbpOpenIddictTestData.App1ClientId, + ClientId = _testData.App1ClientId, ConsentType = OpenIddictConstants.ConsentTypes.Explicit, DisplayName = "Test Application", RedirectUris = @@ -115,14 +136,13 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Phone, - OpenIddictConstants.Permissions.Prefixes.Scope + AbpOpenIddictTestData.Scope1Name + OpenIddictConstants.Permissions.Prefixes.Scope + _testData.Scope1Name } - }); - AbpOpenIddictTestData.App1Id = app1.Id; - - var app2 = (OpenIddictApplicationModel)await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor + })); + + await _applicationManager.CreateAsync(await GetOpenIddictApplicationModelAsync(_testData.App2Id, new OpenIddictApplicationDescriptor { - ClientId = AbpOpenIddictTestData.App2ClientId, + ClientId = _testData.App2ClientId, ConsentType = OpenIddictConstants.ConsentTypes.Explicit, DisplayName = "Test Application", RedirectUris = @@ -164,10 +184,79 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Phone, - OpenIddictConstants.Permissions.Prefixes.Scope + AbpOpenIddictTestData.Scope1Name, - OpenIddictConstants.Permissions.Prefixes.Scope + AbpOpenIddictTestData.Scope2Name, + OpenIddictConstants.Permissions.Prefixes.Scope + _testData.Scope1Name, + OpenIddictConstants.Permissions.Prefixes.Scope + _testData.Scope2Name, } - }); - AbpOpenIddictTestData.App2Id = app2.Id; + })); + } + + private async Task GetOpenIddictApplicationModelAsync(Guid id, OpenIddictApplicationDescriptor applicationDescriptor) + { + var application = new OpenIddictApplicationModel{Id = id}; + await _applicationManager.PopulateAsync(application, applicationDescriptor); + return application; + } + + private async Task CreateTokensAsync() + { + await _tokenManager.CreateAsync(await GetOpenIddictTokenModelAsync(_testData.Token1Id, new OpenIddictTokenDescriptor + { + ApplicationId = _testData.App1Id.ToString(), + AuthorizationId = _testData.Authorization1Id.ToString(), + Subject = "TestSubject1", + Type = "TestType1", + Status = OpenIddictConstants.Statuses.Redeemed, + Payload = "TestPayload1", + ReferenceId = "TestReferenceId1", + ExpirationDate = _clock.Now.AddDays(-30), + CreationDate = _clock.Now.AddDays(-30) + })); + + await _tokenManager.CreateAsync(await GetOpenIddictTokenModelAsync(_testData.Token2Id, new OpenIddictTokenDescriptor + { + ApplicationId = _testData.App2Id.ToString(), + AuthorizationId = _testData.Authorization2Id.ToString(), + Subject = "TestSubject2", + Type = "TestType2", + Status = OpenIddictConstants.Statuses.Valid, + Payload = "TestPayload2", + ReferenceId = "TestReferenceId2", + })); + } + + private async Task GetOpenIddictTokenModelAsync(Guid id, OpenIddictTokenDescriptor tokenDescriptor) + { + var token = new OpenIddictTokenModel{Id = id}; + await _tokenManager.PopulateAsync(token, tokenDescriptor); + return token; + } + + private async Task CreateAuthorizationsAsync() + { + await _authorizationManager.CreateAsync(await GetOpenIddictAuthorizationModelAsync(_testData.Authorization1Id, new OpenIddictAuthorizationDescriptor + { + ApplicationId = _testData.App1Id.ToString(), + Status = "TestStatus1", + Subject = "TestSubject1", + Type = OpenIddictConstants.AuthorizationTypes.Permanent, + CreationDate = _clock.Now.AddDays(-30) + + })); + + await _authorizationManager.CreateAsync(await GetOpenIddictAuthorizationModelAsync(_testData.Authorization2Id, new OpenIddictAuthorizationDescriptor + { + ApplicationId = _testData.App2Id.ToString(), + Status = "TestStatus2", + Subject = "TestSubject2", + Type = OpenIddictConstants.AuthorizationTypes.AdHoc, + CreationDate = _clock.Now + })); + } + + private async Task GetOpenIddictAuthorizationModelAsync(Guid id, OpenIddictAuthorizationDescriptor authorizationDescriptor) + { + var authorization = new OpenIddictAuthorizationModel{Id = id}; + await _authorizationManager.PopulateAsync(authorization, authorizationDescriptor); + return authorization; } } diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictScopeRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictScopeRepository_Tests.cs new file mode 100644 index 0000000000..1fcb0c31da --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictScopeRepository_Tests.cs @@ -0,0 +1,71 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.Scopes; +using Xunit; + +namespace Volo.Abp.OpenIddict; + +public abstract class OpenIddictScopeRepository_Tests : OpenIddictTestBase + where TStartupModule : IAbpModule +{ + private readonly IOpenIddictScopeRepository _scopeRepository; + private readonly AbpOpenIddictTestData _testData; + + public OpenIddictScopeRepository_Tests() + { + _scopeRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetListAsync() + { + (await _scopeRepository.GetListAsync("id", 0, int.MaxValue)).Count.ShouldBe(2); + (await _scopeRepository.GetListAsync("id", 0, int.MaxValue, filter: _testData.Scope1Name)).Count.ShouldBe(1); + } + + [Fact] + public async Task GetCountAsync() + { + (await _scopeRepository.GetCountAsync()).ShouldBe(2); + (await _scopeRepository.GetCountAsync(filter: _testData.Scope1Name)).ShouldBe(1); + } + + [Fact] + public async Task FindByIdAsync() + { + var scope = await _scopeRepository.FindByIdAsync(_testData.Scope1Id); + + scope.ShouldNotBeNull(); + scope.Id.ShouldBe(_testData.Scope1Id); + } + + [Fact] + public async Task FindByNameAsync() + { + var scope = await _scopeRepository.FindByNameAsync(_testData.Scope1Name); + + scope.ShouldNotBeNull(); + scope.Name.ShouldBe(_testData.Scope1Name); + } + + [Fact] + public async Task FindByNamesAsync() + { + (await _scopeRepository.FindByNamesAsync(new []{_testData.Scope1Name, _testData.Scope2Name})).Count.ShouldBe(2); + } + + [Fact] + public async Task FindByResourceAsync() + { + (await _scopeRepository.FindByResourceAsync("TestScope1Resource")).Count.ShouldBe(1); + } + + [Fact] + public async Task ListAsync() + { + (await _scopeRepository.ListAsync(int.MaxValue, 0)).Count.ShouldBe(2); + (await _scopeRepository.ListAsync(int.MaxValue, 2)).Count.ShouldBe(0); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBase.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictTestBase.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBase.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictTestBase.cs diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBaseModule.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictTestBaseModule.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBaseModule.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictTestBaseModule.cs diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictTokenRepository_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictTokenRepository_Tests.cs new file mode 100644 index 0000000000..4ed651eee6 --- /dev/null +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictTokenRepository_Tests.cs @@ -0,0 +1,104 @@ +using System; +using System.Threading.Tasks; +using OpenIddict.Abstractions; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.Tokens; +using Xunit; + +namespace Volo.Abp.OpenIddict; + +public abstract class OpenIddictTokenRepository_Tests : OpenIddictTestBase + where TStartupModule : IAbpModule +{ + private readonly IOpenIddictTokenRepository _tokenRepository; + private readonly AbpOpenIddictTestData _testData; + + public OpenIddictTokenRepository_Tests() + { + _tokenRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task DeleteManyByApplicationIdAsync() + { + await _tokenRepository.DeleteManyByApplicationIdAsync(new Guid()); + (await _tokenRepository.GetCountAsync()).ShouldBe(2); + + await _tokenRepository.DeleteManyByApplicationIdAsync(_testData.App1Id); + (await _tokenRepository.GetCountAsync()).ShouldBe(1); + } + + [Fact] + public async Task DeleteManyByAuthorizationIdAsync() + { + await _tokenRepository.DeleteManyByAuthorizationIdAsync(new Guid()); + (await _tokenRepository.GetCountAsync()).ShouldBe(2); + + await _tokenRepository.DeleteManyByAuthorizationIdAsync(_testData.Authorization1Id); + (await _tokenRepository.GetCountAsync()).ShouldBe(1); + } + + [Fact] + public async Task FindAsync() + { + (await _tokenRepository.FindAsync("TestSubject1", new Guid())).Count.ShouldBe(0); + (await _tokenRepository.FindAsync("TestSubject1", _testData.App1Id)).Count.ShouldBe(1); + (await _tokenRepository.FindAsync("TestSubject1", _testData.App1Id, "NonExistsStatus")).Count.ShouldBe(0); + (await _tokenRepository.FindAsync("TestSubject1", _testData.App1Id, OpenIddictConstants.Statuses.Redeemed)).Count.ShouldBe(1); + (await _tokenRepository.FindAsync("TestSubject1", _testData.App1Id, OpenIddictConstants.Statuses.Redeemed, "NonExistsType")).Count.ShouldBe(0); + (await _tokenRepository.FindAsync("TestSubject1", _testData.App1Id, OpenIddictConstants.Statuses.Redeemed, "TestType1")).Count.ShouldBe(1); + } + + [Fact] + public async Task FindByApplicationIdAsync() + { + (await _tokenRepository.FindByApplicationIdAsync(_testData.App1Id)).Count.ShouldBe(1); + } + + [Fact] + public async Task FindByAuthorizationIdAsync() + { + (await _tokenRepository.FindByAuthorizationIdAsync(_testData.Authorization1Id)).Count.ShouldBe(1); + } + + [Fact] + public async Task FindByIdAsync() + { + var token = await _tokenRepository.FindByIdAsync(_testData.Token1Id); + + token.ShouldNotBeNull(); + token.Id.ShouldBe(_testData.Token1Id); + } + + [Fact] + public async Task FindByReferenceIdAsync() + { + var token = await _tokenRepository.FindByIdAsync(_testData.Token1Id); + token = await _tokenRepository.FindByReferenceIdAsync(token.ReferenceId); + + token.ShouldNotBeNull(); + token.ReferenceId.ShouldBe(token.ReferenceId); + } + + [Fact] + public async Task FindBySubjectAsync() + { + (await _tokenRepository.FindBySubjectAsync("TestSubject1")).Count.ShouldBe(1); + } + + [Fact] + public async Task ListAsync() + { + (await _tokenRepository.ListAsync(int.MaxValue, 0)).Count.ShouldBe(2); + (await _tokenRepository.ListAsync(int.MaxValue, 2)).Count.ShouldBe(0); + } + + [Fact] + public async Task GetPruneListAsync() + { + var threshold = DateTime.UtcNow - TimeSpan.FromDays(14); + (await _tokenRepository.GetPruneListAsync(threshold, int.MaxValue)).Count.ShouldBe(1); + } +} \ No newline at end of file diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/Security/FakeCurrentPrincipalAccessor.cs similarity index 100% rename from modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Security/FakeCurrentPrincipalAccessor.cs rename to modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/Security/FakeCurrentPrincipalAccessor.cs diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts index 824b013843..a103b11a46 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts @@ -1,4 +1,5 @@ import { + AfterViewInit, ChangeDetectorRef, Directive, Input, @@ -8,20 +9,24 @@ import { TemplateRef, ViewContainerRef, } from '@angular/core'; -import { Subscription } from 'rxjs'; -import { distinctUntilChanged } from 'rxjs/operators'; +import { ReplaySubject, Subscription } from 'rxjs'; +import { distinctUntilChanged, take } from 'rxjs/operators'; import { PermissionService } from '../services/permission.service'; @Directive({ selector: '[abpPermission]', }) -export class PermissionDirective implements OnDestroy, OnChanges { +export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit { @Input('abpPermission') condition: string | undefined; @Input('abpPermissionRunChangeDetection') runChangeDetection = true; subscription!: Subscription; + cdrSubject = new ReplaySubject(); + + rendered = false; + constructor( @Optional() private templateRef: TemplateRef, private vcRef: ViewContainerRef, @@ -41,7 +46,11 @@ export class PermissionDirective implements OnDestroy, OnChanges { this.vcRef.clear(); if (isGranted) this.vcRef.createEmbeddedView(this.templateRef); if (this.runChangeDetection) { - this.cdRef.detectChanges(); + if (!this.rendered) { + this.cdrSubject.next(); + } else { + this.cdRef.detectChanges(); + } } else { this.cdRef.markForCheck(); } @@ -55,4 +64,9 @@ export class PermissionDirective implements OnDestroy, OnChanges { ngOnChanges() { this.check(); } + + ngAfterViewInit() { + this.cdrSubject.pipe(take(1)).subscribe(() => this.cdRef.detectChanges()); + this.rendered = true; + } } diff --git a/npm/ng-packs/packages/core/src/lib/services/environment.service.ts b/npm/ng-packs/packages/core/src/lib/services/environment.service.ts index 9fd1e280a3..a4e74cf16a 100644 --- a/npm/ng-packs/packages/core/src/lib/services/environment.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/environment.service.ts @@ -7,6 +7,13 @@ import { InternalStore } from '../utils/internal-store-utils'; const mapToApiUrl = (key: string) => (apis: Apis) => (apis[key] || apis.default).url || apis.default.url; +const mapToIssuer = (issuer: string) => { + if (!issuer) { + return issuer; + } + return issuer.endsWith('/') ? issuer : issuer + '/'; +}; + @Injectable({ providedIn: 'root' }) export class EnvironmentService { private readonly store = new InternalStore({} as Environment); @@ -34,4 +41,13 @@ export class EnvironmentService { setState(environment: Environment) { this.store.set(environment); } + + getIssuer() { + const issuer = this.store.state.oAuthConfig.issuer; + return mapToIssuer(issuer); + } + + getIssuer$() { + return this.store.sliceState(state => state.oAuthConfig.issuer).pipe(map(mapToIssuer)); + } } diff --git a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts index 37d792787c..4e64e61da8 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts @@ -76,6 +76,20 @@ describe('PermissionDirective', () => { expect(detectChanges).toHaveBeenCalled(); }); + it('should not call change detection before ngAfterViewInit', () => { + // hook before ngAfterViewInit + + const detectChanges = jest.spyOn(cdr, 'detectChanges'); + spectator.setHostInput({ condition: 'test' }); + grantedPolicy$.next(true); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + directive.onInit = () => { + expect(detectChanges).not.toHaveBeenCalled(); + }; + expect(detectChanges).toHaveBeenCalled(); + }); + describe('#subscription', () => { it('should call the unsubscribe', () => { const spy = jest.fn(() => {}); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts index 65b759a21e..33c6e1741c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts @@ -2,10 +2,10 @@ export const DEFAULT_VALIDATION_BLUEPRINTS = { creditCard: 'AbpValidation::ThisFieldIsNotAValidCreditCardNumber.', email: 'AbpValidation::ThisFieldIsNotAValidEmailAddress.', invalid: 'AbpValidation::ThisFieldIsNotValid.', - max: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', + max: 'AbpValidation::ThisFieldMustBeLessOrEqual{0}[{{ max }}]', maxlength: 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}[{{ requiredLength }}]', - min: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', + min: 'AbpValidation::ThisFieldMustBeGreaterThanOrEqual{0}[{{ min }}]', minlength: 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}[{{ requiredLength }}]', ngbDate: 'AbpValidation::ThisFieldIsNotValid.', diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MyProjectNameMongoDbContext.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MyProjectNameMongoDbContext.cs index 4033323cd8..437d8422b0 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MyProjectNameMongoDbContext.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MyProjectNameMongoDbContext.cs @@ -14,7 +14,7 @@ public class MyProjectNameMongoDbContext : AbpMongoDbContext { base.CreateModel(modelBuilder); - //builder.Entity(b => + //modelBuilder.Entity(b => //{ // //... //});