diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 874c6983c9..36f88f6f28 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -50,7 +50,7 @@ "AbpCommercialShortDescription": "ABP Commercial provides pre-built application modules, rapid application development tooling, professional UI themes, premium support and more.", "LiveDemo": "Live Demo", "LiveDemoLead": "{1} using your ABP account, {3} to abp.io
or fill the form below to create a live demo now", - "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "There is already an account with the given email address: {0}
You can login with your account to proceed.", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "There is already an account with the given email address: {0}
You should login with your account to proceed.", "GetLicence": "Get a License", "Application": "Application", "StartupTemplates": "Startup Templates", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index d179b969a8..0ea5c73e71 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -844,6 +844,14 @@ "ComesWithTheSourceCode_Description": "Mobil uygulamalar kaynak koduyla birlikte sağlanır. Marka yönergelerini karşılamak için uygulamalarınızın UX/UI'sini kolayca özelleştirin.", "MultipleOrganizationInfo": "Tüm Organizasyonlarınızı Görün", "PaymentFailedInfo": "Üzgünüz, Ödeme başarısız oldu! Bu hata, yatersiz bakiye, yanlış kredi kartı numarası veya yanlış PIN numarasından dolayı olabilir.", - "UsedPayment": "Bu ödeme zaten kullanımda." + "UsedPayment": "Bu ödeme zaten kullanımda.", + "TestimonialText": "Referans Yazınız", + "Position": "Poziyonunuz", + "ExperienceYear": "Yazılım Sektöründeki Tecrübeniz (Yıl)", + "Select": "Seçiniz", + "TestimonialTitle": "Referans", + "TestimonialInfo": "Düşüncelerinizi Paylaşın", + "Share": "Paylaş", + "YouAreNotAuthorizedToWriteTestimonial" : "Referansınızı paylaşabilmeniz için giriş yapmanız gerekmektedir" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index c1818fd879..7c79878cf5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -440,7 +440,29 @@ "Index_Page_Testimonial_2": "ABP Framework is not only a framework, it is also a guidance for project development/management, because it provides DDD, GenericRepository, DI, Microservice, Modularity trainings. Even if you are not going to use framework itself, you can develop yourself with docs.abp.io which is well and professionally prepared. (OpenIddict, Redis, Quartz etc.)\nBecause many thing pre-built, it shortens project development time significantly. (Such as login page, exception handling, data filtering-seeding, audit logging, localization, auto api controller etc.)\nAs an example from our app, i have used Local Event Bus for stock control. So, I am able to manage order movements by writing stock handler.\nIt is wonderful not to lose time for CreationTime, CreatorId. They are filled automatically.", "VideosLoginAndRegisterMessage": "To be able to watch videos, you must sign in.", "Filter": "Filter", - "VideoCourses": "Video Courses" + "VideoCourses": "Video Courses", + "TestimonialText": "Your testimonial", + "Position": "Position", + "ExperienceYear": "Years of Experience", + "FullName": "Full Name", + "CompanySize": "Company Size", + "Image": "Your profile picture", + "TestimonialTitle": "Let's hear your testimonial", + "TestimonialInfo": "What our customers say matters! Tell us about your experience with our product and service.", + "Country": "Country", + "TestimonialTextPlaceholder": "Write a brief story about how ABP helped you build and deliver your project. ", + "PositionPlaceholder": "Your position at your company.", + "SelectExperienceYearPlaceholder": "How many years have you been in software stuff", + "FullNamePlaceholder": "Your full name.", + "CompanyNamePlaceholder": "Your company name.", + "SelectCompanySizePlaceholder": "Employee count", + "ImagePlaceholder": "Your image.", + "SelectCountryPlaceholder": "Your country.", + "YouAreNotAuthorizedToWriteTestimonial": "To be able to write testimonial letter, you must be sign in.", + "UnAuthorizeTestimonialInfo": "If you want to share your opinion, you must be sign in", + "TheFileIsTooLargeForImage": "Your profile picture cannot be more than 1 MB", + "ThisExtensionIsNotAllowedForImage": "This extension is not allowed.", + "FileUploadError": "File upload error" } } diff --git a/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md b/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md index cc154ad9c1..c0bf748876 100644 --- a/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md +++ b/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md @@ -2,7 +2,7 @@ A new .NET version was released on November 14, 2023 and ABP 8.0 RC.1 shipped based on .NET 8.0 just after Microsoft's .NET 8.0 release. Therefore, it's a good time to see what we need to do to upgrade our existing projects to .NET 8.0. -Despite all the related dependency upgrades and changes made on ABP Framework and ABP Commercial sides, we still need to make some changes. Let's see the required actions that need to be taken in the following sections. +Despite all the related dependency upgrades and changes made on the ABP Framework and ABP Commercial sides, we still need to make some changes. Let's see the required actions that need to be taken in the following sections. ## Installing the .NET 8.0 SDK @@ -52,7 +52,7 @@ For example, you can update the ASP.NET Core image as follows: ```diff - FROM mcr.microsoft.com/dotnet/aspnet:7.0-bullseye-slim AS base -+ FROM mcr.microsoft.com/dotnet/aspnet:8.0-bullseye-slim AS base ++ FROM mcr.microsoft.com/dotnet/aspnet:8.0 ``` You can check the related images from Docker Hub and update them accordingly: @@ -63,22 +63,28 @@ You can check the related images from Docker Hub and update them accordingly: ## Upgrading Your Existing Projects to ABP 8.0 -Updating your application to ABP 8.0 is pretty straight-forward. You first need to upgrade the ABP CLI to version `8.0.0-rc.1` using a command line terminal: +Updating your application to ABP 8.0 is pretty straight-forward. You first need to upgrade the ABP CLI to version `8.0.0` using a command line terminal: ````bash -dotnet tool update Volo.Abp.Cli -g --version 8.0.0-rc.1 +dotnet tool update Volo.Abp.Cli -g --version 8.0.0 ```` **or install** it if you haven't before: ````bash -dotnet tool install Volo.Abp.Cli -g --version 8.0.0-rc.1 +dotnet tool install Volo.Abp.Cli -g --version 8.0.0 ```` Then, you can use the `abp update` command to update all the ABP related NuGet and NPM packages in your solution: ```bash -abp update --version 8.0.0-rc.1 +abp update --version 8.0.0 +``` + +Also, if you are using ABP Commercial, you can update the ABP Suite version with the following command: + +```bash +abp suite update --version 8.0.0 ``` After that, you need to check the migration guide documents, listed below: diff --git a/docs/en/Tutorials/Part-1.md b/docs/en/Tutorials/Part-1.md index 6795204936..e5a8750f39 100644 --- a/docs/en/Tutorials/Part-1.md +++ b/docs/en/Tutorials/Part-1.md @@ -368,7 +368,7 @@ public class CreateUpdateBookDto { [Required] [StringLength(128)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Required] public BookType Type { get; set; } = BookType.Undefined; diff --git a/docs/en/Tutorials/Part-10.md b/docs/en/Tutorials/Part-10.md index e71beccd6f..601905f522 100644 --- a/docs/en/Tutorials/Part-10.md +++ b/docs/en/Tutorials/Part-10.md @@ -614,19 +614,19 @@ using System.Threading.Tasks; using Acme.BookStore.Authors; using Shouldly; using Volo.Abp.Application.Dtos; +using Volo.Abp.Modularity; using Volo.Abp.Validation; using Xunit; namespace Acme.BookStore.Books; - {{if DB=="Mongo"}} -[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} -public class BookAppService_Tests : BookStoreApplicationTestBase +public abstract class BookAppService_Tests : BookStoreApplicationTestBase + where TStartupModule : IAbpModule { private readonly IBookAppService _bookAppService; private readonly IAuthorAppService _authorAppService; - public BookAppService_Tests() + protected BookAppService_Tests() { _bookAppService = GetRequiredService(); _authorAppService = GetRequiredService(); @@ -643,7 +643,7 @@ public class BookAppService_Tests : BookStoreApplicationTestBase //Assert result.TotalCount.ShouldBeGreaterThan(0); result.Items.ShouldContain(b => b.Name == "1984" && - b.AuthorName == "George Orwell"); + b.AuthorName == "George Orwell"); } [Fact] @@ -788,7 +788,7 @@ public class CreateModalModel : BookStorePageModel [Required] [StringLength(128)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Required] public BookType Type { get; set; } = BookType.Undefined; @@ -871,7 +871,7 @@ public class EditModalModel : BookStorePageModel [Required] [StringLength(128)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Required] public BookType Type { get; set; } = BookType.Undefined; diff --git a/docs/en/Tutorials/Part-4.md b/docs/en/Tutorials/Part-4.md index 072392e82b..c97bce6bd7 100644 --- a/docs/en/Tutorials/Part-4.md +++ b/docs/en/Tutorials/Part-4.md @@ -82,19 +82,18 @@ using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Application.Dtos; +using Volo.Abp.Modularity; using Volo.Abp.Validation; using Xunit; namespace Acme.BookStore.Books; -{{if DB=="Mongo"}} -[Collection(BookStoreTestConsts.CollectionDefinitionName)] -{{end}} -public class BookAppService_Tests : BookStoreApplicationTestBase +public abstract class BookAppService_Tests : BookStoreApplicationTestBase + where TStartupModule : IAbpModule { private readonly IBookAppService _bookAppService; - public BookAppService_Tests() + protected BookAppService_Tests() { _bookAppService = GetRequiredService(); } @@ -114,6 +113,41 @@ public class BookAppService_Tests : BookStoreApplicationTestBase } ```` +{{if DB == "EF"}} +Add a new implementation class of `BookAppService_Tests` class, named `EfCoreBookAppService_Tests` in the `EntityFrameworkCore\Applications\Books` namespace (folder) of the `Acme.BookStore.EntityFrameworkCore.Tests` project: + +````csharp +using Acme.BookStore.Books; +using Xunit; + +namespace Acme.BookStore.EntityFrameworkCore.Applications.Books; + +[Collection(BookStoreTestConsts.CollectionDefinitionName)] +public class EfCoreBookAppService_Tests : BookAppService_Tests +{ + +} +```` +{{end}} + +{{if DB == "Mongo"}} +Add a new implementation class of `BookAppService_Tests` class, named `MongoDBBookAppService_Tests` in the `MongoDb\Applications\Books` namespace (folder) of the `Acme.BookStore.MongoDB.Tests` project: + +````csharp +using Acme.BookStore.MongoDB; +using Acme.BookStore.Books; +using Xunit; + +namespace Acme.BookStore.MongoDb.Applications.Books; + +[Collection(BookStoreTestConsts.CollectionDefinitionName)] +public class MongoDBBookAppService_Tests : BookAppService_Tests +{ + +} +```` +{{end}} + * `Should_Get_List_Of_Books` test simply uses `BookAppService.GetListAsync` method to get and check the list of books. * We can safely check the book "1984" by its name, because we know that this books is available in the database since we've added it in the seed data. @@ -174,19 +208,18 @@ using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Application.Dtos; +using Volo.Abp.Modularity; using Volo.Abp.Validation; using Xunit; namespace Acme.BookStore.Books; -{{if DB=="Mongo"}} -[Collection(BookStoreTestConsts.CollectionDefinitionName)] -{{end}} -public class BookAppService_Tests : BookStoreApplicationTestBase +public abstract class BookAppService_Tests : BookStoreApplicationTestBase + where TStartupModule : IAbpModule { private readonly IBookAppService _bookAppService; - public BookAppService_Tests() + protected BookAppService_Tests() { _bookAppService = GetRequiredService(); } @@ -203,7 +236,7 @@ public class BookAppService_Tests : BookStoreApplicationTestBase result.TotalCount.ShouldBeGreaterThan(0); result.Items.ShouldContain(b => b.Name == "1984"); } - + [Fact] public async Task Should_Create_A_Valid_Book() { diff --git a/docs/en/Tutorials/Part-6.md b/docs/en/Tutorials/Part-6.md index 40b334808c..2cb525b4a4 100644 --- a/docs/en/Tutorials/Part-6.md +++ b/docs/en/Tutorials/Part-6.md @@ -75,9 +75,9 @@ public class Author : FullAuditedAggregateRoot internal Author( Guid id, - [NotNull] string name, + string name, DateTime birthDate, - [CanBeNull] string shortBio = null) + string? shortBio = null) : base(id) { SetName(name); @@ -85,13 +85,13 @@ public class Author : FullAuditedAggregateRoot ShortBio = shortBio; } - internal Author ChangeName([NotNull] string name) + internal Author ChangeName(string name) { SetName(name); return this; } - private void SetName([NotNull] string name) + private void SetName(string name) { Name = Check.NotNullOrWhiteSpace( name, @@ -146,9 +146,9 @@ public class AuthorManager : DomainService } public async Task CreateAsync( - [NotNull] string name, + string name, DateTime birthDate, - [CanBeNull] string shortBio = null) + string? shortBio = null) { Check.NotNullOrWhiteSpace(name, nameof(name)); @@ -167,8 +167,8 @@ public class AuthorManager : DomainService } public async Task ChangeNameAsync( - [NotNull] Author author, - [NotNull] string newName) + Author author, + string newName) { Check.NotNull(author, nameof(author)); Check.NotNullOrWhiteSpace(newName, nameof(newName)); diff --git a/docs/en/Tutorials/Part-8.md b/docs/en/Tutorials/Part-8.md index 9d638e909e..a1563f6b2c 100644 --- a/docs/en/Tutorials/Part-8.md +++ b/docs/en/Tutorials/Part-8.md @@ -123,12 +123,12 @@ public class CreateAuthorDto { [Required] [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Required] public DateTime BirthDate { get; set; } - public string ShortBio { get; set; } + public string? ShortBio { get; set; } } ```` @@ -146,12 +146,12 @@ public class UpdateAuthorDto { [Required] [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Required] public DateTime BirthDate { get; set; } - public string ShortBio { get; set; } + public string? ShortBio { get; set; } } ```` @@ -481,18 +481,17 @@ Finally, we can write some tests for the `IAuthorAppService`. Add a new class, n using System; using System.Threading.Tasks; using Shouldly; +using Volo.Abp.Modularity; using Xunit; namespace Acme.BookStore.Authors; - {{if DB=="Mongo"}} -[Collection(BookStoreTestConsts.CollectionDefinitionName)] -{{end}} -public class AuthorAppService_Tests : BookStoreApplicationTestBase +public abstract class AuthorAppService_Tests : BookStoreApplicationTestBase + where TStartupModule : IAbpModule { private readonly IAuthorAppService _authorAppService; - public AuthorAppService_Tests() + protected AuthorAppService_Tests() { _authorAppService = GetRequiredService(); } @@ -554,6 +553,41 @@ public class AuthorAppService_Tests : BookStoreApplicationTestBase } ```` +{{if DB == "EF"}} +Add a new implementation class of `AuthorAppService_Tests` class, named `EfCoreAuthorAppService_Tests` in the `EntityFrameworkCore\Applications\Authors` namespace (folder) of the `Acme.BookStore.EntityFrameworkCore.Tests` project: + +````csharp +using Acme.BookStore.Authors; +using Xunit; + +namespace Acme.BookStore.EntityFrameworkCore.Applications.Authors; + +[Collection(BookStoreTestConsts.CollectionDefinitionName)] +public class EfCoreAuthorAppService_Tests : AuthorAppService_Tests +{ + +} +```` +{{end}} + +{{if DB == "Mongo"}} +Add a new implementation class of `AuthorAppService_Tests` class, named `MongoDBAuthorAppService_Tests` in the `MongoDb\Applications\Authors` namespace (folder) of the `Acme.BookStore.MongoDB.Tests` project: + +````csharp +using Acme.BookStore.MongoDB; +using Acme.BookStore.Authors; +using Xunit; + +namespace Acme.BookStore.MongoDb.Applications.Authors; + +[Collection(BookStoreTestConsts.CollectionDefinitionName)] +public class MongoDBAuthorAppService_Tests : AuthorAppService_Tests +{ + +} +```` +{{end}} + Created some tests for the application service methods, which should be clear to understand. ## The Next Part diff --git a/docs/en/Tutorials/Part-9.md b/docs/en/Tutorials/Part-9.md index 704d5f016b..358448c4d2 100644 --- a/docs/en/Tutorials/Part-9.md +++ b/docs/en/Tutorials/Part-9.md @@ -331,14 +331,14 @@ public class CreateModalModel : BookStorePageModel { [Required] [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Required] [DataType(DataType.Date)] public DateTime BirthDate { get; set; } [TextArea] - public string ShortBio { get; set; } + public string? ShortBio { get; set; } } } ``` @@ -454,14 +454,14 @@ public class EditModalModel : BookStorePageModel [Required] [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Required] [DataType(DataType.Date)] public DateTime BirthDate { get; set; } [TextArea] - public string ShortBio { get; set; } + public string? ShortBio { get; set; } } } ``` diff --git a/docs/en/UI/Angular/Authorization.md b/docs/en/UI/Angular/Authorization.md index 448a83e0cd..2e4a9af343 100644 --- a/docs/en/UI/Angular/Authorization.md +++ b/docs/en/UI/Angular/Authorization.md @@ -1,9 +1,9 @@ ## Authorization in Angular UI -OAuth is preconfigured in Angular application templates. So, when you start a project using the CLI (or Suite, for that matter), authorization already works. ABP Angular UI packages are using [angular-oauth2-oidc library](https://github.com/manfredsteyer/angular-oauth2-oidc#logging-in) for managing OAuth in the Angular client. +OAuth is preconfigured in Angular application templates. So, when you start a project using the CLI (or Suite, for that matter), authorization already works. ABP Angular UI packages are using [angular-oauth2-oidc library](https://github.com/manfredsteyer/angular-oauth2-oidc#logging-in) for managing OAuth in the Angular client. You can find **OAuth configuration** in the _environment.ts_ files. -### Authorization Code Flow +### Authorization Code Flow ```js import { Config } from '@abp/ng.core'; @@ -29,7 +29,6 @@ export const environment = { This configuration results in an [OAuth authorization code flow with PKCE](https://tools.ietf.org/html/rfc7636). According to this flow, the user is redirected to an external login page which is built with MVC. So, if you need **to customize the login page**, please follow [this community article](https://community.abp.io/articles/how-to-customize-the-login-page-for-mvc-razor-page-applications-9a40f3cd). - ### Resource Owner Password Flow If you have used the [Angular UI account module](./Account-Module) in your project, you can switch to the resource owner password flow by changing the OAuth configuration in the _environment.ts_ files as shown below: @@ -52,3 +51,128 @@ export const environment = { ``` According to this flow, the user is redirected to the login page in the account module. + +### Error Filtering + +In [AuthFlowStrategy](https://github.com/abpframework/abp/blob/21e70fd66154d4064d03b1a438f20a2e4318715e/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts#L24) class, there is a method called `listenToOauthErrors` that listens to `OAuthErrorEvent` errors. This method clears the localStorage for OAuth keys. However, in certain cases, we might want to skip this process. To achieve this, we can use the `AuthErrorFilterService`. +The `AuthErrorFilterService` is an abstract service that needs to be replaced with a custom implementation + +> By default, this service is replaced in the `@abp/ng.oauth` package + +**Usage** + +1.Create an auth-filter.provider + +```js +import { APP_INITIALIZER, inject } from '@angular/core'; +import { AuthErrorFilter, AuthErrorEvent, AuthErrorFilterService } from '@abp/ng.core'; +import { eCustomersAuthFilterNames } from '../enums'; + +export const CUSTOMERS_AUTH_FILTER_PROVIDER = [ + { provide: APP_INITIALIZER, useFactory: configureAuthFilter, multi: true }, +]; + +type Reason = object & { error: { grant_type: string | undefined } }; + +function configureAuthFilter() { + const errorFilterService = inject( + AuthErrorFilterService, AuthErrorEvent>, + ); + const filter: AuthErrorFilter = { + id: eCustomersAuthFilterNames.LinkedUser, + executable: true, + execute: (event: AuthErrorEvent) => { + const { reason } = event; + const { + error: { grant_type }, + } = (reason || {}); + + return !!grant_type && grant_type === eCustomersAuthFilterNames.LinkedUser; + }, + }; + + return () => errorFilterService.add(filter); +} +``` + +- `AuthErrorFilter:` is a model for filter object and it have 3 properties + + - `id:` a unique key in the list for the filter object + - `executable:` a status for the filter object. If it's false then it won't work, yet it'll stay in the list + - `execute:` a function that stores the skip logic + + 2.Add to the FeatureConfigModule + +```js +import { ModuleWithProviders, NgModule } from "@angular/core"; +import { CUSTOMERS_AUTH_FILTER_PROVIDER } from "./providers/auth-filter.provider"; + +@NgModule() +export class CustomersConfigModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: CustomersConfigModule, + providers: [CUSTOMERS_AUTH_FILTER_PROVIDER], + }; + } +} +``` + +Now it'll skip the clearing of OAuth storage keys for `LinkedUser` grant_type if any `OAuthErrorEvent` occurs + +**Replace with custom implementation** + +- Use the `AbstractAuthErrorFilter` class for signs of process. + +**Example** + +`my-auth-error-filter.service.ts` + +```js +import { Injectable, signal } from '@angular/core'; +import { MyAuthErrorEvent } from 'angular-my-auth-oidc'; +import { AbstractAuthErrorFilter, AuthErrorFilter } from '@abp/ng.core'; + +@Injectable({ providedIn: 'root' }) +export class OAuthErrorFilterService extends AbstractAuthErrorFilter< + AuthErrorFilter, + MyAuthErrorEvent +> { + protected readonly _filters = signal>>([]); + readonly filters = this._filters.asReadonly(); + + get(id: string): AuthErrorFilter { + return this._filters().find(({ id: _id }) => _id === id); + } + + add(filter: AuthErrorFilter): void { + this._filters.update(items => [...items, filter]); + } + + patch(item: Partial>): void { + const _item = this.filters().find(({ id }) => id === item.id); + if (!_item) { + return; + } + + Object.assign(_item, item); + } + + remove(id: string): void { + const item = this.filters().find(({ id: _id }) => _id === id); + if (!item) { + return; + } + + this._filters.update(items => items.filter(({ id: _id }) => _id !== id)); + } + + run(event: MyAuthErrorEvent): boolean { + return this.filters() + .filter(({ executable }) => !!executable) + .map(({ execute }) => execute(event)) + .some(item => item); + } +} + +``` diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs index af3c37c14f..0130c6e950 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs @@ -73,6 +73,7 @@ public class ProjectReferenceReplaceStep : ProjectBuildPipelineStep private readonly List _entries; private readonly bool _isMicroserviceServiceTemplate; private readonly string _projectName; + protected bool CentralPackageManagement { get; } protected ProjectReferenceReplacer( ProjectBuildContext context, @@ -81,6 +82,7 @@ public class ProjectReferenceReplaceStep : ProjectBuildPipelineStep _entries = context.Files; _isMicroserviceServiceTemplate = MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.Template?.Name); _projectName = projectName; + CentralPackageManagement = context.Files.Any(x => x.Name.EndsWith("Directory.Packages.props")); } public void Run() @@ -165,7 +167,7 @@ public class ProjectReferenceReplaceStep : ProjectBuildPipelineStep includeAttr.Value = ConvertToNugetReference(oldNodeIncludeValue); newNode.Attributes.Append(includeAttr); - var versionAttr = doc.CreateAttribute("Version"); + var versionAttr = doc.CreateAttribute(CentralPackageManagement ? "VersionOverride" : "Version"); versionAttr.Value = _nugetPackageVersion; newNode.Attributes.Append(versionAttr); return newNode; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RandomizeAuthServerPassPhraseStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RandomizeAuthServerPassPhraseStep.cs index a41c870f41..b29998438a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RandomizeAuthServerPassPhraseStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RandomizeAuthServerPassPhraseStep.cs @@ -12,6 +12,8 @@ public class RandomizeAuthServerPassPhraseStep : ProjectBuildPipelineStep private const string LocalhostPfx = "localhost.pfx -p 00000000-0000-0000-0000-000000000000"; private const string DotnetDevCerts = "openiddict.pfx -p 00000000-0000-0000-0000-000000000000"; private const string ProductionEncryptionAndSigningCertificate = "AddProductionEncryptionAndSigningCertificate(\"openiddict.pfx\", \"00000000-0000-0000-0000-000000000000\");"; + private const string ReadmeCallout = "`00000000-0000-0000-0000-000000000000`"; + private readonly static string RandomPassword = Guid.NewGuid().ToString("D"); public readonly static string RandomOpenIddictPassword = Guid.NewGuid().ToString("D"); @@ -59,6 +61,13 @@ public class RandomizeAuthServerPassPhraseStep : ProjectBuildPipelineStep RandomOpenIddictPassword)); } + if (lines[i].Contains(ReadmeCallout)) + { + lines[i] = lines[i].Replace(ReadmeCallout, + ReadmeCallout.Replace(DefaultPassword, + RandomOpenIddictPassword)); + } + if (lines[i].Contains(ProductionEncryptionAndSigningCertificate)) { lines[i] = lines[i].Replace(ProductionEncryptionAndSigningCertificate, diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs index 9bb6a6d95c..c867469a22 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs @@ -12,7 +12,6 @@ public class RemoveUnnecessaryPortsStep : ProjectBuildPipelineStep { public override void Execute(ProjectBuildContext context) { - RemoveUnnecessaryDbMigratorClients(context); RemoveUnnecessaryHttpApiHostPorts(context); } @@ -66,36 +65,4 @@ public class RemoveUnnecessaryPortsStep : ProjectBuildPipelineStep httpApiHostAppSettings.SetLines(newlines); } - - private static void RemoveUnnecessaryDbMigratorClients(ProjectBuildContext context) - { - var dbMigratorAppSettings = context.Files - .FirstOrDefault(f => - f.Name.Contains("MyCompanyName.MyProjectName.DbMigrator") && f.Name.EndsWith("appsettings.json")); - - if (dbMigratorAppSettings == null) - { - return; - } - - var appSettingsJsonObject = JObject.Parse(dbMigratorAppSettings.Content); - var authServerJsonObject = (JObject)appSettingsJsonObject?["IdentityServer"] ?? (JObject)appSettingsJsonObject["OpenIddict"]; - var clientsJsonObject = (JObject)authServerJsonObject?["Clients"] ?? (JObject)authServerJsonObject?["Applications"]; - - if (clientsJsonObject == null) - { - return; - } - - if (context.BuildArgs.UiFramework != UiFramework.Blazor) - { - clientsJsonObject.Remove("MyProjectName_Blazor"); - } - if (!context.BuildArgs.PublicWebSite) - { - clientsJsonObject.Remove("MyProjectName_Web_Public"); - } - - dbMigratorAppSettings.SetContent(appSettingsJsonObject.ToString(Formatting.Indented)); - } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs index 88ce572d33..c899270ad2 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs @@ -220,7 +220,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase x).Select(x => x))); - classTemplate.Replace($"{Environment.NewLine}{Environment.NewLine} {MethodPlaceholder}", string.Empty); + classTemplate.Replace($"{Environment.NewLine}{Environment.NewLine} {MethodPlaceholder}", string.Empty).Replace(MethodPlaceholder, string.Empty); filePath = Path.Combine(args.WorkDirectory, folder, $"{clientProxyName}.Generated.cs"); Directory.CreateDirectory(Path.GetDirectoryName(filePath)); diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml index 09ab99a121..9a65911d3b 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml @@ -456,14 +456,9 @@ else var post = Model.PostsList[index];
- - - - - @L["Blog"].Value.ToUpper() - +